ميدياويكي:Gadget-QuickEdit.js

من كوبتيكبيديا
اذهب إلى التنقلاذهب الى البحث
لم تعد النسخة القابلة للطباعة مدعومة وقد تحتوي على أخطاء في العرض. يرجى تحديث علامات متصفحك المرجعية واستخدام وظيفة الطباعة الافتراضية في متصفحك بدلا منها.

ملاحظة: بعد النشر، أنت قد تحتاج إلى إفراغ الكاش الخاص بمتصفحك لرؤية التغييرات.

  • فايرفوكس / سافاري: أمسك Shift أثناء ضغط Reload، أو اضغط على إما Ctrl-F5 أو Ctrl-R (⌘-R على ماك)
  • جوجل كروم: اضغط Ctrl-Shift-R (⌘-Shift-R على ماك)
  • إنترنت إكسبلورر/إيدج: أمسك Ctrl أثناء ضغط Refresh، أو اضغط Ctrl-F5
  • أوبرا: اضغط Ctrl-F5.
/* global mw */
/// <reference path="../typings/jquery/jquery.d.ts"/>
/**
* Wikiplus
* Author:+Eridanus Sora/@妹空酱
* Github:https://github.com/Last-Order/Wikiplus
*/
/**
* 依赖组件:MoeNotification
* https://github.com/Last-Order/MoeNotification
*/
'use strict';

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

function MoeNotification() {
    var self = this;
    this.display = function (text, type, callback) {
        var _callback = callback || function () {};
        var _text = text || 'å–µ~';
        var _type = type || 'success';
        $("#MoeNotification").append($("<div>").addClass('MoeNotification-notice').addClass('MoeNotification-notice-' + _type).append('<span>' + _text + '</span>'));
        $("#MoeNotification").find('.MoeNotification-notice').last().fadeIn(300);
        self.bind();
        self.clear();
        _callback($("#MoeNotification").find('.MoeNotification-notice').last());
    };
    this.create = {
        success: function success(text, callback) {
            var _callback = callback || function () {};
            self.display(text, 'success', _callback);
        },
        warning: function warning(text, callback) {
            var _callback = callback || function () {};
            self.display(text, 'warning', _callback);
        },
        error: function error(text, callback) {
            var _callback = callback || function () {};
            self.display(text, 'error', _callback);
        }
    };
    this.clear = function () {
        if ($(".MoeNotification-notice").length >= 10) {
            $("#MoeNotification").children().first().fadeOut(150, function () {
                $(this).remove();
            });
            setTimeout(self.clear, 300);
        } else {
            return false;
        }
    };
    this.empty = function (f) {
        $(".MoeNotification-notice").each(function (i) {
            if ($.isFunction(f)) {
                var object = this;
                setTimeout(function () {
                    f($(object));
                }, 200 * i);
            } else {
                $(this).delay(i * 200).fadeOut('fast', function () {
                    $(this).remove();
                });
            }
        });
    };
    this.bind = function () {
        $(".MoeNotification-notice").mouseover(function () {
            self.slideRight($(this));
        });
    };
    this.slideRight = function (object, speed) {
        object.css('position', 'relative');
        object.animate({
            right: "200%"
        }, speed || 150, function () {
            $(this).fadeOut('fast', function () {
                $(this).remove();
            });
        });
    };
    this.init = function () {
        $("body").append('<div id="MoeNotification"></div>');
    };
    if (!($("#MoeNotification").length > 0)) {
        this.init();
    }
}

$(function () {
    var i18nData = {};
    var scriptPath = location.protocol + '//wikiplus-app.smartgslb.com';
    i18nData['en-us'] = i18nData['fr-fr'] = i18nData['ar-sa'] = i18nData['ar'] = {
        "__language": "en-us",
        "__author": ["Eridanus Sora", "AnnAngela", "YinYan"],
        "__version": "210",
        "unknown_error_name": "Unknown error",
        "api_unaccessiable": "API of this wiki is not available",
        "api_unwriteable": "Write API of this wiki is not available",
        "fail_to_get_timestamp": "Failed to get the timestamp of this page.",
        "fail_to_get_edittoken": "Failed to get the EditToken of this page.",
        "fail_to_get_pageinfo": "Failed to load infomation of this page",
        "not_autoconfirmed_user": "You are not an autoconfiremd user",
        "hit_abusefilter": "Your edit hit the abusefilter(s)",
        "unknown_edit_error": "Unknown edit error",
        "unknown_edit_error_message": "Unknown edit error($1)",
        "notitle": "The title parameter must be set",
        "notext": "The text parameter must be set",
        "notoken": "The token parameter must be set",
        "invalidsection": "The section parameter must be set to an integer or 'new'",
        "protectedtitle": "This title has been protected from creation",
        "cantcreate": "You don't have permission to create new pages",
        "cantcreate_anon": "Anonymous users can't create new pages",
        "articleexists": "The article you tried to create has already existed",
        "noimageredirect_anon": "Anonymous users can't create image redirects",
        "noimageredirect": "You don't have the permission to create image redirects",
        "spamdetected": "Your edit was rejected because it contained a spam fragment",
        "filtered": "The filter callback function rejected your edit",
        "contenttoobig": "The content you submitted exceeds the article size limit",
        "noedit_anon": "Anonymous users can't edit pages",
        "noedit": "You don't have the permission to edit pages",
        "pagedeleted": "The page was deleted during your edit",
        "emptypage": "Creating new, empty pages is not allowed",
        "emptynewsection": "Creating empty new sections is not possible.",
        "editconflict": "Edit Conflict! Don't panic. Please check the difference between your content below and the existing revision, then refresh the page to make another submit",
        "revwrongpage": "The revision you are editing now is not one a valid reversions of this page",
        "undofailure": "Undo failed due to conflicts.",
        "missingtitle": "Missing title in your edit/creation",
        "mustbeposted": "The edit must be submited by POST method",
        "readapidenied": "Read API Denied",
        "writeapidenied": "Write API Denied",
        "noapiwrite": "No available write API in this wiki",
        "badtoken": "Invalid EditToken",
        "missingparam": "One of the parameters title, pageid is required",
        "invalidparammix": "The parameters title, pageid can not be used together",
        "invalidtitle": "Invalid page title",
        "nosuchpageid": "Inexistent page ID",
        "pagecannotexist": "No access to create a new page in this namespace",
        "nosuchrevid": "Inexisting reversion ID",
        "badmd5": "Invalid MD5",
        "hookaborted": "Your edit was rejected by the hook(s)",
        "parseerror": "Failed to parse the wikitext of this page",
        "summaryrequired": "لم تكتب ملخصا",
        "blocked": "You have been already BLOCKED",
        "ratelimited": "You've exceeded your rate limit. Please have a tea and try again later",
        "unknownerror": "Unknown error",
        "nosuchsection": "There is no such section",
        "sectionsnotsupported": "Can't edit in this section",
        "editnotsupported": "Can't edit in this section by writing section",
        "appendnotsupported": "Can't append/prepend wikitext to this page",
        "redirect_appendonly": "Only append/prepend can be made to this page because of the rules of the redirect page",
        "badformat": "The requested serialization format can not be applied to the page's content model",
        "customcssprotected": "You're not allowed to edit custom CSS pages",
        "customjsprotected": "You're not allowed to edit custom JavaScript pages",
        "cascadeprotected": "This page is under a cascading protection",
        "network_edit_error": "Failed to edit this page because of network errors",
        "redirect_to_summary": "حول إلى [[$1]] بالمحرر السريع",
        "redirect_from_summary": "حول [[$1]] إلى [[$2]] بالمحرر السريع",
        "need_init": "WikiPlus haven't been loaded completely. It's a rare occasion so you can try to refresh and try again.",
        "fail_to_get_wikitext": "Failed to load the wikitext of this page",
        "quickedit_topbtn": "تحرير سريع",
        "quickedit_sectionbtn": "تحرير سريع",
        "fail_to_init_quickedit": "Failed to initialize WikiPlus",
        "back": "رجوع",
        "goto_editbox": "انتقل لصندوق الكتابة",
        "summary_placehold": "الملخص",
        "submit": "احفظ",
        "publish_page": "احفظ الصفحة",
        "publish_change": "احفظ التعديل",
        "preview": "معاينة",
        "cancel": "إلغاء",
        "mark_minoredit": "التعديل طفيف",
        "onclose_confirm": "[Wikiplus] Do you really want to close this page when you are still editing it, as you will lose all your unsaved work?",
        "fail_to_get_wikitext_when_edit": "Failed to load wikitext for your edit",
        "cant_parse_wikitext": "Failed to parse the wikitext",
        "loading_preview": "المعاينة تحمل",
        "submitting_edit": "التعديل يحفظ",
        "edit_success": "التعديل حفظ في $1 جزء ثانية للألف",
        "empty_page_confirm": "The wikitext in your edit is empty, which will empty this page.\r\nPlease set the value of key \"empty\" true to allow this kind of edits. (This is a tip for developers)",
        "cross_page_edit": "The content you are editing belongs to another page, please wait...",
        "cross_page_edit_submit": "يحفظ...",
        "cross_page_edit_error": "Failed to load the infomation",
        "install_tip": "Do you allow WikiPlus to collect insensitive data to help us develop WikiPlus and provide feedback to current site: $1 ?",
        "accept": "نعم",
        "decline": "لا",
        "install_finish": "المحرر السريع مشغل",
        "loading": "تحميل...",
        "cant_add_funcbtn": "Failed to add buttons for WikiPlus",
        "wikiplus_settings": "إعدادات المحرر السريع",
        "wikiplus_settings_desc": "Please modify your setting according to the standards below",
        "wikiplus_settings_placeholder": "Your setting is empty, please modify your setting according to the documentation.",
        "wikiplus_settings_grammar_error": "Syntax error in your setting",
        "wikiplus_settings_saved": "حفظت الإعدادات",
        "redirect_from": "حول إلى هنا",
        "redirect_desc": "اكتب العنوان المرادف الذي تريد أن يحيل إلى هذه الصفحة",
        "empty_input": "Empty input",
        "redirect_saved": "Redirection is finished",
        "uninited": "Wikiplus is not completely initialized, please refeash this page",
        "cant_parse_i18ncache": "Failed to parse the cache of i18n file",
        "cant_load_language": "Failed to load i18n file",
        "history_edit_warning": " // You are trying to edit a history revision of this page. This will apply to the latest revision. Please be careful.",
        "create_page_tip": "<!-- You are now creating a new page. Please delete this line and be careful. -->",
        "continue": "كمل",
        "default_summary_suffix": "تحرير سريع"
    };

    /**
     * åŠ è½½å…¶ä»–è¯­è¨€æ–‡ä»¶
     * @param {string} language 语言名
     */
    function loadLanguage(language) {
        $.ajax({
            url: "https://ar.wikipedia.org/w/index.php?title=MediaWiki:Gadget-QuickEdit/lang.js&action=raw&ctype=text/javascript", //scriptPath + '/languages/get.php?lang=' + language,
            dataType: 'json',
            success: function success(data) {
                if (data.__language && data.__version) {
                    if (i18nData[data.__language]) {
                        if (data.__version >= i18nData[data.__language].__version) {
                            i18nData[data.__language] = data;
                            console.log('更新语言版本' + data.___language + '至' + data.___version);
                        } else {
                            // 服务端未跟进语言版本 不更新本地缓存
                        }
                    } else {
                            i18nData[data.__language] = data;
                        }
                    localStorage.Wikiplus_i18nCache = JSON.stringify(i18nData); //更新缓存
                }
            },
            error: function error(e) {
                console.log('æ— æ³•åŠ è½½è¯­è¨€' + language);
            }
        });
    }
    /**
     * 多语言转换
     * @param {stirng} key å­—æ®µæ ‡è¯†å
     * @return {string} 经过转换的内容 如未找到对应的多语言字段 则返回简体中文
     */
    function i18n(key) {
        var language;
        try {
            language = "ar-sa"; // JSON.parse(localStorage.Wikiplus_Settings)['language'] || window.navigator.language.toLowerCase();
        } catch (e) {
            language = window.navigator.language.toLowerCase();
        }
        if (i18nData[language] && i18nData[language][key]) {
            return i18nData[language][key];
        } else if (i18nData['en-us'][key]) {
            return i18nData['en-us'][key];
        } else {
            return 'undefined';
        }
    }
    /**
     * 获得错误信息
     * @param {stirng} name
     * @return {object} {number,message}
     */
    function getErrorInfo(name) {
        var errorList = {
            unknown_error_name: {
                number: 1001,
                message: i18n('unknown_error_name')
            },
            api_unaccessiable: {
                number: 1002
            },
            api_unwriteable: {
                number: 1003
            },
            fail_to_get_timestamp: {
                number: 1004
            },
            fail_to_get_edittoken: {
                number: 1005
            },
            fail_to_get_pageinfo: {
                number: 1006
            },
            not_autoconfirmed_user: {
                number: 1007
            },
            hit_abusefilter: {
                number: 1008
            },
            unknown_edit_error: {
                number: 1009
            },
            unknown_edit_error_message: {
                number: 1010
            },
            notitle: {
                number: 1011
            },
            notext: {
                number: 1012
            },
            notoken: {
                number: 1013
            },
            invalidsection: {
                number: 1014
            },
            protectedtitle: {
                number: 1015
            },
            cantcreate: {
                number: 1016
            },
            cantcreate_anon: {
                number: 1017
            },
            articleexists: {
                number: 1018
            },
            noimageredirect_anon: {
                number: 1019
            },
            noimageredirect: {
                number: 1020
            },
            spamdetected: {
                number: 1021
            },
            filtered: {
                number: 1022
            },
            contenttoobig: {
                number: 1023
            },
            noedit_anon: {
                number: 1025
            },
            noedit: {
                number: 1026
            },
            pagedeleted: {
                number: 1027
            },
            emptypage: {
                number: 1028
            },
            emptynewsection: {
                number: 1029
            },
            editconflict: {
                number: 1030
            },
            revwrongpage: {
                number: 1031
            },
            undofailure: {
                number: 1032
            },
            missingtitle: {
                number: 1033
            },
            mustbeposted: {
                number: 1034
            },
            readapidenied: {
                number: 1035
            },
            writeapidenied: {
                number: 1036
            },
            noapiwrite: {
                number: 1037
            },
            badtoken: {
                number: 1038
            },
            missingparam: {
                number: 1039
            },
            invalidparammix: {
                number: 1040
            },
            invalidtitle: {
                number: 1041
            },
            nosuchpageid: {
                number: 1042
            },
            pagecannotexist: {
                number: 1043
            },
            nosuchrevid: {
                number: 1044
            },
            badmd5: {
                number: 1045
            },
            hookaborted: {
                number: 1046
            },
            parseerror: {
                number: 1047
            },
            summaryrequired: {
                number: 1048
            },
            blocked: {
                number: 1049
            },
            ratelimited: {
                number: 1050
            },
            unknownerror: {
                number: 1051
            },
            nosuchsection: {
                number: 1052
            },
            sectionsnotsupported: {
                number: 1053
            },
            editnotsupported: {
                number: 1054
            },
            appendnotsupported: {
                number: 1055
            },
            redirect_appendonly: {
                number: 1056
            },
            badformat: {
                number: 1057
            },
            customcssprotected: {
                number: 1058
            },
            customjsprotected: {
                number: 1059
            },
            cascadeprotected: {
                number: 1060
            },
            network_edit_error: {
                number: 1061
            },
            need_init: {
                number: 1062
            },
            fail_to_get_wikitext: {
                number: 1063
            },
            fail_to_init_quickedit: {
                number: 1064
            },
            fail_to_get_wikitext_when_edit: {
                number: 1065
            },
            cant_parse_wikitext: {
                number: 1066
            },
            empty_page_confirm: {
                number: 1067
            },
            uninited: {
                number: 1068
            },
            cant_parse_i18ncache: {
                number: 1069
            },
            cant_load_language: {
                number: 1070
            }
        };
        if (errorList[name]) {
            if (errorList[name].message) {
                return {
                    number: errorList[name].number,
                    message: errorList[name].message
                };
            } else if (i18n(name) !== 'undefined') {
                return {
                    number: errorList[name].number,
                    message: i18n(name)
                };
            } else {
                return {
                    number: errorList[name].number,
                    message: i18n('unknownerror')
                };
            }
        } else {
            return {
                number: errorList.unknown_error_name.number,
                message: errorList.unknown_error_name.message
            };
        }
    }
    /**
     * 判断值是否存在于数组
     * @param {string} value
     * @param {array} array
     * @return {boolean} whether the value is in the array
    */
    function inArray(value) {
        var array = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];

        return $.inArray(value, array) === -1 ? false : true;
    }
    /** 
     * 抛出错误
     * @param {string} name
     * @return boolean
    */
    function throwError(name, message) {
        var errInfo = getErrorInfo(name);
        var e = new Error();
        e.number = errInfo.number;
        e.message = message || errInfo.message;
        console.log('%c致命错误[' + e.number + ']:' + e.message, 'color:red');
        console.log(e);
        return e;
    }
    /**
     * 将mw的段落的id转换为可显示的文本
     * @param {string} URL
     * @return string
     */

    var Wikipage = (function () {
        function Wikipage() {
            var pageName = arguments.length <= 0 || arguments[0] === undefined ? window.mw.config.get('wgPageName') : arguments[0];

            _classCallCheck(this, Wikipage);

            console.log('页面类构建中');
            //可用性和权限检测
            if (!window.mw) {
                console.log('页面Javascript载入不完全或这不是一个Mediawiki站点');
                return;
            }
            if (false || false) {
                throwError('api_unaccessiable');
                return;
            }
            if (!inArray('autoconfirmed', window.mw.config.get('wgUserGroups'))) {
                throwError('not_autoconfirmed_user');
                return;
            }
            //从MediaWiki定义的全局变量中获得信息
            this.pageName = pageName.replace(/ /ig, '_'); // Mediawikiå¤„ç†ç©ºæ ¼æ—¶å¯èƒ½ä¼šå‡ºé”™
            this.revisionId = window.mw.config.get('wgRevisionId');
            this.articleId = window.mw.config.get('wgArticleId');
            this.API = location.protocol + '//' + location.host + window.mw.config.get('wgScriptPath') + '/api.php';
            //从API获得编辑令牌和起始时间戳
            this.editToken = {};
            this.timeStamp = {};
            this.init(this.pageName, {
                success: function success() {
                    console.log('WikiplusåŠ è½½å®Œæ¯•');
                },
                fail: function fail(e) {
                    console.log('Wikiplusæœªèƒ½æ­£ç¡®åŠ è½½(' + e.message + ')');
                }
            });
        }

        /**
         * 针对非本页面的编辑 æä¾›é‡å®šä¹‰æ—¶é—´æˆ³å’Œæƒæ ‡æŽ¥å£
         * @param {string} titile æ ‡é¢˜
         * @param {object} callback 回调函数
         */

        _createClass(Wikipage, [{
            key: 'reConstruct',
            value: function reConstruct(title) {
                var callback = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

                this.init(title, callback);
            }

            /**
             * 获取页面基础信息并记录
             */
        }, {
            key: 'init',
            value: function init(title, callback, config) {
                if (title === undefined) title = this.pageName;
                if (callback === undefined) callback = {};

                var self = this;
                callback.success = callback.success || new Function();
                callback.fail = callback.success || new Function();
                $.ajax({
                    type: 'GET',
                    dataType: 'json',
                    url: this.API,
                    data: {
                        'action': 'query',
                        'prop': 'revisions|info',
                        'titles': title,
                        'rvprop': 'timestamp',
                        'format': 'json'
                    },
                    beforeSend: function beforeSend() {
                        console.time('الوقت ');
                    },
                    success: function success(data) {
                        if (data && data.query && data.query.pages) {
                            var info = data.query.pages;
                            for (var key in info) {
                                if (key !== '-1') {
                                    if (info[key].revisions && info[key].revisions.length > 0) {
                                        self.timeStamp[title] = info[key].revisions[0].timestamp;
                                    } else {
                                        callback.fail(throwError('fail_to_get_timestamp'));
                                    }
                                    if (mw.user.options.get('csrfToken') && mw.user.options.get('csrfToken') !== '+\\') {
                                        self.editToken[title] = mw.user.options.get('csrfToken');
                                        console.log('成功获得编辑令牌 来自前端API');
                                    } else {
                                        //前端拿不到Token 尝试通过API
                                        $.ajax({
                                            url: self.API,
                                            type: "GET",
                                            dataType: "json",
                                            data: {
                                                'action': 'query',
                                                'meta': 'tokens',
                                                'format': 'json'
                                            },
                                            success: function success(data) {
                                                if (data.query && data.query.tokens && data.query.tokens.csrftoken && data.query.tokens.csrftoken !== '+\\') {
                                                    self.editToken[title] = data.query.tokens.csrftoken;
                                                    console.log('成功获得编辑令牌 通过后端API');
                                                } else {
                                                    callback.fail(throwError('fail_to_get_edittoken'));
                                                }
                                            },
                                            error: function error(e) {
                                                callback.fail(throwError('fail_to_get_edittoken'));
                                            }
                                        });
                                        callback.fail(throwError('fail_to_get_edittoken'));
                                    }
                                } else {
                                    if (mw.config.get('wgArticleId') === 0) {
                                        // 如果是空页面就只拿一个edittoken
                                        if (mw.user.options.get('csrfToken') && mw.user.options.get('csrfToken') !== '+\\') {
                                            self.editToken[title] = mw.user.options.get('csrfToken');
                                            console.log('成功获得编辑令牌 来自前端API');
                                            self.inited = true;
                                        } else {
                                            self.inited = false;
                                            callback.fail(throwError('fail_to_get_edittoken'));
                                        }
                                    } else {
                                        // 如果不是 那就是失败了 抛出错误
                                        self.inited = false;
                                        callback.fail(throwError('fail_to_get_pageinfo'));
                                    }
                                }
                            }
                        }
                    }
                }).done(function () {
                    console.timeEnd('获得页面基础信息时间耗时');
                    self.inited = self.inited === false ? false : true;
                    callback.success();
                });
            }

            /**
             * 页面编辑
             * @param {string} content 页面内容
             * @param {string} title  é¡µé¢æ ‡é¢˜ é»˜è®¤ä¸ºå½“å‰é¡µé¢æ ‡é¢˜
             * @param {object} callback 回调函数
             * @param {object} config 设置 覆盖到默认的设置
             */
        }, {
            key: 'edit',
            value: function edit(content) {
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
                var config = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

                var self = this;
                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                if (content === undefined) {
                    if (!config.empty === true) {
                        callback.fail(throwError('empty_page_confirm'));
                        return false;
                    }
                }
                if (self.inited) {
                    $.ajax({
                        type: 'POST',
                        url: self.API,
                        data: $.extend({
                            'action': 'edit',
                            'format': 'json',
                            'text': content,
                            'title': title,
                            'token': self.editToken[title] || self.editToken[self.pageName],
                            'basetimestamp': self.timeStamp[title]
                        }, config),
                        success: function success(data) {
                            if (data && data.edit) {
                                if (data.edit.result && data.edit.result == 'Success') {
                                    callback.success();
                                } else {
                                    if (data.edit.code) {
                                        //防滥用过滤器
                                        callback.fail(throwError('hit_abusefilter', i18n('hit_abusefilter') + ':' + data.edit.info.replace('/Hit AbuseFilter: /ig', '') + '<br><small>' + data.edit.warning + '</small>'));
                                    } else {
                                        callback.fail(throwError('unknown_edit_error'));
                                    }
                                }
                            } else if (data && data.error && data.error.code) {
                                callback.fail(throwError(data.error.code.replace(/-/ig, '_')), i18n('unknown_edit_error_message').replace(/\$1/ig, data.error.code));
                            } else if (data.code) {
                                callback.fail(throwError('unknown_edit_error'), i18n('unknown_edit_error_message').replace(/\$1/ig, data.code));
                            } else {
                                callback.fail(throwError('unknown_edit_error'));
                            }
                        },
                        error: function error(e) {
                            callback.fail(throwError('network_edit_error'));
                        }
                    });
                } else {
                    callback.fail(throwError('uninited'));
                }
            }

            /**
             * 编辑段落
             * @param {number} section 段落编号
             * @param {string} content 内容
             * @param {string} title é¡µé¢æ ‡é¢˜
             * @param {object} callback 回调函数 
             * @param {object} config 设置 
             */
        }, {
            key: 'editSection',
            value: function editSection(section, content) {
                var title = arguments.length <= 2 || arguments[2] === undefined ? this.pageName : arguments[2];
                var config = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
                var callback = arguments.length <= 4 || arguments[4] === undefined ? {} : arguments[4];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                this.edit(content, title, callback, $.extend({
                    'section': section
                }, config));
            }

            /**
             * 重定向页面至
             * @param {string} target ç›®æ ‡é¡µé¢æ ‡é¢˜
             * @param {string} title 页面名 默认为当前页面
             * @param {object} callback 回调函数
             */
        }, {
            key: 'redirectTo',
            value: function redirectTo(target) {
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                this.edit('#REDIRECT [[' + target + ']]', title, callback, {
                    'summary': i18n('redirect_to_summary').replace(/\$1/ig, target)
                });
            }

            /**
             * 重定向自
             * @param {string} origin é‡å®šå‘é¡µæ ‡é¢˜
             * @param {string} title é‡å®šå‘ç›®æ ‡é¡µæ ‡é¢˜ 默认为当前页
             * @param {object} callback
             */
        }, {
            key: 'redirectFrom',
            value: function redirectFrom(origin) {
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
                var force = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                var data = {
                    summary: i18n('redirect_from_summary').replace(/\$1/ig, origin).replace(/\$2/ig, title)
                };
                if (!force) {
                    data.createonly = 'true';
                }
                this.edit('#REDIRECT [[' + title + ']]', origin, callback, data);
            }

            /**
             * 获得页面维基文本
             * @param {object} callback 回调函数
             * @param {string} title é¡µé¢æ ‡é¢˜ 默认为当前页面
             * @param {object} config 设置
             */
        }, {
            key: 'getWikiText',
            value: function getWikiText() {
                var callback = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
                var title = arguments.length <= 1 || arguments[1] === undefined ? this.pageName : arguments[1];
                var config = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                $.ajax({
                    url: location.protocol + '//' + location.host + mw.config.get('wgScriptPath') + '/index.php',
                    type: "GET",
                    dataType: "text",
                    cache: false,
                    data: $.extend({
                        'title': title,
                        'action': 'raw'
                    }, config),
                    beforeSend: function beforeSend() {
                        console.time('الوقت ');
                    },
                    success: function success(data) {
                        console.timeEnd('نجاح ');
                        callback.success(data);
                    },
                    error: function error(e) {
                        callback.fail(throwError('fail_to_get_wikitext'));
                    }
                });
            }

            /**
             * 解析Wikitext
             * @param {string} wikitext 维基文本
             * @param {object} callback 回调函数
             * @param {object} config 设置
             */
        }, {
            key: 'parseWikiText',
            value: function parseWikiText(wikitext, callback, config) {
                if (wikitext === undefined) wikitext = '';
                if (callback === undefined) callback = {};

                callback.success = callback.success || new Function();
                callback.fail = callback.fail || new Function();
                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    data: $.extend({
                        'format': 'json',
                        'action': 'parse',
                        'text': wikitext,
                        'title': this.pageName,
                        'pst': 'true'
                    }, config),
                    url: this.API,
                    success: function success(data) {
                        if (data && data.parse && data.parse.text) {
                            callback.success(data.parse.text['*']);
                        } else {
                            callback.fail(throwError('cant_parse_wikitext'));
                        }
                    }
                });
            }
        }]);

        return Wikipage;
    })();

    $(document).ready(function () {
        var Wikiplus = (function () {
            _createClass(Wikiplus, [{
                key: 'initQuickEdit',

                /**
                 * åŠ è½½å¿«é€Ÿç¼–è¾‘ 第一步 插入页面按钮并绑定入口事件
                 */
                value: function initQuickEdit() {
                    var callback = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

                    var self = this;
                    callback.success = callback.success || new Function();
                    callback.fail = callback.fail || new Function();
                    if (!(mw.config.get('wgIsArticle') && mw.config.get('wgAction') === "view" && mw.config.get('wgIsProbablyEditable'))) {
                        console.log('è¯¥é¡µé¢æ— æ³•ç¼–è¾‘ å¿«é€Ÿç¼–è¾‘ç•Œé¢åŠ è½½ç»ˆæ­¢');
                        return;
                    }
                    //顶部编辑入口
                    var topBtn = $('<li>').attr('id', 'Wikiplus-Edit-TopBtn').append($('<span>').append($('<a>').attr('href', 'javascript:void(0)').text('' + i18n('quickedit_topbtn')))).data({
                        number: -1,
                        target: self.kotori.pageName
                    });
                    if ($('#ca-edit').length > 0 && $('#Wikiplus-Edit-TopBtn').length == 0) {
                        $('#ca-edit').before(topBtn);
                    }
                    if ($('.mw-editsection').length > 0) {
                        self.sectionMap = {};
                        //段落快速编辑按钮
                        var sectionBtn = $('<span>').append($('<span>').addClass('mw-editsection-divider').text(' | ')).append($('<a>').addClass('Wikiplus-Edit-SectionBtn').attr('href', 'javascript:void(0)').text(i18n('quickedit_sectionbtn')));
                        $('.mw-editsection').each(function (i) {
                            try {
                                var editURL = $(this).find("a").last().attr('href');
                                var sectionNumber = editURL.match(/&[ve]*section\=([^&]+)/)[1].replace(/T-/ig, '');
                                var sectionTargetName = decodeURI(editURL.match(/title=(.+?)&/)[1]);
                                var cloneNode = $(this).prev().clone();
                                cloneNode.find('.mw-headline-number').remove();
                                var sectionName = $.trim(cloneNode.text());
                                self.sectionMap[sectionNumber] = {
                                    name: sectionName,
                                    target: sectionTargetName
                                };
                                var _sectionBtn = sectionBtn.clone();
                                _sectionBtn.find('.Wikiplus-Edit-SectionBtn').data({
                                    number: sectionNumber,
                                    name: sectionName,
                                    target: sectionTargetName
                                });
                                $(this).find('.mw-editsection-bracket').last().before(_sectionBtn);
                            } catch (e) {
                                throwError('fail_to_init_quickedit');
                            }
                        });
                    }
                    $('.Wikiplus-Edit-SectionBtn').click(function () {
                        self.initQuickEditInterface($(this)); //直接把DOMä¼ é€’ç»™ä¸‹ä¸€æ­¥
                    });
                    $('#Wikiplus-Edit-TopBtn').click(function () {
                        self.initQuickEditInterface($(this));
                    });
                }

                /**
                 * åŠ è½½å¿«é€Ÿç¼–è¾‘ä¸»ç•Œé¢ç›¸å…³å†…å®¹
                 */
            }, {
                key: 'initQuickEditInterface',
                value: function initQuickEditInterface(obj) {
                    var self = this;
                    var sectionNumber = obj.data('number');
                    var sectionTargetName = obj.data('target');
                    if (this.kotori.inited) {
                        if ($('.noarticletext').length > 0) {
                            //这是一个空页面
                            this.preloadData[sectionTargetName + '.-1'] = i18n('create_page_tip');
                        }
                        if (mw.config.get('wgCurRevisionId') === mw.config.get('wgRevisionId')) {
                            if (this.preloadData[sectionTargetName + '.' + sectionNumber] === undefined) {
                                this.notice.create.success(i18n('loading'));
                                this.preload(sectionNumber, sectionTargetName, {
                                    success: function success(data) {
                                        obj.data('content', data);
                                        self.notice.empty();
                                        self.displayQuickEditInterface(obj);
                                    },
                                    fail: function fail(e) {
                                        throwError('fail_to_get_wikitext_when_edit');
                                    }
                                });
                            } else {
                                obj.data('content', self.preloadData[sectionTargetName + '.' + sectionNumber]);
                                self.displayQuickEditInterface(obj);
                            }
                        } else {
                            this.notice.create.warning(i18n('history_edit_warning'));
                            this.notice.create.success(i18n('loading'));
                            this.preload(sectionNumber, sectionTargetName, {
                                success: function success(data) {
                                    obj.data('content', data);
                                    self.notice.empty();
                                    self.displayQuickEditInterface(obj, '' + i18n('history_edit_warning'));
                                },
                                fail: function fail(data) {
                                    throwError('fail_to_get_wikitext_when_edit');
                                }
                            }, {
                                'oldid': mw.config.get('wgRevisionId')
                            });
                        }
                    }
                }

                /**
                 * 显示快速编辑界面并绑定事件
                 */
            }, {
                key: 'displayQuickEditInterface',
                value: function displayQuickEditInterface(obj) {
                    var message = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1];

                    var self = this;
                    var isNewPage = $('.noarticletext').length > 0;
                    var sectionNumber = obj.data('number');
                    var sectionName = obj.data('name');
                    var sectionTargetName = obj.data('target');
                    var sectionContent = obj.data('content');
                    var summary = self.getSetting('defaultSummary', {
                        'sectionName': sectionName,
                        'sectionNumber': sectionNumber,
                        'sectionTargetName': sectionTargetName
                    });
                    if (summary === undefined) {
                        if (sectionName === undefined) {
                            summary = i18n('default_summary_suffix');
                        } else {
                            summary = '/* ' + sectionName + ' */ ' + i18n('default_summary_suffix');
                        }
                    }
                    //DOM定义
                    var heightBefore = $(document).scrollTop(); //记住当前高度
                    var backBtn = $('<span>').attr('id', 'Wikiplus-Quickedit-Back').addClass('Wikiplus-Btn').text('' + i18n('back')); //返回按钮
                    var jumpBtn = $('<span>').attr('id', 'Wikiplus-Quickedit-Jump').addClass('Wikiplus-Btn').append($('<a>').attr('href', '#Wikiplus-Quickedit').text('' + i18n('goto_editbox'))); //到编辑框
                    var inputBox = $('<textarea>').attr('id', 'Wikiplus-Quickedit'); //主编辑框
                    var previewBox = $('<div>').attr('id', 'Wikiplus-Quickedit-Preview-Output'); //预览输出
                    var summaryBox = $('<input>').attr('id', 'Wikiplus-Quickedit-Summary-Input').attr('placeholder', '' + i18n('summary_placehold')); //编辑摘要输入
                    var editSubmitBtn = $('<button>').attr('id', 'Wikiplus-Quickedit-Submit').text(i18n(isNewPage ? 'publish_page' : 'publish_change') + ' - ctrl+s'); //提交按钮
                    var previewSubmitBtn = $('<button>').attr('id', 'Wikiplus-Quickedit-Preview-Submit').text('' + i18n('preview')); //预览按钮
                    var isMinorEdit = $('<div>').append($('<input>').attr({ 'type': 'checkbox', 'id': 'Wikiplus-Quickedit-MinorEdit' })).append($('<label>').attr('for', 'Wikiplus-Quickedit-MinorEdit').text(i18n('mark_minoredit') + ' - ctrl+shift+s')).css({ 'margin': '5px', 'display': 'inline' });
                    //DOM定义结束
                    var editBody = $('<div>').append(backBtn, jumpBtn, previewBox, inputBox, summaryBox, $('<br>'), editSubmitBtn, previewSubmitBtn, isMinorEdit);
                    this.createDialogBox('' + i18n('quickedit_topbtn') + message, editBody, 1000, function () {
                        $('#Wikiplus-Quickedit').text(sectionContent);
                        $('#Wikiplus-Quickedit-Summary-Input').val(summary);
                        //事件绑定
                        //返回
                        $("#Wikiplus-Quickedit-Back").click(function () {
                            $('.Wikiplus-InterBox').fadeOut('fast', function () {
                                window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                                $(this).remove();
                            });
                        });
                        //预览
                        var onPreload = $('<div>').addClass('Wikiplus-Banner').text('' + i18n('loading_preview'));
                        $('#Wikiplus-Quickedit-Preview-Submit').click(function () {
                            var wikiText = $('#Wikiplus-Quickedit').val();
                            $(this).prop('disabled', true);
                            $('#Wikiplus-Quickedit-Preview-Output').fadeOut(100, function () {
                                $('#Wikiplus-Quickedit-Preview-Output').html('').append(onPreload);
                                $('#Wikiplus-Quickedit-Preview-Output').fadeIn(100);
                            });
                            $('html, body').animate({ scrollTop: heightBefore }, 200); //返回顶部
                            self.kotori.parseWikiText(wikiText, {
                                success: function success(data) {
                                    $('#Wikiplus-Quickedit-Preview-Output').fadeOut('100', function () {
                                        $('#Wikiplus-Quickedit-Preview-Output').html('<hr><div class="mw-body-content">' + data + '</div><hr>');
                                        $('#Wikiplus-Quickedit-Preview-Output').fadeIn('100');
                                        $('#Wikiplus-Quickedit-Preview-Submit').prop('disabled', false);
                                    });
                                }
                            });
                        });
                        //提交
                        $('#Wikiplus-Quickedit-Submit').click(function () {
                            var wikiText = $('#Wikiplus-Quickedit').val();
                            var summary = $('#Wikiplus-Quickedit-Summary-Input').val();
                            var timer = new Date().valueOf();
                            var onEdit = $('<div>').addClass('Wikiplus-Banner').text('' + i18n('submitting_edit'));
                            var addtionalConfig = {
                                'summary': summary
                            };
                            if (sectionNumber !== -1) {
                                addtionalConfig['section'] = sectionNumber;
                            }
                            if ($('#Wikiplus-Quickedit-MinorEdit').is(':checked')) {
                                addtionalConfig['minor'] = 'true';
                            } else {
                                addtionalConfig['notminor'] = 'true';
                            }
                            //准备编辑 禁用各类按钮 返回顶部 显示信息
                            $('#Wikiplus-Quickedit-Submit,#Wikiplus-Quickedit,#Wikiplus-Quickedit-Preview-Submit').prop('disabled', true);
                            $('html, body').animate({ scrollTop: heightBefore }, 200);

                            //开始提交编辑
                            if (sectionTargetName === self.kotori.pageName) {
                                $('#Wikiplus-Quickedit-Preview-Output').fadeOut(100, function () {
                                    $('#Wikiplus-Quickedit-Preview-Output').html('').append(onEdit);
                                    $('#Wikiplus-Quickedit-Preview-Output').fadeIn(100);
                                });
                                self.kotori.edit(wikiText, sectionTargetName, {
                                    success: function success() {
                                        var useTime = new Date().valueOf() - timer;
                                        $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').css('background', 'rgba(6, 239, 92, 0.44)');
                                        $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').text(('' + i18n('edit_success')).replace(/\$1/ig, useTime.toString()));
                                        self.sendStatistic(sectionTargetName, useTime);
                                        window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                                        setTimeout(function () {
                                            location.reload();
                                        }, 500);
                                    },
                                    fail: function fail(e) {
                                        console.log(e);
                                        $('#Wikiplus-Quickedit-Submit,#Wikiplus-Quickedit,#Wikiplus-Quickedit-Preview-Submit').prop('disabled', false);
                                        $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                        $('.Wikiplus-Banner').html(e.message);
                                    }
                                }, addtionalConfig);
                            } else {
                                //ç¼–è¾‘ç›®æ ‡éžå½“å‰é¡µé¢
                                $('#Wikiplus-Quickedit-Preview-Output').fadeOut(100, function () {
                                    $('#Wikiplus-Quickedit-Preview-Output').html('').append(onEdit.text(i18n('cross_page_edit')));
                                    $('#Wikiplus-Quickedit-Preview-Output').fadeIn(100);
                                });
                                self.kotori.reConstruct(sectionTargetName, {
                                    success: function success() {
                                        $('.Wikiplus-Banner').text(i18n('cross_page_edit_submit'));
                                        self.kotori.edit(wikiText, sectionTargetName, {
                                            success: function success() {
                                                var useTime = new Date().valueOf() - timer;
                                                $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').css('background', 'rgba(6, 239, 92, 0.44)');
                                                $('#Wikiplus-Quickedit-Preview-Output').find('.Wikiplus-Banner').text(('' + i18n('edit_success')).replace(/\$1/ig, '' + useTime));
                                                self.sendStatistic(sectionTargetName, useTime);
                                                window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                                                setTimeout(function () {
                                                    location.reload();
                                                }, 500);
                                            },
                                            fail: function fail(e) {
                                                $('#Wikiplus-Quickedit-Submit,#Wikiplus-Quickedit,#Wikiplus-Quickedit-Preview-Submit').prop('disabled', false);
                                                $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                                $('.Wikiplus-Banner').text(e.message);
                                            }
                                        }, addtionalConfig);
                                    },
                                    fail: function fail(e) {
                                        $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                        $('.Wikiplus-Banner').text(i18n('cross_page_edit_error'));
                                    }
                                });
                            }
                        });
                        //快捷键
                        //Ctrl+S提交 Ctrl+Shift+S小编辑
                        $('#Wikiplus-Quickedit,#Wikiplus-Quickedit-Summary-Input,#Wikiplus-Quickedit-MinorEdit').keydown(function (e) {
                            if (e.ctrlKey && e.which == 83) {
                                if (e.shiftKey) {
                                    $('#Wikiplus-Quickedit-MinorEdit').click();
                                }
                                $('#Wikiplus-Quickedit-Submit').click();
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        });
                        //由于是异步提交 Wikiplus即使编辑失败 也不会丢失数据 唯一丢失数据的可能性是手滑关了页面
                        //第一 关闭页面确认
                        $('#Wikiplus-Quickedit').keydown(function () {
                            window.onclose = window.onbeforeunload = function () {
                                return '' + i18n('onclose_confirm');
                            };
                        });

                        //Esc退出
                        if (self.getSetting('esc_to_exit_quickedit') === 'true') {
                            $(document).keydown(function (e) {
                                if (e.which === 27) {
                                    $("#Wikiplus-Quickedit-Back").click();
                                }
                            });
                        }
                    });
                }

                /**
                 * 编辑设置
                 */
            }, {
                key: 'editSettings',
                value: function editSettings() {
                    var self = this;
                    self.addFunctionButton(i18n('wikiplus_settings'), 'Wikiplus-Settings-Intro', function () {
                        var input = $('<textarea>').attr('id', 'Wikiplus-Setting-Input').attr('rows', '10');
                        var applyBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Apply').text(i18n('submit'));
                        var cancelBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Cancel').text(i18n('cancel'));
                        var content = $('<div>').append(input).append($('<hr>')).append(applyBtn).append(cancelBtn); //拼接
                        self.createDialogBox(i18n('wikiplus_settings_desc'), content, 600, function () {
                            if (localStorage.Wikiplus_Settings) {
                                $('#Wikiplus-Setting-Input').val(localStorage.Wikiplus_Settings);
                            } else {
                                $('#Wikiplus-Setting-Input').attr('placeholder', i18n('wikiplus_settings_placeholder'));
                            }
                            $('#Wikiplus-Setting-Apply').click(function () {
                                var settings = $('#Wikiplus-Setting-Input').val();
                                try {
                                    settings = JSON.parse(settings);
                                } catch (e) {
                                    self.notice.create.error(i18n('wikiplus_settings_grammar_error'));
                                    return;
                                }
                                localStorage.Wikiplus_Settings = JSON.stringify(settings);
                                $('.Wikiplus-InterBox-Content').html('').append($('<div>').addClass('Wikiplus-Banner').text(i18n('wikiplus_settings_saved')));

                                $('.Wikiplus-InterBox').fadeOut(300, function () {
                                    $(this).remove();
                                });
                            });
                            $('#Wikiplus-Setting-Cancel').click(function () {
                                $('.Wikiplus-InterBox').fadeOut(300, function () {
                                    $(this).remove();
                                });
                            });
                        });
                    });
                }

                /**
                 * 快速重定向页面至此页面
                 */
            }, {
                key: 'simpleRedirector',
                value: function simpleRedirector() {
                    var self = this;
                    self.addFunctionButton(i18n('redirect_from'), 'Wikiplus-SR-Intro', function () {
                        var input = $('<input>').addClass('Wikiplus-InterBox-Input');
                        var applyBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-SR-Apply').text(i18n('submit') + " - ctrl+s");
                        var cancelBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-SR-Cancel').text(i18n('cancel'));
                        var continueBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-SR-Continue').text(i18n('continue'));
                        var content = $('<div>').append(input).append($('<hr>')).append(applyBtn).append(cancelBtn); //拼接
                        self.createDialogBox(i18n('redirect_desc'), content, 600, function () {
                            applyBtn.click(function () {
                                if ($('.Wikiplus-InterBox-Input').val() != '') {
                                    var title = $('.Wikiplus-InterBox-Input').val();
                                    $('.Wikiplus-InterBox-Content').html('<div class="Wikiplus-Banner">' + i18n('submitting_edit') + '</div>');
                                    self.kotori.redirectFrom(title, self.kotori.pageName, {
                                        success: function success() {
                                            $('.Wikiplus-Banner').text(i18n('redirect_saved'));
                                            $('.Wikiplus-InterBox').fadeOut(300);
                                            location.href = mw.config.get('wgArticlePath').replace(/\$1/ig, title);
                                        },
                                        fail: function fail(e) {
                                            $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                            $('.Wikiplus-Banner').text(e.message);
                                            if (e.number === 1018) {
                                                // ç›®æ ‡é¡µé¢å·²ç»å­˜åœ¨ 确认哟
                                                $('.Wikiplus-InterBox-Content').append($('<hr>')).append(continueBtn).append(cancelBtn);
                                                continueBtn.click(function () {
                                                    $('.Wikiplus-InterBox-Content').html('<div class="Wikiplus-Banner">' + i18n('submitting_edit') + '</div>');
                                                    self.kotori.redirectFrom(title, self.kotori.pageName, {
                                                        success: function success() {
                                                            $('.Wikiplus-Banner').text(i18n('redirect_saved'));
                                                            $('.Wikiplus-InterBox').fadeOut(300);
                                                            location.href = mw.config.get('wgArticlePath').replace(/\$1/ig, title);
                                                        },
                                                        fail: function fail(e) {
                                                            $('.Wikiplus-Banner').css('background', 'rgba(218, 142, 167, 0.65)');
                                                            $('.Wikiplus-Banner').text(e.message);
                                                        }
                                                    }, true);
                                                });
                                                cancelBtn.click(function () {
                                                    $('.Wikiplus-InterBox-Close').click();
                                                });
                                            }
                                        }
                                    });
                                } else {
                                    self.showNotice.create.warning(i18n('empty_input'));
                                }
                            });
                            $('#Wikiplus-SR-Cancel').click(function () {
                                $('.Wikiplus-InterBox').fadeOut(300, function () {
                                    $(this).remove();
                                });
                            });
                            //اختصار تأكيد التحميل
                        $('.Wikiplus-InterBox').keydown(function (e) {
                            if (e.ctrlKey && e.which == 83) {
                                $('#Wikiplus-SR-Apply').click();
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        });
                        });
                    });
                }

                /**
                 * 预读取相关事件绑定
                 */
            }, {
                key: 'preloadEventBinding',
                value: function preloadEventBinding() {
                    var self = this;
                    $("#toc").children("ul").find("a").each(function (i) {
                        $(this).mouseover(function () {
                            $(this).unbind('mouseover');
                            self.preload(i + 1);
                        });
                    });
                }

                /**
                 * 检查多语言定义缓存是否过期
                 */
            }, {
                key: 'checki18nCache',
                value: function checki18nCache() {
                    if (localStorage.Wikiplus_i18nCache) {
                        try {
                            var _i18nData = JSON.parse(localStorage.Wikiplus_i18nCache);
                            for (var languages in _i18nData) {
                                if (_i18nData[languages]['__version'] === this.langVersion) {
                                    i18nData[_i18nData[languages]['__language']] = _i18nData[languages];
                                } else {
                                    console.log('多语言文件[' + languages + ']已经过期');
                                    loadLanguage(_i18nData[languages]['__language']); //尝试重新取
                                }
                            }
                        } catch (e) {
                            throwError('cant_parse_i18ncache');
                        }
                    } else {
                        localStorage.Wikiplus_i18nCache = JSON.stringify(i18nData);
                    }
                }

                /**
                 * ä¸ºæ‰€æœ‰å¯èƒ½çš„ç¼–è¾‘é“¾æŽ¥åŠ ä¸Šå¿«é€Ÿç¼–è¾‘æŒ‰é’®
                 */
            }, {
                key: 'editEveryWhere',
                value: function editEveryWhere() {
                    var self = this;
                    $('#mw-content-text a.external').each(function (i) {
                        var url = $(this).attr('href');
                        var reg = /(([^?&=]+)(?:=([^?&=]*))*)/g;
                        var params = {},
                            match;
                        while (match = reg.exec(url)) {
                            try {
                            	params[match[2]] = decodeURIComponent(match[3]);
                            } catch(e) {
                            	params[match[2]] = '';
                            }
                        }
                        if (params.action === 'edit' && params.title !== undefined && params.section !== 'new') {
                            $(this).after($('<a>').attr({
                                'href': "javascript:void(0)",
                                'class': "Wikiplus-Edit-EveryWhereBtn"
                            }).text('(' + i18n('quickedit_sectionbtn') + ')').data({
                                'target': decodeURIComponent(params.title),
                                'number': params.section || -1
                            }));
                        }
                    });
                    $('.Wikiplus-Edit-EveryWhereBtn').click(function () {
                        self.initQuickEditInterface($(this));
                    });
                }

                /**
                 * ===========================
                 * 以上是功能函数 以下是通用函数
                 * ===========================
                 */

                /**
                 * 创建对话框
                 * @param {string} title å¯¹è¯æ¡†æ ‡é¢˜
                 * @param {HTML} content 内容 
                 * @param {interger} width 宽度 å•ä½åƒç´  默认600px
                 * @param {function} callback 回调函数
                 */
            }, {
                key: 'createDialogBox',
                value: function createDialogBox() {
                    var title = arguments.length <= 0 || arguments[0] === undefined ? 'Dialog Box' : arguments[0];
                    var content = arguments.length <= 1 || arguments[1] === undefined ? $('<div>') : arguments[1];
                    var width = arguments.length <= 2 || arguments[2] === undefined ? 600 : arguments[2];
                    var callback = arguments.length <= 3 || arguments[3] === undefined ? new Function() : arguments[3];

                    if ($('.Wikiplus-InterBox').length > 0) {
                        $('.Wikiplus-InterBox').each(function () {
                            $(this).remove();
                        });
                    }
                    var clientWidth = document.body.clientWidth;
                    var clientHeight = document.body.clientHeight;
                    var diglogBox = $('<div>').addClass('Wikiplus-InterBox').css({
                        'margin-right': clientWidth / 2 - width / 2,
                        'top': $(document).scrollTop() + clientHeight * 0.2,
                        'display': 'none'
                    }).append($('<div>').addClass('Wikiplus-InterBox-Header').html(title)).append($('<div>').addClass('Wikiplus-InterBox-Content').append(content)).append($('<span>').text('×').addClass('Wikiplus-InterBox-Close'));
                    $('body').append(diglogBox);
                    $('.Wikiplus-InterBox').width(width);
                    $('.Wikiplus-InterBox-Close').click(function () {
                        $(this).parent().fadeOut('fast', function () {
                            window.onclose = window.onbeforeunload = undefined; //取消页面关闭确认
                            $(this).remove();
                        });
                    });
                    //拖曳
                    var bindDragging = function bindDragging(element) {
                        element.mousedown(function (e) {
                            var baseX = e.clientX;
                            var baseY = e.clientY;
                            var baseOffsetX = element.parent().offset().right;
                            var baseOffsetY = element.parent().offset().top;
                            $(document).mousemove(function (e) {
                                element.parent().css({
                                    'margin-right': baseOffsetX + e.clientX - baseX,
                                    'top': baseOffsetY + e.clientY - baseY
                                });
                            });
                            $(document).mouseup(function () {
                                element.unbind('mousedown');
                                $(document).unbind('mousemove');
                                $(document).unbind('mouseup');
                                bindDragging(element);
                            });
                        });
                    };
                    bindDragging($('.Wikiplus-InterBox-Header'));
                    $('.Wikiplus-InterBox').fadeIn(500);
                    callback();
                }

                /**
                 * å¢žåŠ åŠŸèƒ½æŒ‰é’®
                 * @param {string} text 按钮名
                 * @param {string} id 按钮id
                 * @param {function} clickEvent 点击事件 
                 */
            }, {
                key: 'addFunctionButton',
                value: function addFunctionButton(text, id, clickEvent) {
                    var button = $('<li></li>').attr('id', id).append($('<a></a>').attr('href', 'javascript:void(0);').text(text));
                    if ($('#p-cactions').length > 0) {
                        $('#p-cactions ul').append(button);
                        $('#p-cactions ul').find('li').last().click(clickEvent);
                    } else {
                        throwError('cant_add_funcbtn');
                    }
                }

                /**
                 * 预读取内容
                 * @param {interger} section 段落编号 默认为-1即全页
                 * @param {string} title 页面名 默认为当前页面
                 * @param {object} callback 回调
                 */
            }, {
                key: 'preload',
                value: function preload() {
                    var section = arguments.length <= 0 || arguments[0] === undefined ? -1 : arguments[0];
                    var title = arguments.length <= 1 || arguments[1] === undefined ? this.kotori.pageName : arguments[1];
                    var callback = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
                    var config = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

                    callback.success = callback.success || new Function();
                    callback.fail = callback.fail || new Function();
                    var self = this;
                    if (config.oldid !== undefined) {
                        // oldid 优先于 页面名
                        console.log(typeof config.oldid);
                        if (this.preloadData[config.oldid + '.' + section]) {
                            console.log('[修订版本' + config.oldid + '.' + section + ']已经预读取 跳过本次预读取');
                            callback.success(this.preloadData[config.oldid + '.' + section]);
                            return;
                        }
                    } else {
                        if (this.preloadData[title + '.' + section]) {
                            console.log('[' + title + '.' + section + ']已经预读取 跳过本次预读取');
                            callback.success(this.preloadData[title + '.' + section]);
                            return;
                        }
                    }
                    this.kotori.getWikiText({
                        success: function success(data) {
                            if (config.oldid !== undefined) {
                                self.preloadData[config.oldid + '.' + section] = data;
                                console.log('预读取[修订版本' + config.oldid + '.' + section + ']成功');
                            } else {
                                self.preloadData[title + '.' + section] = data;
                                console.log('预读取[' + title + '.' + section + ']成功');
                            }
                            callback.success(data);
                        },
                        fail: function fail(e) {
                            if (config.oldid !== undefined) {
                                console.log('预读取[修订版本' + config.oldid + '.' + section + ']失败');
                            } else {
                                console.log('预读取[' + title + '.' + section + ']失败:' + e.message);
                            }
                            callback.fail(e);
                        }
                    }, title, $.extend({
                        section: section === -1 ? '' : section
                    }, config));
                }

                /**
                 * 提交统计数据
                 * @param {string} title 页面名
                 * @param {interger} useTime 用时 单位毫秒
                 */
            }, {
                key: 'sendStatistic',
                value: function sendStatistic(title, useTime) {
                    if (title === undefined) title = mw.config.get('wgPageName');

                    if (localStorage.Wikiplus_SendStatistics == 'True') {
                        $.ajax({
                            url: scriptPath + '/statistics/api/submit',
                            type: 'POST',
                            dataType: 'json',
                            data: {
                                'wikiname': mw.config.get('wgSiteName'),
                                'usetime': useTime,
                                'username': mw.config.get('wgUserName'),
                                'pagename': title
                            },
                            success: function success(data) {
                                //提交成功
                            }
                        });
                    }
                }

                /**
                 * 检查安装
                 * @param {function} callback 回调函数
                 */
            }, {
                key: 'checkInstall',
                value: function checkInstall(callback) {
                    var self = this;
                    if (!localStorage.Wikiplus_Installed || localStorage.Wikiplus_Installed == 'False') {
                        //安装
                        var install = function install() {
                            localStorage.Wikiplus_Installed = 'True'; //æ ‡è®°å·²å®‰è£…
                            localStorage.Wikiplus_Version = self.version;
                            localStorage.Wikiplus_StartUseAt = new Date().valueOf();
                            localStorage.Wikiplus_SrartEditCount = mw.config.get('wgUserEditCount');
                            localStorage.Wikiplus_Settings = JSON.stringify(self.defaultSettings);
                            $('.Wikiplus-InterBox').fadeOut('fast', function () {
                                self.notice.create.success(i18n('install_finish'));
                                $(this).remove();
                            });
                        };
                        /*var notice = $('<div>').text(i18n('install_tip').replace(/\$1/ig, mw.config.get('wgSiteName'))).attr('id', 'Wikiplus-InterBox-Content');
                        var applyBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Apply').text(i18n('accept'));
                        var cancelBtn = $('<div>').addClass('Wikiplus-InterBox-Btn').attr('id', 'Wikiplus-Setting-Cancel').text(i18n('decline'));
                        var content = $('<div>').append(notice).append($('<hr>')).append(applyBtn).append(cancelBtn); //拼接
                        self.createDialogBox('安装Wikiplus', content, 600, function () {
                            $('#Wikiplus-InterBox-Content').css('display', 'none');
                            $('#Wikiplus-Setting-Apply').click(function () {
                                localStorage.Wikiplus_SendStatistics = 'False';
                                install();
                            });
                            
                            $('#Wikiplus-Setting-Cancel').click(function () {
                                localStorage.Wikiplus_SendStatistics = 'False';
                                install();
                            });
                            
                        });*/
                    }
                }

                /**
                 * 获取设置值
                 * @param {string} key 键名
                 * @param {object} object ä¼ å…¥å¯ç”¨å‚æ•°
                 */
            }, {
                key: 'getSetting',
                value: function getSetting(key, object) {
                    var w = object;
                    try {
                        var settings = JSON.parse(localStorage.Wikiplus_Settings);
                    } catch (e) {
                        return localStorage.Wikiplus_Settings || '';
                    }
                    try {
                        var _setting = new Function('return ' + settings[key]);
                        if (typeof _setting == 'function') {
                            try {
                                if (_setting()(w) === true) {
                                    return undefined;
                                } else {
                                    return _setting()(w) || settings[key];
                                }
                            } catch (e) {
                                return settings[key];
                            }
                        } else {
                            return settings[key];
                        }
                    } catch (e) {
                        try {
                            return settings[key];
                        } catch (e) {
                            return undefined;
                        }
                    }
                }
            }, {
                key: 'initBasicFunctions',
                value: function initBasicFunctions() {
                    this.initQuickEdit(); //åŠ è½½å¿«é€Ÿç¼–è¾‘
                    this.editSettings(); //编辑设置
                    this.simpleRedirector(); //快速重定向
                    this.preloadEventBinding(); //预读取
                    if (!this.getSetting('disableEditEveryWhere')) {
                        this.editEveryWhere(); //任意编辑
                    }
                }
            }, {
                key: 'initRecentChangesPageFunctions',
                value: function initRecentChangesPageFunctions() {}
            }, {
                key: 'initAdvancedFunctions',
                value: function initAdvancedFunctions() {}
            }]);

            function Wikiplus() {
                _classCallCheck(this, Wikiplus);

                this.version = '2.2.14';
                this.langVersion = '210';
                this.releaseNote = 'Bug 修正';
                this.notice = new MoeNotification();
                this.inValidNameSpaces = [-1, 8964];
                this.defaultSettings = {
                    'key': 'value',
                    'documatation': 'http://zh.moegirl.org/User:%E5%A6%B9%E7%A9%BA%E9%85%B1/Wikiplus/%E8%AE%BE%E7%BD%AE%E8%AF%B4%E6%98%8E'
                };
                console.log('æ­£åœ¨åŠ è½½Wikiplus ' + this.version);
                //载入CSS
                $("head").append("<link>");
                $("head").children(":last").attr({
                    rel: "stylesheet",
                    type: "text/css",
                    href: "//ar.wikipedia.org/w/index.php?title=MediaWiki:Gadget-QuickEdit.css&action=raw&ctype=text/css"
                });
                //一些初始化工作
                this.preloadData = {};
                this.checkInstall(); //安装检查
                //语言检测
                var language = this.getSetting('language') && this.getSetting('language').toLowerCase() || window.navigator.language.toLowerCase();
                //版本检查
                /*if (!(this.version === localStorage.Wikiplus_Version)) {
                    localStorage.Wikiplus_Version = this.version;
                    this.notice.create.success('Wikiplus ' + this.version);
                    this.notice.create.success(language === 'zh-cn' ? this.releaseNote : 'Minor bug fixes.'); // 避免给其他语言用户不必要的理解困难
                }*/
                if (i18nData[language] === undefined) {
                    loadLanguage(language);
                }
                //真正的初始化
                if (!inArray(mw.config.get('wgNameSpaceNumber'), this.inValidNameSpaces) && mw.config.get('wgIsArticle') && mw.config.get('wgAction') === "view") {
                    this.kotori = new Wikipage();
                    this.checki18nCache();
                    this.initBasicFunctions();
                } else {
                    console.log('ä¸ç¬¦åˆåŠ è½½æ¡ä»¶ Wikiplus终止');
                }
            }

            return Wikiplus;
        })();

        window.Wikiplus = new Wikiplus();
    });
});