/// User:PerfektesChaos/js/keyboardMapper.js
// Establish keyboard mapper for particular pages and forms
/// 2018-08-24 [email protected]
// ResourceLoader: compatible;
// dependencies: user, jquery.textSelection
/// Fingerprint: #0#0#
/// @license GPL [//www.mediawiki.org/w/COPYING] (+GFDL, LGPL, CC-BY-SA)
/// <nowiki>
/* global window: false */
/* jshint forin: false,
bitwise:true, curly:true, eqeqeq:true, latedef:true,
laxbreak:true,
nocomma:true, strict:true, undef:true, unused:true */
( function ( mw, $ ) {
"use strict";
var Version = -1.7,
Signature = "keyboardMapper",
CNF = { bib: mw.libs,
divert: [ "meta", "alt", "ctrl", "shift" ],
doc: "w:en:PerfektesChaos/js/" + Signature,
env: null,
list: false,
listen: false,
live: false,
pad: { "+": "Add",
",": "Comma", // thousands sep
".": "Decimal", // decimal sep
"/": "Divide",
"=": "Equal",
"#": "Hash",
"*": "Multiply",
"-": "Subtract" },
plains: null,
scope: " edit ve ",
signature: false,
transform: null,
user: null,
ve: false
};
function factory() {
// Create transformation map from user defined map
// Uses:
// > CNF.user
// > CNF.divert
// > CNF.pad
// >< CNF.plains
// < CNF.transform
// 2017-07-12 [email protected]
var suitable = " number string function boolean ",
i, k, o, s, second, seek, t, v;
CNF.transform = null;
if ( typeof CNF.user === "object" ) {
for ( i = 0; i < CNF.user.length; i++ ) {
v = CNF.user[ i ];
if ( typeof v === "object"
&& v &&
typeof v.seek === "string"
&& v.seek ) {
s = typeof v.transfer;
if ( suitable.indexOf( s ) > 0
&& v.transfer ) {
if ( s === "number" ) {
if ( v.transfer < 32 ) {
t = false;
} else {
t = String.fromCharCode( v.transfer );
}
} else if ( v.transfer ) {
t = v.transfer;
}
if ( t ) {
second = "*";
seek = v.seek;
for ( k = 0; k < CNF.divert.length; k++ ) {
s = CNF.divert[ k ];
if ( typeof v[ s ] === "boolean"
&& v[ s ] ) {
second = s;
break; // for k
}
} // for k
if ( typeof v.num === "boolean" ) {
if ( v.num ) {
if ( typeof CNF.pad[ seek ] === "string" ) {
seek = CNF.pad[ seek ];
}
seek = "Numpad" + seek;
} else if ( seek.length === 1 ) {
if ( typeof CNF.pad[ seek ] === "string" ) {
seek = CNF.pad[ seek ];
} else {
k = seek.charCodeAt( 0 );
if ( k >= 48 && k <= 57 ) {
seek = "Digit" + seek;
}
}
}
}
o = { transfer: t };
if ( typeof v.leave === "boolean"
&& v.leave ) {
o.leave = true;
} else {
o.leave = false;
}
switch ( typeof v.say ) {
case "object":
if ( v.say &&
typeof v.say.en === "string" ) {
o.say = v.say;
}
break;
case "string":
if ( v.say ) {
o.say = v.say;
}
break;
} // switch typeof v.say
if ( ! CNF.transform ) {
CNF.transform = { };
}
if ( ! CNF.transform[ seek ] ) {
CNF.transform[ seek ] = { };
}
CNF.transform[ seek ][ second ] = o;
}
}
}
} // for i
}
if ( CNF.transform && ! CNF.plains ) {
CNF.plains = [ ];
CNF.plains.push( 2 * CNF.divert.length );
for ( k = CNF.divert.length; k >= 0; k-- ) {
s = CNF.divert[ k ];
CNF.plains.push( s );
CNF.plains.push( s + "Key" );
} // for k--
}
CNF.bib.transform = CNF.transform;
} // factory()
function fake( apply, assigned ) {
// Insert text
// Precondition:
// apply -- string, with text
// assigned -- object, with options
// Uses:
// ve
// > CNF.learn
// $.textSelection()
// 2017-09-01 [email protected]
var submit = "",
elt, i, k, params,
veFrag, veSurface, veSModel;
for ( i = 0; i < apply.length; i++ ) {
k = apply.charCodeAt( i );
if ( k === 10 || k >= 32 ) {
submit = submit + String.fromCharCode( k );
}
} // for i
if ( submit ) {
elt = window.document.activeElement;
if ( elt &&
typeof elt.tagName === "string" &&
( elt.tagName === "INPUT" ||
elt.tagName === "TEXTAREA" ) ) {
if ( assigned.leave ) {
params = { peri: "",
pre: submit,
replace: false };
} else {
params = { peri: submit,
replace: true };
}
if ( typeof assigned.learn === "boolean" ) {
params.selectPeri = assigned.learn;
}
$( elt ).textSelection( "encapsulateSelection", params );
} else if ( typeof window.ve === "object"
&& window.ve &&
typeof window.ve.init === "object"
&& window.ve.init &&
typeof window.ve.init.target === "object"
&& window.ve.init.target
&& window.ve.init.target.active ) {
veSurface = window.ve.init.target.getSurface();
veSModel = veSurface.getModel();
veFrag = veSModel.getFragment();
if ( ! veFrag.isNull() ) {
veFrag.insertContent( submit );
}
}
}
} // fake()
function features() {
// Load survey code
// Uses:
// > CNF.divert
// > CNF.pad
// > Signature
// < CNF.bib.divert
// < CNF.bib.reverse
// mw.loader.load()
// 2017-07-18 [email protected]
var maxage = 0,
s;
CNF.bib.divert = CNF.divert;
CNF.bib.reverse = { };
for ( s in CNF.pad ) {
CNF.bib.reverse[ CNF.pad[ s ] ] = s;
} // for s in CNF.pad
mw.loader.load( "https://en.wikipedia.org"
+ "/w/index.php?title="
+ "User:PerfektesChaos/js/"
+ Signature + "/config.js"
+ "&bcache=1&maxage=" + maxage
+ "&action=raw"
+ "&ctype=text/javascript" );
} // features()
function feed( event ) {
// Handler for keyboard event
// Precondition:
// event -- DOM event
// Uses:
// > CNF.plains
// > CNF.transform
// fake()
// 2017-07-12 [email protected]
var blocker, k, s, second, t;
if ( typeof CNF.transform[ event.code ] === "object" ) {
t = CNF.transform[ event.code ];
} else if ( typeof CNF.transform[ event.key ] === "object" ) {
t = CNF.transform[ event.key ];
}
if ( t ) {
second = "*";
for ( k = CNF.plains[ 0 ]; k > 0; k -= 2 ) {
if ( event[ CNF.plains[ k ] ] ) {
second = CNF.plains[ k - 1 ];
break; // for k--
}
} // for k--
if ( typeof t[ second ] === "object" ) {
blocker = [ "preventDefault",
"stopImmediatePropagation",
"stopPropagation" ];
for ( s in blocker ) {
if ( typeof event[ s ] === "function" ) {
event[ s ]();
}
} // for s in blocker
t = t[ second ];
if ( typeof t.transfer === "function" ) {
s = t.transfer( event );
} else {
s = t.transfer;
}
if ( typeof s === "string" && s ) {
fake( s, t );
}
}
}
return;
} // feed()
function feeder() {
// Enable or disable listener
// Uses:
// > CNF.user
// > CNF.transform
// >< CNF.live
// >< CNF.listen
// < CNF.bib.listen
// factory()
// (feed)
// 2017-07-12 [email protected]
var listen = CNF.live;
if ( CNF.live ) {
if ( CNF.user && ! CNF.transform ) {
factory();
}
if ( CNF.transform ) {
if ( ! CNF.listen ) {
$( function () {
window.addEventListener( "keydown", feed, true );
} );
}
} else {
listen = false;
}
} else if ( CNF.listen ) {
window.removeEventListener( "keydown", feed, true );
listen = false;
}
CNF.listen = listen;
CNF.bib.listen = listen;
} // feeder()
function fetch( assign ) {
// Retrieve user defined mapping
// Precondition:
// assign -- Array, with mapping objects
// Uses:
// > CNF.list
// < CNF.user
// < CNF.bib.user
// < CNF.transform
// < CNF.bib.transform
// factory()
// mw.hook()
// feeder()
// 2017-07-12 [email protected]
var user;
if ( assign &&
typeof assign === "object" &&
typeof assign.length === "number"
&& assign.length ) {
user = assign;
}
if ( user ) {
CNF.user = user;
} else {
CNF.user = null;
}
CNF.bib.user = user;
if ( CNF.list ) {
factory();
mw.hook( Signature + ".updated" ).fire( CNF.transform );
} else {
CNF.transform = null;
CNF.bib.transform = null;
feeder();
}
} // fetch()
function fire( actions ) {
// Start regular workflow in edit mode, if appropriate
// Precondition:
// actions -- string, with space separated list of actions
// Uses:
// > CNF.env
// > CNF.list
// >< CNF.reTrim
// < CNF.scope
// < CNF.live
// mw.hook()
// features()
// mw.loader.using()
// feeder()
// (feeder)
// 2017-07-19 [email protected]
var loved, s;
if ( typeof actions === "string" ) {
if ( typeof CNF.reTrim !== "object" ) {
CNF.reTrim = new RegExp( "^\\s*(\\S.*\\S|-)?\\s*$" );
}
s = actions.replace( CNF.reTrim, "$1" );
if ( s === "-" ) {
CNF.scope = false;
} else if ( s === "*" ) {
CNF.scope = true;
loved = true;
} else if ( s ) {
CNF.scope = " " + s + " ";
} else {
CNF.scope = false;
}
}
if ( CNF.scope ) {
if ( typeof CNF.scope === "string" ) {
if ( CNF.scope.indexOf( " edit " ) >= 0 ) {
CNF.scope = CNF.scope + " submit ";
}
loved = ( CNF.scope.indexOf( " ve " ) > 0 );
s = " " + CNF.env.wgAction + " ";
CNF.live = ( CNF.scope.indexOf( s ) >= 0 );
}
if ( loved && CNF.env.wgAction === "view" ) {
mw.hook( "ve.activationComplete" ).add(
function () {
CNF.live = true;
feeder();
}
);
mw.hook( "ve.deactivate" ).add(
function () {
feeder();
}
);
}
} else if ( CNF.list ) {
features();
}
if ( CNF.live ) {
mw.loader.using( [ "jquery.textSelection" ],
feeder );
} else {
feeder();
}
mw.hook( Signature + ".keymap" ).add( fetch );
} // fire()
function first() {
// Autorun on loading
// Uses:
// > Signature
// > Version
// < CNF.signature
// < CNF.env
// < CNF.scope
// < CNF.list
// < CNF.bib
// mw.loader.getState()
// mw.loader.state()
// mw.config.get()
// mw.loader.using()
// mw.hook()
// (fetch)
// (fire)
// 2018-08-24 [email protected]
var rls;
CNF.signature = "ext.gadget." + Signature;
if ( mw.loader.getState( CNF.signature ) !== "ready" ) {
rls = { };
rls[ CNF.signature ] = "ready";
mw.loader.state( rls );
CNF.env = mw.config.get( [ "wgAction",
"wgCanonicalSpecialPageName" ] );
CNF.bib[ Signature ] = { doc: "[[" + CNF.doc + "]]",
type: Signature,
vsn: Version };
CNF.bib = CNF.bib[ Signature ];
if ( CNF.env.wgCanonicalSpecialPageName === "Blankpage" ) {
CNF.env.wgTitle = mw.config.get( "wgTitle" );
if ( CNF.env.wgTitle.indexOf( "/" + Signature ) > 0 ) {
CNF.scope = false;
CNF.list = true;
}
}
if ( ! CNF.list ) {
mw.hook( Signature + ".actions" ).add( fire );
}
mw.loader.using( [ "user" ],
fire );
mw.hook( Signature + ".ready" ).fire( CNF.bib );
}
} // first()
first();
}( window.mediaWiki, window.jQuery ) );
/// EOF </nowiki> keyboardMapper/d.js