diff --git a/web/source/kmwbase.ts b/web/source/kmwbase.ts index 08e35c3d19..461a102ed1 100644 --- a/web/source/kmwbase.ts +++ b/web/source/kmwbase.ts @@ -648,7 +648,24 @@ namespace com.keyman { * @return {Object} DIV object with filled keyboard layer content */ ['BuildVisualKeyboard'](PInternalName, Pstatic, argFormFactor, argLayerId): HTMLElement { - return com.keyman.osk.VisualKeyboard.buildDocumentationKeyboard(PInternalName, Pstatic, argFormFactor, argLayerId); + let PKbd: com.keyman.keyboards.Keyboard = null; + + if(PInternalName != null) { + var p=PInternalName.toLowerCase().replace('keyboard_',''); + var keyboardsList = this.keyboardManager.keyboards; + + for(let Ln=0; Ln(nodeName:E) { var e = document.createElement(nodeName); diff --git a/web/source/osk/oskManager.ts b/web/source/osk/oskManager.ts index 815f42cc59..8278e2ffe2 100644 --- a/web/source/osk/oskManager.ts +++ b/web/source/osk/oskManager.ts @@ -309,6 +309,15 @@ namespace com.keyman.osk { } } + private layerChangeHandler: text.SystemStoreMutationHandler = function(this: OSKManager, + source: text.MutableSystemStore, + newValue: string) { + if(source.value != newValue) { + this.vkbd.layerId = newValue; + this._Show(); + } + }.bind(this); + /** * Function _GenerateVisualKeyboard * Scope Private @@ -322,8 +331,13 @@ namespace com.keyman.osk { if(this.vkbd) { this.vkbd.shutdown(); } - this.vkbd = new com.keyman.osk.VisualKeyboard(keyboard); + let util = com.keyman.singleton.util; + this.vkbd = new VisualKeyboard(keyboard, util.device); + + // Ensure the OSK's current layer is kept up to date. + let core = com.keyman.singleton.core; // Note: will eventually be a class field. + core.keyboardProcessor.layerStore.handler = this.layerChangeHandler; // Set box class - OS and keyboard added for Build 360 this._Box.className=util.device.formFactor+' '+ util.device.OS.toLowerCase() + ' kmw-osk-frame'; @@ -346,7 +360,7 @@ namespace com.keyman.osk { this._Box.appendChild(this.resizeBar()); // For other devices, adjust the object heights, allowing for viewport scaling } else { - this.vkbd.adjustHeights(); + this.vkbd.adjustHeights(this); } } @@ -1266,7 +1280,7 @@ namespace com.keyman.osk { // The following code will always be executed except for externally created OSK such as EuroLatin if(this.vkbd && this.vkbd.ddOSK) { // Enable the currently active keyboard layer and update the default nextLayer member - this.vkbd.show(); + this.vkbd.show(this); // Extra style changes and overrides for touch-mode. if(device.touchable) { diff --git a/web/source/osk/visualKeyboard.ts b/web/source/osk/visualKeyboard.ts index 21929d3d2b..700d281a30 100644 --- a/web/source/osk/visualKeyboard.ts +++ b/web/source/osk/visualKeyboard.ts @@ -622,7 +622,7 @@ namespace com.keyman.osk { */ layout: keyboards.ActiveLayout; layers: keyboards.LayoutLayer[]; - private layerId: string = "default"; + private _layerId: string = "default"; readonly isRTL: boolean; layerIndex: number; @@ -672,6 +672,14 @@ namespace com.keyman.osk { keytip: {key: KeyElement, state: boolean, element?: HTMLDivElement}; popupCallout: HTMLDivElement; + get layerId(): string { + return this._layerId; + } + + set layerId(value: string) { + this._layerId = value; + } + //#region OSK constructor and helpers /** @@ -681,19 +689,14 @@ namespace com.keyman.osk { * @param {Number} kbdBitmask Keyboard modifier bitmask * Description Generates the base visual keyboard element, prepping for attachment to KMW */ - constructor(keyboard: keyboards.Keyboard, device?: Device, isStatic?: boolean) { - let keyman = com.keyman.singleton; - // Ensure the OSK's current layer is kept up to date. - keyman.core.keyboardProcessor.layerStore.handler = this.layerChangeHandler; - - let util = keyman.util; - this.device = device = device || util.device; + constructor(keyboard: keyboards.Keyboard, device: Device, isStatic?: boolean) { + this.device = device; if(isStatic) { this.isStatic = isStatic; } // Create the collection of HTML elements from the device-dependent layout object - var Lkbd=util._CreateElement('div'); + var Lkbd=document.createElement('div'); let layout: keyboards.ActiveLayout; if(keyboard) { layout = this.layout = keyboard.layout(device.formFactor as utils.FormFactor); @@ -839,11 +842,10 @@ namespace com.keyman.osk { keyboard = new keyboards.Keyboard(null); } let layout = keyboard.layout(formFactor); - let util = com.keyman.singleton.util; let oskManager = com.keyman.singleton.osk; let rowsPercent = 100; - var lDiv=util._CreateElement('div'), ls=lDiv.style, totalHeight=0; + var lDiv=document.createElement('div'), ls=lDiv.style, totalHeight=0; // Set OSK box default style lDiv.className='kmw-key-layer-group'; @@ -885,9 +887,6 @@ namespace com.keyman.osk { var tKey=this.getDefaultKeyObject(); tKey['fontsize']=ls.fontSize; - // Identify key labels (e.g. *Shift*) that require the special OSK font - var specialLabel=/\*\w+\*/; - // ***Delete any empty rows at the end added by compiler bug... for(n=0; n void = function(this: VisualKeyboard, e: TouchEvent) { - let util = com.keyman.singleton.util; + let keyman = com.keyman.singleton; e.preventDefault(); e.cancelBubble=true; @@ -1339,8 +1331,8 @@ namespace com.keyman.osk { y=typeof e.touches == 'object' ? e.touches[0].clientY : e.clientY; // Move target key and highlighting - var t = this.touchPending = e.changedTouches[0], - t1 = document.elementFromPoint(x,y), + this.touchPending = e.changedTouches[0]; + var t1 = document.elementFromPoint(x,y), key0 = this.keyPending, key1 = this.keyTarget(t1); // Not only gets base keys, but also gets popup keys! @@ -1371,7 +1363,7 @@ namespace com.keyman.osk { this.touchPending=null; } else { if(key1 == this.popupBaseKey) { - if(!util.hasClass(key1,'kmw-key-touched')) { + if(!key1.classList.contains('kmw-key-touched')) { this.highlightKey(key1,true); } this.keyPending = key1; @@ -1419,7 +1411,6 @@ namespace com.keyman.osk { // Cancel touch if moved up and off keyboard, unless popup keys visible } else { // _Box has (most of) the useful client values. - let keyman = com.keyman.singleton; let _Box = this.kbdDiv.parentElement ? this.kbdDiv.parentElement : keyman.osk._Box; let height = (this.kbdDiv.firstChild as HTMLElement).offsetHeight; // firstChild == layer-group, has height info. // We need to adjust the offset properties by any offsets related to the active banner. @@ -1477,19 +1468,17 @@ namespace com.keyman.osk { * @return {Object} the key element (or null) **/ keyTarget(target: HTMLElement | EventTarget): KeyElement { - let keyman = com.keyman.singleton; - let util = keyman.util; let t = target; try { if(t) { - if(util.hasClass(t,'kmw-key')) { + if(t.classList.contains('kmw-key')) { return getKeyFrom(t); } - if(t.parentNode && util.hasClass( t.parentNode,'kmw-key')) { + if(t.parentNode && (t.parentNode as HTMLElement).classList.contains('kmw-key')) { return getKeyFrom(t.parentNode); } - if(t.firstChild && util.hasClass( t.firstChild,'kmw-key')) { + if(t.firstChild && (t.firstChild as HTMLElement).classList.contains('kmw-key')) { return getKeyFrom(t.firstChild); } } @@ -1635,7 +1624,7 @@ namespace com.keyman.osk { * Description Updates the OSK's visual style for any toggled state keys */ _UpdateVKShiftStyle(layerId?: string) { - var i, n, layer=null, layerElement=null; + var i, n, layer=null; let core = com.keyman.singleton.core; if(layerId) { @@ -1716,7 +1705,6 @@ namespace com.keyman.osk { } let keyman = com.keyman.singleton; - let util = keyman.util; let device = this.device; // A tag we directly set on a key element during its construction. @@ -1730,8 +1718,6 @@ namespace com.keyman.osk { // position:static and display:inline-block var subKeys=document.createElement('DIV'),i; - var tKey = this.getDefaultKeyObject(); - subKeys.id='kmw-popup-keys'; this.popupBaseKey = e; @@ -1767,7 +1753,7 @@ namespace com.keyman.osk { let layer = e['key'].layer; if(typeof(layer) != 'string' || layer == '') { // Use the currently-active layer. - layer = keyman.core.keyboardProcessor.layerId; + layer = this.layerId; } let keyGenerator = new com.keyman.osk.OSKSubKey(subKeySpec[i], layer); let kDiv = keyGenerator.construct(this, e, needsTopMargin); @@ -2064,7 +2050,7 @@ namespace com.keyman.osk { return null; } - show() { + show(host: OSKManager) { let device = this.device; var n,nLayer=-1, b = this.kbdDiv.childNodes[0].childNodes; @@ -2096,7 +2082,7 @@ namespace com.keyman.osk { // Do NOT condition upon form-factor; this line prevents a bug with displaying // the predictive-text banner on the initial keyboard load. (Issue #2907) if(device.OS == 'iOS') { - this.adjustHeights(); + this.adjustHeights(host); } } @@ -2108,9 +2094,9 @@ namespace com.keyman.osk { * Adjust the absolute height of each keyboard element after a rotation * **/ - adjustHeights() { + adjustHeights(host: OSKManager) { let keyman = com.keyman.singleton; - let _Box = keyman.osk._Box; + let _Box = host._Box; let device = this.device; if(!_Box || !this.kbdDiv || !this.kbdDiv.firstChild || !this.kbdDiv.firstChild.firstChild.childNodes) { @@ -2123,34 +2109,32 @@ namespace com.keyman.osk { fs=fs/keyman.util.getViewportScale(); } - let oskHeight = this.computedAdjustedOskHeight(); + let paddedHeight = this.computedAdjustedOskHeight(host.getKeyboardHeight()); var b: HTMLElement = _Box, bs=b.style; - bs.height=bs.maxHeight=oskHeight+'px'; + bs.height=bs.maxHeight=paddedHeight+'px'; b = this.kbdDiv.firstChild as HTMLElement; bs=b.style; // Sets the layer group to the correct height. - bs.height=bs.maxHeight=oskHeight+'px'; + bs.height=bs.maxHeight=paddedHeight+'px'; bs.fontSize=fs+'em'; - this.adjustLayerHeights(oskHeight); + this.adjustLayerHeights(paddedHeight, host.getKeyboardHeight()); return true; } - private computedAdjustedOskHeight(): number { - let oskManager = com.keyman.singleton.osk; + private computedAdjustedOskHeight(allottedHeight: number): number { let device = this.device; var layers=this.kbdDiv.firstChild.childNodes; - let kbdHeight = oskManager.getKeyboardHeight(); let oskHeight = 0; // In case the keyboard's layers have differing row counts, we check them all for the maximum needed oskHeight. for(let i = 0; i < layers.length; i++) { let nRows = layers[i].childNodes.length; - let rowHeight = Math.floor(kbdHeight/(nRows == 0 ? 1 : nRows)); + let rowHeight = Math.floor(allottedHeight/(nRows == 0 ? 1 : nRows)); let layerHeight = nRows * rowHeight; if(layerHeight > oskHeight) { @@ -2169,8 +2153,7 @@ namespace com.keyman.osk { return oskPaddedHeight; } - private adjustLayerHeights(oskHeight: number) { - let oskManager = com.keyman.singleton.osk; + private adjustLayerHeights(paddedHeight: number, trueHeight: number) { let device = this.device; let layers = this.kbdDiv.firstChild.childNodes; @@ -2178,12 +2161,12 @@ namespace com.keyman.osk { // Check the heights of each row, in case different layers have different row counts. let layer = layers[nLayer] as HTMLElement; let nRows=layers[nLayer].childNodes.length; - ( layers[nLayer]).style.height=(oskHeight)+'px'; + ( layers[nLayer]).style.height=(paddedHeight)+'px'; - let rowHeight = Math.floor(oskManager.getKeyboardHeight()/(nRows == 0 ? 1 : nRows)); + let rowHeight = Math.floor(trueHeight/(nRows == 0 ? 1 : nRows)); if(device.OS == 'Android' && 'devicePixelRatio' in window) { - layer.style.height = layer.style.maxHeight = oskHeight + 'px'; + layer.style.height = layer.style.maxHeight = paddedHeight + 'px'; rowHeight /= window.devicePixelRatio; } @@ -2199,7 +2182,7 @@ namespace com.keyman.osk { rs.maxHeight=rs.lineHeight=rs.height=rowHeight+'px'; // Calculate the exact vertical coordinate of the row's center. - this.layout.layer[nLayer].row[nRow].proportionalY = ((oskHeight - bottom) - rowHeight/2) / oskHeight; + this.layout.layer[nLayer].row[nRow].proportionalY = ((paddedHeight - bottom) - rowHeight/2) / paddedHeight; let keys=layers[nLayer].childNodes[nRow].childNodes as NodeListOf; this.adjustRowHeights(keys, rowHeight, bottom, rowPad); @@ -2222,7 +2205,7 @@ namespace com.keyman.osk { // Must set the height of the btn DIV, not the label (if any) var j; for(j=0; j key.firstChild, - kcs = kc.style, kts = tip.element.style, ktLabel = tip.element.childNodes[1], ktls = ktLabel.style, @@ -2578,7 +2541,7 @@ namespace com.keyman.osk { // Find key text element for(var i=0; i key.childNodes[i]; - if(util.hasClass(kc,'kmw-key-text')) { + if(kc.classList.contains('kmw-key-text')) { break; } } @@ -2661,8 +2624,7 @@ namespace com.keyman.osk { * @param {number} edge -1 left edge, 1 right edge, else 0 */ drawPreview(canvas: HTMLCanvasElement, w: number, h: number, edge: number, delta?: number) { - let util = com.keyman.singleton.util; - let device = util.device; + let device = this.device; delta = delta || 0; @@ -2734,15 +2696,14 @@ namespace com.keyman.osk { */ createKeyTip() { let keyman = com.keyman.singleton; - let util = keyman.util; - if(keyman.util.device.formFactor == 'phone') { + if(this.device.formFactor == 'phone') { if(this.keytip == null) { this.keytip = { key: null, state: false } - let tipElement = this.keytip.element=util._CreateElement('div'); + let tipElement = this.keytip.element=document.createElement('div'); tipElement.className='kmw-keytip'; tipElement.id = 'kmw-keytip'; @@ -2750,8 +2711,8 @@ namespace com.keyman.osk { tipElement.style.pointerEvents='none'; // Add CANVAS element for outline and SPAN for key label - tipElement.appendChild(util._CreateElement('canvas')); - tipElement.appendChild(util._CreateElement('span')); + tipElement.appendChild(document.createElement('canvas')); + tipElement.appendChild(document.createElement('span')); } // Always append to _Box (since cleared during OSK Load) @@ -2767,9 +2728,8 @@ namespace com.keyman.osk { */ addCallout(key: KeyElement, delta?: number): HTMLDivElement { let keyman = com.keyman.singleton; - let util = keyman.util; - if(util.device.formFactor != 'phone' || util.device.OS != 'iOS') { + if(this.device.formFactor != 'phone' || this.device.OS != 'iOS') { return null; } @@ -2778,7 +2738,7 @@ namespace com.keyman.osk { let calloutHeight = key.offsetHeight - delta; if(calloutHeight > 0) { - var cc = util._CreateElement('div'), ccs = cc.style; + var cc = document.createElement('div'), ccs = cc.style; cc.id = 'kmw-popup-callout'; keyman.osk._Box.appendChild(cc);