470
edits
No edit summary |
No edit summary |
||
Line 11: | Line 11: | ||
$("#content").removeAttr("onmousedown"); | $("#content").removeAttr("onmousedown"); | ||
$("#content").removeAttr("onselectstart"); | $("#content").removeAttr("onselectstart"); | ||
mw.loader.load( '/index.php?title=MediaWiki:OCR.js&action=raw&ctype=text/javascript'); | |||
} | } | ||
}); | }); | ||
Line 99: | Line 99: | ||
} | } | ||
}); | }); | ||
/** | |||
* Convert numbers between numeral systems. | |||
* | |||
* Dependencies: jquery.cookie, mediawiki.util, mediawiki.user | |||
* Source: https://www.mediawiki.org/wiki/MediaWiki:Gadget-Numerakri.js | |||
* Revision: 2019-01-11 | |||
* | |||
* @copyright 2012 Daniel Friesen | |||
* @copyright 2012 Siddhartha Ghai | |||
* @copyright 2014 Bhawani Gautam | |||
* @copyright 2012-2018 Timo Tijhof | |||
* @license <https://opensource.org/licenses/MIT> | |||
*/ | |||
/*jshint browser:true, unused:true, forin:false */ | |||
/*global $, mw */ | |||
(function () { | |||
'use strict'; | |||
var msgs = { | |||
'option-default': { | |||
en: 'Default', | |||
bho: 'डिफ़ॉल्ट', | |||
gu: 'ડિફોલ્ટ', | |||
hi: 'डिफ़ॉल्ट', | |||
ne: 'डिफल्ट', | |||
pa: 'ਅਸਲ ਦਿੱਖ', | |||
sa: 'उत्सर्गः' | |||
}, | |||
'option-arabic': { | |||
en: '1 2 3' | |||
}, | |||
'option-devanagari': { | |||
en: 'Devanagari', | |||
bho: '१२३', | |||
hi: '१२३', | |||
ne: '१२३', | |||
sa: '१२३' | |||
}, | |||
'option-gujarati': { | |||
en: '૧ ૨ ૩', | |||
gu: '૧ ૨ ૩' | |||
}, | |||
'option-gurmukhi': { | |||
en: 'Gurmukhi', | |||
pa: '੧੨੩' | |||
}, | |||
'label-url': { | |||
en: '//www.mediawiki.org/wiki/MediaWiki_talk:Gadget-Numerakri.js', | |||
gu: '//gu.wikipedia.org/wiki/વિકિસૂક્તિઃઅંક_પરિવર્તક', | |||
hi: '//hi.wikipedia.org/wiki/विकिपीडिया:अंक_परिवर्तक', | |||
ne: '//ne.wikipedia.org/wiki/विकिपीडिया:अंक_परिवर्तक', | |||
pa: '//pa.wikipedia.org/wiki/ਵਿਕੀਪੀਡੀਆ:ਅੰਕ ਬਦਲੋ', | |||
sa: '//sa.wikipedia.org/wiki/विकिपीडिया:अङ्कपरिवर्तकम्' | |||
}, | |||
'label-text': { | |||
en: 'Convert numerals', | |||
bho: 'अंक बदलाव', | |||
gu: 'અંક પરિવર્તક', | |||
hi: 'अंक परिवर्तन', | |||
ne: 'अंक परिवर्तन', | |||
pa: 'ਅੰਕ ਬਦਲੋ', | |||
sa: 'अङ्कपरिवर्तकम्' | |||
}, | |||
'label-tooltip': { | |||
en: 'Convert between Arabic and Devanagari numerals', | |||
bho: 'नागरी आ अरबी अंकों में अदला-बदली करीं', | |||
gu: 'ગુજરાતી અને અંગ્રેજી અંકોમાં પરિવર્તન કરો', | |||
hi: 'नागरी और अरबी अंकों में परिवर्तन करें', | |||
ne: 'देवनागरी र अरबी अंकहरूमा परिवर्तन गर्नुहोस्', | |||
pa: 'ਅੰਕਾਂ ਨੂ ਗੁਰਮੁਖੀ ਤੇ ਅਰਬੀ ਵਿਚ ਬਦਲੇਂ', | |||
sa: 'देवनागरी-अरबी-अङ्कयोः चयनं करोतु' | |||
} | |||
}, | |||
maps = { | |||
arabic: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], | |||
devanagari: ['०', '१', '२', '३', '४', '५', '६', '७', '८', '९'], | |||
gujarati: ['૦', '૧', '૨', '૩', '૪', '૫', '૬', '૭', '૮', '૯'], | |||
gurmukhi: ['੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯'] | |||
}, | |||
availableMaps, | |||
currentType = 'default', | |||
matchers = {}, | |||
walker, | |||
styleTag; | |||
function isValidType(type) { | |||
return type === 'default' || availableMaps.indexOf(type) !== -1; | |||
} | |||
/** @return {Object.<RegExp>} */ | |||
function getMatchers(targetType) { | |||
var rChars; | |||
if (!matchers[targetType]) { | |||
rChars = { 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [] }; | |||
$.each(maps, function (type, map) { | |||
if (type !== targetType) { | |||
for (var i = 0; i <= 9; i++) { | |||
rChars[i].push(map[i]); | |||
} | |||
} | |||
}); | |||
$.each(rChars, function (num, chars) { | |||
rChars[num] = new RegExp('(' + chars.map(mw.RegExp.escape).join('|') + ')', 'g'); | |||
}); | |||
matchers[targetType] = rChars; | |||
} | |||
return matchers[targetType]; | |||
} | |||
function msg(key) { | |||
return msgs[key][mw.config.get('wgUserLanguage')] || msgs[key].en; | |||
} | |||
/** | |||
* @param {HTMLElement|TextNode} node | |||
* @return {number} NodeFilter.FILTER_* constant | |||
*/ | |||
function filterNode(node) { | |||
if (node.nodeType === Node.TEXT_NODE) { | |||
return NodeFilter.FILTER_ACCEPT; | |||
} | |||
var n = node.nodeName && node.nodeName.toLowerCase(); | |||
if (n === 'input' || n === 'textarea' || $(node).hasClass('mw-numerakri-skip')) { | |||
// Skip this element and skip its children | |||
return NodeFilter.FILTER_REJECT; | |||
} | |||
// Skip this element, but check its children | |||
return NodeFilter.FILTER_SKIP; | |||
} | |||
/** | |||
* @param {TextNode} node | |||
*/ | |||
function handleTextNode(node) { | |||
var original = node.nodeValue, | |||
changed = original, | |||
matchers = getMatchers(currentType), | |||
i = 0; | |||
for (; i <= 9; i++) { | |||
changed = changed.replace(matchers[i], maps[currentType][i]); | |||
} | |||
if (original !== changed) { | |||
node.nodeValue = changed; | |||
} | |||
} | |||
// https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw-method-requestIdleCallback | |||
function idleWalker(deadline) { | |||
var el; | |||
if (!walker) { | |||
return; | |||
} | |||
while (deadline.timeRemaining() > 0) { | |||
el = walker.nextNode(); | |||
if (!el) { | |||
// Reached the end | |||
walker = null; | |||
return; | |||
} | |||
handleTextNode(el); | |||
} | |||
// The user may interact with the page. We pause so the browser can process | |||
// interaction. The text handler will continue after that. | |||
if (walker) { | |||
mw.requestIdleCallback(idleWalker); | |||
} | |||
} | |||
/** | |||
* Save a browser cookie for 30 days, or remove it. | |||
* @param {string|null} value | |||
*/ | |||
function saveType(value) { | |||
mw.requestIdleCallback(function () { | |||
$.cookie('mw-numerakri-type', value, { expires: 30, path: '/' }); | |||
}); | |||
} | |||
/** | |||
* @return {string} | |||
*/ | |||
function getStoredType() { | |||
var value = $.cookie('mw-numerakri-type'); | |||
if (value !== null && !isValidType(value)) { | |||
// Remove bad cookie | |||
saveType(null); | |||
value = null; | |||
} | |||
return value || 'default'; | |||
} | |||
function startPageConversion() { | |||
if (styleTag) { | |||
// Undo style for a previously selected type | |||
$(styleTag).remove(); | |||
styleTag = null; | |||
} | |||
if (currentType === 'default') { | |||
// Don't change the page | |||
return; | |||
} | |||
if (currentType === 'arabic') { | |||
styleTag = mw.loader.addStyleTag('.mw-parser-output ol, ol.references, li.references { list-style-type: decimal; }'); | |||
} else if (currentType === 'devanagari') { | |||
styleTag = mw.loader.addStyleTag('.mw-parser-output ol, ol.references, li.references { list-style-type: devanagari; }'); | |||
} | |||
// If a walker is already active, replace it. | |||
// If no walker is active yet, start it. | |||
if (!walker) { | |||
mw.requestIdleCallback(idleWalker); | |||
} | |||
walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, filterNode, false); | |||
} | |||
/** @return {HTMLElement} */ | |||
function createSelector() { | |||
var $select = $('<select>').addClass('mw-numerakri-skip').append( | |||
$('<option>').val('default').text(msg('option-default')) | |||
); | |||
availableMaps.forEach(function (type) { | |||
$select.append($('<option>').val(type).text(msg('option-' + type))); | |||
}); | |||
$select.val(currentType); | |||
$select.on('change', function () { | |||
currentType = this.value; | |||
startPageConversion(); | |||
saveType(currentType); | |||
}); | |||
return $select[0]; | |||
} | |||
function init() { | |||
var potlet, menu; | |||
// Decide which types to show | |||
availableMaps = ['gujarati', 'arabic']; | |||
// Decide selected type | |||
currentType = getStoredType(); | |||
startPageConversion(); | |||
potlet = mw.util.addPortletLink( | |||
'p-personal', | |||
msg('label-url'), | |||
msg('label-text'), | |||
'pt-numconvert', | |||
msg('label-tooltip'), | |||
null, | |||
mw.user.isAnon() ? '#pt-createaccount' : '#pt-userpage' | |||
); | |||
menu = $('<div>').addClass('mw-numerakri-menu').append(createSelector())[0]; | |||
if(potlet) { | |||
potlet.appendChild(menu); | |||
} | |||
} | |||
$(function () { | |||
mw.requestIdleCallback(init); | |||
}); | |||
}()); |