diff --git a/web/source/keymanweb.ts b/web/source/keymanweb.ts index 01d7c769aa..5e10889dd0 100644 --- a/web/source/keymanweb.ts +++ b/web/source/keymanweb.ts @@ -1958,21 +1958,6 @@ if(!window['keyman']['initialized']) { } return e; } - - /** - * Function _push - * Scope Private - * @param {Array} Parray Array - * @param {*} Pval Value to be pushed or appended to array - * @return {Array} Returns extended array - * Description Push (if possible) or append a value to an array - */ - keymanweb._push = function(Parray, Pval) - { - if(Parray.push) Parray.push(Pval); - else Parray=Parray.concat(Pval); - return Parray; - } /** * Function attachToControl diff --git a/web/source/kmwapi.ts b/web/source/kmwapi.ts index b69737c2cc..cffce136ce 100644 --- a/web/source/kmwapi.ts +++ b/web/source/kmwapi.ts @@ -1,6 +1,7 @@ /// /// /// +/// // Allows proper minification handling. /// @@ -17,6 +18,11 @@ // kmwbase.ts goog.exportProperty(keyman, "build", keyman); // Only works on individual instances. goog.exportSymbol("KeymanBase.prototype.isFontAvailable", KeymanBase.prototype.isFontAvailable); +goog.exportSymbol("KeymanBase.prototype.GetLastActiveElement", KeymanBase.prototype.getLastActiveElement); +goog.exportSymbol("KeymanBase.prototype.FocusLastActiveElement", KeymanBase.prototype.focusLastActiveElement); +goog.exportSymbol("KeymanBase.prototype.HideHelp", KeymanBase.prototype.hideHelp); +goog.exportSymbol("KeymanBase.prototype.ShowHelp", KeymanBase.prototype.showHelp); +goog.exportSymbol("KeymanBase.prototype.ShowPinnedHelp", KeymanBase.prototype.showPinnedHelp); // Util.ts @@ -45,4 +51,41 @@ goog.exportSymbol("Util.prototype.saveCookie", Util.prototype.saveCookie); goog.exportSymbol("Util.prototype.toNumber", Util.prototype.toNumber); goog.exportSymbol("Util.prototype.toFloat", Util.prototype.toFloat); goog.exportSymbol("Util.prototype.toNzString", Util.prototype.nzString); -goog.exportSymbol("Util.prototype.alert", Util.prototype.alert); \ No newline at end of file +goog.exportSymbol("Util.prototype.alert", Util.prototype.alert); + +// kmwcallback.ts +(function() { + var exportKBCallback = function(miniName: string, longName: string, func:() => any) { + goog.exportSymbol("KeyboardInterface.prototype." + longName, func); + goog.exportSymbol("KeyboardInterface.prototype." + miniName, func); + } + + var exportKBCallbackWithArgs = function(miniName: string, longName: string, func:(...args: any[]) => any) { + goog.exportSymbol("KeyboardInterface.prototype." + longName, func); + goog.exportSymbol("KeyboardInterface.prototype." + miniName, func); + } + + exportKBCallback('KSF', 'saveFocus', KeyboardInterface.prototype.saveFocus); + exportKBCallback('KBR', 'beepReset', KeyboardInterface.prototype.beepReset); + + exportKBCallbackWithArgs('KT', 'insertText', KeyboardInterface.prototype.insertText); + exportKBCallbackWithArgs('KR', 'registerKeyboard', KeyboardInterface.prototype.registerKeyboard); + exportKBCallbackWithArgs('KRS', 'registerStub', KeyboardInterface.prototype.registerStub); + exportKBCallbackWithArgs('KC', 'context', KeyboardInterface.prototype.context); + exportKBCallbackWithArgs('KN', 'nul', KeyboardInterface.prototype.nul); + exportKBCallbackWithArgs('KCM', 'contextMatch', KeyboardInterface.prototype.contextMatch); + exportKBCallbackWithArgs('KIK', 'isKeypress', KeyboardInterface.prototype.isKeypress); + exportKBCallbackWithArgs('KKM', 'keyMatch', KeyboardInterface.prototype.keyMatch); + exportKBCallbackWithArgs('KSM', 'stateMatch', KeyboardInterface.prototype.stateMatch); + exportKBCallbackWithArgs('KKI', 'keyInformation', KeyboardInterface.prototype.keyInformation); + exportKBCallbackWithArgs('KDM', 'deadkeyMatch', KeyboardInterface.prototype.deadkeyMatch); + exportKBCallbackWithArgs('KB', 'beep', KeyboardInterface.prototype.beep); + exportKBCallbackWithArgs('KA', 'any', KeyboardInterface.prototype.any); + exportKBCallbackWithArgs('KO', 'output', KeyboardInterface.prototype.output); + exportKBCallbackWithArgs('KDO', 'deadkeyOutput', KeyboardInterface.prototype.deadkeyOutput); + exportKBCallbackWithArgs('KIO', 'indexOutput', KeyboardInterface.prototype.indexOutput); + exportKBCallbackWithArgs('KIFS', 'ifStore', KeyboardInterface.prototype.ifStore); + exportKBCallbackWithArgs('KSETS', 'setStore', KeyboardInterface.prototype.setStore); + exportKBCallbackWithArgs('KLOAD', 'loadStore', KeyboardInterface.prototype.loadStore); + exportKBCallbackWithArgs('KSAVE', 'saveStore', KeyboardInterface.prototype.saveStore); +}()); \ No newline at end of file diff --git a/web/source/kmwbase.ts b/web/source/kmwbase.ts index d4ae995e05..8028f6dd25 100644 --- a/web/source/kmwbase.ts +++ b/web/source/kmwbase.ts @@ -2,6 +2,7 @@ /// // Includes KMW-added property declaration extensions for HTML elements. /// +/// /*** KeymanWeb 10.0 @@ -9,6 +10,8 @@ ***/ declare var keyman: any +declare var KeymanWeb: any + var keyman = window['keyman'] || {}; window['keyman'] = keyman; // To preserve the name _here_ in case of minification. @@ -43,7 +46,6 @@ class KeymanBase { deferredStubs = []; // Array of pending keyboard stubs from addKeyboard(), to register after initialization deferredKRS = []; // Array of pending keyboard stubs from KRS, to register afterf initialization deferredKR = []; // Array of pending keyboards, to be installed at end of initialization - waiting = null; // Element displayed during keyboard load time warned = false; // Warning flag (to prevent multiple warnings) baseFont = 'sans-serif'; // Default font for mapped input elements appliedFont = ''; // Chain of fonts to be applied to mapped input elements @@ -74,6 +76,7 @@ class KeymanBase { util: Util; osk: any; ui: any; + interface: KeyboardInterface; // Defines option-tracking object as a string map. options: { [name: string]: string; } = { @@ -85,24 +88,13 @@ class KeymanBase { 'ui':null };; - // Stub functions (defined later in code only if required) - setDefaultDeviceOptions(opt){} - getStyleSheetPath(s){return s;} - getKeyboardPath(f, p){return f;} - KC_(n, ln, Pelem){return '';} - handleRotationEvents(){} - alignInputs(b){} - - setInitialized(val: number) { - this.initialized = this['initialized'] = val; - } - - refreshElementContent = null; - // ------------- constructor() { this.util = this['util'] = new Util(this); + window['KeymanWeb'] = this.interface = this['interface'] = new KeyboardInterface(this); + + this.osk = {ready:false}; // Temporary. // Load properties from their static variants. this.__BUILD__ = KeymanBase.__BUILD__; @@ -128,6 +120,62 @@ class KeymanBase { isFontAvailable(fName: string): boolean { return this.util.checkFont({'family':fName}); } + + /** + * Legacy entry points (non-standard names)- included only to allow existing IME keyboards to continue to be used + */ + getLastActiveElement(): HTMLElement { + return this._LastActiveElement; + } + + focusLastActiveElement(): void { + (this)._FocusLastActiveElement(); + } + + //The following entry points are defined but should not normally be used in a keyboard, as OSK display is no longer determined by the keyboard + hideHelp(): void { + this.osk._Hide(true); + } + + showHelp(Px: number, Py: number): void { + this.osk._Show(Px,Py); + } + + showPinnedHelp(): void { + this.osk.userPositioned=true; + this.osk._Show(-1,-1); + } + + // Stub functions (defined later in code only if required) + setDefaultDeviceOptions(opt){} + getStyleSheetPath(s){return s;} + getKeyboardPath(f, p){return f;} + KC_(n, ln, Pelem){return '';} + handleRotationEvents(){} + alignInputs(b){} + + /** + * Function _push + * Scope Private + * @param {Array} Parray Array + * @param {*} Pval Value to be pushed or appended to array + * @return {Array} Returns extended array + * Description Push (if possible) or append a value to an array + */ + _push(Parray: T[], Pval: T) { + if(Parray.push) { + Parray.push(Pval); + } else { + Parray=Parray.concat(Pval); + } + return Parray; + } + + setInitialized(val: number) { + this.initialized = this['initialized'] = val; + } + + refreshElementContent = null; } /** @@ -158,28 +206,19 @@ KeymanBase.__BUILD__ = keyman.__BUILD__; if(!window['keyman']['loaded']) { (function() { + /* We only recreate the 'keyman' object if it's not been loaded. + * As this is the base object, not creating it prevents a KMW system reset. + */ + var keymanweb = window['keyman'] = new KeymanBase(); // Define public OSK, user interface and utility function objects var osk: any; - osk = keymanweb['osk'] = {ready:false}; + osk = keymanweb['osk']; var ui: any; ui = keymanweb['ui'] = {}; - var kbdInterface = keymanweb['interface'] = { - // Cross-reference with /windows/src/global/inc/Compiler.h - these are the Developer codes for the respective system stores. - // They're named here identically to their use in that header file. - TSS_LAYER: 33, - TSS_PLATFORM: 31, - - _AnyIndices: [], // AnyIndex - array of any/index match indices - _BeepObjects: [], // BeepObjects - maintains a list of active 'beep' visual feedback elements - _BeepTimeout: 0, // BeepTimeout - a flag indicating if there is an active 'beep'. - // Set to 1 if there is an active 'beep', otherwise leave as '0'. - _DeadKeys: [] // DeadKeys - array of matched deadkeys - }; - osk.highlightSubKeys = function(k,x,y){} osk.createKeyTip = function(){} osk.optionKey = function(e,keyName,keyDown){} diff --git a/web/source/kmwcallback.ts b/web/source/kmwcallback.ts index 78e70d6f75..affc447446 100644 --- a/web/source/kmwcallback.ts +++ b/web/source/kmwcallback.ts @@ -1,53 +1,117 @@ /// // Includes KMW-added property declaration extensions for HTML elements. /// // Includes type definitions for basic KMW types. +/// /*** KeymanWeb 10.0 Copyright 2017 SIL International ***/ +/** + * Cache of context storing and retrieving return values from KC + * Must be reset prior to each keystroke and after any text changes + * MCD 3/1/14 + **/ +class CachedContext { + _cache: string[][] = []; + + reset(): void { + this._cache = []; + } + + get(n: number, ln: number): string { + // return null; // uncomment this line to disable context caching + if(typeof this._cache[n] == 'undefined') { + return null; + } else if(typeof this._cache[n][ln] == 'undefined') { + return null; + } + return this._cache[n][ln]; + } + + set(n: number, ln: number, val: string): void { + if(typeof this._cache[n] == 'undefined') { + this._cache[n] = []; + } + this._cache[n][ln] = val; + } +}; + +// Defines the base Deadkey-tracking object. +class Deadkey { + p: number; // Position of deadkey + d: number; // Numerical id of the deadkey + matched: number; + + constructor(pos: number, id: number) { + this.p = pos; + this.d = id; + } + + match(p: number, d: number): boolean { + var result:boolean = (this.p == p && this.d == d); + this.matched = result ? 1 : 0; + + return result; + } + + set(): void { + this.matched = 1; + } + + reset(): void { + this.matched = 0; + } +} + +class BeepData { + e: HTMLElement; + c: string; + + constructor(e: HTMLElement) { + this.e = e; + this.c = e.style.backgroundColor; + } + + reset(): void { + this.e.style.backgroundColor = this.c; + } +} + // If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the // KMW system, so we use the fact that 'initialized' is only 1 / true after all scripts are loaded for the initial // load of KMW. -if(!window['keyman']['initialized']) { - (function() { - // Declare KeymanWeb and util objects - var keymanweb=window['keyman'], kbdInterface=window['KeymanWeb']=keymanweb['interface'], KeymanWeb=kbdInterface, - util=keymanweb['util'], osk=keymanweb['osk'],device=util.device,dbg=keymanweb.debug; //osk defined here, build 350 +//if(!window['keyman']['initialized']) { +// (function() { - class Deadkey { - p: number; // Position of deadkey - d: number; // Numerical id of the deadkey - matched: number; + class KeyboardInterface { + keymanweb: KeymanBase; + cachedContext: CachedContext = new CachedContext(); - constructor(pos: number, id: number) { - this.p = pos; - this.d = id; - } + TSS_LAYER: number = 33; + TSS_PLATFORM: number = 31; - match(p: number, d: number): boolean { - var result:boolean = (this.p == p && this.d == d); - this.matched = result ? 1 : 0; + _AnyIndices = []; // AnyIndex - array of any/index match indices + _BeepObjects: BeepData[] = []; // BeepObjects - maintains a list of active 'beep' visual feedback elements + _BeepTimeout: number = 0; // BeepTimeout - a flag indicating if there is an active 'beep'. + // Set to 1 if there is an active 'beep', otherwise leave as '0'. + _DeadKeys: Deadkey[] = []; // DeadKeys - array of matched deadkeys - return result; - } - - set(): void { - this.matched = 1; - } - - reset(): void { - this.matched = 0; - } + constructor(kmw: KeymanBase) { + this.keymanweb = kmw; } + // // Declare KeymanWeb and util objects + // var keymanweb=window['keyman'], kbdInterface=window['KeymanWeb']=keymanweb['interface'], KeymanWeb=kbdInterface, + // util=keymanweb['util'], osk=keymanweb['osk'],device=util.device,dbg=keymanweb.debug; //osk defined here, build 350 + /** * Function KSF * Scope Public * Description Save keyboard focus */ - KeymanWeb['KSF'] = kbdInterface['saveFocus'] = kbdInterface.saveFocus = function(): void { - keymanweb._IgnoreNextSelChange = 1; + saveFocus(): void { + this.keymanweb._IgnoreNextSelChange = 1; } /** @@ -58,19 +122,19 @@ if(!window['keyman']['initialized']) { * @return {boolean} true if inserted * Description Insert text into active control */ - KeymanWeb['KT'] = kbdInterface['insertText'] = kbdInterface.insertText = function(Ptext: string, PdeadKey:number): boolean { - kbdInterface.resetContextCache(); + insertText(Ptext: string, PdeadKey:number): boolean { + this.resetContextCache(); //_DebugEnter('InsertText'); - var Lelem = keymanweb._LastActiveElement, Ls, Le, Lkc, Lsel, Lv=false; + var Lelem = this.keymanweb._LastActiveElement, Ls, Le, Lkc, Lsel, Lv=false; if(Lelem != null) { Ls=Lelem._KeymanWebSelectionStart; Le=Lelem._KeymanWebSelectionEnd; - Lsel=keymanweb._Selection; + Lsel=this.keymanweb._Selection; - keymanweb._IsActivatingKeymanWebUI = 1; - keymanweb._IgnoreNextSelChange = 100; - keymanweb._FocusLastActiveElement(); - if(keymanweb._IsMozillaEditableIframe(Lelem,0)) { + this.keymanweb._IsActivatingKeymanWebUI = 1; + this.keymanweb._IgnoreNextSelChange = 100; + (this.keymanweb)._FocusLastActiveElement(); + if((this.keymanweb)._IsMozillaEditableIframe(Lelem,0)) { Lelem = Lelem.documentElement; // I3363 (Build 301) } if(document.selection && Lsel != null) { @@ -78,12 +142,12 @@ if(!window['keyman']['initialized']) { } Lelem._KeymanWebSelectionStart=Ls; Lelem._KeymanWebSelectionEnd=Le; - keymanweb._IgnoreNextSelChange = 0; + this.keymanweb._IgnoreNextSelChange = 0; if(Ptext!=null) { - kbdInterface.output(0, Lelem, Ptext); + this.output(0, Lelem, Ptext); } if((typeof(PdeadKey)!=='undefined') && (PdeadKey !== null)) { - kbdInterface.deadkeyOutput(0, Lelem, PdeadKey); + this.deadkeyOutput(0, Lelem, PdeadKey); } Lelem._KeymanWebSelectionStart=null; Lelem._KeymanWebSelectionEnd=null; @@ -99,49 +163,49 @@ if(!window['keyman']['initialized']) { * @param {Object} Pk Keyboard object * Description Register and load the keyboard */ - KeymanWeb['KR'] = kbdInterface['registerKeyboard'] = kbdInterface.registerKeyboard = function(Pk): void { + registerKeyboard(Pk): void { // If initialization not yet complete, list the keyboard to be registered on completion of initialization - if(!keymanweb['initialized']) { - keymanweb.deferredKR.push(Pk); return; + if(!this.keymanweb['initialized']) { + this.keymanweb.deferredKR.push(Pk); return; } var Li,Lstub; // Check if the active stub refers to this keyboard, else find applicable stub - var Ps=keymanweb._ActiveStub, savedActiveStub = keymanweb._ActiveStub; + var Ps=this.keymanweb._ActiveStub, savedActiveStub = this.keymanweb._ActiveStub; if(!Ps || !('KI' in Ps) || (Ps['KI'] != Pk['KI'])) { // Find the first stub for this keyboard - for(Lstub=0;Lstub < keymanweb._KeyboardStubs.length; Lstub++) { // I1511 - array prototype extended - Ps=keymanweb._KeyboardStubs[Lstub]; + for(Lstub=0;Lstub < this.keymanweb._KeyboardStubs.length; Lstub++) { // I1511 - array prototype extended + Ps=this.keymanweb._KeyboardStubs[Lstub]; if(Pk['KI'] == Ps['KI'])break; Ps=null; } } // Build 369: ensure active stub defined when loading local keyboards - if(keymanweb._ActiveStub == null && Ps != null) { - keymanweb._ActiveStub = Ps; + if(this.keymanweb._ActiveStub == null && Ps != null) { + this.keymanweb._ActiveStub = Ps; } // Register the stub for this language (unless it is already registered) // keymanweb.KRS(Ps?Ps:Pk); // Test if keyboard already loaded - for(Li=0; Lithis.keymanweb).doKeyboardLoaded(Pk['KI']); // Restore the originally-active stub to its prior state. No need to change it permanently. - keymanweb._ActiveStub = savedActiveStub; + this.keymanweb._ActiveStub = savedActiveStub; } /** @@ -154,18 +218,18 @@ if(!window['keyman']['initialized']) { * @return {?number} 1 if already registered, else null */ //var ts0=new Date().toTimeString().substr(3,5); - KeymanWeb['KRS'] = kbdInterface['registerStub'] = kbdInterface.registerStub = function(Pstub): number { + registerStub(Pstub): number { var Lk; // In initialization not complete, list the stub to be registered on completion of initialization - if(!keymanweb['initialized']) { - keymanweb.deferredKRS.push(Pstub); + if(!this.keymanweb['initialized']) { + this.keymanweb.deferredKRS.push(Pstub); return null; } // The default stub is always the first keyboard stub loaded [and will be ignored by desktop browsers - not for beta, anyway] - if(keymanweb.dfltStub == null) { - keymanweb.dfltStub=Pstub; + if(this.keymanweb.dfltStub == null) { + this.keymanweb.dfltStub=Pstub; //if(device.formFactor == 'desktop') return 1; //Needs further thought before release } @@ -181,23 +245,23 @@ if(!window['keyman']['initialized']) { } // If language code already defined (or not specified in stub), check to see if stub already registered - for(Lk=0; Lkthis.keymanweb).doKeyboardRegistered(Pstub['KI'],Pstub['KL'],Pstub['KN'],Pstub['KLC'],Pstub['KP']); return null; } @@ -216,14 +280,14 @@ if(!window['keyman']['initialized']) { * KC(10,10,Pelem) == "abcdef" i.e. return as much as possible of the requested string */ - KeymanWeb['KC'] = kbdInterface['context'] = kbdInterface.context = function(n: number, ln:number, Pelem:HTMLElement): string { - var v = kbdInterface.cachedContext.get(n, ln); + context(n: number, ln:number, Pelem:HTMLElement): string { + var v = this.cachedContext.get(n, ln); if(v !== null) { return v; } - var r = keymanweb.KC_(n, ln, Pelem); - kbdInterface.cachedContext.set(n, ln, r); + var r = this.keymanweb.KC_(n, ln, Pelem); + this.cachedContext.set(n, ln, r); return r; } @@ -240,8 +304,8 @@ if(!window['keyman']['initialized']) { * KN(2,Pelem) == FALSE * KN(4,Pelem) == TRUE */ - KeymanWeb['KN'] = kbdInterface['nul'] = kbdInterface.nul = function(n:number, Ptarg:HTMLElement): boolean { - var cx=kbdInterface.context(n+1, 1, Ptarg); + nul(n: number, Ptarg: HTMLElement): boolean { + var cx=this.context(n+1, 1, Ptarg); // With #31, the result will be a replacement character if context is empty. return cx === "\uFFFE"; @@ -257,14 +321,13 @@ if(!window['keyman']['initialized']) { * @return {boolean} True if selected context matches val * Description Test keyboard context for match */ - KeymanWeb['KCM'] = kbdInterface['contextMatch'] = kbdInterface.contextMatch = - function(n:number, Ptarg:HTMLElement, val:string, ln:number): boolean { + contextMatch(n: number, Ptarg: HTMLElement, val: string, ln: number): boolean { //KeymanWeb._Debug('KeymanWeb.KCM(n='+n+', Ptarg, val='+val+', ln='+ln+'): return '+(kbdInterface.context(n,ln,Ptarg)==val)); - var cx=kbdInterface.context(n, ln, Ptarg); + var cx=this.context(n, ln, Ptarg); if(cx === val) { return true; // I3318 } - kbdInterface._DeadkeyResetMatched(); // I3318 + this._DeadkeyResetMatched(); // I3318 return false; } @@ -275,11 +338,11 @@ if(!window['keyman']['initialized']) { * @return {boolean} true if keypress event * Description Test if event as a keypress event */ - KeymanWeb['KIK'] = kbdInterface['isKeypress'] = kbdInterface.isKeypress = function(e: KeyEvent):boolean { - if(keymanweb._ActiveKeyboard['KM']) { // I1380 - support KIK for positional layouts + isKeypress(e: KeyEvent):boolean { + if(this.keymanweb._ActiveKeyboard['KM']) { // I1380 - support KIK for positional layouts return !e.LisVirtualKey; // will now return true for U_xxxx keys, but not for T_xxxx keys } else { - return keymanweb._USKeyCodeToCharCode(e) ? true : false; // I1380 - support KIK for positional layouts + return (this.keymanweb)._USKeyCodeToCharCode(e) ? true : false; // I1380 - support KIK for positional layouts } } @@ -292,12 +355,11 @@ if(!window['keyman']['initialized']) { * @return {boolean} True if key matches rule * Description Test keystroke with modifiers against rule */ - KeymanWeb['KKM'] = kbdInterface['keyMatch'] = kbdInterface.keyMatch = - function(e: KeyEvent, Lruleshift:number, Lrulekey:number): boolean { + keyMatch(e: KeyEvent, Lruleshift:number, Lrulekey:number): boolean { var retVal = false; // I3318 var keyCode = (e.Lcode == 173 ? 189 : e.Lcode); //I3555 (Firefox hyphen issue) - var bitmask = keymanweb.getKeyboardModifierBitmask(); + var bitmask = (this.keymanweb).getKeyboardModifierBitmask(); if(e.vkCode > 255) { keyCode = e.vkCode; // added to support extended (touch-hold) keys for mnemonic layouts @@ -311,7 +373,7 @@ if(!window['keyman']['initialized']) { retVal = (keyCode == Lrulekey); // I3318, I3555 } if(!retVal) { - kbdInterface._DeadkeyResetMatched(); // I3318 + this._DeadkeyResetMatched(); // I3318 } return retVal; // I3318 }; @@ -323,7 +385,7 @@ if(!window['keyman']['initialized']) { * @param {number} Lstate * Description Test keystroke against state key rules */ - KeymanWeb['KSM'] = kbdInterface['stateMatch'] = kbdInterface.stateMatch = function(e: KeyEvent, Lstate:number) { + stateMatch(e: KeyEvent, Lstate: number) { return ((Lstate & e.Lstates) == Lstate); } @@ -334,7 +396,7 @@ if(!window['keyman']['initialized']) { * @return {Object} Object with event's virtual key flag, key code, and modifiers * Description Get object with extended key event information */ - KeymanWeb['KKI'] = kbdInterface['keyInformation'] = kbdInterface.keyInformation = function(e: KeyEvent): KeyInformation { + keyInformation(e: KeyEvent): KeyInformation { var ei = new KeyInformation(); ei['vk'] = e.LisVirtualKey; ei['code'] = e.Lcode; @@ -351,21 +413,20 @@ if(!window['keyman']['initialized']) { * @return {boolean} True if deadkey found selected context matches val * Description Match deadkey at current cursor position */ - KeymanWeb['KDM'] = kbdInterface['deadkeyMatch'] = kbdInterface.deadkeyMatch = - function(n: number, Ptarg: HTMLElement, d: number): boolean { - if(kbdInterface._DeadKeys.length == 0) { + deadkeyMatch(n: number, Ptarg: HTMLElement, d: number): boolean { + if(this._DeadKeys.length == 0) { return false; // I3318 } - var sp=keymanweb._SelPos(Ptarg); + var sp=(this.keymanweb)._SelPos(Ptarg); n = sp - n; - for(var i = 0; i < kbdInterface._DeadKeys.length; i++) { - if(kbdInterface._DeadKeys[i].match(n, d)) { - kbdInterface._DeadKeys[i].set(); + for(var i = 0; i < this._DeadKeys.length; i++) { + if(this._DeadKeys[i].match(n, d)) { + this._DeadKeys[i].set(); return true; // I3318 } } - kbdInterface._DeadkeyResetMatched(); // I3318 + this._DeadkeyResetMatched(); // I3318 return false; } @@ -375,15 +436,15 @@ if(!window['keyman']['initialized']) { * Scope Public * Description Reset/terminate beep or flash (not currently used: Aug 2011) */ - KeymanWeb['KBR'] = kbdInterface['beepReset'] = kbdInterface.beepReset = function(): void { - kbdInterface.resetContextCache(); + beepReset(): void { + this.resetContextCache(); var Lbo; - kbdInterface._BeepTimeout = 0; - for(Lbo=0;Lbo= 0; } @@ -444,12 +505,12 @@ if(!window['keyman']['initialized']) { * @param {string} s string to output * Description Keyboard output */ - KeymanWeb['KO'] = kbdInterface['output'] = kbdInterface.output = function(dn: number, Pelem, s:string): void { - kbdInterface.resetContextCache(); + output(dn: number, Pelem, s:string): void { + this.resetContextCache(); // KeymanTouch for Android uses direct insertion of the character string - if('oninserttext' in keymanweb) { - keymanweb['oninserttext'](dn,s); + if('oninserttext' in this.keymanweb) { + this.keymanweb['oninserttext'](dn,s); } if(Pelem.body) { @@ -460,13 +521,13 @@ if(!window['keyman']['initialized']) { var Li, Ldv; if(Pelem.className.indexOf('keymanweb-input') >= 0) { - var t=keymanweb.getTextBeforeCaret(Pelem); + var t=(this.keymanweb).getTextBeforeCaret(Pelem); if(dn > 0) { t=t._kmwSubstr(0,t._kmwLength()-dn)+s; } else { t=t+s; } - keymanweb.setTextBeforeCaret(Pelem,t); + (this.keymanweb).setTextBeforeCaret(Pelem,t); return; } @@ -476,7 +537,7 @@ if(!window['keyman']['initialized']) { /* Editable iframe and contentEditable elements for mozilla */ var _IsEditableIframe = Ldoc.designMode.toLowerCase() == 'on'; if(_IsEditableIframe) { - var _CacheableCommands = kbdInterface._CacheCommands(Ldoc); + var _CacheableCommands = this._CacheCommands(Ldoc); } var Lsel = Ldv.getSelection(); @@ -520,19 +581,19 @@ if(!window['keyman']['initialized']) { } if(_IsEditableIframe) { - kbdInterface._CacheCommandsReset(Ldoc, _CacheableCommands, null);// I2457 - support contentEditable elements in mozilla, webkit + this._CacheCommandsReset(Ldoc, _CacheableCommands, null);// I2457 - support contentEditable elements in mozilla, webkit } Lsel.collapseToEnd(); // Adjust deadkey positions if(dn >= 0) { - kbdInterface._DeadkeyDeleteMatched(); // I3318 - kbdInterface._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318 + this._DeadkeyDeleteMatched(); // I3318 + this._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318 } // Internet Explorer (including IE9) } else if(Ldoc && (Ldv=Ldoc.selection)) { // build 77 - use elem.ownerDocument.selection if(Ldoc.body.isContentEditable || Ldoc.designMode.toLowerCase()=='on') { // I1295 - isContentEditable - var _CacheableCommands = kbdInterface._CacheCommands(Ldoc); + var _CacheableCommands = this._CacheCommands(Ldoc); } var Lrange = Ldv.createRange(), Ls1; @@ -557,7 +618,7 @@ if(!window['keyman']['initialized']) { if(Ldoc.body.isContentEditable || Ldoc.designMode.toLowerCase()=='on') { // I1295 - isContentEditable Lrange.moveStart('character',-s.length); - kbdInterface._CacheCommandsReset(Ldoc, _CacheableCommands,Lrange.select); + this._CacheCommandsReset(Ldoc, _CacheableCommands,Lrange.select); Lrange.moveStart('character',s.length); Lrange.select(); } @@ -571,13 +632,13 @@ if(!window['keyman']['initialized']) { LselectionStart = Pelem.value._kmwCodeUnitToCodePoint(Pelem.selectionStart); // I3319 } - kbdInterface._DeadkeyDeleteMatched(); // I3318 - kbdInterface._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318 + this._DeadkeyDeleteMatched(); // I3318 + this._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318 } - keymanweb._Selection = Ldv.createRange(); - keymanweb._Selection.select(); - keymanweb._Selection.scrollIntoView(); + this.keymanweb._Selection = Ldv.createRange(); + this.keymanweb._Selection.select(); + this.keymanweb._Selection.scrollIntoView(); // Mozilla et al; IE9+ also recognizes setSelectionRange, but does not seem to work in exactly the same way as Mozilla } else if (Pelem.setSelectionRange) { var LselectionStart, LselectionEnd; @@ -606,8 +667,8 @@ if(!window['keyman']['initialized']) { // Adjust deadkey positions if(dn >= 0) { - kbdInterface._DeadkeyDeleteMatched(); // I3318 - kbdInterface._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318,I3319 + this._DeadkeyDeleteMatched(); // I3318 + this._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318,I3319 } if (typeof(LscrollTop) != 'undefined') { @@ -622,8 +683,8 @@ if(!window['keyman']['initialized']) { } // Refresh element content after change (if needed) - if(typeof(keymanweb.refreshElementContent) == 'function') { - keymanweb.refreshElementContent(Pelem); + if(typeof(this.keymanweb.refreshElementContent) == 'function') { + this.keymanweb.refreshElementContent(Pelem); } } @@ -635,16 +696,16 @@ if(!window['keyman']['initialized']) { * @param {number} Pd deadkey id * Description Record a deadkey at current cursor position, deleting Pdn characters first */ - KeymanWeb['KDO'] = kbdInterface['deadkeyOutput'] = kbdInterface.deadkeyOutput = function(Pdn: number, Pelem: HTMLElement, Pd: number): void { - kbdInterface.resetContextCache(); + deadkeyOutput(Pdn: number, Pelem: HTMLElement, Pd: number): void { + this.resetContextCache(); if(Pdn >= 0) { - kbdInterface.output(Pdn,Pelem,""); //I3318 corrected to >= + this.output(Pdn,Pelem,""); //I3318 corrected to >= } - var Lc: Deadkey = new Deadkey(keymanweb._SelPos(Pelem), Pd); + var Lc: Deadkey = new Deadkey((this.keymanweb)._SelPos(Pelem), Pd); - kbdInterface._DeadKeys=keymanweb._push(kbdInterface._DeadKeys,Lc); + this._DeadKeys=this.keymanweb._push(this._DeadKeys,Lc); // _DebugDeadKeys(Pelem, 'KDeadKeyOutput: dn='+Pdn+'; deadKey='+Pd); } @@ -657,11 +718,10 @@ if(!window['keyman']['initialized']) { * @param {Object} Pelem element to output to * Description Output a character selected from the string according to the offset in the index array */ - KeymanWeb['KIO'] = kbdInterface['indexOutput'] = kbdInterface.indexOutput = - function(Pdn:number, Ps:string, Pn:number, Pelem:HTMLElement): void { - kbdInterface.resetContextCache(); - if(kbdInterface._AnyIndices[Pn-1] < Ps._kmwLength()) { //I3319 - kbdInterface.output(Pdn,Pelem,Ps._kmwCharAt(kbdInterface._AnyIndices[Pn-1])); //I3319 + indexOutput(Pdn: number, Ps: string, Pn: number, Pelem: HTMLElement): void { + this.resetContextCache(); + if(this._AnyIndices[Pn-1] < Ps._kmwLength()) { //I3319 + this.output(Pdn,Pelem,Ps._kmwCharAt(this._AnyIndices[Pn-1])); //I3319 } } @@ -672,7 +732,7 @@ if(!window['keyman']['initialized']) { * @return {Array.} List of style commands that are cacheable * Description Build reate list of styles that can be applied in iframes */ - kbdInterface._CacheCommands = function(_Document: Document): StyleCommand[] { // I1204 - style application in IFRAMEs, I2192, I2134, I2192 + private _CacheCommands = function(_Document: Document): StyleCommand[] { // I1204 - style application in IFRAMEs, I2192, I2134, I2192 //var _CacheableBackColor=(_Document.selection?'hilitecolor':'backcolor'); var _CacheableCommands=[ @@ -682,12 +742,12 @@ if(!window['keyman']['initialized']) { new StyleCommand('superscript',0), new StyleCommand('underline',0) ]; if(_Document.defaultView) { - keymanweb._push(_CacheableCommands,['hilitecolor',1]); + this.keymanweb._push(_CacheableCommands,['hilitecolor',1]); } for(var n=0;n < _CacheableCommands.length; n++) { // I1511 - array prototype extended //KeymanWeb._Debug('Command:'+_CacheableCommands[n][0]); - keymanweb._push(_CacheableCommands[n], _CacheableCommands[n][1] ? + this.keymanweb._push(_CacheableCommands[n], _CacheableCommands[n][1] ? _Document.queryCommandValue(_CacheableCommands[n][0]) : _Document.queryCommandState(_CacheableCommands[n][0])); } @@ -702,7 +762,7 @@ if(!window['keyman']['initialized']) { * _func * Description Restore styles in IFRAMEs (??) */ - kbdInterface._CacheCommandsReset = function(_Document: HTMLDocument, _CacheableCommands: StyleCommand[], _func: () => void): void { + private _CacheCommandsReset = function(_Document: HTMLDocument, _CacheableCommands: StyleCommand[], _func: () => void): void { for(var n=0;n < _CacheableCommands.length; n++) { // I1511 - array prototype extended //KeymanWeb._Debug('ResetCacheCommand:'+_CacheableCommands[n][0]+'='+_CacheableCommands[n][2]); if(_CacheableCommands[n][1]) { @@ -730,19 +790,18 @@ if(!window['keyman']['initialized']) { * @param {Object} Pelem Currently active element (may be needed by future tests) * @return {boolean} True if the test succeeds */ - KeymanWeb['KIFS'] = kbdInterface['ifStore'] = kbdInterface.ifStore = - function(systemId: number, strValue:string, Pelem: HTMLElement): boolean { + ifStore(systemId: number, strValue: string, Pelem: HTMLElement): boolean { var result=true; - if(systemId == kbdInterface.TSS_LAYER) { - result = (osk.layerId === strValue); - } else if(systemId == kbdInterface.TSS_PLATFORM) { + if(systemId == this.TSS_LAYER) { + result = (this.keymanweb.osk.layerId === strValue); + } else if(systemId == this.TSS_PLATFORM) { var i,constraint,constraints=strValue.split(' '); for(i=0; i_Dk[Li]).reset(); } @@ -923,8 +925,8 @@ if(!window['keyman']['initialized']) { * Scope Private * Description Delete matched deadkeys from context */ - kbdInterface._DeadkeyDeleteMatched = function(): void { - var Li, _Dk = kbdInterface._DeadKeys; + _DeadkeyDeleteMatched(): void { + var Li, _Dk = this._DeadKeys; for(Li = 0; Li < _Dk.length; Li++) { if(_Dk[Li].matched) { _Dk.splice(Li,1); @@ -939,8 +941,8 @@ if(!window['keyman']['initialized']) { * @param {number} Ldelta characters to adjust by * Description Adjust saved positions of deadkeys in context */ - kbdInterface._DeadkeyAdjustPos = function(Lstart: number, Ldelta: number): void { - var Li, _Dk = kbdInterface._DeadKeys; + _DeadkeyAdjustPos(Lstart: number, Ldelta: number): void { + var Li, _Dk = this._DeadKeys; for(Li = 0; Li < _Dk.length; Li++) { if(_Dk[Li].p > Lstart) { _Dk[Li].p += Ldelta; @@ -948,8 +950,8 @@ if(!window['keyman']['initialized']) { } } - kbdInterface.clearDeadkeys = function(): void { - kbdInterface._DeadKeys = []; + clearDeadkeys = function(): void { + this._DeadKeys = []; } // I3318 - deadkey changes END @@ -962,19 +964,20 @@ if(!window['keyman']['initialized']) { * Description Encapsulates calls to keyboard input processing. * @returns {number} 0 if no match is made, otherwise 1. */ - kbdInterface.processKeystroke = function(device, element: HTMLElement, keystroke:KeyEvent) { + processKeystroke = function(device, element: HTMLElement, keystroke:KeyEvent) { // Clear internal state tracking data from prior keystrokes. - keymanweb._CachedSelectionStart = null; // I3319 - kbdInterface._DeadkeyResetMatched(); // I3318 - kbdInterface.resetContextCache(); + this.keymanweb._CachedSelectionStart = null; // I3319 + this._DeadkeyResetMatched(); // I3318 + this.resetContextCache(); // Ensure the settings are in place so that KIFS/ifState activates and deactivates // the appropriate rule(s) for the modeled device. - util.activeDevice = device; + this.keymanweb.util.activeDevice = device; // Calls the start-group of the active keyboard. - return keymanweb._ActiveKeyboard['gs'](element, keystroke); + return this.keymanweb._ActiveKeyboard['gs'](element, keystroke); } - - })(); -} + + } +// })(); +//} diff --git a/web/source/kmwnative.ts b/web/source/kmwnative.ts index dbf97cb04b..2326f1cf4f 100644 --- a/web/source/kmwnative.ts +++ b/web/source/kmwnative.ts @@ -40,7 +40,7 @@ if(!window['keyman']['initialized']) { // Keyboards loaded with page are initialized before the page is ready, // so cannot use the wait indicater (and don't need it, anyway) // Do not display if a blocking cloud server error has occurred (to prevent multiple errors) - var bg=keymanweb.waiting; + var bg=this.waiting; if(typeof(bg) == 'undefined' || bg == null || keymanweb.warned) { return; } diff --git a/web/source/kmwutils.ts b/web/source/kmwutils.ts index 19a859550d..74d6a4bba0 100644 --- a/web/source/kmwutils.ts +++ b/web/source/kmwutils.ts @@ -108,8 +108,11 @@ class Device { class Util { // Generalized component event registration device: Device; + activeDevice: Device; physicalDevice: Device; + waiting: HTMLDivElement; // The element displayed for util.wait and util.alert. + // An object mapping event names to individual event lists. Maps strings to arrays. private events: { [name: string]: ((Object) => boolean)[];} = {}; private currentEvents: string[] = []; // The event messaging call stack. @@ -129,6 +132,7 @@ class Util { initDevices(): void { this.device = new Device(); this.physicalDevice = new Device(); + this.activeDevice = this.device; // Initialize the true device values. this.device.detect(this._GetIEVersion()); @@ -1108,11 +1112,12 @@ class Util { * @param {function()=} fn function to call when alert dismissed */ alert(s: string, fn: () => void): void { - var bg = this.keyman.waiting, nn=bg.firstChild.childNodes; - nn[0].style.display='block'; - nn[1].className='kmw-alert-text'; - nn[1].innerHTML=s; - nn[2].style.display='none'; + var bg = this.waiting; + var nn=bg.firstChild.childNodes; + (nn[0]).style.display='block'; + (nn[1]).className='kmw-alert-text'; + (nn[1]).innerHTML=s; + (nn[2]).style.display='none'; bg.style.display='block'; if(arguments.length > 1) { bg.dismiss=fn; @@ -1126,7 +1131,7 @@ class Util { * Should not be called before options are defined during initialization **/ prepareWait(): void { - var bg=document.createElement('DIV'), + var bg: HTMLDivElement = document.createElement('DIV'), lb=document.createElement('DIV'), lt=document.createElement('DIV'), gr=document.createElement('DIV'), @@ -1162,7 +1167,7 @@ class Util { lb.appendChild(gr); bg.appendChild(lb); document.body.appendChild(bg); - this.keyman.waiting=bg; + this.waiting=bg; } /** diff --git a/web/source/tsconfig.embedded.json b/web/source/tsconfig.embedded.json index 5de062ac51..02c0155189 100644 --- a/web/source/tsconfig.embedded.json +++ b/web/source/tsconfig.embedded.json @@ -11,6 +11,7 @@ "kmwcallback.ts", "kmwkeymaps.ts", "kmwlayout.ts", - "kmwinit.ts" + "kmwinit.ts", + "kmwapi.ts" ] }