From 6971f09c4db2933e8d1db0f9241b1cd4df2adcd3 Mon Sep 17 00:00:00 2001 From: jahorton Date: Thu, 26 Aug 2021 14:16:36 +0700 Subject: [PATCH] refactor(web): activeElement, lastActiveElement as properties --- web/source/dom/domEventHandlers.ts | 48 ++++++++++++++-------------- web/source/dom/domManager.ts | 42 +++++++++++++----------- web/source/dom/domOverrides.ts | 4 +-- web/source/dom/utils.ts | 2 +- web/source/keyboards/kmwkeyboards.ts | 10 +++--- web/source/kmwbase.ts | 6 ++-- web/source/osk/oskView.ts | 4 +-- web/source/osk/preProcessor.ts | 2 +- web/source/osk/visualKeyboard.ts | 4 +-- 9 files changed, 64 insertions(+), 58 deletions(-) diff --git a/web/source/dom/domEventHandlers.ts b/web/source/dom/domEventHandlers.ts index 1029133e54..18a3f53713 100644 --- a/web/source/dom/domEventHandlers.ts +++ b/web/source/dom/domEventHandlers.ts @@ -16,8 +16,8 @@ namespace com.keyman.dom { _Selection = null; _SelectionControl: any = null; // Type behavior is as with activeElement and the like. - activeElement: HTMLElement; - lastActiveElement: HTMLElement; + _activeElement: HTMLElement; + _lastActiveElement: HTMLElement; focusing: boolean; focusTimer: number; @@ -107,7 +107,11 @@ namespace com.keyman.dom { return true; } - DOMTouchHandlers.states.activeElement = Ltarg; // I3363 (Build 301) + // We condition on 'priorElement' below as a check to allow KMW to set a default active keyboard. + var priorElement = DOMEventHandlers.states._lastActiveElement; + this.keyman.domManager.lastActiveElement = Ltarg; + + this.keyman.domManager.activeElement = Ltarg; // I3363 (Build 301) if (Ltarg.nodeType == 3) { // defeat Safari bug Ltarg = Ltarg.parentNode as HTMLElement; @@ -129,10 +133,7 @@ namespace com.keyman.dom { //??keymanweb._Selection = null; - // We condition on 'priorElement' below as a check to allow KMW to set a default active keyboard. - var priorElement = DOMEventHandlers.states.lastActiveElement; - DOMEventHandlers.states.lastActiveElement = Ltarg; - + if(this.keyman.uiManager.justActivated) { this._BlurKeyboardSettings(); } else { @@ -150,7 +151,7 @@ namespace com.keyman.dom { } //Execute external (UI) code needed on focus if required - this.doControlFocused(LfocusTarg, DOMEventHandlers.states.lastActiveElement); + this.doControlFocused(LfocusTarg, this.keyman.domManager.lastActiveElement); // Force display of OSK for touch input device, or if a CJK keyboard, to ensure visibility of pick list if(osk) { @@ -222,12 +223,12 @@ namespace com.keyman.dom { } // Hide the touch device input caret, if applicable I3363 (Build 301) - if(dom.Utils.instanceof(DOMEventHandlers.states.activeElement, "TouchAliasElement")) { - let lastAlias = DOMEventHandlers.states.activeElement; + if(dom.Utils.instanceof(this.keyman.domManager.activeElement, "TouchAliasElement")) { + let lastAlias = this.keyman.domManager.activeElement; lastAlias.hideCaret(); } - DOMEventHandlers.states.activeElement = null; // I3363 (Build 301) + this.keyman.domManager.activeElement = null; // I3363 (Build 301) if (Ltarg.nodeType == 3) { // defeat Safari bug Ltarg = Ltarg.parentNode as HTMLElement; @@ -243,7 +244,7 @@ namespace com.keyman.dom { this._BlurKeyboardSettings(); // Now that we've handled all prior-element maintenance, update the 'last active element'. - DOMEventHandlers.states.lastActiveElement = Ltarg; + this.keyman.domManager.lastActiveElement = Ltarg; /* If the KeymanWeb UI is active as a user changes controls, all UI-based effects should be restrained to this control in case * the user is manually specifying languages on a per-control basis. @@ -302,7 +303,7 @@ namespace com.keyman.dom { langCode = PLgCode; } - var lastElem = DOMEventHandlers.states.lastActiveElement; + var lastElem = this.keyman.domManager.lastActiveElement; if(lastElem && lastElem._kmwAttachment.keyboard != null) { lastElem._kmwAttachment.keyboard = keyboardID; @@ -321,7 +322,7 @@ namespace com.keyman.dom { * element's loss of control is guaranteed. */ _FocusKeyboardSettings(blockGlobalChange: boolean) { - var lastElem = DOMEventHandlers.states.lastActiveElement; + var lastElem = this.keyman.domManager.lastActiveElement; if(lastElem && lastElem._kmwAttachment.keyboard != null) { this.keyman.keyboardManager.setActiveKeyboard(lastElem._kmwAttachment.keyboard, @@ -407,7 +408,6 @@ namespace com.keyman.dom { */ _KeyDown: (e: KeyboardEvent) => boolean = function(this: DOMEventHandlers, e: KeyboardEvent): boolean { var activeKeyboard = this.keyman.core.activeKeyboard; - var osk = this.keyman.osk; var util = this.keyman.util; if(DOMEventHandlers.states._DisableInput || activeKeyboard == null) { @@ -573,8 +573,8 @@ namespace com.keyman.dom { tEvent={clientX:0, clientY:0} // Will usually be called from setActiveElement, which should define DOMEventHandlers.states.lastActiveElement - if(DOMEventHandlers.states.lastActiveElement) { - tEvent.target = DOMEventHandlers.states.lastActiveElement; + if(this.keyman.domManager.lastActiveElement) { + tEvent.target = this.keyman.domManager.lastActiveElement; // Shouldn't happen, but... just in case. Implemented late in 14.0 beta, so // this detail was kept, though it's likely safe to eliminate. if(tEvent.target['kmw_ip']) { @@ -609,9 +609,9 @@ namespace com.keyman.dom { let scroller = target.firstChild as HTMLElement; // Move the caret and refocus if necessary - if(DOMEventHandlers.states.activeElement != target) { + if(this.keyman.domManager.activeElement != target) { // Hide the KMW caret - let prevTarget = DOMEventHandlers.states.activeElement; + let prevTarget = this.keyman.domManager.activeElement; // We're not 100% sure whether or not the next line can occur, // but it's a decent failsafe regardless. @@ -624,7 +624,7 @@ namespace com.keyman.dom { prevTarget.hideCaret(); } - DOMEventHandlers.states.activeElement=target; + this.keyman.domManager.activeElement=target; // The issue here is that touching a DIV does not actually set the focus for iOS, even when enabled to accept focus (by setting tabIndex=0) // We must explicitly set the focus in order to remove focus from any non-KMW input target.focus(); //Android native browsers may not like this, but it is needed for Chrome, Safari @@ -732,7 +732,7 @@ namespace com.keyman.dom { this._BlurKeyboardSettings(); // With the attachment API update, we now directly track the old legacy control behavior. - DOMEventHandlers.states.lastActiveElement = target; + this.keyman.domManager.lastActiveElement = target; target.showCaret(); /** @@ -753,10 +753,10 @@ namespace com.keyman.dom { * Close OSK and remove simulated caret on losing focus */ cancelInput(): void { - if(DOMEventHandlers.states.activeElement && Utils.instanceof(DOMEventHandlers.states.activeElement, "TouchAliasElement")) { - (DOMEventHandlers.states.activeElement as TouchAliasElement).hideCaret(); + if(this.keyman.domManager.activeElement && Utils.instanceof(this.keyman.domManager.activeElement, "TouchAliasElement")) { + (this.keyman.domManager.activeElement as TouchAliasElement).hideCaret(); } - DOMEventHandlers.states.activeElement=null; + this.keyman.domManager.activeElement=null; this.keyman.osk.hideNow(); }; diff --git a/web/source/dom/domManager.ts b/web/source/dom/domManager.ts index 8d23b228a8..e82a155fc7 100644 --- a/web/source/dom/domManager.ts +++ b/web/source/dom/domManager.ts @@ -436,9 +436,9 @@ namespace com.keyman.dom { baseElement.onkeyup = this.getHandlers(Pelem)._KeyUp; } - var lastElem = this.getLastActiveElement(); + var lastElem = this.lastActiveElement; if(lastElem == Pelem || lastElem == Pelem['kmw_ip']) { - this.clearLastActiveElement(); + this.lastActiveElement = null; this.keyman.osk._Hide(false); } @@ -1124,7 +1124,7 @@ namespace com.keyman.dom { } } - this.clearLastActiveElement(); + this.lastActiveElement = null; }.bind(this); /* ------ Defines independent, per-control keyboard setting behavior for the API. ------ */ @@ -1163,7 +1163,7 @@ namespace com.keyman.dom { // If Pelem is the focused element/active control, we should set the keyboard in place now. // 'kmw_ip' is the touch-alias for the original page's control. - var lastElem = this.getLastActiveElement(); + var lastElem = this.lastActiveElement; if(lastElem && (lastElem == Pelem || lastElem == Pelem['kmw_ip'])) { if(Pkbd != null && Plc != null) { // Second part necessary for Closure. @@ -1215,7 +1215,7 @@ namespace com.keyman.dom { * Set focus to last active target element (browser-dependent) */ focusLastActiveElement() { - var lastElem = this.getLastActiveElement(); + var lastElem = this.lastActiveElement; if(!lastElem) { return; } @@ -1231,20 +1231,24 @@ namespace com.keyman.dom { * * @return {Element} */ - getLastActiveElement(): HTMLElement { - return DOMEventHandlers.states.lastActiveElement; + get lastActiveElement(): HTMLElement { + return DOMEventHandlers.states._lastActiveElement; } - clearLastActiveElement() { - DOMEventHandlers.states.lastActiveElement = null; + set lastActiveElement(Pelem: HTMLElement) { + DOMEventHandlers.states._lastActiveElement = Pelem; + + // TODO: Pass to OSK! } - getActiveElement(): HTMLElement { - return DOMEventHandlers.states.activeElement; + get activeElement(): HTMLElement { + return DOMEventHandlers.states._activeElement; } - _setActiveElement(Pelem: HTMLElement) { - DOMEventHandlers.states.activeElement = Pelem; + set activeElement(Pelem: HTMLElement) { + DOMEventHandlers.states._activeElement = Pelem; + + // TODO: Pass to OSK! } /** @@ -1280,11 +1284,13 @@ namespace com.keyman.dom { } // No need to reset context if we stay within the same element. - if(DOMEventHandlers.states.activeElement != e) { + if(DOMEventHandlers.states._activeElement != e) { this.keyman['resetContext'](e as HTMLElement); } - DOMEventHandlers.states.activeElement = DOMEventHandlers.states.lastActiveElement=e; + //DOMEventHandlers.states.activeElement = DOMEventHandlers.states.lastActiveElement=e; + // TODO: Needs revisiting. + this.activeElement = DOMEventHandlers.states._lastActiveElement = e; if(!this.keyman.isEmbedded) { this.keyman.touchAliasing._FocusKeyboardSettings(false); } @@ -1311,8 +1317,8 @@ namespace com.keyman.dom { * @param {Element} */ initActiveElement(Lelem: HTMLElement) { - if(DOMEventHandlers.states.activeElement == null) { - DOMEventHandlers.states.activeElement = Lelem; + if(this.activeElement == null) { + this.activeElement = Lelem; } } @@ -1326,7 +1332,7 @@ namespace com.keyman.dom { * @param {number|boolean} bBack Direction to move (0 or 1) */ moveToNext(bBack: number|boolean) { - var i,t=this.sortedInputs, activeBase=this.getActiveElement(); + var i,t=this.sortedInputs, activeBase = this.activeElement; var touchable = this.keyman.util.device.touchable; if(t.length == 0) { diff --git a/web/source/dom/domOverrides.ts b/web/source/dom/domOverrides.ts index 7c401582d7..8bcd5cd0ac 100644 --- a/web/source/dom/domOverrides.ts +++ b/web/source/dom/domOverrides.ts @@ -18,18 +18,18 @@ namespace com.keyman.dom { let headlessRuleBehaviorFinalize = text.RuleBehavior.prototype.finalize; text.RuleBehavior.prototype.finalize = function(this: text.RuleBehavior, processor: text.KeyboardProcessor, outputTarget: text.OutputTarget) { + let keyman = com.keyman.singleton; // Execute the standard baseline stuff first. headlessRuleBehaviorFinalize.call(this, processor); // If the transform isn't empty, we've changed text - which should produce a 'changed' event in the DOM. let ruleTransform = this.transcription.transform; if(ruleTransform.insert != "" || ruleTransform.deleteLeft > 0 || ruleTransform.deleteRight > 0) { - if(outputTarget instanceof targets.OutputTarget && outputTarget.getElement() == dom.DOMEventHandlers.states.activeElement) { + if(outputTarget instanceof targets.OutputTarget && outputTarget.getElement() == keyman.domManager.activeElement) { dom.DOMEventHandlers.states.changed = true; } } - let keyman = com.keyman.singleton; // KMEA and KMEI (embedded mode) use direct insertion of the character string if(keyman.isEmbedded) { // A special embedded callback used to setup direct callbacks to app-native code. diff --git a/web/source/dom/utils.ts b/web/source/dom/utils.ts index fee21e3361..2c16bede30 100644 --- a/web/source/dom/utils.ts +++ b/web/source/dom/utils.ts @@ -11,7 +11,7 @@ namespace com.keyman.dom { // Since this may be used to test modularly, we can't depend on the existence of the KMW global. let keyman = com.keyman['singleton']; if(keyman) { - Lelem = keyman.domManager.getLastActiveElement(); + Lelem = keyman.domManager.lastActiveElement; } if(!Lelem) { diff --git a/web/source/keyboards/kmwkeyboards.ts b/web/source/keyboards/kmwkeyboards.ts index 651c13af05..f433121735 100644 --- a/web/source/keyboards/kmwkeyboards.ts +++ b/web/source/keyboards/kmwkeyboards.ts @@ -471,7 +471,7 @@ namespace com.keyman.keyboards { this.doBeforeKeyboardChange(PInternalName,PLgCode); let p: Promise = this._SetActiveKeyboard(PInternalName,PLgCode,true); - if(this.keymanweb.domManager.getLastActiveElement() != null) { + if(this.keymanweb.domManager.lastActiveElement != null) { this.keymanweb.domManager.focusLastActiveElement(); // TODO: Resolve without need for the cast. } // If we ever allow PLgCode to be set by default, we can auto-detect the language code @@ -593,7 +593,7 @@ namespace com.keyman.keyboards { // As a rotation may have occurred since the keyboard was swapped out, // we should refresh its layouts. keyman.core.activeKeyboard.refreshLayouts(); - this.keymanweb.domManager._SetTargDir(this.keymanweb.domManager.getLastActiveElement()); // I2077 - LTR/RTL timing + this.keymanweb.domManager._SetTargDir(this.keymanweb.domManager.lastActiveElement); // I2077 - LTR/RTL timing // and update the active stub for(var Ls=0; Ls= 0) { keyman.uiManager.setActivatingUI(false); oskManager._Hide(true); - let active = keyman.domManager.getActiveElement(); + let active = keyman.domManager.activeElement; if(dom.Utils.instanceof(active, "TouchAliasElement")) { (active as dom.TouchAliasElement).hideCaret(); } - keyman.domManager.clearLastActiveElement(); + keyman.domManager.lastActiveElement = null; } } };