User:T12/scripts/SKLChanger.js: Difference between revisions
< User:T12
Jump to navigation
Jump to search
(++) |
m (Abhidevananda moved page User:Tito Dutta/scripts/SKLChanger.js to User:T12/scripts/SKLChanger.js: Automatically moved page while renaming the user "Tito Dutta" to "T12") |
(No difference)
|
Latest revision as of 11:37, 6 November 2022
/* Simple Keyboard Layout Changer v. 2013-11-17
* http://en.wikipedia.org/wiki/User:V111P/js/Simple_Keyboard_Layout_Changer
*
* With this script you can transform the characters you type in input boxes and textareas
* into different characters - for example, into characters from a different language.
* The script supports multiple groups of characters to convert to and you can switch
* between the different groups with a click on a link.
* Warning: Test the undo function (Ctrl-Z) in your browser to see if you like it.
* Undo doesn't work in Google Chrome 30 at all.
*
* CC0 Public Domain Dedication:
* http://creativecommons.org/publicdomain/zero/1.0/
*/
window.sKLChanger = (function ($) {
'use strict';
// US keyboard layout is used by default
var defaultCharsToConvert = '`-='
+ 'qwertyuiop[]\\'
+ 'asdfghjkl;\''
+ 'zxcvbnm,./'
// with shift
+ '~!@#$%^&*()_+'
+ 'QWERTYUIOP{}|'
+ 'ASDFGHJKL:"'
+ 'ZXCVBNM<>?';
var lang = mw.config.get('wgUserLanguage');
var msgs = {
indicatorLabelWhenTurnedOff_short: (lang == 'bg' ? 'Изкл.' : 'OFF'),
indicatorLabelWhenTurnedOff_long: (lang == 'bg'
? 'Превключвателят е изключен'
: 'The Keyboard Layout Changer is turned off'),
nonsupportedBrowserMsg_short: '<s>OFF</s>',
nonsupportedBrowserMsg_long: (lang == 'bg'
? 'Превключвателят на клавиатурни подредби няма да работи с вашия браузър'
: 'Simple Keyboard Layout Changer: Browser not supported')
};
var defaultIndicatorPos = {
nearElementSelector: '#editform', //'prepend' on #editform doesn't (always) work in IE
position: 'before' // 'before', 'after', 'prepend', 'append'
};
var inputBoxesSelector = 'textarea, input[type="text"], input[type="password"], '
+ 'input:not([type]), input[name="search"], input#searchInput';
// Some MediaWiki skins don't have type="text" attribute on their search input boxes.
// :not() not supported in older browsers
var inputBoxesDeselector = 'input#wpAntispam'; // #wpAntispam is a hidden input box in MediaWiki
var showLayoutHint; // if true, the string with the characters will be shown
// in the title attribute of the long-label indicator link
var longLabelClassName = 'sKL_longIndicator';
var keyboardLayouts = [];
var currLayoutN = -1; // none initially
var charsToConvertMap = {};
var keyboardLayoutIndicator = $([]); // create an empty jQuery object
var browser; // 'ok', 'ie', 'other'
// init() - auto called if a window.sKLChangerConfig object exists at the time of the loading of this file
function init(configObj) {
// jQuery is passing a function as an argument on $(init)
configObj = (typeof configObj == 'object' ? configObj : (window.sKLChangerConfig || {}));
var inputArea = $(inputBoxesSelector).not(inputBoxesDeselector)
.filter(':visible')[0]; // hidden elements cause an error in Firefox 6
if (!inputArea)
return;
setCharsToConvert(configObj.charsToConvert || defaultCharsToConvert);
showLayoutHint = (configObj.showLayoutHint === false ? false : true);
// add-and-replace the passed messages to the msgs object
$.extend(msgs, configObj.messages);
if (typeof configObj.offName == 'string')
msgs.indicatorLabelWhenTurnedOff_short = configObj.offName;
if (typeof configObj.offLabel == 'string')
msgs.indicatorLabelWhenTurnedOff_long = configObj.offLabel;
if ((window.wikEd && wikEd.useWikEd)
|| (inputArea && typeof inputArea.selectionStart != 'undefined')
)
browser = 'ok';
else if (document.selection && document.selection.createRange)
browser = 'ie'; // old IE & IE in Compatibility View mode
else {
browser = 'other'; // won't work
msgs.indicatorLabelWhenTurnedOff_long = msgs.nonsupportedBrowserMsg_long;
}
removeAllLayouts();
if (configObj.layouts)
$.each(configObj.layouts, function (i, val) {
addLayout(val.name, val.label, val.chars);
});
addIndicator(configObj.indicatorPosition);
var defaultLayout = configObj.defaultLayout;
if (typeof defaultLayout != 'undefined')
turnOn(defaultLayout);
}
function addIndicator(positionObj) {
var longIndicatorID = 'sKL_indicator2';
var label_short = msgs.indicatorLabelWhenTurnedOff_short;
var label_long = msgs.indicatorLabelWhenTurnedOff_long;
if (browser == 'other') {
label_short = msgs.nonsupportedBrowserMsg_short;
label_long = msgs.nonsupportedBrowserMsg_long;
}
keyboardLayoutIndicator.remove(); // remove any indicators already on the page
keyboardLayoutIndicator = $([]);
$('#sKLChangerPortlet').remove();
$('#'+longIndicatorID).remove();
// first add the indicator in the "personal bar"
mw.util.addPortletLink('p-personal', '#', '[' + label_short + ']',
'sKLChangerPortlet', label_long);
var indicatorLink = $('#sKLChangerPortlet').find('a');
keyboardLayoutIndicator = keyboardLayoutIndicator.add(indicatorLink);
// then add the indicator/switch near the specified element, if it exists
var nearElementSelector = defaultIndicatorPos.nearElementSelector;
var position = defaultIndicatorPos.position;
if (positionObj
&& typeof positionObj.nearElementSelector == 'string'
&& typeof positionObj.position == 'string'
&& $(positionObj.nearElementSelector).length != 0
) {
nearElementSelector = positionObj.nearElementSelector;
position = positionObj.position;
}
if ($(nearElementSelector).length > 0) {
var indicator2 = $('<a/>', {
href: '#',
id: longIndicatorID,
'class': longLabelClassName,
text: '[' + label_long + ']'
});
switch (position) {
case 'before' : indicator2.insertBefore(nearElementSelector); break;
case 'after' : indicator2.insertAfter(nearElementSelector); break;
case 'prepend': indicator2.prependTo(nearElementSelector); break;
case 'append' : default: indicator2.appendTo(nearElementSelector);
}
keyboardLayoutIndicator = keyboardLayoutIndicator.add(indicator2);
}
// finally, attach the event handler to all indicators
keyboardLayoutIndicator.bind('click', function(event) {
event.preventDefault();
nextLayout();
});
}
function removeLayout(layoutToRemove) {
if (typeof layoutToRemove == 'string') {
$.each(keyboardLayouts, function(indexInArray, layout) {
if (layout.name == layoutToRemove) {
turnOff();
keyboardLayouts.splice(indexInArray, 1);
return false;
}
});
}
else if (typeof layoutToRemove == 'number') {
turnOff();
keyboardLayouts.splice(layoutToRemove, 1);
}
}
function removeAllLayouts() {
turnOff();
keyboardLayouts = [];
}
function getAllLayouts() {
return keyboardLayouts;
}
function addLayout(name, label, layoutStr, position) {
if (!name || !label || !layoutStr)
return;
if (typeof position == 'undefined'
|| position >= keyboardLayouts.length
|| position < 0
)
position = keyboardLayouts.length;
var layout = {name: name, label: label, layoutStr: layoutStr};
keyboardLayouts.splice(position, 0, layout);
if (position <= currLayoutN)
currLayoutN++; // keep current layout
}
function setCharsToConvert(charStr) {
charStr = charStr || '';
// each character code of the chars in charStr is converted
// to a property name in charsToConvertMap with the value being
// the position of the char in charStr.
for (var i = 0; i < charStr.length; i++) {
charsToConvertMap[charStr.charCodeAt(i)] = i;
}
}
function error(msg) {
if (console && console.error)
console.error('Simple Keyboard Layout Changer: ' + msg);
}
function layoutNameToIndex(layoutName) {
if (typeof layoutName != 'string') {
error('layoutNameToIndex: layout-name string expected, got: ' + layoutName);
return -1;
}
for (var i = 0; i < keyboardLayouts.length; i++)
if (keyboardLayouts[i].name === layoutName)
return i;
error('layoutNameToIndex: Can\'t find layout with name "' + layoutName + '"');
return -1;
}
function turnOn(layoutName) {
if (keyboardLayouts.length == 0) {
error('No keyboard layouts defined.');
return;
}
if (typeof layoutName == 'undefined')
currLayoutN = 0;
else {
currLayoutN = layoutNameToIndex(layoutName);
if (currLayoutN == -1) {
turnOff();
return;
}
}
$(inputBoxesSelector).on('keypress.sKLChanger', keyPressed);
if (window.wikEd) {
wikEd.AddEventListener(wikEd.frameDocument, 'keypress', keyPressed, true);
}
setIndicatorLabel();
}
function turnOff() {
$(inputBoxesSelector).off('keypress.sKLChanger');
currLayoutN = -1;
setIndicatorLabel();
if (window.wikEd) {
wikEd.RemoveEventListener(wikEd.frameDocument, 'keypress', keyPressed, true);
}
}
function nextLayout() {
if (currLayoutN + 1 == keyboardLayouts.length)
turnOff();
else
if (currLayoutN == -1)
turnOn();
else {
currLayoutN++;
setIndicatorLabel();
}
}
function setIndicatorLabel() {
setTimeout(safeSetIndicatorLabel, 1);
}
function safeSetIndicatorLabel() {
var layoutName, layoutLabel;
var longIndicatorTitleAttr = (currLayoutN > -1 && showLayoutHint
? keyboardLayouts[currLayoutN].layoutStr
: '');
if (currLayoutN > -1) {
layoutName = keyboardLayouts[currLayoutN].name;
layoutLabel = keyboardLayouts[currLayoutN].label;
}
else {
layoutName = msgs.indicatorLabelWhenTurnedOff_short;
layoutLabel = msgs.indicatorLabelWhenTurnedOff_long;
}
keyboardLayoutIndicator.each(function(index, indicatorEl) {
var indicator = $(indicatorEl);
var txt, title;
if (indicator.hasClass(longLabelClassName)) {
txt = layoutLabel;
title = longIndicatorTitleAttr;
}
else {
txt = layoutName;
title = layoutLabel;
}
setTimeout(function () {
indicator.text('[' + txt + ']').attr('title', title);
}, 1);
});
}
function keyPressed(event) {
var charCode = event.charCode || event.keyCode;
if (event.charCode === 0)
charCode = 0; // Firefox non-printable
if (charCode == 0 || event.ctrlKey || event.altKey || event.metaKey)
return true;
switch (charCode) {
case 0: //Non-printable
case 13: //Enter
case 27: //Esc (for IE)
case 32: //Space
return true;
}
var currLayoutStr = keyboardLayouts[currLayoutN].layoutStr;
var index = charsToConvertMap[charCode];
if (typeof index == 'undefined')
return true;
var charToReplaceWith = currLayoutStr.charAt(index);
if (charToReplaceWith) {
event.preventDefault();
var inputBox = this;
setTimeout(function () { // if the textarea value is changed directly, IE clears its undo history
insertStr(charToReplaceWith, inputBox);
}, 1);
}
}
function insertStr(str, inputBox) {
if (window.wikEd && wikEd.useWikEd && inputBox == wikEd.frameDocument) {
wikEd.FrameExecCommand('inserthtml',
str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'));
}
else if (browser == 'ok') {
var startPos = inputBox.selectionStart;
var endPos = inputBox.selectionEnd;
var scrollTop = inputBox.scrollTop;
var pos = startPos + str.length;
inputBox.value = inputBox.value.substring(0, startPos)
+ str
+ inputBox.value.substring(endPos, inputBox.value.length);
inputBox.focus();
inputBox.setSelectionRange(pos, pos);
inputBox.scrollTop = scrollTop;
}
else if (browser == 'ie') {
var range = document.selection.createRange();
if (range.text)
document.selection.clear();
range.text = str;
}
}
if (window.sKLChangerConfig) {
if (document.readyState == 'complete' || document.readyState == 'interactive')
init();
else
$(init); // but $() doesn't work after errors
}
return {
init: init,
removeLayout: removeLayout,
removeAllLayouts: removeAllLayouts,
getAllLayouts: getAllLayouts,
addLayout: addLayout,
setCharsToConvert: setCharsToConvert,
turnOn: turnOn,
turnOff: turnOff,
nextLayout: nextLayout,
// variables / constants:
defaultCharsToConvert: defaultCharsToConvert
};
})(jQuery);