Benutzer:Schnark/js/fliegelflagel.js/load.js
aus Wikipedia, der freien Enzyklopädie
< Benutzer:Schnark | js | fliegelflagel.js
Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.
- Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
- Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
- Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
- Opera: Strg+F5
//<nowiki>
/*global mediaWiki*/
(function ($, mw) {
"use strict";
var hasOwn = Object.prototype.hasOwnProperty, l10n = {
//jscs:disable maximumLineLength
en: {
'schnark-fliegelflagel': 'Fliegelflagel',
'tooltip-u-schnark-fliegelflagel': 'Manage user scripts',
'schnark-fliegelflagel-version-update-console': 'Fliegelflagel: You should update the code to load Fliegelflagel, see https://de.wikipedia.org/wiki/Benutzer:Schnark/js/fliegelflagel for the current version.'
},
de: {
'tooltip-u-schnark-fliegelflagel': 'Benutzerskripte verwalten',
'schnark-fliegelflagel-version-update-console': 'Fliegelflagel: Du solltest den Code aktualisieren, mit dem du Fliegelflagel lädst, siehe https://de.wikipedia.org/wiki/Benutzer:Schnark/js/fliegelflagel für die aktuelle Version.'
}
//jscs:enable maximumLineLength
}, didRunVePlugins, $errorIndicator,
loadUrl = document.currentScript && document.currentScript.src;
function getUserOption (id, def) {
return String(mw.user.options.get('userjs-' + id, def));
}
function initL10N (l10n) {
var i, chain = mw.language.getFallbackLanguageChain();
for (i = chain.length - 1; i >= 0; i--) {
if (chain[i] in l10n) {
mw.messages.set(l10n[chain[i]]);
}
}
}
function showErrors (errors) {
if (!$errorIndicator) {
$errorIndicator = $('<li>')
.text('!').css({color: '#d33', fontWeight: 'bold'})
.appendTo('#p-personal ul');
}
$errorIndicator.attr('title', errors.join('\n'));
}
function initErrorHandler () {
var mwLogWarn = mw.log.warn, errors = [];
mw.log.warn = function (msg) {
mwLogWarn(msg);
errors.push(msg);
showErrors(errors);
};
$(window).on('error', function (e) {
try {
mw.log.warn('Error: ' + e.originalEvent.message);
} catch (e) {
window.alert('Fliegelflagel: Error while reporting an error!');
}
});
}
//Loader
function Loader (debugProtocol, debug) {
this.cache = {};
this.debug = debug || {};
this.debugProtocol = debugProtocol;
this.initDebug();
}
Loader.interwiki = function (base, title) {
var m, lang, project, code,
mono = {
c: 'commons.wikimedia',
commons: 'commons.wikimedia',
d: 'www.wikidata',
m: 'meta.wikimedia',
meta: 'meta.wikimedia',
mw: 'www.mediawiki'
}, iwmap = {
b: 'wikibooks',
n: 'wikinews',
q: 'wikiquote',
s: 'wikisource',
v: 'wikiversity',
voy: 'wikivoyage',
w: 'wikipedia',
wikt: 'wiktionary'
};
m = /^https:\/\/([a-z\-]+\.[a-z]+)\.org\/w\/index\.php$/.exec(base);
if (!m) {
return [base, title];
}
base = m[1];
m = base.split('.');
lang = m[0];
project = m[1];
for (m in mono) {
if (mono[m] === base) {
lang = 'en';
project = m;
break;
}
}
m = title.split(':');
if (m[0] === '') {
m.shift();
}
while (true) {
if (m.length === 1 || !(/^[a-z\-]+$/.test(m[0]))) {
break;
}
code = m.shift();
if (code in mono) {
lang = 'en';
project = code;
} else if (code in iwmap) {
if (iwmap[code] === project) {
lang = 'en';
} else {
project = iwmap[code];
}
} else {
lang = code;
if (project in mono) {
project = 'wikipedia';
}
}
}
title = m.join(':');
if (project in mono) {
base = mono[project];
} else {
base = lang + '.' + project;
}
return ['https://' + base + '.org/w/index.php', title];
};
Loader.prototype.initDebug = function () {
var debug = this.debug, proto = this.debugProtocol, script;
for (script in debug) {
if (hasOwn.call(debug, script)) {
mw.log.warn('Debug: ' + script);
}
}
$.ajaxPrefilter(function (o, opts) {
if (opts.url && opts.url.indexOf(proto + ':') === 0) {
return proto;
}
});
$.ajaxTransport(proto, function (o) {
var script = o.url.slice(proto.length + 1);
o.dataTypes = o.dataTypes.filter(function (dt) {
return dt !== proto;
});
if (script !== '') {
script = debug[script] || '';
}
return {
send: function (h, callback) {
callback(200, 'success', {text: script});
},
abort: $.noop
};
});
};
Loader.prototype.getUrl = function (script, base) {
var ret;
if (mw.config.get('wgAction') === 'submit' && script.replace(/[\s_]+/g, '_') === mw.config.get('wgPageName')) {
//TODO Benutzerin: <-> Benutzer: etc.
return this.debugProtocol + ':';
}
if (script in this.debug) {
return this.debugProtocol + ':' + script;
}
if (!(/^(?:https?:)?\/\//).test(script)) {
ret = Loader.interwiki(base, script);
script = ret[0] + '?title=' +
encodeURIComponent(ret[1].replace(/[\s_]+/g, '_'))
//siehe mw.util.wikiUrlencode
.replace(/'/g, '%27')
.replace(/%3B/g, ';')
.replace(/%40/g, '@')
.replace(/%24/g, '$')
.replace(/%2C/g, ',')
.replace(/%2F/g, '/')
.replace(/%3A/g, ':') +
'&action=raw&ctype=text/javascript';
}
return script;
};
Loader.prototype.loadUrl = function (url, reload) {
if (reload || !(url in this.cache)) {
this.cache[url] = $.ajax({
url: url,
dataType: 'script',
crossDomain: true, //<script> statt eval
cache: true, //jQuery hat für script als Standardwert hier false
async: true
});
}
return this.cache[url];
};
Loader.prototype.loadUrls = function (urls, reload) {
var d = this.loadUrl(urls[0], reload), i;
function makeNext (i, that) {
return function () {
return that.loadUrl(urls[i], reload);
};
}
for (i = 1; i < urls.length; i++) {
d = d.then(makeNext(i, this));
}
return d;
};
//Script
function Script (id, data, collection) {
this.id = id;
this.data = data;
this.collection = collection;
}
Script.getUserOption = getUserOption;
Script.prototype.extend = function (data) {
$.extend(this.data, data);
};
Script.prototype.addConfig = function (callback) {
this.configCallback = callback;
};
Script.prototype.getScripts = function () {
var scripts = this.data.scripts;
if (!Array.isArray(scripts)) {
scripts = [scripts];
}
return scripts.map(function (script) {
return script.replace(/^\[+|\]+$/g, '');
});
};
Script.prototype.getUrls = function () {
return this.getScripts().map(function (script) {
return this.collection.loader.getUrl(script, this.data.base);
}, this);
};
Script.prototype.runBefore = function () {
var before = this.data.before;
if (typeof before === 'function') {
before = before();
}
if (before) {
return this.collection.loader.loadUrl(before);
} else {
return $.Deferred().resolve().promise();
}
};
Script.prototype.runAfter = function (data) {
if (this.data.after) {
this.data.after(data);
}
if (this.configCallback) {
try {
this.configCallback(data);
} catch (e) {
mw.log.warn(e);
}
}
};
Script.prototype.load = function (reload) {
var urls = this.getUrls(), didRunAfter = false, d = $.Deferred().resolve();
mw.hook('userjs.load-script.' + this.id).add(function (data) {
didRunAfter = true;
this.runAfter(data);
}.bind(this));
if (this.data.readyWait) {
d = $.Deferred();
mw.hook('userjs.script-ready.' + this.id).add(d.resolve);
}
return this.runBefore().then(function () {
return this.collection.loader.loadUrls(urls, reload).then(function () {
if (!didRunAfter) {
this.runAfter();
}
return d;
}.bind(this));
}.bind(this));
};
Script.prototype.loadAsVePlugin = function (reload) {
this.collection.addVePlugin(function () {
return this.load(reload);
}.bind(this));
};
Script.prototype.checkExists = function (global) {
var wiki = mw.config.get('wgDBname');
return !this.data.wiki ||
wiki === 'my_wiki' ||
(!global && this.data.wiki.indexOf(wiki) > -1) ||
(global && this.data.wiki.length > 1);
};
Script.prototype.getEnabledKey = function (profile) {
var key = 'schnark-fliegelflagel-' + this.id + '-enabled';
if (profile) {
key += '-' + profile;
}
return key;
};
Script.prototype.getUserEnabled = function (profile, def) {
return Script.getUserOption(this.getEnabledKey(profile), def);
};
Script.prototype.checkDefaultEnabled = function (profile) {
/*jshint bitwise: false*/
if (this.data.defaultEnabled === true) {
return true;
}
if (profile) {
return this.checkEnabled();
}
return !!((this.data.defaultEnabled || 0) & Number(Script.getUserOption('schnark-fliegelflagel-defaultEnabled', '3')));
};
Script.prototype.checkEnabled = function (profile) {
return this.getUserEnabled(profile, this.checkDefaultEnabled(profile) ? '1' : '0') === '1';
};
Script.prototype.checkNeeded = function (data) {
return !this.data.only || this.data.only(data.ns, data.action);
};
Script.prototype.run = function (data) {
var needed, reRun = true, done;
if (!this.checkExists()) {
return false;
}
if (!this.checkEnabled(data.profile)) {
return false;
}
needed = data.force || this.checkNeeded(data);
if (needed && this.data.type !== 've') {
done = this.load();
reRun = false;
}
if (this.data.type === 'hybrid' || (needed && this.data.type === 've')) {
this.loadAsVePlugin(this.data.type === 'hybrid');
reRun = false;
}
return reRun || done;
};
//Collection
function Collection (base, debug) {
this.list = [];
this.scripts = {};
this.checkRun = {};
this.vePlugins = [];
this.base = base || (mw.config.get('wgServer') + mw.config.get('wgScript'));
this.loader = new Loader('fliegelflagel-debug', debug);
this.order = 0;
}
Collection.prototype.getOrder = function () {
this.order++;
return this.order;
};
Collection.prototype.getById = function (id) {
if (this.list.indexOf(id) === -1) {
mw.log.warn('Fliegelflagel: Unknown ID "' + id + '"!');
return;
}
return this.scripts[id];
};
Collection.prototype.bulkWork = function (data, callback) {
var id;
for (id in data) {
if (hasOwn.call(data, id)) {
callback.call(this, id, data[id]);
}
}
};
Collection.prototype.forAll = function (callback, order) {
var i, id, scripts = this.scripts, list = this.list.slice();
if (order) {
list.sort(function (a, b) {
return (scripts[a].data.order || Infinity) - (scripts[b].data.order || Infinity);
});
}
for (i = 0; i < list.length; i++) {
id = list[i];
callback.call(this, scripts[id], id);
}
};
Collection.prototype.addScript = function (id, data) {
if (this.list.indexOf(id) > -1) {
mw.log.warn('Fliegelflagel: Duplicate ID "' + id + '"!');
return;
}
if (!(/^[a-zA-Z0-9_\-]{1,200}$/.test(id))) {
mw.log.warn('Fliegelflagel: Invalid ID "' + id + '"!');
return;
}
if (typeof data === 'string') {
data = {
scripts: data,
defaultEnabled: true
};
}
this.list.push(id);
this.checkRun[id] = true;
this.scripts[id] = new Script(id, $.extend({base: this.base}, data), this);
};
Collection.prototype.extendScript = function (id, data) {
id = this.getById(id);
if (id) {
id.extend($.extend({order: this.getOrder()}, data));
}
};
Collection.prototype.configureScript = function (id, config) {
id = this.getById(id);
if (id) {
id.addConfig(config);
}
};
Collection.prototype.bulkAdd = function (data) {
this.bulkWork(data, this.addScript);
};
Collection.prototype.bulkExtend = function (data) {
this.bulkWork(data, this.extendScript);
};
Collection.prototype.bulkConfigure = function (data) {
this.bulkWork(data, this.configureScript);
};
Collection.prototype.run = function (data) {
var done = [], result;
this.forAll(function (script, id) {
if (this.checkRun[id]) {
result = script.run(data);
if (typeof result !== 'boolean') {
done.push(result);
result = false;
}
this.checkRun[id] = result;
}
});
return $.when.apply($, done);
};
Collection.prototype.addVePlugin = function (load) {
this.vePlugins.push(load);
};
Collection.prototype.loadVePlugins = function () {
var plugins = this.vePlugins.slice();
this.vePlugins = [];
return $.when.apply($, plugins.map(function (load) {
return load();
}));
};
//init
function addNavLink () {
$.when(mw.loader.using(['mediawiki.util', 'mediawiki.language']), $.ready).then(function () {
mw.util.addPortletLink(
'p-personal',
mw.util.getUrl('Special:Fliegelflagel'),
mw.msg('schnark-fliegelflagel'),
'pt-fliegelflagel',
mw.msg('tooltip-u-schnark-fliegelflagel'),
null, //access key
'#pt-watchlist'
);
});
}
function getProfile (profile) {
var possibleProfiles, i, key, temp, ua;
possibleProfiles = {
mobile: /mobile|tablet|ip(ad|hone|od)|android/i,
old: /Mozilla\/[0-4]|Trident|Presto|(?:Chrome|Firefox)\/[12]?\d\.|AppleWebKit\/[1-5]?\d?\d\./
};
if (typeof profile === 'function') {
profile = profile();
}
if (profile === undefined) {
profile = ['mobile'];
}
if (Array.isArray(profile)) {
temp = {};
for (i = 0; i < profile.length; i++) {
key = profile[i];
if (hasOwn.call(possibleProfiles, key)) {
temp[key] = possibleProfiles[key];
}
}
profile = temp;
}
if ($.isPlainObject(profile)) {
ua = navigator.userAgent;
for (key in profile) {
if (hasOwn.call(profile, key) && profile[key].test(ua)) {
profile = key;
break;
}
}
profile = '';
}
if (typeof profile !== 'string') {
mw.log.warn('Fliegelflagel: Wrong type for profile!');
return '';
}
if (!(/^[a-zA-Z0-9_\-]{0,20}$/.test(profile))) {
mw.log.warn('Fliegelflagel: Wrong format for profile!');
return '';
}
return profile;
}
function getAction () {
var m;
switch (mw.config.get('wgAction')) {
case 'submit': return 'edit';
case 'historysubmit': return 'diff';
case 'view':
if (location.search.search(/[?&]diff=/) > -1) {
return 'diff';
}
/* falls through */
case 'nosuchaction':
m = (/^[^#]*[&?]action=([^&#]*)/).exec(document.location.href);
if (m && m.length > 1) {
return decodeURIComponent(m[1].replace(/\+/g, '%20'));
}
/* falls through */
default: return mw.config.get('wgAction') || 'view';
}
}
function checkClearCache () {
if (mw.config.get('wgNamespaceNumber') !== -1 || mw.config.get('wgTitle') !== 'FliegelflagelPurge') {
return false;
}
if (window.name === 'cache-cleared') {
window.name = '';
return false;
}
window.name = 'cache-cleared';
mw.hook('userjs.script-ready.fliegelflagel').add(function () {
window.location.reload(true);
});
return true;
}
function init (internal, user, debug) {
var data, collection = new Collection(internal.base, debug);
data = {
ns: mw.config.get('wgNamespaceNumber'),
action: getAction(),
profile: getProfile(user.profile),
force: checkClearCache()
};
mw.loader.using(['mediawiki.language']).then(function () {
initL10N(l10n);
if (user.warnVersionUpdate) {
mw.log.warn(mw.msg('schnark-fliegelflagel-version-update-console'));
}
});
if (getUserOption('schnark-fliegelflagel-manage-nolink', '0') === '0') {
addNavLink();
}
collection.removableOptions = internal.removableOptions;
collection.bulkAdd(internal.modules);
collection.bulkAdd(user.additional || {});
collection.bulkConfigure(user.config || {});
mw.hook('userjs.schnark-fliegelflagel.l10n').add(function (data) {
mw.loader.using('mediawiki.language').then(function () {
initL10N(data);
});
});
mw.hook('userjs.schnark-fliegelflagel.configdefine').add(function (data) {
collection.bulkExtend(data.scripts || data);
//TODO bisherige Daten .scripts verschieben,
//.removableOptions und .suggestedOptions dort speichern und hier auslesen
});
mw.hook('userjs.schnark-fliegelflagel.configextend').add(function (extend) {
var modules = mw.loader.using([
'mediawiki.language', 'mediawiki.util', 'mediawiki.jqueryMsg',
'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows', 'oojs-ui.styles.icons-alerts'
]), data;
if (user.global) {
data = mw.loader.using('mediawiki.api').then(function () {
var api = new mw.Api();
return api.get({
action: 'query',
meta: 'globalpreferences'
});
}).then(function (data) {
return data.query.globalpreferences.preferences;
});
} else {
data = $.Deferred().resolve().promise();
}
$.when(data, modules).then(function (globalPrefs) {
extend(Script, Collection);
$(function () {
collection.initConfigure(data.profile, globalPrefs, user.warnVersionUpdate);
});
});
});
collection.run(data).then(function () {
mw.hook('userjs.script-ready.fliegelflagel').fire();
});
mw.hook('userjs.schnark-fliegelflagel.ve').add(function (d) {
didRunVePlugins = true;
collection.loadVePlugins().then(d.resolve);
setTimeout(d.resolve, 10000); //nach 10 Sekunden aufgeben und VE auch ohne Plugins laden
});
mw.hook('ve.activationComplete').add(function () {
data.action = 've';
collection.run(data);
});
mw.hook('ve.deactivationComplete').add(function () {
data.action = 'view';
collection.run(data);
});
}
function getPromise (name) {
var d = $.Deferred();
mw.hook('userjs.schnark-fliegelflagel.' + name).add(d.resolve);
return d.promise();
}
function checkDisabled (key) {
try {
if (localStorage[key]) {
mw.log.warn(
'Fliegelflagel is disabled. ' +
'To enable again, execute `delete localStorage[\'' + key + '\']`.'
);
return true;
}
} catch (e) {
}
try {
if (sessionStorage[key]) {
mw.log.warn(
'Fliegelflagel is disabled in this tab. ' +
'To enable again, execute `delete sessionStorage[\'' + key + '\']`.'
);
return true;
}
} catch (e) {
}
}
function validateUserConfig (user, defineUrl, debug) {
var versionUpdater = {
1.0: function () {
user.version = 1.1;
if ($('html.ve-available').length) { //only warn when VE is available, there are no benefits otherwise
user.warnVersionUpdate = true;
}
},
1.1: true
}, urls = {
//jscs:disable maximumLineLength
define: 'https://de.wikipedia.org/w/index.php?title=Benutzer:Schnark/js/fliegelflagel.js/define.js&action=raw&ctype=text/javascript',
load: 'https://de.wikipedia.org/w/index.php?title=Benutzer:Schnark/js/fliegelflagel.js/load.js&action=raw&ctype=text/javascript'
//jscs:enable maximumLineLength
};
mw.hook('ve.activationComplete').add(function () {
if (!didRunVePlugins) {
mw.log.warn('Fliegelflagel: VE activated without plugins!');
}
});
while (user.version in versionUpdater && versionUpdater[user.version] !== true) {
versionUpdater[user.version]();
}
if (!versionUpdater[user.version]) {
mw.log.warn('Fliegelflagel: Wrong version!');
return;
}
if (user.global && !debug) { //TODO
mw.log.warn('user.global isn\'t ready yet');
return;
}
if (loadUrl) {
if (loadUrl !== urls.load || defineUrl !== urls.define) {
user.warnVersionUpdate = true;
}
}
return user;
}
$.when(getPromise('define'), getPromise('userdefine'), mw.loader.using('user.options')).then(function (internal, user) {
var debug;
if (checkDisabled('fliegelflagel-disable')) {
return;
}
if (getUserOption('schnark-fliegelflagel-manage-debug', '0') === '1') {
initErrorHandler();
try {
debug = JSON.parse(sessionStorage['fliegelflagel-debug']);
} catch (e) {
}
}
user = validateUserConfig(user || {}, internal.defineUrl, debug);
if (user) {
init(internal, user, debug);
}
});
})(jQuery, mediaWiki);
//</nowiki>