跳转到内容

User:Liangent/Scripts/Libraries/MediaWiki.uncompressed.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。

// TODO: callbacks: accept 'this' as returned value (about multi-values?); done in 'each' callbacks, conforming to jQuery's each

MediaWiki = {};

MediaWiki.Config = {};

MediaWiki.Error = function(code, info) {
    this.code = code;
    this.info = info;
};

MediaWiki.Warning = function(xml) {
    this.xml = xml;
};

MediaWiki.NotImplemented = function(msg) {
    this.message = msg;
};

MediaWiki.Exception = function(msg) {
    this.message = msg;
};

MediaWiki._dummy = function() {};

MediaWiki._methodWrapper = function(func) {
    return function(data, callback, callbackError) {
        if (jQuery.isFunction(data)) {
            callbackError = callback;
            callback = data;
            data = {};
        }
        if (data === undefined) {
            data = {};
        }
        if (callback === undefined) {
            callback = MediaWiki._dummy;
        }
        if (callbackError === undefined) {
            callbackError = MediaWiki._dummy;
        }
        func(data, callback, callbackError);
    };
};

MediaWiki._errorReport = MediaWiki._methodWrapper(function(data, callback, callbackError) {
    if (data.type == 'ajax') return; // too frequent
    var comment;
    if ((MediaWiki.Config.errorReport && MediaWiki.Config.errorReport == 'all') ||
        (MediaWiki.Config.errorReport != 'none' &&
           (comment = prompt('The script has detected that an error has occurred.\n\n' +
            'To send an error report, input some text to describe what you are doing (or simply leave blank), and click OK.\n\n' +
            'To skip sending it, click Cancel.')) != null)) {
        report = '{\{subst:ErrorReport/Scripts/MediaWiki/2' +
            '|type=' + data.type +
            '|request=' + jQuery.param(data.request) + // '|' will be escaped
            '|status=' + data.status +
            '|comment=' + comment +
            '|skin=' + skin +
            '|action=' + wgAction +
            '|username=' + wgUserName +
            '|language=' + wgUserLanguage;
        data.type = data.request = data.status = null;
        for (var key in data) {
            var value = data[key];
            if (value == null) continue;
            if (key == 'xml') value = '<source lang="xml">' + value.Xml + '</source>';
            else if (key == 'requeststack') value = '<pre>' + value + '</pre>';
            else value = '<nowiki>' + value.toString() + '</nowiki>';
            if (data[key] != null) {
                report += '|' + key + '=' + value;
            }
        }
        try {(0)();} catch (e) {
            report += '|stack=<pre>' + e.stack + '</pre>';
        }
        report += '}}';
        MediaWiki.Page('Project:错误报告/Scripts/MediaWiki').newSection(
            {text: report}, function(xhr, status) {
                callback(xhr, status);
                alert('The error report has been sent.');
            }, callbackError
        );
    }
});

MediaWiki._request = MediaWiki._methodWrapper(function(data, callback, callbackError) {
    var requeststack;
    try {(0)();} catch (e) {
        requeststack = e.stack;
    }
    data.format = 'xml';
    jQuery.ajax({
        type: 'POST',
        url: wgScriptPath + '/api.php',
        data: data,
        error: function(xhr, status, error) {
            // users can know what's happened when considering whether send or not
            callbackError(xhr, status);
            MediaWiki._errorReport({
                type: 'ajax',
                request: data,
                status: status,
                error: error,
                requeststack: requeststack
            });
        },
        success: function(xhr, status) {
            if (jQuery('api>error', xhr).length == 1) {
                error = jQuery('api>error', xhr);
                callbackError(xhr, status, new MediaWiki.Error(error.attr('code'), error.attr('info')));
                MediaWiki._errorReport({
                    type: 'mwerror',
                    request: data,
                    status: status,
                    code: error.attr('code'),
                    info: error.attr('info'),
                    requeststack: requeststack    
                });
            } else if (jQuery('api>warnings', xhr).length >= 1) {
                var xmlnode = jQuery('api>warnings', xhr)[0];
                callbackError(xhr, status, new MediaWiki.Warning(xmlnode));
                MediaWiki._errorReport({
                    type: 'mwwarning',
                    request: data,
                    status: status,
                    xml: xmlnode,
                    requeststack: requeststack
                });
            } else {
                callback(xhr, status);
            }
        }
    });
});

MediaWiki.currentTime = MediaWiki._methodWrapper(function(data, callback, callbackError) {
    MediaWiki._request({
        action: 'expandtemplates',
        text: '{{#time:U}}'
    }, function(xhr, status) {
        var date = new Date();
        var unixtime = parseInt(jQuery('api>expandtemplates', xhr).text());
        if (isNaN(unixtime)) {
            callbackError(xhr, status,
                new MediaWiki.Exception('Malformed time response from server')
            );
        } else {
            date.setTime(unixtime * 1000);
            callback(date);
        }
    }, callbackError);
});

MediaWiki._Tokens = {};

MediaWiki._Tokens.edit = function(callback, callbackError) {
    if (MediaWiki._Tokens._edit === undefined) {
        MediaWiki._Tokens._edit = 0;
        MediaWiki._request({
            action: 'query',
            prop: 'info',
            titles: '-',
            intoken: 'edit'
        }, function(xhr, status) {
            MediaWiki._Tokens._edit = jQuery('api>query>pages>page', xhr).attr('edittoken');
            if (MediaWiki._Tokens._editCallbacks != undefined) {
                jQuery.each(MediaWiki._Tokens._editCallbacks, function() {
                    this.success(MediaWiki._Tokens._edit);
                });
                MediaWiki._Tokens._editCallbacks = [];
            }
            callback(MediaWiki._Tokens._edit);
        }, function(xhr, status, err) {
            MediaWiki._Tokens._edit = undefined;
            if (MediaWiki._Tokens._editCallbacks != undefined) {
                jQuery.each(MediaWiki._Tokens._editCallbacks, function() {
                    this.error(xhr, status, err);
                });
                MediaWiki._Tokens._editCallbacks = [];
            }
            callbackError(xhr, status, err);
        });
    } else if (MediaWiki._Tokens._edit == 0) {
        if (MediaWiki._Tokens._editCallbacks === undefined) {
            MediaWiki._Tokens._editCallbacks = [{success: callback, error: callbackError}];
        } else {
            MediaWiki._Tokens._editCallbacks.push({success: callback, error: callbackError});
        }
    } else {
        callback(MediaWiki._Tokens._edit); // in a new "thread"?
    }
};

// are they always the same?
MediaWiki._Tokens.remove = MediaWiki._Tokens.protect = MediaWiki._Tokens.move = MediaWiki._Tokens.block =
MediaWiki._Tokens.unblock = MediaWiki._Tokens.email = MediaWiki._Tokens.import = MediaWiki._Tokens.edit;

MediaWiki._inherit = function(ancestor) {
    var child = {};
    for (var k in ancestor) {
        child[k] = ancestor[k];
    }
    return child;
};

MediaWiki._List = function(paramgen, elemproc) {
    var me = {};
    
    me.each = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        if (!jQuery.isArray(data)) {
            data = paramgen(data);
        }
        data[0]['action'] = 'query'; // force this, like format=xml
        data[0]['rawcontinue'] = ''; // force old-style continuation
        var query = data[0], tagname = data[1];
        MediaWiki._request(query, function(xhr, status) {
            var elem = jQuery('api>query', xhr)[0];
            if (elemproc !== undefined) {
                elem = elemproc(elem);
            }
            if (elem != null) {
                callback.call(elem);
            }
            var cont = jQuery('api>query-continue', xhr);
            if (cont.length != 0) {
                jQuery.each(cont.children(tagname)[0].attributes, function(attr) {
                    query[attr.name] = attr.value;
                });
                me.each([query, tagname], callback, callbackError);
            }
        }, callbackError);
    });
    
    return me;
};

MediaWiki._SimpleList = function(paramgen, elemproc) {
    var ancestor = MediaWiki._List(paramgen);
    var me = MediaWiki._inherit(ancestor);
    
    me.each = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        if (!jQuery.isArray(data)) {
            data = paramgen(data);
        }
        ancestor.each(data, function() {
            jQuery(this).children(data[1]).children().each(function() {
                var elem = this;
                if (elemproc !== undefined) {
                    elem = elemproc(elem);
                }
                if (elem != null) {
                    callback.call(elem);
                }
            });
        }, callbackError);
    });
    
    return me;
};

MediaWiki.Page = function(title) {
    var me = {};
    me._isCurrentPage = false;
    
    if (title === undefined) {
        me._title = wgPageName.replace(/_/g, ' ');
        me._isCurrentPage = true;
    } else {
        me._title = title;
    }
    
    me.creator = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        MediaWiki._request({
            action: 'query',
            prop: 'revisions',
            titles: me._title,
            rvlimit: '1',
            rvprop: 'user',
            rvdir: 'newer'
        }, function(xhr, status) {
            callback(jQuery('api>query>pages>page>revisions>rev', xhr).attr('user'));
        }, callbackError);
    });
    
    me.newSection = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        MediaWiki._Tokens.edit(function(token) {
            MediaWiki._request({
                action: 'edit',
                title: me._title,
                section: 'new',
                summary: data.subject === undefined ? (data.headline === undefined ? '' : data.headline) : data.subject,
                text: data.text === undefined ? '' : data.text,
                token: token
            }, callback, callbackError);
        }, callbackError);
    });
    
    me.text = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        if (data.text === undefined) {
            MediaWiki._request({
                action: 'query',
                prop: 'revisions',
                titles: me._title,
                rvprop: 'content'
            }, function(xhr, status) {
                callback(jQuery('api>query>pages>page>revisions>rev', xhr).text());
            }, callbackError);
        } else {
            MediaWiki._Tokens.edit(function(token) {
                MediaWiki._request({
                    action: 'edit',
                    title: me._title,
                    text: data.text === undefined ? '' : data.text,
                    summary: data.summary === undefined ? '' : data.summary,
                    token: token
                }, callback, callbackError);
            }, callbackError);
        }
    });
    
    me.patrolled = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        var reqdata = {
            action: 'query',
            list: 'recentchanges',
            rcshow: '!patrolled',
            rclimit: 500,
            rctype: 'new'
        };
        if (me._isCurrentPage) {
            reqdata.rcnamespace = wgNamespaceNumber;
        }
        if (data.patrolled === undefined) {
            reqdata.rcprop = 'title';
            MediaWiki._request(reqdata, function(xhr, status) {
                callback(jQuery('api>query>recentchanges>rc[title=' + me._title + ']', xhr).length == 0);
            }, callbackError);
        } else if (data.patrolled == true) {
            reqdata.rcprop = 'title|ids';
            reqdata.rctoken = 'patrol';
            MediaWiki._request(reqdata, function(xhr, status) {
                if (jQuery('api>query>recentchanges>rc[title=' + me._title + ']', xhr).length == 0) {
                    callbackError(xhr, status,
                        new MediaWiki.Exception('Maybe this page is too old or already patrolled.')
                    );
                } else {
                    rc = jQuery('api>query>recentchanges>rc[title=' + me._title + ']', xhr);
                    MediaWiki._request({
                        action: 'patrol',
                        rcid: rc.attr('rcid'),
                        token: rc.attr('patroltoken')
                    }, callback, callbackError);
                }
            }, callbackError);
        } else if (data.patrolled == false) {
            throw new MediaWiki.Exception('Cannot mark a page as unpatrolled.');
        }
    });
    
    me.patrol = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        me.patrolled({patrolled: true}, callback, callbackError);
    });
    
    me.redirect = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        MediaWiki._request({
            action: 'query',
            prop: 'info',
            titles: me._title
        }, function(xhr, status) {
            callback(jQuery('api>query>pages>page', xhr).attr('redirect'));
        }, callbackError);
    });
    
    me.remove = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        MediaWiki._Tokens.remove(function(token) {
            MediaWiki._request({
                action: 'delete',
                title: me._title,
                token: token,
                reason: data.reason === undefined ? '' : data.reason
            }, callback, callbackError);
        }, callbackError);
    });
    
    me.watched = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        if (data.watched === undefined) {
            var reqdata = {
                action: 'query',
                rawcontinue: '',
                list: 'watchlistraw',
                wrlimit: 500
            };
            if (me._isCurrentPage) {
                reqdata.wrnamespace = wgNamespaceNumber;
            }
            function cb(xhr, status) {
                if (jQuery('api>watchlistraw>wr[title=' + me._title + ']', xhr).length != 0) {
                    callback(true);
                } else if (jQuery('api>query-continue', xhr).length != 0) {
                    reqdata.wrcontinue = jQuery('api>query-continue>watchlistraw', xhr).attr('wrcontinue');
                    MediaWiki._request(reqdata, cb, callbackError);
                } else {
                    callback(false);
                }
            }
            MediaWiki._request(reqdata, cb, callbackError); // or start just by calling cb?
        } else {
            var reqdata = {
                action: 'watch',
                title: me._title
            };
            if (data.watched == false) {
                reqdata.unwatch = true;
            }
            MediaWiki._request(reqdata, callback, callbackError);
        }
    });
    
    me._tokens = {};
    
    // rollback tokens are different on different pages
    me._tokens.rollback = function(callback, callbackError) {
        MediaWiki._request({
            action: 'query',
            prop: 'revisions',
            titles: me._title,
            rvprop: '',
            rvtoken: 'rollback'
        }, function(xhr, status) {
            callback(jQuery('api>query>pages>page>revisions>rev', xhr).attr('rollbacktoken'));
        }, callbackError);
    };
    
    me.rollback = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        me._tokens.rollback(function(token) {
            MediaWiki._request({
                action: 'rollback',
                title: me._title,
                user: data.user === undefined ? '' : data.user,
                token: token,
                summary: data.summary === undefined ? '' : data.summary
            }, callback, callbackError);
        }, callbackError);
    });
    
    me.purge = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        MediaWiki._request({
            action: 'purge',
            titles: me._title
        }, callback, callbackError);
    });
    
    me.title = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        callback(me._title);
    });
    
    me.exists = MediaWiki._methodWrapper(function(data, callback, callbackError) {
        MediaWiki._request({
            action: 'query',
            titles: me._title
        }, function(xhr) {
            callback(jQuery('api>query>pages>page', xhr).attr('missing') === undefined);
        }, callbackError);
    });
    
    return me;
};

MediaWiki.Category = function(title) {
    var ancestor = MediaWiki.Page(title);
    var me = MediaWiki._inherit(ancestor);
    
    me.members = MediaWiki._SimpleList(function(data) {
        return [{
            list: 'categorymembers',
            cmtitle: me._title,
            cmprop: 'title',
            cmlimit: 500
        }, 'categorymembers'];
    }, function(elem) {
        return MediaWiki.Page(jQuery(elem).attr('title'))
    });
    
    return me;
};