User:Becasita/common.js
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: hold down Ctrl and click the Refresh or Reload button. Firefox: hold down ⇧ Shift while clicking Reload (or press Ctrl+⇧ Shift+R). Google Chrome and Safari users can just click the Reload button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/**
* Main JS function.
*/
(function(window, $, mw, console, delay) {
"use strict";
const LAST_LOG = '23:28, 5 February 2024 (UTC)'; //<pre>
mw.loader.using( ['mediawiki.api', 'mediawiki.util'] ).done(function() {
/**
* Global objects.
*/
const conf = mw.config.get([
'wgNamespaceNumber',
'wgPageName'
]);
$.extend(conf, {
action: mw.util.getParamValue('action'),
api: function(query, callbacks, method) {
return new mw.Api()[method || 'get'](query)
.done(callbacks.done)
.fail(callbacks.fail)
.always(callbacks.always);
}
});
const page = {
hasContent: $('#ca-history').length && conf.wgNamespaceNumber !== -1,
$content: $('#content'),
$mwHead: $('#mw-head'),
$userBar: $('#p-personal').children('ul'),
$leftNav: $('#left-navigation').find('#p-namespaces').children('ul'),
$rightNav: $('#right-navigation').find('#p-views').children('ul'),
$rightMenu: $('#right-navigation').find('#p-cactions').find('ul'),
$star: $('#ca-watch').length ? $('#ca-watch') : $('#ca-unwatch')
};
/** End. */
/**
* Constructors and prototypes.
*/
// ------
// String:
String.prototype.strip = function(c) {
return String(this).replace(new RegExp(c || ' ', 'g'), '');
};
// ------
// Query:
function Query(endpoint, query) {
// query | url | full | endpoint
if($.isPlainObject(endpoint)) {
query = endpoint;
endpoint = undefined;
}
this.query = query || {};
this.url = this.fetch();
this.full = this.extend();
this.endpoint = String(endpoint || '').trim().toLowerCase().strip('.php');
}
// Extend prototype:
$.extend(Query.prototype, {
// "Private" methods:
extend: function() {
return $.extend({}, this.url, this.query);
},
fetch: function(parameters) {
const query = {};
const getValue = function(parameter) {
return query[parameter];
};
const getValues = function(parameters) {
return (Array.isArray(parameters)
? parameters.map(function(v) {
return getValue(v);
})
: getValue(parameters)
);
};
window.location.search.slice(1).split('&').forEach(function(component) {
if(!component.trim()) return;
const parts = component.split('=');
query[window.decodeURIComponent(parts[0])] = window.decodeURIComponent(parts[1] || '');
});
return parameters ? getValues(parameters) : query;
},
// "Getters":
getEndpoint: function() {
return this.endpoint;
},
getQuery: function(type) {
switch((type+'').trim().toLowerCase()) {
case 'full': return this.full;
case 'url': return this.url;
default: return this.query;
}
},
// Other:
print: function(full) {
const query = this.getQuery(full && 'full');
return [
mw.util.wikiScript(this.getEndpoint()),
Object.keys(query).map(function(key) {
return [
window.encodeURIComponent(key),
window.encodeURIComponent(query[key])
].join('=');
}).join('&')
].join('?');
},
});
// Static method:
Query.fetch = Query.prototype.fetch;
// ------
// State:
function State(message) {
this.message = message || 'Pending...';
this.status = 'pending';
}
$.extend(State.prototype, {
getMessage: function() {
return this.message;
},
setMessage: function(m) {
this.message = m || '';
return this;
},
getStatus: function() {
return this.status;
},
setStatus: function(s) { // Private.
this.status = s || '';
return this;
},
pending: function() {
return this.setStatus('pending');
},
done: function() {
return this.setStatus('done');
},
failed: function() {
return this.setStatus('failed');
},
show: function() {
items.$specialMessages.removeClass('hide')
.children()
.removeClass().addClass(this.getStatus())
.text(this.getMessage());
return this;
}
});
/** End. */
/**
* Utility functions.
*/
/** End. */
/**
* Buttons.
*/
const items = {
$searchBar: $('<li>', {
id: 'pt-search',
html: $('#p-search')
}),
$specialMessages: $('<li>', {
id: 'pt-special-messages',
html: $('<span>', {
id: 'special-messages',
class: 'hide'
})
}),
$userBarBottom: $('<div>', {
id: 'p-bottom'
}),
$diff: $('<li>', {
id: 'ca-diff',
class: 'collapsible',
html: $('<span>', {
html: $('<a>', {
title: 'Last diff for this page.',
text: 'Diff'
})
})
}),
$raw: $('<li>', {
id: 'ca-raw',
html: $('<a>', {
href: new Query({
title: conf.wgPageName,
action: 'raw'
}).print(),
title: 'View the raw content.',
text: 'Raw'
})
}),
$safe: $('<li>', {
id: 'ca-safe',
html: $('<a>', {
href: new Query({
title: conf.wgPageName,
safemode: true
}).print(true),
title: 'View the page in safemode.',
text: 'Safe'
})
}),
$debug: $('<li>', {
id: 'ca-debug',
html: $('<a>', {
href: new Query({
title: conf.wgPageName,
debug: true
}).print(true),
title: 'View page in debug mode.',
text: 'Debug'
})
}),
$contentLabels: $('<li>', {
id: 'ca-labels-qqx',
html: $('<a>', {
href: new Query( Query.fetch().uselang === 'qqx'
? { title: conf.wgPageName }
: {
title: conf.wgPageName,
uselang: 'qqx'
}
).print(true),
title: 'Toggle content labels.',
text: 'qqx'
})
}),
$toggle: $('<li>', {
id: 'ca-toggle',
html: $('<a>', {
href: '#',
title: 'Toggle hidden content.',
text: 'Toggle'
})
})
};
// Change "View history" button label to simply "History".
$('#ca-history').find('a').text('History');
// Move the search bar and add container for special messages to the user bar:
page.$userBar
.prepend(items.$searchBar)
.append(items.$specialMessages);
// Place the buttons for the page inside a container in the user bar:
page.$mwHead.append(
items.$userBarBottom.append(
$('#left-navigation')
).append(
$('#right-navigation')
)
);
// Extract the buttons from the right "More" menu and place them next to the other ones:
page.$rightMenu.children().each(function() {
const $this = $(this);
page.$rightNav.append(
$this.addClass('collapsible').html(function() {
return $('<span>', {
html: $this.html()
});
})
);
});
// Add button to display raw content and last diff (only if the page has content):
if(page.hasContent) {
page.$rightMenu.append(items.$raw);
$('#ca-history').after(items.$diff);
}
// Add a safemode button and a toggle button to the right "More" menu:
page.$rightMenu
.append(items.$labels)
.append(items.$safe)
.append(items.$debug)
.append(items.$toggle);
// Place the (un)watch star in the last spot.
page.$rightNav.append(page.$star);
/** End. */
/**
* Procedures.
*/
// -----------------------------------------------------
// Adapt the top buttons to the diff pages: ("prettyfy")
$(function selectDiffButton() {
if(Query.fetch('diff')) {
$('#ca-diff').addClass('selected');
$('#ca-view').removeClass('selected');
}
});
// ----------------------
// Get lastest diff link:
$(function getLatestDiffLink() {
const mainFunctionName = 'getLatestDiffLink'; //arguments.callee.name;
const query = {
action: 'query',
prop: 'revisions',
titles: conf.wgPageName,
rvprop: 'ids|user|timestamp|size|parsedcomment|flags',
rvlimit: 2,
formatversion: 2,
format: 'json'
};
const callbacks = {
done: function(data) {
try {
const currentRevision = data.query.pages[0].revisions[0];
items.$diff.off('click')
.find('a')
.attr('href', new Query({
diff: currentRevision.revid
}).print());
} catch(e) {
console.log('%c«' + mainFunctionName + '()» error!', 'color: red;');
if(e instanceof TypeError) {
console.log("%cCan't get diff!", 'color: red;', '(known)');
} else {
console.error(e);
}
console.log(new Query('api', query).print(), data);
return;
}
},
fail: console.log,
always: function() {
console.log('%cDiff getter loaded!', 'color: blue;');
}
};
return conf.api(query, callbacks);
});
// -------------------------
// Toggle stuff I've hidden:
$(function toggleWhatIHaveHidden() {
[ // Add toggle class to all selectors:
'#siteNotice', '#editpage-copywarn',
'.mw-editTools', '.smw-editpage-help',
'#n-Twitter', '#n-Facebook', '#p-random'
].forEach(function(selector) {
$(selector).addClass('toggle');
});
});
/**
* Events.
*/
// Diff:
items.$diff.click(function(e) {
// Prevent default event:
e.preventDefault();
// Display state as failed: (if successfull, the Api request done() will "off" this event.)
new State('Failed to get diff!').failed().show();
});
// Toggle:
items.$toggle.click(function(e) {
e.preventDefault();
$('.toggle').toggle();
});
/** End. */
/*************************************************************************/
/**
* Add a link to Special:PrefiIndex to the sidebar.
*/
$( '#p-tb' ).find( 'ul' ).append( $( '<li>', {
id: 't-prefixindex',
html: $( '<a>', {
href: '/wiki/Special:PrefixIndex/' + conf.wgPageName,
text: 'Prefix index',
} ),
} ) );
/*************************************************************************/
});
/**
* Return.
*/
console.log(
'%cUser Common.js loaded! Last version from ' + LAST_LOG + '.',
'color: blue;'
);
return true;
/** End. */
})(window, window.jQuery, window.mediaWiki, window.console, (function(window, $) {
"use strict";
return function(t, fn) {
if(!fn && $.isFunction(t)) {
fn = t;
t = undefined;
}
return window.setTimeout(fn, t);
};
})(window, window.jQuery));
/** End. */
//</pre>