MediaWiki:Gadget-U2693.js
Jump to navigation
Jump to search
Note: You may have to bypass your browser’s cache to see the changes. In addition, after saving a sitewide CSS file such as MediaWiki:Common.css, it will take 5-10 minutes before the changes take effect, even if you clear your cache.
- Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
- Konqueror and Chrome: click Reload or press F5;
- Opera: clear the cache in Tools → Preferences;
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.
- The following documentation is located at MediaWiki:Gadget-U2693.js/documentation. [edit]
- This script is a part of the
U2693
gadget (edit definitions)- Description (edit): ⚓: add copyable anchor links to sections
- Useful links: subpage list • links • redirects
Explanation for the name: U+2693 is the code point for the anchor character, ⚓.
See also: Special:Gadgets.
/* jshint undef:true, latedef:true, shadow:true, boss:true, scripturl:true */
/* global mw, jQuery */
// <nowiki>
'use strict';
jQuery(document).ready(function () {
var curRevisionId = mw.config.get('wgCurRevisionId');
function createAnchorLink(label, href, wikilink, title) {
var span = document.createElement('span');
var link = document.createElement('a');
link.href = href;
link.addEventListener('click', function (ev) {
ev.preventDefault();
// IE
if (window.clipboardData && window.clipboardData.setData) {
window.clipboardData.setData('text', wikilink);
mw.util.jsMessage('Wikitext copied to the clipboard.');
return;
}
// XXX: there is a brand new shiny ClipboardEvent API, but I could not get it to work on my browser.
// plus, there is no graceful fallback if it fails to work. going back to good ol' prompt().
prompt('Hit Ctrl-C to copy this to your clipboard', wikilink);
}, false);
link.appendChild(document.createTextNode(label));
link.title = title;
span.appendChild(document.createTextNode('['));
span.appendChild(link);
span.appendChild(document.createTextNode(']'));
span.className = 'mw-editsection-like anchor-gadget-link';
return span;
}
// XXX: not ideal; it may over-unescape things, but it usually works as intended
function unescapeAnchor(anchor) {
anchor = anchor.replace(/_/g, ' ');
try {
return decodeURIComponent(anchor.replace(/\.([0-9A-F][0-9A-F])/g, '%$1'));
} catch (e) {
return anchor;
}
}
function forEachHeader(callback) {
var headers = document.getElementsByClassName('mw-headline');
for (var i = 0; i < headers.length; ++i) {
var links = headers[i].parentNode.getElementsByTagName('a');
var title = null;
for (var j = 0; j < links.length; ++j) {
try {
var u = new mw.Uri(links[j].href);
if ((u.host === location.host) && (u.path === mw.config.get('wgScript')) && (u.query.action === 'edit') && !u.query.redlink) {
title = new mw.Title(u.query.title);
}
} catch (e) {
/* screw it */
}
}
if (!title)
continue;
callback(headers[i], title);
}
}
function getRevInfo(oldid, callback) {
// XXX: of course I have it right on the page, but I cannot rely on it being in any particular format.
// hence wasting bandwidth on an API request.
mw.loader.using(['mediawiki.api', 'mediawiki.util'], function () {
var api = new mw.Api();
api.get({
'action': 'query',
'pageids': mw.config.get('wgArticleId'),
'prop': 'revisions',
'rvprop': 'user|timestamp',
'rvstartid': oldid,
'rvlimit': 1
}).then(function (result) {
var revobj = result.query.pages[mw.config.get('wgArticleId')].revisions[0];
callback(revobj);
});
});
}
function createUnsignedLink(revobj) {
var userpart = (mw.util.isIPv4Address(revobj.user) || mw.util.isIPv6Address(revobj.user) ? '{{unsigned-ip|' : '{{unsigned|') + revobj.user;
var datepart = '}}';
var m;
if (m = /^(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/.exec(revobj.timestamp)) {
var monthNames = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'
];
datepart = '|' + m[4] + ':' + m[5] + ', ' + m[3].replace(/^0+/, '') + ' ' + monthNames[parseInt(m[2], 10) - 1] + ' ' + m[1] + ' (UTC)}}';
}
return createAnchorLink('✎',
'javascript:void window.warranty',
userpart + datepart,
'{{unsigned}}'
);
}
if (mw.config.get('wgAction') !== 'view')
return;
mw.util.addCSS(".anchor-gadget-link { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; }");
if (mw.util.getParamValue('diff')) { // viewing a diff
var oldid, newid;
var ot = document.getElementById('mw-diff-otitle1');
var nt = document.getElementById('mw-diff-ntitle1');
if (ot) { ot = new mw.Uri(ot.getElementsByTagName('a')[0].href); oldid = ot.query.oldid; }
if (nt) { nt = new mw.Uri(nt.getElementsByTagName('a')[0].href); newid = nt.query.oldid; }
document.getElementById('firstHeading').appendChild(createAnchorLink('⚓',
mw.config.get('wgScript') + '?oldid=' + oldid + '&diff=' + newid,
'[[Special:Diff/' + oldid + '/' + newid + ']]',
'Link to this diff'
));
if ((document.getElementsByClassName('diffmulti').length === 0) && (mw.config.get('wgArticleId'))) {
getRevInfo(newid, function (revobj) {
document.getElementById('firstHeading').appendChild(createUnsignedLink(revobj));
});
}
} else if (mw.util.getParamValue('oldid') || curRevisionId) { // viewing an old page revision
var oldid = mw.util.getParamValue('oldid') || curRevisionId;
document.getElementById('firstHeading').appendChild(createAnchorLink('⚓',
mw.config.get('wgScript') + '?oldid=' + oldid,
'[[Special:Permalink/' + oldid + ']]',
'Link to this revision'
));
getRevInfo(oldid, function (revobj) {
document.getElementById('firstHeading').appendChild(createUnsignedLink(revobj));
});
}
if (mw.config.get('wgRevisionId') === curRevisionId
// 100 = appendix, 114 = citations
&& [0, 100, 114].indexOf(mw.config.get('wgNamespaceNumber')) === -1) {
forEachHeader(function(header, title) {
header.parentNode.appendChild(createAnchorLink('⚓',
mw.util.getUrl(title.getPrefixedDb()) + '#' + header.id,
'[[' + title.getPrefixedText() + '#' + unescapeAnchor(header.id) + ']]'
));
});
}
});
// </nowiki>