Fandom Developers Wiki
Register
m (Fix dark theme patches)
m (Knew keeping in the skin-specific stuff was a bad idea)
Line 17: Line 17:
 
(function() {
 
(function() {
 
if (window.dev && dev.showCustomModal) return;
 
if (window.dev && dev.showCustomModal) return;
 
var skin = mw.config.get('skin');
 
   
 
var closeModal = function($modals) {
 
var closeModal = function($modals) {
Line 113: Line 111:
 
var ts = Math.round(Date.now() / 1000);
 
var ts = Math.round(Date.now() / 1000);
 
var id = settings.id || ($dialog.attr('id') || ts) + 'Wrapper';
 
var id = settings.id || ($dialog.attr('id') || ts) + 'Wrapper';
var wrapper;
+
var wrapper = $('<section>', {
 
'class': 'SCMModal modalWrapper',
 
if (skin === 'oasis' || settings.appendToBody) {
+
'id': id
wrapper = $('<section>', {
+
}).append($('<section>', {
'class': 'SCMModal modalWrapper',
+
'class': 'modalContent'
'id': id
+
}).append($dialog)).appendTo('body');
}).append($('<section>', {
 
'class': 'modalContent'
 
}).append($dialog)).appendTo('body');
 
} else {
 
$dialog.wrap('<div class="SCMModal modalWrapper" id="' + id + '"></div>');
 
wrapper = $dialog.closest('.modalWrapper');
 
wrapper.appendTo('#positioned_elements');
 
}
 
   
 
if (settings.className) {
 
if (settings.className) {
Line 145: Line 135:
 
}
 
}
   
  +
var modalTabs = wrapper.find('.modal-tabs');
if (settings.tabsOutsideContent || skin === 'oasis') {
 
var modalTabs = wrapper.find('.modal-tabs');
+
if (modalTabs.length !== 0) {
if (modalTabs.length !== 0) {
+
modalTabs.insertBefore(wrapper.find('.modalContent'));
modalTabs.insertBefore(wrapper.find('.modalContent'));
 
}
 
 
}
 
}
   
if (skin === 'oasis') {
+
if (settings.width !== 'auto') {
if (settings.width !== 'auto') {
+
if (settings.width !== undefined) {
if (settings.width !== undefined) {
+
modalWidth = settings.width + 40;
modalWidth = settings.width + 40;
+
} else {
} else {
+
mainContent = $('#WikiaMainContent');
mainContent = $('#WikiaMainContent');
+
if (mainContent.length > 0) {
if (mainContent.length > 0) {
+
modalWidth = mainContent.width();
modalWidth = mainContent.width();
 
}
 
 
}
 
}
} else {
 
modalWidth = 'auto';
 
 
}
 
}
 
wrapper.width(modalWidth).css({
 
left: '50%',
 
height: settings.height,
 
'margin-left': -wrapper.outerWidth(false) / 2,
 
top: $(window).scrollTop() + settings.topOffset,
 
zIndex: calculatedZIndex
 
});
 
} else if (settings.suppressDefaultStyles) {
 
wrapper.css({
 
zIndex: calculatedZIndex,
 
top: $(window).scrollTop() + settings.topOffset
 
});
 
 
} else {
 
} else {
wrapper.width(settings.width).css({
+
modalWidth = 'auto';
marginLeft: -wrapper.outerWidth(false) / 2,
 
top: getModalTopOffset(wrapper),
 
zIndex: calculatedZIndex
 
}).fadeIn('fast');
 
 
}
 
}
  +
 
wrapper.width(modalWidth).css({
 
left: '50%',
 
height: settings.height,
 
'margin-left': -wrapper.outerWidth(false) / 2,
 
top: $(window).scrollTop() + settings.topOffset,
 
zIndex: calculatedZIndex
 
});
   
 
if (settings.showCloseButton) {
 
if (settings.showCloseButton) {
Line 233: Line 208:
 
}
 
}
   
$(window).on('resize.modal', function() {
+
// $(window).on('resize.modal', function() {
if (window.skin == 'oasis' || !settings.resizeModal) {
+
// if (!settings.resizeModal) {
return;
+
// return;
}
+
// }
   
wrapper.css('top', getModalTopOffset(wrapper));
+
// wrapper.css('top', getModalTopOffset(wrapper));
$('.blackout:last').height($(document).height());
+
// $('.blackout:last').height($(document).height());
});
+
// });
   
 
var blackoutOpacity = 0.65;
 
var blackoutOpacity = 0.65;
Line 269: Line 244:
 
});
 
});
   
 
blackout.appendTo('body');
if (skin == 'oasis' || settings.appendToBody) {
 
blackout.appendTo('body');
 
} else {
 
blackout.appendTo('#positioned_elements');
 
}
 
   
 
wrapper.data('blackout', blackout);
 
wrapper.data('blackout', blackout);

Revision as of 21:20, 1 June 2021

/* ShowCustomModal
 *
 * $.showCustomModal brought to UCP without polluting the jQuery global
 * QoL updates include:
 * - Let you pass the options as the 2nd argument instead of 3rd, with `content` replacing the content
 * - closeModal functions now properly handle multiple inputs
 * - Buttons don't need an id not to have id="undefined"
 * Pain points not addressed:
 * - Body class .modalShown still unstable if more than one modal shown at once, don't rely on it
 * - Ugly code inside
 *
 * @author Dorumin, kinda
 *
 * Used files: [[File:SCM-icon-close.png]]
 */

(function() {
    if (window.dev && dev.showCustomModal) return;

    var closeModal = function($modals) {
        $modals.each(function(_, modal) {
            var $modal = $(modal);
            $(window).off('.modal' + $modal.attr('id'));
            $modal.animate({
                top: $modal.offset().top + 100,
                opacity: 0
            }, 'fast', function() {
                $modal.remove();
            });

            var $blackout = $modal.data('blackout');
            var settings = $modal.data('settings');
            $blackout.fadeOut('fast', function() {
                $modal.remove();
                $blackout.remove();

                var callback = settings && settings.onAfterClose;
                if ($.isFunction(callback)) {
                    callback();
                }
            });
            $(document.body).removeClass('modalShown');
        });
    };

    var hideModal = function($modals) {
        $modals.each(function(_, modal) {
            var $modal = $(modal);
            var $blackout = $modal.data('blackout');
            var settings = $modal.data('settings');
            $blackout.fadeOut('fast').addClass('blackoutHidden');
            $modal.animate({
                top: $modal.offset().top + 100,
                opacity: 0
            }, 'fast', function() {
                $modal.hide();
                var callback = settings && settings.onAfterClose;
                if ($.isFunction(callback)) {
                    callback();
                }
            });
            $(document.body).removeClass('modalShown');
        });
    };

    var showModal = function($modal) {
        var wrapper = $modal.closest('.modalWrapper');
        var zIndex = 5001101 + ($('body').children('.blackout').length) * 2;
        var $blackout = $modal.data('blackout');
        var blackoutOpacity = $blackout.attr('data-opacity');
        if (!blackoutOpacity) {
            blackoutOpacity = 0.65;
        }
        $blackout.css({
            display: 'block',
            opacity: blackoutOpacity,
            zIndex: zIndex
        }).removeClass('blackoutHidden');
        wrapper.css({
            top: wrapper.getModalTopOffset(),
            zIndex: zIndex + 1,
            opacity: 1,
            display: 'block'
        });
        $(document.body).addClass('modalShown');
    };

    var getModalTopOffset = function($wrapper) {
        var top = Math.max((($(window).height() - $wrapper.outerHeight()) / 2), 20);
        var opts = $wrapper.data('settings');
        if (opts && typeof opts.topMaximum == 'number') {
            top = Math.min(top, opts.topMaximum);
        }
        return $(window).scrollTop() + top;
    };

    var makeModal = function($dialog, options) {
        var settings = {
            showCloseButton: true,
            width: 400,
            height: 'auto',
            tabsOutsideContent: !1,
            topOffset: 50,
            escapeToClose: !0
        }, calculatedZIndex, modalWidth, mainContent;

        if (options) {
            $.extend(settings, options);
        }

        var ts = Math.round(Date.now() / 1000);
        var id = settings.id || ($dialog.attr('id') || ts) + 'Wrapper';
        var wrapper = $('<section>', {
            'class': 'SCMModal modalWrapper',
            'id': id
        }).append($('<section>', {
            'class': 'modalContent'
        }).append($dialog)).appendTo('body');

        if (settings.className) {
            wrapper.addClass(settings.className);
        }

        var zIndex = settings.zIndex ? parseInt(settings.zIndex) : (5001101 + ($('body').children('.blackout').length) * 2);
        calculatedZIndex = zIndex + 1;
        wrapper.data('settings', settings);
        if (!settings.noHeadline) {
            var headline = wrapper.find('h1:first');
            if (headline.length !== 0) {
                headline.remove();
            } else {
                headline = $('<h1>').html($dialog.attr('title') || '');
            }
            headline.prependTo(wrapper);
        }

        var modalTabs = wrapper.find('.modal-tabs');
        if (modalTabs.length !== 0) {
            modalTabs.insertBefore(wrapper.find('.modalContent'));
        }

        if (settings.width !== 'auto') {
            if (settings.width !== undefined) {
                modalWidth = settings.width + 40;
            } else {
                mainContent = $('#WikiaMainContent');
                if (mainContent.length > 0) {
                    modalWidth = mainContent.width();
                }
            }
        } else {
            modalWidth = 'auto';
        }

        wrapper.width(modalWidth).css({
            left: '50%',
            height: settings.height,
            'margin-left': -wrapper.outerWidth(false) / 2,
            top: $(window).scrollTop() + settings.topOffset,
            zIndex: calculatedZIndex
        });

        if (settings.showCloseButton) {
            wrapper.prepend('<button class="close wikia-chiclet-button"><img src="https://images.wikia.com/dev/images/3/31/SCM-icon-close.png"></button>');
        }

        $dialog.removeAttr('title');
        var persistent = (typeof settings.persistent == 'boolean') ? settings.persistent : !1;
        var closeOnBlackoutClick = (typeof settings.closeOnBlackoutClick == 'boolean') ? settings.closeOnBlackoutClick : !0;
        wrapper.find('.close').on('click', function() {
            var wrapper = $dialog.closest('.modalWrapper');
            var settings = wrapper.data('settings');
            if (typeof settings.onClose == 'function') {
                if (settings.onClose({
                    click: 1
                }) === false) {
                    return;
                }
            }

            if (persistent) {
                hideModal(wrapper);
            } else {
                closeModal(wrapper);
            }
        });

        if (settings.escapeToClose) {
            $(window).on('keydown.modal' + id, function(event) {
                if (event.keyCode == 27) {
                    if (typeof settings.onClose == 'function') {
                        if (settings.onClose({
                            keypress: 1
                        }) === false) {
                            return;
                        }
                    }

                    if (persistent) {
                        hideModal(wrapper);
                    } else {
                        closeModal(wrapper);
                    }

                    return false;
                }
            });
        }

        // $(window).on('resize.modal', function() {
        //     if (!settings.resizeModal) {
        //         return;
        //     }

        //     wrapper.css('top', getModalTopOffset(wrapper));
        //     $('.blackout:last').height($(document).height());
        // });

        var blackoutOpacity = 0.65;
        if (settings.blackoutOpacity) {
            blackoutOpacity = settings.blackoutOpacity;
        }

        var blackout = $('<div>').addClass('SCMBlackout blackout').attr('data-opacity', blackoutOpacity);
        blackout.css({
            zIndex: zIndex,
            opacity: 0
        }).fadeTo('fast', blackoutOpacity).on('click', function() {
            if (!closeOnBlackoutClick) {
                return;
            }
            if (typeof settings.onClose == 'function') {
                if (settings.onClose({
                    click: 1
                }) == false) {
                    return;
                }
            }
            if (persistent) {
                hideModal(wrapper);
            } else {
                closeModal(wrapper);
            }
        });

        blackout.appendTo('body');

        wrapper.data('blackout', blackout);
        if (typeof settings.onCreate == 'function') {
            settings.onCreate($dialog, wrapper);
        }
        $(document.body).addClass('modalShown');

        return wrapper;
    };

    var showCustomModal = function(title, content, options) {
        var buttons = '', buttonNo, button, dialog, modal;
        if (typeof options === 'undefined' && typeof content === 'object') {
            options = content;
            content = content.content || '';
            delete options.content;
        }
        if (typeof options !== 'object') {
            options = {};
        }

        if (options.buttons) {
            buttons = $('<div class="neutral modalToolbar"></div>');

            for (buttonNo = 0; buttonNo < options.buttons.length; buttonNo++) {
                var button = options.buttons[buttonNo];
                var $button = $('<a>');
                if (button.id) {
                    $button.attr('id', button.id);
                }

                $button.addClass('wikia-button');
                if (!button.defaultButton) {
                    $button.addClass('secondary');
                }

                $button.html(button.message);
                $button.on('click', button.handler);

                $button.appendTo(buttons);
            }
        }

        dialog = $('<div>').append(content).attr('title', title).append(buttons);
        $('body').append(dialog);

        if (typeof options.callbackBefore === 'function') {
            options.callbackBefore();
        }

        modal = makeModal(dialog, options);

        if (typeof options.callback === 'function') {
            options.callback(modal);
        }

        return modal;
    };

    showCustomModal.makeModal = makeModal;
    showCustomModal.hideModal = hideModal;
    showCustomModal.showModal = showModal;
    showCustomModal.closeModal = closeModal;
    showCustomModal.getModalTopOffset = getModalTopOffset;

    var imported = importArticle({
        type: 'style',
        article: 'w:c:dev:MediaWiki:ShowCustomModal.css'
    });
    var fire = function() {
        mw.hook('dev.showCustomModal').fire(showCustomModal);
    };

    function patchStyles() {
        // Thank u sophie
        var textColor = getComputedStyle(document.documentElement).getPropertyValue('--theme-article-text-color');
        var isDark = textColor === '#e6e6e6';

        if (isDark) {
            mw.util.addCSS('\
.modalWrapper {\
    box-shadow: 0 10px 60px 0 black;\
}');
        }
    }

    imported.then(function() {
        patchStyles();
        fire();
    });

    window.dev = window.dev || {};
    dev.showCustomModal = showCustomModal;
})();