MediaWiki:EditConflictAlert.js

/* EditConflictAlert * * Tells the user when a page that is currently being edited is updated. * * @author Dorumin */ (function { $.fn.extend({ getModalTopOffset: function { var top = Math.max((($(window).height - this.outerHeight) / 2), 20); var opts = this.data('settings'); if (opts && typeof opts.topMaximum == "number") { top = Math.min(top, opts.topMaximum); }       return $(window).scrollTop + top; },   makeModal: function(options) { var settings = { showCloseButton: !0, width: 400, height: "auto", tabsOutsideContent: !1, topOffset: 50, escapeToClose: !0 }, calculatedZIndex, modalWidth, mainContent; if (options) { $.extend(settings, options); }       var ts = Math.round((new Date).getTime / 1000), id = settings.id || ($(this).attr('id') || ts) + 'Wrapper', wrapper; if (mw.config.get('skin') === 'timeless' || settings.appendToBody) { wrapper = $(' ', {               'class': 'modalWrapper',                'id': id            }).append($(' ', { 'class': 'modalContent' }).append(this)).appendTo('body'); } else { this.wrap(' '); wrapper = this.closest(".modalWrapper"); wrapper.appendTo('#positioned_elements'); }       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 (mw.config.get('skin') === 'timeless') { if (settings.width !== 'auto') { if (settings.width !== undefined) { modalWidth = settings.width + 40; } else { mainContent = $("#mw-content #content.mw-body"); 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            }); } else if (settings.suppressDefaultStyles) { wrapper.css({               zIndex: calculatedZIndex,                top: $(window).scrollTop + settings.topOffset            }); } else { wrapper.width(settings.width).css({               marginLeft: -wrapper.outerWidth(false) / 2,                top: wrapper.getModalTopOffset,                zIndex: calculatedZIndex            }).fadeIn("fast"); }       if (settings.showCloseButton) { wrapper.prepend(' '); }       this.removeAttr('title'); var persistent = (typeof settings.persistent == 'boolean') ? settings.persistent : !1; var onClose = (typeof settings.onClose == 'function') ? settings.onClose : !1; var closeOnBlackoutClick = (typeof settings.closeOnBlackoutClick == 'boolean') ? settings.closeOnBlackoutClick : !0; wrapper.find('.close').bind("click", function {           var wrapper = $(this).closest('.modalWrapper');            var settings = wrapper.data('settings');            if (typeof settings.onClose == 'function') {                if (settings.onClose({                    click: 1                }) == false) {                    return;                }            }            if (persistent) {                wrapper.hideModal;            } else {                wrapper.closeModal;            }        }); if (settings.escapeToClose) { $(window).bind("keydown.modal" + id, function(event) {               if (event.keyCode == 27) {                    if (typeof settings.onClose == 'function') {                        if (settings.onClose({                            keypress: 1                        }) == false) {                            return;                        }                    }                    if (persistent) {                        wrapper.hideModal;                    } else {                        wrapper.closeModal;                    }                    return false;                }            }); }       $(window).bind("resize.modal", function {            if (mw.config.get('skin') == 'timeless' || !settings.resizeModal) {                return;            }            wrapper.css("top", wrapper.getModalTopOffset);            $(".blackout:last").height($(document).height);        }); var blackoutOpacity = 0.65; if (settings.blackoutOpacity) { blackoutOpacity = settings.blackoutOpacity; }       var blackout = $(' ').addClass('blackout').attr('data-opacity', blackoutOpacity); blackout.css({           zIndex: zIndex        }).fadeTo("fast", blackoutOpacity).bind("click", function {            if (!closeOnBlackoutClick) {                return;            }            if (typeof settings.onClose == 'function') {                if (settings.onClose({                    click: 1                }) == false) {                    return;                }            }            if (persistent) {                wrapper.hideModal;            } else {                wrapper.closeModal;            }        }); if (mw.config.get('skin') == 'timeless' || settings.appendToBody) { blackout.appendTo("body"); } else { blackout.appendTo("#positioned_elements"); }       wrapper.data('blackout', blackout); if (typeof settings.onCreate == 'function') { settings.onCreate(this, wrapper); }       $(document.body).addClass('modalShown'); return wrapper; },   closeModal: function { $(window).unbind(".modal" + this.attr('id')); this.animate({           top: this.offset["top"] + 100,            opacity: 0        }, "fast", function {            $(this).remove;        }); var blackout = $(this).data('blackout') , settings = $(this).data('settings'); blackout.fadeOut("fast", function {           $(this).remove;            var callback = settings && settings.onAfterClose;            if ($.isFunction(callback)) {                callback;            }        }); $(document.body).removeClass('modalShown'); },   hideModal: function { var blackout = $(this).data('blackout') , settings = $(this).data('settings'); blackout.fadeOut("fast").addClass('blackoutHidden'); this.animate({           top: this.offset["top"] + 100,            opacity: 0        }, "fast", function {            $(this).hide;            var callback = settings && settings.onAfterClose;            if ($.isFunction(callback)) {                callback;            }        }); $(document.body).removeClass('modalShown'); },   showModal: function { var wrapper = this.closest(".modalWrapper"); var zIndex = 5001101 + ($('body').children('.blackout').length) * 2; var blackout = $(this).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"        }).log('showModal: #' + this.attr('id')); $(document.body).addClass('modalShown'); },   resizeModal: function(width) { width = parseInt(width); var wrapper = this.closest(".modalWrapper"); wrapper.width(width).css('marginLeft', -wrapper.outerWidth(false) >> 1).log('resizeModal: #' + this.attr('id') + ' resized to ' + width + 'px'); },   isModalShown: function { return $(document.body).hasClass('modalShown'); },   getModalWrapper: function { return $('.modalWrapper'); } }); $.showCustomModal = function(title, content, options) {       var buttons = , buttonNo, button, dialog, modal;        options = (typeof options !== 'object') ? {} : options;        if (options.buttons) {            buttons = $(' ');            for (buttonNo = 0; buttonNo < options.buttons.length; buttonNo++) {                button = '' + options.buttons[buttonNo].message + '';                $(button).bind('click', options.buttons[buttonNo].handler).appendTo(buttons);            }        }        dialog = $(' ').html(content).attr('title', title).append(buttons);        $('body').append(dialog);        if (typeof options.callbackBefore === 'function') {            options.callbackBefore;        }        modal = dialog.makeModal(options); if (typeof options.callback === 'function') { options.callback(modal); }       return modal; };   var config = mw.config.get([        'wgAction',        'wgArticleId',        'wgNamespaceIds',        'wgNamespaceNumber',        'wgPageName',        'wgContentLanguage',        'wguserName',        'stylepath',        'wgScriptPath'    ]); if (       !(config.wgAction === 'edit' || config.wgAction === 'submit') ||        {1201: 1, 1200: 1, 2002: 1}[config.wgNamespaceNumber] ||        config.wgArticleId === 0 ||        window.EditConflictAlertInit    )  { return; }   window.EditConflictAlertInit = true; mw.loader.using('mediawiki.api').then(function {       var Api = new mw.Api,        help = Object.keys(config.wgNamespaceIds).filter(function(id) { return config.wgNamespaceIds[id] === 12; })[0].replace(/\b./g, function(char) { return char.toUpperCase; }),       cur_id,        old_id,        diff,        content;

function fetch_revs(with_content) { return Api.get({               action: 'query',                prop: 'revisions',                rvprop: 'ids|user' + (with_content ? '|content' : ''),               titles: config.wgPageName,                cb: Date.now            }); }

function load_diff { $.get(config.wgScriptPath + '/?diffonly=1&diff=' + cur_id + '&oldid=' + old_id, function(page) {               var $el = $(page).find('.diff');                diff = $(' ').append($el.clone).html;                $('#ajax-indicator').replaceWith(diff);            }); }

function add_content { $('#diff-modal').closeModal; $('.banner-notification .close').click; $('#diff, #myedit').remove; $('[name="wpStarttime"]').val(new Date.toISOString.replace(/\D/g, '').slice(0, -3)); var $edit_area = $('#wpTextbox1'), your_text = $edit_area.val, $diff = $(' ', {               id: 'diff'            }).append($(' ', { append: $(' ', {                   class: 'mw-headline',                    id: 'The_differences_.28help.29',                    append: [                        'The differences',                        ' (', $('', {                           target: '_blank',                            href: config.wgScriptPath + '/wiki/' + help + ':Diff',                            title: help + ':Diff',                            text: 'help'                        }), ')'                   ]                })            }), $(diff)), $myedit = $(' ', {               id: 'myedit'            }).append($(' ', { append: $(' ', {                   class: 'mw-headline',                    id: 'myedit-header',                    text: 'This is your edit. Copy your changes to the box above!'                }) }), $(' ', {               id: 'wpTextbox2', name: 'wpTextbox2', tabindex: 6, readonly: true, accesskey: ',', cols: 80, rows: 25, lang: config.wgContentLanguage, dir: document.documentElement.dir, val: your_text }));           $edit_area.val(content); $('.mw-editTools').after($diff, $myedit); }

function add_ace_content { $('#diff-modal').closeModal; $('.banner-notification .close').click; $('#diff, #myedit').remove; $('[name="wpStarttime"]').val(new Date.toISOString.replace(/\D/g, '').slice(0, -3)); var $edit_area = $('#wpTextbox1'), your_text = $edit_area.val, $diff = $(' ', {               id: 'diff'            }).append($(' ', { append: $(' ', {                   class: 'mw-headline',                    id: 'The_differences_.28help.29',                    append: [                        'The differences',                        ' (', $('', {                           target: '_blank',                            href: config.wgScriptPath + '/wiki/' + help + ':Diff',                            title: help + ':Diff',                            text: 'help'                        }), ')'                   ]                })            }), $(diff)), $myedit = $(' ', {               id: 'myedit'            }).append($(' ', { append: $(' ', {                   class: 'mw-headline',                    id: 'myedit-header',                    text: 'This is their edit. Copy the changes to the box above!'                }) }), $(' ', {               id: 'wpTextbox2', name: 'wpTextbox2', tabindex: 6, readonly: true, accesskey: ',', cols: 80, rows: 25, lang: config.wgContentLanguage, dir: document.documentElement.dir, val: content }));           $('.mw-editTools').after($diff, $myedit); }

function show_diff_modal { $.showCustomModal('Difference between revisions', $(' ').attr({ id: 'ajax-indicator', src: 'https://static.miraheze.org/dcwiki/0/05/Ajax.gif', title: 'Loading...', alt: 'Loading...' }).css({ float: 'center', margin: '2em auto', display: 'block' }), {               width: Math.min(window.innerWidth - 200, 1000),                id: 'diff-modal',                callback: load_diff,                buttons: [{                    message: 'Close',                    handler: function {                        $('#diff-modal').closeModal;                    }                }, {                    defaultButton: true,                    message: 'Update!',                    handler: window.ace ? add_ace_content : add_content                }]            }); }

function init { fetch_revs(false).done(function(data) {               var d = data.query.pages;                old_id = cur_id = d[Object.keys(d)[0]].revisions[0].revid;            });

setInterval(function {               fetch_revs(true).done(function(data) { var d = data.query.pages, p = d[Object.keys(d)[0]]; if (!p.revisions) { // We are editing a nonexistent page. return; }                   var r = p.revisions[0]; content = r['*']; if (r.revid !== cur_id && r.user !== config.wgUserName) { if ($('.wds-alert[data-id="' + r.revid + '"]').length) return; if ($('#diff-modal').length) { $('#diff-modal').closeModal; }                       cur_id = r.revid; var message = 'A new edit was made to this page since you started editing!' + ' ('                           + 'diff'                            + ')'; $("#mw-content").before('&times; Warning! ' + message + ' '); $('#view-diff').click(function(e) {                           e.preventDefault;                            show_diff_modal;                        }); }               });            }, window.EditConflictAlertInterval ||            5000); }        init; }) });