diff --git a/common/predictive-text/unit_tests/in_browser/manual.conf.cjs b/common/predictive-text/unit_tests/in_browser/manual.conf.cjs
index 9f94634473..738f2b7713 100644
--- a/common/predictive-text/unit_tests/in_browser/manual.conf.cjs
+++ b/common/predictive-text/unit_tests/in_browser/manual.conf.cjs
@@ -19,7 +19,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- // Can't set in base.conf.js b/c of constant's definition style.
+ // Can't set in base.conf.cjs b/c of constant's definition style.
logLevel: config.LOG_INFO
};
diff --git a/common/web/keyboard-processor/tests/dom/CI.conf.cjs b/common/web/keyboard-processor/tests/dom/CI.conf.cjs
index c7c9813df7..a96ffebbed 100644
--- a/common/web/keyboard-processor/tests/dom/CI.conf.cjs
+++ b/common/web/keyboard-processor/tests/dom/CI.conf.cjs
@@ -18,7 +18,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- // Can't set in base.conf.js b/c of constant's definition style.
+ // Can't set in base.conf.cjs b/c of constant's definition style.
logLevel: config.LOG_INFO
};
diff --git a/common/web/keyboard-processor/tests/dom/manual.conf.cjs b/common/web/keyboard-processor/tests/dom/manual.conf.cjs
index 88e20d283c..37d982e9b5 100644
--- a/common/web/keyboard-processor/tests/dom/manual.conf.cjs
+++ b/common/web/keyboard-processor/tests/dom/manual.conf.cjs
@@ -18,7 +18,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- // Can't set in base.conf.js b/c of constant's definition style.
+ // Can't set in base.conf.cjs b/c of constant's definition style.
logLevel: config.LOG_INFO
};
diff --git a/web/package.json b/web/package.json
index 0f7559e0c9..9c06e3d5b0 100644
--- a/web/package.json
+++ b/web/package.json
@@ -72,7 +72,6 @@
"@keymanapp/web-sentry-manager": "*",
"@sentry/cli": "2.2.0",
"chai": "^4.3.4",
- "google-closure-compiler-java": "^20200224.0.0",
"karma": "^6.4.1",
"karma-browserstack-launcher": "^1.6.0",
"karma-chai": "^0.1.0",
diff --git a/web/src/app/browser/src/utilApiEndpoint.ts b/web/src/app/browser/src/utilApiEndpoint.ts
index b622d68f0c..04e2670b32 100644
--- a/web/src/app/browser/src/utilApiEndpoint.ts
+++ b/web/src/app/browser/src/utilApiEndpoint.ts
@@ -8,6 +8,7 @@ import {
} from "keyman/engine/dom-utils";
import { DomEventTracker } from "keyman/engine/events";
import { BrowserConfiguration, BrowserInitOptionSpec } from "./configuration.js";
+import { getStyleValue } from "./utils/getStyleValue.js";
/**
* Calls document.createElement for the specified node type and also applies
@@ -205,6 +206,8 @@ export class UtilApiEndpoint {
this.domEventTracker.detachDOMEvent(Pelem as any, Peventname as any, Phandler, PuseCapture);
}
+ getStyleValue = getStyleValue;
+
shutdown() {
this.stylesheetManager?.unlinkAll();
this.domEventTracker?.shutdown();
diff --git a/web/src/app/ui/build-bundler.js b/web/src/app/ui/build-bundler.js
index bfc57b20b0..a09c61bf7f 100644
--- a/web/src/app/ui/build-bundler.js
+++ b/web/src/app/ui/build-bundler.js
@@ -30,7 +30,7 @@ let es5ClassAnnotationAsPurePlugin = {
}
}
-const modules = ['kmwuitoggle', 'kmwuitoolbar'];
+const modules = ['kmwuibutton', 'kmwuifloat', 'kmwuitoggle', 'kmwuitoolbar'];
for(let module of modules) {
await esbuild.build({
diff --git a/web/src/app/ui/kmwuibutton.ts b/web/src/app/ui/kmwuibutton.ts
index 1205c7b6e4..d81bc11b67 100644
--- a/web/src/app/ui/kmwuibutton.ts
+++ b/web/src/app/ui/kmwuibutton.ts
@@ -1,12 +1,14 @@
/***
- KeymanWeb 11.0
- Copyright 2019 SIL International
+ KeymanWeb 17.0
+ Copyright 2019-2023 SIL International
***/
-// If a UI module has been loaded, we can rely on the publically-published 'name' property
-// having been set as a way to short-out a UI reload. Its parent object always exists by
-// this point in the build process.
-if(!window['keyman']['ui']['name']) {
+import type { KeymanEngine, KeyboardCookie, UIModule } from 'keyman/app/browser';
+import type { FloatingOSKViewCookie } from 'keyman/engine/osk';
+
+declare var keyman: KeymanEngine
+
+if(!keyman?.ui?.name) {
/********************************/
/* */
@@ -25,390 +27,635 @@ if(!window['keyman']['ui']['name']) {
try {
// Declare KeymanWeb, OnScreen keyboard and Util objects
- var keymanweb=window['keyman'],
- util=keymanweb['util'],dbg=keymanweb['debug'];
+ const keymanweb = keyman;
+ const util=keymanweb.util;
+ // var dbg=keymanweb['debug'];
// Disable UI for touch devices
- if(util['isTouchDevice']()) throw '';
-
- // User interface global and variables
- keymanweb['ui'] = {};
- var ui=keymanweb['ui'];
- ui['name'] = 'button';
-
- ui.init = false;
- ui.initTimer = null;
- ui.KeyboardSelector = null;
-
- ui.KeymanWeb_DefaultKeyboardHelp='KeymanWeb is not running. Choose a keyboard from the list';
- ui._KeymanWeb_KbdList = null;
- ui._KMWSel = null;
- ui._IsHelpVisible = false;
- ui._DefaultKeyboardID = '';
-
- ui.updateTimer = null;
- ui.updateList = true;
-
- /**
- * Highlight the currently active keyboard in the list of keyboards
- **/
- ui._ShowSelected = function()
- {
- var _rv,kbd=keymanweb['getActiveKeyboard'](),lgc=keymanweb['getActiveLanguage'](),
- kList = ui._KeymanWeb_KbdList.childNodes,
- _r = /^KMWSel_(.*)\$(.*)$/;
-
- for(var i=1; i= kList.length) i=1;
- kList[i].childNodes[0].className = 'selected';
+ if(util.isTouchDevice()) {
+ throw '';
}
- /**
- * Select keyboard by id
- *
- * @param {Event} _id keyboard selection event
- * @return {boolean}
- */
- ui._SelectKeyboard = function(_id)
- {
- if(typeof(_id) == 'object')
- {
- var t=null;
- if((typeof(_id.target) != 'undefined') && _id.target) t=_id.target;
- else if((typeof(_id.srcElement) != 'undefined') && _id.srcElement) t=_id.srcElement;
- if(t) _id=t.id;
- }
+ class UIButton implements UIModule {
+ // User interface global and variables
+ readonly name = 'button';
- var _r=/^KMWSel_(.*)\$(.*)$/;
- var _rv=_r.exec(_id),_lgc='',_name='';
- if(_rv !== null)
- {
- _name = _rv[1].split('$')[0]; //new code
- _lgc = _id.split('$')[1];
- if(ui._KMWSel != null) ui._KMWSel.className = '';
- var _k = document.getElementById(_id);
- if(_k) _k.className='selected';
- ui._KMWSel = _k;
- keymanweb['setActiveKeyboard'](_name,_lgc);
- }
- else
- _name=null;
+ init = false;
- keymanweb['focusLastActiveElement']();
- let osk = keymanweb.osk;
- if(osk && osk['isEnabled']()) osk['show'](true);
-
- ui._ShowKeyboardButton(_name);
- return false;
- }
-
- /**
- * Set KMW UI activation state on mouse click
- *
- * @param {Event} e event
- */
- ui._SelectorMouseDown = function(e)
- {
- var x=keymanweb['getLastActiveElement']();
-
- // Set the focus to an input field, to get correct OSK display behaviour
- if(!x) ui._FocusFirstInput(); else keymanweb['focusLastActiveElement']();
-
- if(keymanweb['activatingUI']) keymanweb['activatingUI'](1);
- }
-
- /**
- * Set focus on mouse up
- *
- * @param {Event} e event
- */
- ui._SelectorMouseUp = function(e)
- {
- var x=keymanweb['getLastActiveElement']();
-
- // Set the focus to an input field, to get correct OSK display behaviour
- if(!x) ui._FocusFirstInput(); else keymanweb['focusLastActiveElement']();
- }
-
- /**
- * Set KMW UI activation state on mouse over
- *
- * @param {Event} e event
- */
- ui._SelectorMouseOver = function(e)
- {
- // highlight the currently active keyboard
- ui._ShowSelected();
-
- if(keymanweb['activatingUI']) keymanweb['activatingUI'](1);
- document.getElementById("kmwico_li").className="sfhover";
-
- // Conditionally display keyboard button
- ui._ShowKeyboardButton();
- }
-
- /**
- * Sets the focus to the first input or textarea found on the current page
- * to ensure consistent keyboard selection and OSK display behaviour
- */
- ui._FocusFirstInput = function()
- {
- var i,ip=null,tp=null,
- iList=document.getElementsByTagName("input"),
- tList=document.getElementsByTagName("textarea");
-
- for(i=0; i 0) tp = tList[0];
-
- if((!ip) && (!tp))
- return;
- else if(ip && !tp)
- ip.focus();
- else if(tp && !ip)
- tp.focus();
- else if(ip.offsetTop < tp.offsetTop)
- ip.focus();
- else if(ip.offsetTop > tp.offsetTop)
- tp.focus();
- else if(ip.offsetLeft < tp.offsetLeft)
- ip.focus();
- else
- tp.focus();
- }
-
- /**
- * Clear KMW UI activation state on mouse out
- *
- * @param {Event} e event
- */
- ui._SelectorMouseOut = function(e)
- {
- if(keymanweb['activatingUI']) keymanweb['activatingUI'](0);
- document.getElementById("kmwico_li").className="sfunhover";
- }
-
- /**
- * Disable the button to show/hide the OSK if no active keyboard or active keyboard is CJK (user cannot hide)
- *
- * @param {?string=} _name current keyboard name
- */
- ui._ShowKeyboardButton = function(_name)
- {
- var kbdName = keymanweb['getActiveKeyboard'](), kbdId=document.getElementById("KMW_Keyboard");
- if(arguments.length > 0) kbdName = _name;
- if(kbdId)
- {
- if((kbdName == '') || keymanweb['isCJK']())
- {
- kbdId.className='kmw_disabled';
- }
- else
- {
- let osk = keymanweb.osk;
- kbdId.className = osk && osk['isEnabled']() ? 'kmw_show' : 'kmw_hide';
- }
- }
- }
-
- ui.registerEvents = function() {
- let osk = keymanweb.osk;
- if(!osk) {
- return;
- }
/**
- * UI Functions called by KeymanWeb or OSK
+ * Initialization timeout handle.
*/
- osk['addEventListener']('show', function(oskPosition) {
- var t=keymanweb['getLastActiveElement']();
- if(t)
- {
- if(!oskPosition['userLocated'])
- {
- oskPosition['x'] = util['getAbsoluteX'](t);
- oskPosition['y'] = util['getAbsoluteY'](t)+t.offsetHeight;
+ private initTimer: number = null;
+ private keyboardSelector = null; // not referenced
+
+ // not referenced
+ private KeymanWeb_DefaultKeyboardHelp='KeymanWeb is not running. Choose a keyboard from the list';
+
+
+ private _KeymanWeb_KbdList: HTMLUListElement = null;
+
+ /**
+ * Tracks the element corresponding to the active keyboard on the keyboard list.
+ *
+ * Is also set when activating it due to user interaction.
+ */
+ private _KMWSel: HTMLElement = null;
+ private _IsHelpVisible = false;
+ private _DefaultKeyboardID = '';
+
+ updateTimer: number = 0;
+ updateList = true;
+
+ /**
+ * If no id == 'KeymanWebControl' element exists during init, this UI module
+ * will make its own, auto-insert it, and track the element here.
+ */
+ private _insertedElem: HTMLElement = null;
+
+ /**
+ * Highlight the currently active keyboard in the list of keyboards
+ **/
+ private _ShowSelected() {
+ let kbd=keymanweb.getActiveKeyboard();
+ let lgc=keymanweb.getActiveLanguage();
+ let kList = this._KeymanWeb_KbdList.childNodes;
+ let _r = /^KMWSel_(.*)\$(.*)$/;
+
+ for(let i=1; i= kList.length) {
+ i=1;
+ }
+ (kList[i].childNodes[0] as HTMLElement).className = 'selected';
+ }
+
+ /**
+ * Select keyboard by id
+ *
+ * @param {Event} _id keyboard selection event
+ * @return {boolean}
+ */
+ readonly _SelectKeyboard = (_id: Event) => {
+ let id: string = '';
+ if(typeof(_id) == 'object') {
+ let t: HTMLElement = null;
+ if((typeof(_id.target) != 'undefined') && _id.target) {
+ t=_id.target as HTMLElement;
+ } else if((typeof(_id.srcElement) != 'undefined') && _id.srcElement) {
+ t=_id.srcElement as HTMLElement;
+ }
+
+ if(t) {
+ id=t.id;
}
}
- ui._ShowKeyboardButton();
- return oskPosition;
- });
-
- /* TODO: why is this still needed??? Does it actually do anything?? */
- osk['addEventListener']('hide', function(hiddenByUser) {
- if((arguments.length > 0) && hiddenByUser)
- {
- var _a = document.getElementById('KMW_Keyboard');
- if(_a) _a.className = 'kmw_hide';
+ let _r=/^KMWSel_(.*)\$(.*)$/;
+ let _rv=_r.exec(id),_lgc='',_name='';
+ if(_rv !== null) {
+ _name = _rv[1].split('$')[0]; //new code
+ _lgc = id.split('$')[1];
+ if(this._KMWSel != null) {
+ this._KMWSel.className = '';
+ }
+ let _k = document.getElementById(id);
+ if(_k) {
+ _k.className='selected';
+ }
+ this._KMWSel = _k;
+ keymanweb.setActiveKeyboard(_name,_lgc);
+ } else {
+ _name=null;
}
- });
- }
- /**
- * Show or hide the OSK (always visible for CJK keyboards)
- *
- * @param {Object} _anchor anchor element (?)
- * @return {boolean}
- **/
- ui._ShowKeymanWebKeyboard = function(_anchor)
- {
- var kbdId=document.getElementById("KMW_Keyboard");
- let osk = keymanweb.osk;
+ keymanweb.focusLastActiveElement();
+ let osk = keymanweb.osk;
+ if(osk && osk.isEnabled()) {
+ osk.show(true);
+ }
- if((kbdId.className!='kmw_disabled') && osk && osk['show'])
- {
- if(osk['isEnabled']()) osk['hide'](); else osk['show'](true);
- }
- if(window.event) window.event.returnValue=false;
-
- keymanweb['focusLastActiveElement']();
- return false;
- }
-
- /**
- * Initialize Button User Interface
- **/
- ui['initialize'] = ui.Initialize = function() {
- if(ui.initTimer) {
- window.clearTimeout(ui.initTimer);
- ui.initTimer = null;
+ this._ShowKeyboardButton(_name);
+ return false;
}
- //Never initialize UI before KMW (parameters will be undefined)
- if(!keymanweb['initialized']) {
- ui.initTimer = window.setTimeout(ui.Initialize, 50);
- return;
+ /**
+ * Set KMW UI activation state on mouse click
+ *
+ * @param {Event} e event
+ */
+ readonly _SelectorMouseDown = (e: MouseEvent) => {
+ const x=keymanweb.getLastActiveElement();
+
+ // Set the focus to an input field, to get correct OSK display behaviour
+ if(!x) {
+ this._FocusFirstInput();
+ } else {
+ keymanweb.focusLastActiveElement();
+ }
+
+ if(keymanweb.activatingUI) {
+ keymanweb.activatingUI(1);
+ }
}
- if(ui.init || util['isTouchDevice']()) {
- return;
+ /**
+ * Set focus on mouse up
+ *
+ * @param {Event} e event
+ */
+ readonly _SelectorMouseUp = (e: MouseEvent) => {
+ const x=keymanweb.getLastActiveElement();
+
+ // Set the focus to an input field, to get correct OSK display behaviour
+ if(!x) {
+ this._FocusFirstInput();
+ } else {
+ keymanweb.focusLastActiveElement();
+ }
}
- ui.init = true;
+ /**
+ * Set KMW UI activation state on mouse over
+ *
+ * @param {Event} e event
+ */
+ readonly _SelectorMouseOver = (e: MouseEvent) => {
+ // highlight the currently active keyboard
+ this._ShowSelected();
- util['addStyleSheet'](ui._Appearance);
+ if(keymanweb.activatingUI) {
+ keymanweb.activatingUI(1);
+ }
- ui._KeymanWeb_KbdList = util['createElement']('ul');
- ui._KeymanWeb_KbdList.id = 'KeymanWeb_KbdList';
+ document.getElementById("kmwico_li").className="sfhover";
- var _elem = document.getElementById('KeymanWebControl');
- if(!_elem)
- {
- var _elems = document.getElementsByTagName('div');
- for(var _i = 0; _i < _elems.length; _i++)
- {
- if(_elems[_i].className == 'KeymanWebControl')
- {
- _elem = _elems[_i]; break;
+ // Conditionally display keyboard button
+ this._ShowKeyboardButton();
+ }
+
+ /**
+ * Sets the focus to the first input or textarea found on the current page
+ * to ensure consistent keyboard selection and OSK display behaviour
+ */
+ private _FocusFirstInput() {
+ let ip: HTMLInputElement = null;
+ let tp: HTMLTextAreaElement = null;
+ const iList=document.getElementsByTagName("input");
+ const tList=document.getElementsByTagName("textarea");
+
+ let i: number;
+ for(i=0; i 0) {
+ tp = tList[0];
+ }
+
+ if((!ip) && (!tp)) {
+ return;
+ } else if(ip && !tp) {
+ ip.focus();
+ } else if(tp && !ip) {
+ tp.focus();
+ } else if(ip.offsetTop < tp.offsetTop) {
+ ip.focus();
+ } else if(ip.offsetTop > tp.offsetTop) {
+ tp.focus();
+ } else if(ip.offsetLeft < tp.offsetLeft) {
+ ip.focus();
+ } else {
+ tp.focus();
+ }
+ }
+
+ /**
+ * Clear KMW UI activation state on mouse out
+ *
+ * @param {Event} e event
+ */
+ readonly _SelectorMouseOut = (e: MouseEvent) => {
+ if(keymanweb.activatingUI) {
+ keymanweb.activatingUI(0);
+ }
+ document.getElementById("kmwico_li").className="sfunhover";
+ }
+
+ /**
+ * Disable the button to show/hide the OSK if no active keyboard or active keyboard is CJK (user cannot hide)
+ *
+ * @param {?string=} _name current keyboard name
+ */
+ private _ShowKeyboardButton(_name?: string) {
+ let kbdName = keymanweb.getActiveKeyboard();
+ let kbdId = document.getElementById("KMW_Keyboard");
+ if(arguments.length > 0) {
+ kbdName = _name;
+ }
+
+ if(kbdId) {
+ if((kbdName == '') || keymanweb.isCJK()) {
+ kbdId.className='kmw_disabled';
+ } else {
+ let osk = keymanweb.osk;
+ kbdId.className = osk && osk.isEnabled() ? 'kmw_show' : 'kmw_hide';
}
}
}
- // Insert as first child of body if not defined by user
- if(!_elem && (document.body != null))
- {
- _elem=document.createElement('DIV');
- _elem.id='KeymanWebControl';
- document.body.insertBefore(_elem,document.body.firstChild);
- ui._insertedElem = _elem;
+ registerEvents() {
+ let osk = keymanweb.osk;
+ if(!osk) {
+ return;
+ }
+ /**
+ * UI Functions called by KeymanWeb or OSK
+ */
+ osk.addEventListener('show', (oskPosition) => {
+ const t=keymanweb.getLastActiveElement();
+ if(t) {
+ if(!oskPosition['userLocated']) {
+ oskPosition['x'] = util.getAbsoluteX(t);
+ oskPosition['y'] = util.getAbsoluteY(t)+t.offsetHeight;
+ }
+ }
+
+ this._ShowKeyboardButton();
+ return oskPosition;
+ });
+
+ /* TODO: why is this still needed??? Does it actually do anything?? */
+ osk.addEventListener('hide', function(obj) {
+ if((arguments.length > 0) && obj['hiddenByUser']) {
+ let _a = document.getElementById('KMW_Keyboard');
+ if(_a) {
+ _a.className = 'kmw_hide';
+ }
+ }
+ });
}
+ /**
+ * Show or hide the OSK (always visible for CJK keyboards)
+ *
+ * @param {Object} _anchor anchor element (?)
+ * @return {boolean}
+ **/
+ readonly _ShowKeymanWebKeyboard = () => {
+ const kbdId=document.getElementById("KMW_Keyboard");
+ let osk = keymanweb.osk;
- var imgPath=util['getOption']('resources')+'ui/button/';
- if(_elem)
- {
- // Append another DIV to follow the main control with clear:both to prevent selection over entire width of window
- var dx=document.createElement('DIV'),ds=dx.style;
- ds.clear='both';
- _elem.parentNode.insertBefore(dx,_elem.nextSibling);
+ if((kbdId.className!='kmw_disabled') && osk && osk.show) {
+ if(osk.isEnabled()) {
+ osk.hide();
+ } else {
+ osk.show(true);
+ }
+ }
+ if(window.event) {
+ window.event.returnValue=false;
+ }
- var _btn=util['createElement']('img'), _ul=util['createElement']('ul'),_li0=util['createElement']('li');
- _btn.id = 'kmwico_a';
- _btn.src = imgPath+'kmw_button.gif';
- _btn.onclick = function(){return false;} //may want to use this in iOS *****
- _li0.appendChild(_btn);
- _li0.id = 'kmwico_li';
- _ul.appendChild(_li0);
- _ul.id = 'kmwico';
- _ul.style.display = 'block';
- _elem.appendChild(_ul);
- }
- // Do not define any UI behaviour if no controller element can be found
- else return;
-
- if(!keymanweb['iOS'])
- {
- var _li = util['createElement']('li');
- var _a = util['createElement']('a');
- var _img = util['createElement']('img');
- _img.src = imgPath+'kbdicon.gif';
- _a.appendChild(_img);
-
- var _txt1 = document.createTextNode(' Hide Keyboard');
- var _txt2 = document.createTextNode(' Show Keyboard');
- var _sp1 = util['createElement']('span');
- _sp1.id = 'KMW_KbdVisibleMsg';
- _sp1.appendChild(_txt1);
- _a.appendChild(_sp1);
-
- var _sp2 = util['createElement']('span');
- _sp2.id = 'KMW_KbdHiddenMsg';
- _sp2.appendChild(_txt2);
- _a.appendChild(_sp2);
- _a.onmousedown = ui._ShowKeymanWebKeyboard;
- _a.href = '#';
- _a.id = 'KMW_Keyboard';
- _li.id = 'KMW_ButtonUI_KbdIcon';
- _li.appendChild(_a);
- ui._KMWSel = _a;
- ui._KeymanWeb_KbdList.appendChild(_li);
+ keymanweb.focusLastActiveElement();
+ return false;
}
- var _li1 = util['createElement']('li');
- _li1.id = 'KMW_ButtonUI_KbdList';
- var _a1 = util['createElement']('a');
- _a1.appendChild(document.createTextNode('(System keyboard)'));
+ /**
+ * Initialize Button User Interface
+ **/
+ readonly initialize = () => {
+ if(this.initTimer) {
+ window.clearTimeout(this.initTimer);
+ this.initTimer = null;
+ }
- _a1.onclick = ui._SelectKeyboard;
- _a1.href = '#';
- _a1.id='KMWSel_$';
- _a1.className='selected';
- _li1.appendChild(_a1);
- ui._KMWSel = _a1;
- ui._KeymanWeb_KbdList.appendChild(_li1);
+ //Never initialize UI before KMW (parameters will be undefined)
+ if(!keymanweb.initialized) {
+ this.initTimer = window.setTimeout(this.initialize, 50);
+ return;
+ }
- var _kbds = keymanweb['getKeyboards'](), _added = [];
+ if(this.init || util.isTouchDevice()) {
+ return;
+ }
- ui.updateKeyboardList();
+ this.init = true;
- document.getElementById('kmwico_li').appendChild(ui._KeymanWeb_KbdList);
+ util.addStyleSheet(this._Appearance);
- var _sfEl = document.getElementById("kmwico_li");
- util['attachDOMEvent'](_sfEl,'mousedown',ui._SelectorMouseDown);
- util['attachDOMEvent'](_sfEl,'mouseover',ui._SelectorMouseOver);
- util['attachDOMEvent'](_sfEl,'mouseout',ui._SelectorMouseOut);
- util['attachDOMEvent'](_sfEl,'mouseup',ui._SelectorMouseUp);
+ this._KeymanWeb_KbdList = util.createElement('ul');
+ this._KeymanWeb_KbdList.id = 'KeymanWeb_KbdList';
- ui.registerEvents();
- keymanweb['focusLastActiveElement'](); //TODO: this needs to be extended - if no element is active, try and identify an enabled input element
+ let _elem = document.getElementById('KeymanWebControl');
+ if(!_elem) {
+ const _elems = document.getElementsByTagName('div');
+ for(let _i = 0; _i < _elems.length; _i++) {
+ if(_elems[_i].className == 'KeymanWebControl') {
+ _elem = _elems[_i]; {
+ break;
+ }
+ }
+ }
+ }
+
+ // Insert as first child of body if not defined by user
+ if(!_elem && (document.body != null)) {
+ _elem=document.createElement('DIV');
+ _elem.id='KeymanWebControl';
+ document.body.insertBefore(_elem,document.body.firstChild);
+ this._insertedElem = _elem;
+ }
+
+
+ let imgPath=util.getOption('resources')+'ui/button/';
+ if(_elem) {
+ // Append another DIV to follow the main control with clear:both to prevent selection over entire width of window
+ const dx=document.createElement('DIV')
+ const ds=dx.style;
+ ds.clear='both';
+ _elem.parentNode.insertBefore(dx,_elem.nextSibling);
+
+ const _btn=util.createElement('img');
+ const _ul=util.createElement('ul');
+ const _li0=util.createElement('li');
+
+ _btn.id = 'kmwico_a';
+ _btn.src = imgPath+'kmw_button.gif';
+ _btn.onclick = function() {
+ return false;
+ } //may want to use this in iOS *****
+ _li0.appendChild(_btn);
+ _li0.id = 'kmwico_li';
+ _ul.appendChild(_li0);
+ _ul.id = 'kmwico';
+ _ul.style.display = 'block';
+ _elem.appendChild(_ul);
+ } else {
+ // Do not define any UI behaviour if no controller element can be found
+ return;
+ }
+
+ // ... wait, what? I can't find any evidence of this reference point existing.
+ // Even tag `release-web-stable-2.0` turns up results only for this specific sourcefile.
+ // Thus, in essence: if(true) { /* ... */ }
+ if(!keymanweb['iOS']) {
+ var _li = util.createElement('li');
+ var _a = util.createElement('a');
+ var _img = util.createElement('img');
+ _img.src = imgPath+'kbdicon.gif';
+ _a.appendChild(_img);
+
+ const _txt1 = document.createTextNode(' Hide Keyboard');
+ const _txt2 = document.createTextNode(' Show Keyboard');
+ const _sp1 = util.createElement('span');
+ _sp1.id = 'KMW_KbdVisibleMsg';
+ _sp1.appendChild(_txt1);
+ _a.appendChild(_sp1);
+
+ var _sp2 = util.createElement('span');
+ _sp2.id = 'KMW_KbdHiddenMsg';
+ _sp2.appendChild(_txt2);
+ _a.appendChild(_sp2);
+ _a.onmousedown = this._ShowKeymanWebKeyboard;
+ _a.href = '#';
+ _a.id = 'KMW_Keyboard';
+ _li.id = 'KMW_ButtonUI_KbdIcon';
+ _li.appendChild(_a);
+ this._KMWSel = _a;
+ this._KeymanWeb_KbdList.appendChild(_li);
+ }
+
+ var _li1 = util.createElement('li');
+ _li1.id = 'KMW_ButtonUI_KbdList';
+ var _a1 = util.createElement('a');
+ _a1.appendChild(document.createTextNode('(System keyboard)'));
+
+ _a1.onclick = this._SelectKeyboard;
+ _a1.href = '#';
+ _a1.id='KMWSel_$';
+ _a1.className='selected';
+ _li1.appendChild(_a1);
+ this._KMWSel = _a1;
+ this._KeymanWeb_KbdList.appendChild(_li1);
+
+ this.updateKeyboardList();
+
+ document.getElementById('kmwico_li').appendChild(this._KeymanWeb_KbdList);
+
+ var _sfEl = document.getElementById("kmwico_li");
+ util.attachDOMEvent(_sfEl,'mousedown',this._SelectorMouseDown);
+ util.attachDOMEvent(_sfEl,'mouseover',this._SelectorMouseOver);
+ util.attachDOMEvent(_sfEl,'mouseout',this._SelectorMouseOut);
+ util.attachDOMEvent(_sfEl,'mouseup',this._SelectorMouseUp);
+
+ this.registerEvents();
+ keymanweb.focusLastActiveElement(); //TODO: this needs to be extended - if no element is active, try and identify an enabled input element
+ }
+
+ shutdown() {
+ const root = this._insertedElem;
+ if(root) {
+ root.parentNode.removeChild(root);
+ }
+ }
+
+ /**
+ * Update the entire menu when keyboards are registered or deregistered
+ **/
+ readonly updateKeyboardList = () => {
+ this.updateList = false;
+
+ if(!this.init) {
+ return;
+ }
+
+ // Clear existing list first (first two nodes must be preserved)
+ for(let i = this._KeymanWeb_KbdList.childNodes.length; i>2; i--) {
+ this._KeymanWeb_KbdList.removeChild(this._KeymanWeb_KbdList.childNodes[i-1]);
+ }
+
+ const kbds=keymanweb.getKeyboards();
+ if(kbds.length > 0) {
+ for(var i:number=0; i 26) {
+ _t=_t.substr(0,24)+'\u2026';
+ }
+ _a2.appendChild(document.createTextNode(_t));
+ _a2.onclick = this._SelectKeyboard;
+ _a2.href = '#';
+ _a2.id='KMWSel_'+Lki+'$'+Lklc;
+ _li2.appendChild(_a2);
+ this._KeymanWeb_KbdList.appendChild(_li2);
+ }
+
+ // Define appearance of this interface
+ private _Appearance = `
+#kmwico, #kmwkbd {
+ vertical-align: middle;
+}
+
+#KeymanWebControl {
+ float:left;
+}
+
+#KeymanWebControl * {
+ letter-spacing: 0px !important;
+ line-height: 1li !important;
+ white-space: nowrap !important;
+}
+
+#KeymanWebControl #kmwico img {
+ vertical-align: top;
+ padding: 0;
+ margin: 0;
+ border: none;
+}
+
+#KeymanWebControl #kmwico, #kmwico ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+
+#KeymanWebControl #kmwico_a {
+ display: block;
+ /* border: none !important; */
+ width: 22px; height: 23px; /* sizes needed for kmw_button.gif */
+}
+
+#KeymanWebControl #kmwico li {
+ text-align: left;
+}
+
+#KeymanWebControl #kmwico li ul {
+ display: block;
+ position: absolute;
+ left: -5999px;
+ border: solid 2px #ad4a28;
+ background: white;
+ border-radius: 4px;
+ box-shadow: 4px 4px 2px #666;
+ z-index: 10011; /* above the osk */
+}
+
+#KeymanWebControl #kmwico li.sfunhover ul {
+ display: none; left: -5999px;
+}
+
+#KeymanWebControl #kmwico li:hover ul, #kmwico li.sfhover ul {
+ display: block;
+ left: auto;
+}
+
+#KeymanWebControl #kmwico ul li {
+ float: none;
+ padding: 0 !important;
+ margin: 0 !important;
+ width: 136px !important;
+}
+
+#KeymanWebControl #KMW_LanguageName {
+ font-weight: bold;
+}
+
+#KeymanWebControl #kmwico ul li a, #kmwico ul li a:visited {
+ display: block;
+ padding: 2px 4px !important;
+ border: none !important;
+ /* width: auto; */
+ color: #404040;
+ font-family: Tahoma,Verdana,Arial,sans-serif;
+ font-size: 8pt;
+ text-decoration: none;
+}
+
+#KeymanWebControl #kmwico ul li a.selected {
+ font-weight: bold;
+ color: black;
+}
+
+#KeymanWebControl #kmwico ul li a:hover {
+ color: white;
+ background-color: #ad4a28;
+}
+
+#KeymanWebControl #kmwico ul li a.kmw_disabled, #KeymanWebControl #kmwico ul li a.kmw_disabled:hover {
+ color: #c0c0c0; cursor: default;
+ background-color: white;
+}
+
+#KeymanWebControl #kmwico ul li a.kmw_show span#KMW_KbdHiddenMsg, #KeymanWebControl #kmwico ul li a.kmw_disabled span#KMW_KbdVisibleMsg {
+ display: none;
+}
+
+#KeymanWebControl #kmwico ul li a.kmw_show span#KMW_KbdVisibleMsg {
+ display: inline;
+}
+
+#KeymanWebControl #kmwico ul li a.kmw_hide span#KMW_KbdHiddenMsg {
+ display: inline;
+}
+
+#KeymanWebControl #kmwico ul li a.kmw_hide span#KMW_KbdVisibleMsg {
+ display: none;
+}
+
+#KeymanWebControl #kmwico ul li#KMW_ButtonUI_KbdIcon {
+ border-bottom: solid 1px #ad4a28;
+}
+`
}
- ui.shutdown = function() {
- var root = ui._insertedElem;
- if(root) {
- root.parentNode.removeChild(root);
- }
- }
+ const ui = keymanweb.ui = new UIButton();
/**
* Keyboard registration event handler
@@ -416,182 +663,15 @@ if(!window['keyman']['ui']['name']) {
* Set a timer to update the UI keyboard list on timeout after each keyboard is registered,
* thus updating only once when only if multiple keyboards are registered together
*/
- keymanweb['addEventListener']('keyboardregistered',
- function(p)
- {
- ui.updateList = true;
- if(ui.updateTimer) clearTimeout(ui.updateTimer);
- ui.updateTimer = setTimeout(ui.updateKeyboardList,20);
- });
-
-
- /**
- * Update the entire menu when keyboards are registered or deregistered
- **/
- ui.updateKeyboardList = function()
- {
- ui.updateList = false;
-
- if(!ui.init) return;
-
- // Clear existing list first (first two nodes must be preserved)
- for(var i:number=ui._KeymanWeb_KbdList.childNodes.length; i>2; i--)
- ui._KeymanWeb_KbdList.removeChild(ui._KeymanWeb_KbdList.childNodes[i-1]);
-
- var kbds=keymanweb['getKeyboards']();
- if(kbds.length > 0)
- {
- for(var i:number=0; i 26) _t=_t.substr(0,24)+'\u2026';
- _a2.appendChild(document.createTextNode(_t));
- _a2.onclick = ui._SelectKeyboard;
- _a2.href = '#';
- _a2.id='KMWSel_'+Lki+'$'+Lklc;
- _li2.appendChild(_a2);
- ui._KeymanWeb_KbdList.appendChild(_li2);
- }
-
- // Define appearance of this interface
- ui._Appearance =
- "#kmwico, #kmwkbd {"+
- "vertical-align: middle;"+
- "} "+
-
- "#KeymanWebControl {float:left;} "+
-
- "#KeymanWebControl * "+
- "{"+
- "letter-spacing: 0px !important;"+
- "line-height: 1li !important;"+
- "white-space: nowrap !important;"+
- "} "+
-
- "#KeymanWebControl #kmwico img {"+
- "vertical-align: top;"+
- "padding: 0;"+
- "margin: 0;"+
- "border: none;"+
- "} "+
-
- "#KeymanWebControl #kmwico, #kmwico ul {"+
- "padding: 0;"+
- "margin: 0;"+
- "list-style: none;"+
- "} "+
-
- "#KeymanWebControl #kmwico_a {"+
- "display: block;"+
- //"border: none !important;"+
- "width: 22px; height: 23px; "+ /* sizes needed for kmw_button.gif */
- "} "+
-
- "#KeymanWebControl #kmwico li { "+
- "text-align: left;"+
- "} "+
-
- "#KeymanWebControl #kmwico li ul {"+
- "display: block;"+
- "position: absolute;"+
- "left: -5999px;"+
- "border: solid 2px #ad4a28;"+
- "background: white;"+
- "border-radius: 4px;"+
- "box-shadow: 4px 4px 2px #666;"+
- "z-index: 10011;"+ /* above the osk */
- "} "+
-
- "#KeymanWebControl #kmwico li.sfunhover ul {"+
- "display: none; left: -5999px;"+
- "} "+
-
- "#KeymanWebControl #kmwico li:hover ul, #kmwico li.sfhover ul {"+
- "display: block;"+
- "left: auto;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li {"+
- "float: none;"+
- "padding: 0 !important;"+
- "margin: 0 !important;"+
- "width: 136px !important;"+
- "} "+
-
- "#KeymanWebControl #KMW_LanguageName {"+
- "font-weight: bold;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a, #kmwico ul li a:visited {"+
- "display: block;"+
- "padding: 2px 4px !important;"+
- "border: none !important;"+
- // "width: auto;"+
- "color: #404040;"+
- "font-family: Tahoma,Verdana,Arial,sans-serif;"+
- "font-size: 8pt;"+
- "text-decoration: none;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a.selected {"+
- "font-weight: bold;"+
- "color: black;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a:hover {"+
- "color: white;"+
- "background-color: #ad4a28;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a.kmw_disabled, #KeymanWebControl #kmwico ul li a.kmw_disabled:hover {"+
- "color: #c0c0c0; cursor: default;"+
- "background-color: white;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a.kmw_show span#KMW_KbdHiddenMsg, #KeymanWebControl #kmwico ul li a.kmw_disabled span#KMW_KbdVisibleMsg {"+
- "display: none;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a.kmw_show span#KMW_KbdVisibleMsg {"+
- "display: inline;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a.kmw_hide span#KMW_KbdHiddenMsg {"+
- "display: inline;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li a.kmw_hide span#KMW_KbdVisibleMsg {"+
- "display: none;"+
- "} "+
-
- "#KeymanWebControl #kmwico ul li#KMW_ButtonUI_KbdIcon {"+
- "border-bottom: solid 1px #ad4a28;"+
- "} ";
+ ui.updateTimer = window.setTimeout(ui.updateKeyboardList, 20);
+ });
// but also call initialization when script loaded, which is after KMW initialization for asynchronous script loading
- ui.Initialize();
+ ui.initialize();
} catch(err){}
}
\ No newline at end of file
diff --git a/web/src/app/ui/kmwuifloat.ts b/web/src/app/ui/kmwuifloat.ts
index b9313f6e2f..0d15a3d649 100644
--- a/web/src/app/ui/kmwuifloat.ts
+++ b/web/src/app/ui/kmwuifloat.ts
@@ -1,12 +1,17 @@
/***
- KeymanWeb 11.0
- Copyright 2019 SIL International
+ KeymanWeb 17.0
+ Copyright 2019-2023 SIL International
***/
+import type { KeymanEngine, KeyboardCookie, UIModule } from 'keyman/app/browser';
+import type { FloatingOSKViewCookie } from 'keyman/engine/osk';
+
+declare var keyman: KeymanEngine
+
// If a UI module has been loaded, we can rely on the publically-published 'name' property
// having been set as a way to short-out a UI reload. Its parent object always exists by
// this point in the build process.
-if(!window['keyman']['ui']['name']) {
+if(!keyman?.ui?.name) {
/********************************/
/* */
/* Floating User Interface */
@@ -25,531 +30,573 @@ if(!window['keyman']['ui']['name']) {
try {
// Declare KeymanWeb, OnScreen keyboard and Util objects
- var keymanweb=window['keyman'];
- var util=keymanweb['util'];
+ const keymanweb = keyman;
+ const util=keymanweb.util;
+
var dbg=keymanweb['debug'];
// Disable UI for touch devices
- if(util['isTouchDevice']()) throw '';
-
- // User interface global and local variables
- keymanweb['ui'] = {};
- var ui=keymanweb['ui'];
- ui['name'] = 'float';
-
- ui.KeyboardSelector = null;
-
- ui.outerDiv = null; // replaces DivKeymanWeb
- ui.innerDiv = null; // replaces Lkdiv
- ui.oskButton = null; // toggles OSK on or off
- ui.kbdIcon = null; // keyboard icon within OSK button
- ui.selecting = false; // control focus behaviour during selection
- ui.updateList = true; // control keyboard list updating
- ui.updateTimer = null; // prevent unnecessary list refreshing
- ui.floatRight = false; // align left by default
- ui.initialized = false; // initialization flag
- ui.initTimer = null;
-
- /**
- * Display or hide the OSK from the OSK icon link
- */
- ui.toggleOSK = function()
- {
- keymanweb['activatingUI'](true);
- let osk = keymanweb['osk'];
- if(osk && osk['show'])
- {
- if(osk['isEnabled']()) osk['hide'](); else osk['show'](true);
- }
- if(window.event) window.event.returnValue=false;
- keymanweb['focusLastActiveElement']();
- keymanweb['activatingUI'](false);
- return false;
+ if(util.isTouchDevice()) {
+ throw '';
}
- /**
- * Function Initialize
- * Scope Private
- * Description UI Initialization
- **/
- ui['initialize'] = ui.Initialize = function() {
- if(ui.initTimer) {
- window.clearTimeout(ui.initTimer);
- ui.initTimer = null;
+ class UIFloat implements UIModule {
+ // User interface global and local variables
+ readonly name = 'float';
+
+ /**
+ * The top-level element for the keyboard-selection drop menu
+ */
+ KeyboardSelector: HTMLSelectElement = null;
+
+ /**
+ * Container for all Float UI elements (visible when KeymanWeb is active)
+ */
+ outerDiv: HTMLDivElement = null; // replaces DivKeymanWeb
+
+ innerDiv: HTMLDivElement = null; // replaces Lkdiv
+
+ /**
+ * The button element allowing users to toggle the OSK on or off
+ */
+ oskButton: HTMLDivElement = null;
+
+ /**
+ * keyboard icon within the OSK button
+ */
+ kbdIcon: HTMLImageElement = null;
+
+ /**
+ * Tracks ongoing user interactions with the Float UI. This is used to help
+ * control focus-related behaviors during selection so that KMW may more easily
+ * maintain the user's intended focus & expected context.
+ */
+ selecting = false;
+
+ updateList = true; // control keyboard list updating
+ updateTimer: number = 0; // prevent unnecessary list refreshing
+ floatRight = false; // align left by default
+ initialized = false; // initialization flag
+ initTimer: number = 0;
+
+ /**
+ * Display or hide the OSK from the OSK icon link
+ */
+ readonly toggleOSK = () => {
+ keymanweb.activatingUI(true);
+ let osk = keymanweb.osk;
+ if(osk && osk.show) {
+ if(osk.isEnabled()) {
+ osk.hide();
+ } else {
+ osk.show(true);
+ }
+ }
+ if(window.event) {
+ window.event.returnValue=false;
+ }
+ keymanweb.focusLastActiveElement();
+ keymanweb.activatingUI(false);
+ return false;
}
- // Must always initialize after keymanWeb itself, otherwise options are undefined
- if(!keymanweb['initialized']) {
- ui.initTimer = window.setTimeout(ui.Initialize, 50);
- return;
- }
-
- if(ui.initialized || util['isTouchDevice']()) {
- return;
- }
-
- var imgPath=util['getOption']('resources')+"ui/float/";
-
- ui.outerDiv = util['createElement']('DIV'); // Container for UI (visible when KeymanWeb is active)
- ui.innerDiv = util['createElement']('DIV'); // inner div for UI
- ui.kbdIcon = util['createElement']('IMG');
- ui.outerDiv.innerHTML = ""
- + "
"; /* I2081 */
-
- var s=ui.outerDiv.style;
- s.backgroundColor='white'; s.border='solid 1px black'; s.position='absolute'; s.height='18px';
- s.font='bold 8pt sans-serif'; s.display='none'; s.textAlign='left';s.overflow='hidden';
-
- util['attachDOMEvent'](ui.outerDiv,'mousedown',ui._SelectorMouseDown);
- util['attachDOMEvent'](ui.outerDiv,'mouseover',ui._SelectorMouseOver);
- util['attachDOMEvent'](ui.outerDiv,'mouseout',ui._SelectorMouseOut);
-
- // Register keymanweb events
- ui.registerEvents();
-
- ui.kbdIcon.src = imgPath+'kbdicon.gif';
- ui.kbdIcon.title = 'Display visual keyboard';
-
- // Set initial OSK button style (off by default)
- ui.oskButtonState(false);
-
- var Lhdiv = util['createElement']('DIV');
- ui.oskButton = Lhdiv;
- Lhdiv.onclick = ui.toggleOSK;
- Lhdiv.appendChild(ui.kbdIcon);
- ui.innerDiv.appendChild(Lhdiv);
- ui.outerDiv.appendChild(ui.innerDiv);
- document.body.appendChild(ui.outerDiv);
-
- ui.KeyboardSelector = util['createElement']('SELECT'); // ControlSelector - KeymanWeb keyboard selector
-
- s=ui.KeyboardSelector.style;
- s.font='8pt sans-serif'; s.backgroundColor='#f3e5de'; s.border='solid 1px #7B9EBD'; s.height='16px';s.margin='1px 2px 0px 2px';
- s.left='20px'; s.top='0px'; s.position='absolute'; s.maxWidth='150px';
-
- util['attachDOMEvent'](ui.KeyboardSelector,'change',ui.SelectKeyboardChange);
- util['attachDOMEvent'](ui.KeyboardSelector,'blur',ui.SelectBlur);
-
- ui.innerDiv.appendChild(ui.KeyboardSelector); //this may need to be moved up....
-
- // Check required interface alignment and default keyboard
- var opt=util['getOption']('ui'),dfltKeyboard='(System keyboard)';
- if(opt && typeof(opt) == 'object')
- {
- if(typeof(opt['position']) == 'string' && opt['position'] == 'right')
- ui.floatRight = true;
- if(typeof(opt['default']) == 'string')
- dfltKeyboard = opt['default'];
- }
-
- var Lopt = util['createElement']('OPTION');
- Lopt.value = '-';
- Lopt.innerHTML = dfltKeyboard;
- ui.KeyboardSelector.appendChild(Lopt);
- Lopt = null;
-
- // This must be set before updating the keyboard list to prevent recursion!
- ui.initialized = true;
-
- // Update the keyboard list if required
- ui.updateKeyboardList();
-
- //may also want to initialize style sheet here ??
- }
-
- ui._UnloadUserInterface = function() {
- ui.KeyboardSelector = ui.innerDiv = ui.outerDiv = ui.kbdIcon = null;
- };
- /**
- * UI removal - resource cleanup
- */
- keymanweb['addEventListener']('unloaduserinterface', ui._UnloadUserInterface);
-
-
- ui.shutdown = function() {
- var root = ui.outerDiv;
- if(root) {
- root.parentNode.removeChild(root);
- }
-
- ui._UnloadUserInterface();
-
- if(window.removeEventListener) {
- window.removeEventListener('resize', ui._Resize, false);
- }
- }
-
- /**
- * Update list of keyboards shown by UI
- */
- ui.updateKeyboardList = function()
- {
- // Do nothing unless list requires updating
- if(ui.updateList)
- {
- if(!ui.initialized) ui.Initialize();
-
- // Remove current list (except for default element)
- var i,opts=ui.KeyboardSelector.getElementsByTagName('OPTION');
- for(i=opts.length; i>1; i--)
- {
- ui.KeyboardSelector.removeChild(opts[i-1]);
+ /**
+ * Function Initialize
+ * Scope Private
+ * Description UI Initialization
+ **/
+ readonly initialize = () => {
+ if(this.initTimer) {
+ window.clearTimeout(this.initTimer);
+ this.initTimer = null;
}
- // Loop over installed keyboards and add to selection list
- var Ln,Lopt,Lkbds=keymanweb['getKeyboards']();
+ // Must always initialize after keymanWeb itself, otherwise options are undefined
+ if(!keymanweb.initialized) {
+ this.initTimer = window.setTimeout(this.initialize, 50);
+ return;
+ }
- for(Ln=0; Ln"; /* I2081 */
+
+ var s=this.outerDiv.style;
+ s.backgroundColor='white'; s.border='solid 1px black'; s.position='absolute'; s.height='18px';
+ s.font='bold 8pt sans-serif'; s.display='none'; s.textAlign='left';s.overflow='hidden';
+
+ util.attachDOMEvent(this.outerDiv, 'mousedown', this._SelectorMouseDown);
+ util.attachDOMEvent(this.outerDiv, 'mouseover', this._SelectorMouseOver);
+ util.attachDOMEvent(this.outerDiv, 'mouseout', this._SelectorMouseOut);
+
+ // Register keymanweb events
+ this.registerEvents();
+
+ this.kbdIcon.src = imgPath+'kbdicon.gif';
+ this.kbdIcon.title = 'Display visual keyboard';
+
+ // Set initial OSK button style (off by default)
+ this.oskButtonState(false);
+
+ var Lhdiv = util.createElement('div');
+ this.oskButton = Lhdiv;
+ Lhdiv.onclick = this.toggleOSK;
+ Lhdiv.appendChild(this.kbdIcon);
+ this.innerDiv.appendChild(Lhdiv);
+ this.outerDiv.appendChild(this.innerDiv);
+ document.body.appendChild(this.outerDiv);
+
+ this.KeyboardSelector = util.createElement('select'); // ControlSelector - KeymanWeb keyboard selector
+
+ s=this.KeyboardSelector.style;
+ s.font='8pt sans-serif';
+ s.backgroundColor='#f3e5de';
+ s.border='solid 1px #7B9EBD';
+ s.height='16px';
+ s.margin='1px 2px 0px 2px';
+ s.left='20px';
+ s.top='0px';
+ s.position='absolute';
+ s.maxWidth='150px';
+
+ util.attachDOMEvent(this.KeyboardSelector, 'change', this.SelectKeyboardChange);
+ util.attachDOMEvent(this.KeyboardSelector, 'blur', this.SelectBlur);
+
+ this.innerDiv.appendChild(this.KeyboardSelector); //this may need to be moved up....
+
+ // Check required interface alignment and default keyboard
+ var opt=util.getOption('ui'), dfltKeyboard='(System keyboard)';
+ if(opt && typeof(opt) == 'object') {
+ if(typeof(opt['position']) == 'string' && opt['position'] == 'right') {
+ this.floatRight = true;
+ } if(typeof(opt['default']) == 'string') {
+ dfltKeyboard = opt['default'];
+ }
+ }
+
+ var Lopt = util.createElement('option');
+ Lopt.value = '-';
+ Lopt.innerHTML = dfltKeyboard;
+ this.KeyboardSelector.appendChild(Lopt);
+ Lopt = null;
+
+ // This must be set before updating the keyboard list to prevent recursion!
+ this.initialized = true;
+
+ // Update the keyboard list if required
+ this.updateKeyboardList();
+
+ //may also want to initialize style sheet here ??
+ }
+
+ readonly _UnloadUserInterface = () => {
+ this.KeyboardSelector = this.innerDiv = this.outerDiv = this.kbdIcon = null;
+ };
+
+ /**
+ * UI removal - resource cleanup
+ */
+ shutdown() {
+ var root = this.outerDiv;
+ if(root) {
+ root.parentNode.removeChild(root);
+ }
+
+ this._UnloadUserInterface();
+
+ if(window.removeEventListener) {
+ window.removeEventListener('resize', this._Resize, false);
+ }
+ }
+
+ /**
+ * Update list of keyboards shown by UI
+ */
+ readonly updateKeyboardList = () => {
+ // Do nothing unless list requires updating
+ if(this.updateList) {
+ if(!this.initialized) {
+ this.initialize();
}
- ui.KeyboardSelector.appendChild(Lopt);
- Lopt = null;
+ // Remove current list (except for default element)
+ const opts=this.KeyboardSelector.getElementsByTagName('OPTION');
+ for(let i=opts.length; i>1; i--) {
+ this.KeyboardSelector.removeChild(opts[i-1]);
+ }
+
+ // Loop over installed keyboards and add to selection list
+ var Lkbds=keymanweb.getKeyboards();
+
+ for(let Ln=0; Ln {
+ var i=0;
- // Redisplay the UI to correct width for any new language entries
- if(keymanweb['getLastActiveElement']())
- {
- ui.HideInterface();
- ui.ShowInterface();
- }
- }
+ // This can be called during startup before fully initialized - ignore if so
+ if(!this.initialized) {
+ return;
+ }
- /**
- * Function updateMenu
- * Scope Private
- * @param {string} kbd
- * @param {string} lg
- * Description Update the UI menu selection
- * Separate arguments passed to allow better control of selection when a keyboard
- * is listed more than once for different language codes
- */
- ui.updateMenu = function(kbd,lg)
- {
- var i=0;
+ var match = kbd;
+ if(lg != '') {
+ match += ':' + lg;
+ }
- // This can be called during startup before fully initialized - ignore if so
- if(!ui.initialized) return;
+ if(kbd == '') {
+ this.KeyboardSelector.selectedIndex=0;
+ } else {
+ const opt=this.KeyboardSelector.getElementsByTagName('option');
+ for(i=0; i {
+ var s = this.kbdIcon.style;
+ s.width='24px';
+ s.height='13px';
+ s.top='1px';
+ s.verticalAlign='bottom';
+ s.padding='2px 2px 1px 2px';
+ s.position='absolute';
+ s.border=oskEnabled ? 'inset 1px #808080' : 'none';
+ s.background=oskEnabled ? '#f7e7de' : 'white';
+ s.display = 'block';
+ if(this.initialized) {
+ this.oskButton.style.display = 'block';
+ }
+ }
+
+ /**
+ * Register all keymanweb and OSK events only after keymanweb is fully initialized
*
- * Set a timer to update the UI keyboard list on timeout after each keyboard is registered,
- * thus updating only once when only if multiple keyboards are registered together
- */
- keymanweb['addEventListener']('keyboardregistered',
- function(p)
- {
- ui.updateList = true;
- if(ui.updateTimer) clearTimeout(ui.updateTimer);
- ui.updateTimer = setTimeout(ui.updateKeyboardList,200);
+ **/
+ registerEvents() {
+ /**
+ * Keyboard registration event handler
+ *
+ * Set a timer to update the UI keyboard list on timeout after each keyboard is registered,
+ * thus updating only once when only if multiple keyboards are registered together
+ */
+ keymanweb.addEventListener('keyboardregistered', (p) => {
+ this.updateList = true;
+ if(this.updateTimer) {
+ clearTimeout(this.updateTimer);
+ }
+ this.updateTimer = window.setTimeout(this.updateKeyboardList, 200);
});
- /**
- * Keyboard load event handler
- *
- * Set the menu selector to the currently saved keyboard when a keyboard is loaded
- *
- * Note: Cannot simply set it to the loaded keyboard,
- * as more than one language may be supported by that keyboard.
- */
- keymanweb['addEventListener']('keyboardloaded',
- function(p) {
- var sk = keymanweb['getSavedKeyboard']().split(':');
- if(sk.length > 1) ui.updateMenu(sk[0],sk[1]);
+ /**
+ * Keyboard load event handler
+ *
+ * Set the menu selector to the currently saved keyboard when a keyboard is loaded
+ *
+ * Note: Cannot simply set it to the loaded keyboard,
+ * as more than one language may be supported by that keyboard.
+ */
+ keymanweb.addEventListener('keyboardloaded', (p) => {
+ const sk = keymanweb.getSavedKeyboard().split(':');
+ if(sk.length > 1) {
+ this.updateMenu(sk[0],sk[1]);
+ }
});
- /**
- * Keyboard change event handler
- *
- * Update menu selection and control OSK display appropriately
- */
- keymanweb['addEventListener']('keyboardchange',
- function(p)
- {
+ /**
+ * Keyboard change event handler
+ *
+ * Update menu selection and control OSK display appropriately
+ */
+ keymanweb.addEventListener('keyboardchange', (p) => {
// Update the keyboard selector whenever a keyboard is loaded
- ui.updateMenu(p['internalName'],p['languageCode']);
+ this.updateMenu(p.internalName, p.languageCode);
// (Conditionally) display the OSK button, and set the style
- ui.addButtonOSK();
+ this.addButtonOSK();
});
- let osk = keymanweb['osk'];
- if(!osk) {
- return;
- }
- /**
- * Show OSK event handler: show or hide the OSK button (never display if a CJK keyboard)
- */
- osk['addEventListener']('show',
- function(oskPosition)
- {
- ui.addButtonOSK();
+ let osk = keymanweb.osk;
+ if(!osk) {
+ return;
+ }
+
+ /**
+ * Show OSK event handler: show or hide the OSK button (never display if a CJK keyboard)
+ */
+ osk.addEventListener('show', (oskPosition) => {
+ this.addButtonOSK();
return oskPosition;
});
- /**
- * Hide OSK event handler
- */
+ /**
+ * Hide OSK event handler
+ */
- osk['addEventListener']('hide',
- function(hiddenByUser)
- {
- if(ui.initialized) ui.oskButtonState(false);
- });
- }
-
- /**
- * Function _SelectorMouseDown
- * Scope Private
- * @param {Object} e event
- * Description Set KMW UI activation state on mouse click
- */
- ui._SelectorMouseDown = function(e)
- {
- if(keymanweb['activatingUI']) keymanweb['activatingUI'](1);
- }
-
- /**
- * Function _SelectorMouseOver
- * Scope Private
- * @param {Object} e event
- * Description Set KMW UI activation state on mouse over
- */
- ui._SelectorMouseOver = function(e)
- {
- if(keymanweb['activatingUI']) keymanweb['activatingUI'](1);
- }
-
- /**
- * Function _SelectorMouseOut
- * Scope Private
- * @param {Object} e event
- * Description Clear KMW UI activation state on mouse out
- */
- ui._SelectorMouseOut = function(e)
- {
- if(keymanweb['activatingUI']) keymanweb['activatingUI'](0);
- }
-
- /**
- * Function _SelectKeyboardChange
- * Scope Private
- * @param {Object} e event
- * Description Change active keyboard in response to user selection event
- */
- ui.SelectKeyboardChange = function(e)
- {
- keymanweb['activatingUI'](true);
- if(ui.KeyboardSelector.value != '-')
- {
- var i=ui.KeyboardSelector.selectedIndex;
- var t=ui.KeyboardSelector.options[i].value.split(':');
- keymanweb['setActiveKeyboard'](t[0],t[1]);
- }
- else
- keymanweb['setActiveKeyboard']('');
-
- //if(osk['show']) osk['show'](osk['isEnabled']()); handled by keyboard change event???
- keymanweb['focusLastActiveElement']();
- keymanweb['activatingUI'](false);
- ui.selecting = true;
- }
-
- /**
- * Function _SelectBlur
- * Scope Private
- * @param {Object} e event
- * Description Ensure OSK is hidden when moving focus after reselecting a keyboard
- */
- ui.SelectBlur = function(e)
- {
- if(!ui.selecting) keymanweb['focusLastActiveElement']();
- ui.selecting = false;
- }
-
- /**
- * Function ShowInterface
- * Scope Private
- * @param {number=} Px x-position for KMW window
- * @param {number=} Py y-position for KMW window
- * Description Display KMW window at specified position
- */
- ui.ShowInterface = function(Px, Py)
- {
- if(!ui.initialized) return;
-
- var Ls = ui.outerDiv.style;
-
- if(Px && Py) {
- Ls.left = Px + 'px';
- Ls.top = Py + 'px';
- }
- Ls.display = 'block';
-
- ui.kbdIcon.style.left = ui.KeyboardSelector.offsetWidth + 24 + 'px';
-
- // (Conditionally) display the OSK button
- ui.addButtonOSK();
-
- // Set the language selection to the currently active keyboard, if listed
- ui.updateMenu(keymanweb['getActiveKeyboard'](),keymanweb['getActiveLanguage']());
- }
-
- /**
- * Function HideInterface
- * Scope Private
- * Description Completely hide KMW window
- */
- ui.HideInterface = function()
- {
- if(!ui.initialized) return;
-
- ui.outerDiv.style.display = 'none';
- }
-
-
- /**
- * Function addButtonOSK
- * Scope Private
- * Description Display the OSK button unless a CJK keyboard (or English)
- */
- ui.addButtonOSK = function()
- {
- if(ui.oskButton != null)
- {
- if(keymanweb['isCJK']() || (ui.KeyboardSelector.selectedIndex==0))
- {
- ui.oskButton.style.display = 'none';
- ui.outerDiv.style.width = ui.KeyboardSelector.offsetWidth+30+'px';
- }
- else
- {
- ui.oskButton.style.display = 'block';
- let osk = keymanweb['osk'];
- if(osk) {
- ui.oskButtonState(osk['isEnabled']());
- } else {
- ui.oskButtonState(false);
+ osk.addEventListener('hide', (hiddenByUser) => {
+ if(this.initialized) {
+ this.oskButtonState(false);
}
- ui.outerDiv.style.width = ui.KeyboardSelector.offsetWidth+56+'px';
+ });
+ }
+
+ /**
+ * Function _SelectorMouseDown
+ * Scope Private
+ * @param {Object} e event
+ * Description Set KMW UI activation state on mouse click
+ */
+ readonly _SelectorMouseDown = (e: MouseEvent) => {
+ if(keymanweb.activatingUI) {
+ keymanweb.activatingUI(1);
}
}
- }
- //TODO: had to expose properties of params - what does that do? (focus event doesn't normally include these properties?)
- keymanweb['addEventListener']('controlfocused',
- function(params)
- {
- if(params['activeControl'] == null || params['activeControl']['_kmwAttachment'])
- {
- /*if(keymanweb.domManager._IsEditableIframe(Ltarg))
- Ltarg = Ltarg.defaultView.frameElement;*/
- if(ui.floatRight) // I1296
- ui.ShowInterface(util['getAbsoluteX'](params.target) + params.target.offsetWidth + 1, util['getAbsoluteY'](params.target) + 1);
- else
- ui.ShowInterface(util['getAbsoluteX'](params.target), util['getAbsoluteY'](params.target)
- - parseInt(util['getStyleValue'](ui.outerDiv,'height'),10) - 2);
+
+ /**
+ * Function _SelectorMouseOver
+ * Scope Private
+ * @param {Object} e event
+ * Description Set KMW UI activation state on mouse over
+ */
+ readonly _SelectorMouseOver = (e: MouseEvent) => {
+ if(keymanweb.activatingUI) {
+ keymanweb.activatingUI(1);
+ }
+ }
+
+ /**
+ * Function _SelectorMouseOut
+ * Scope Private
+ * @param {Object} e event
+ * Description Clear KMW UI activation state on mouse out
+ */
+ readonly _SelectorMouseOut = (e: MouseEvent) => {
+ if(keymanweb.activatingUI) {
+ keymanweb.activatingUI(0);
+ }
+ }
+
+ /**
+ * Function _SelectKeyboardChange
+ * Scope Private
+ * @param {Object} e event
+ * Description Change active keyboard in response to user selection event
+ */
+ readonly SelectKeyboardChange = (e) => {
+ keymanweb.activatingUI(true);
+
+ if(this.KeyboardSelector.value != '-') {
+ var i=this.KeyboardSelector.selectedIndex;
+ var t=this.KeyboardSelector.options[i].value.split(':');
+ keymanweb.setActiveKeyboard(t[0],t[1]);
+ } else {
+ keymanweb.setActiveKeyboard('');
+ }
+
+ //if(osk['show']) osk['show'](osk['isEnabled']()); handled by keyboard change event???
+ keymanweb.focusLastActiveElement();
+ keymanweb.activatingUI(false);
+ this.selecting = true;
+ }
+
+ /**
+ * Function _SelectBlur
+ * Scope Private
+ * @param {Object} e event
+ * Description Ensure OSK is hidden when moving focus after reselecting a keyboard
+ */
+ readonly SelectBlur = (e) => {
+ if(!this.selecting) {
+ keymanweb.focusLastActiveElement();
+ }
+ this.selecting = false;
+ }
+
+ /**
+ * Function ShowInterface
+ * Scope Private
+ * @param {number=} Px x-position for KMW window
+ * @param {number=} Py y-position for KMW window
+ * Description Display KMW window at specified position
+ */
+ readonly ShowInterface = (Px?: number, Py?: number) => {
+ if(!this.initialized) return;
+
+ var Ls = this.outerDiv.style;
+
+ if(Px && Py) {
+ Ls.left = Px + 'px';
+ Ls.top = Py + 'px';
+ }
+ Ls.display = 'block';
+
+ this.kbdIcon.style.left = this.KeyboardSelector.offsetWidth + 24 + 'px';
+
+ // (Conditionally) display the OSK button
+ this.addButtonOSK();
+
+ // Set the language selection to the currently active keyboard, if listed
+ this.updateMenu(keymanweb.getActiveKeyboard(), keymanweb.getActiveLanguage());
+ }
+
+ /**
+ * Function HideInterface
+ * Scope Private
+ * Description Completely hide KMW window
+ */
+ readonly HideInterface = () => {
+ if(!this.initialized) {
+ return;
+ }
+
+ this.outerDiv.style.display = 'none';
+ }
+
+ /**
+ * Function addButtonOSK
+ * Scope Private
+ * Description Display the OSK button unless a CJK keyboard (or English)
+ */
+ readonly addButtonOSK = () => {
+ if(this.oskButton != null) {
+ if(keymanweb.isCJK() || (this.KeyboardSelector.selectedIndex==0)) {
+ this.oskButton.style.display = 'none';
+ this.outerDiv.style.width = this.KeyboardSelector.offsetWidth+30+'px';
+ } else {
+ this.oskButton.style.display = 'block';
+ let osk = keymanweb.osk;
+ if(osk) {
+ this.oskButtonState(osk.isEnabled());
+ } else {
+ this.oskButtonState(false);
+ }
+ this.outerDiv.style.width = this.KeyboardSelector.offsetWidth+56+'px';
+ }
+ }
+ }
+
+ /**
+ * Function _Resize
+ * Scope Private
+ * @param {Object} e event object
+ * @return {boolean}
+ * Description Display KMW OSK at specified position (returns nothing)
+ */
+ readonly _Resize = (e) => {
+ if(this.outerDiv.style.display =='block') {
+ var elem = keymanweb.getLastActiveElement();
+ if(this.floatRight) { // I1296
+ this.ShowInterface(util.getAbsoluteX(elem) + elem.offsetWidth + 1, util.getAbsoluteY(elem) + 1);
+ } else {
+ this.ShowInterface(util.getAbsoluteX(elem) + 1, util.getAbsoluteY(elem) + elem.offsetHeight + 1);
+ }
}
return true;
- });
+ }
+ }
- keymanweb['addEventListener']('controlblurred',
- function(params)
- {
- if(!params['event']) return true; // I2404 - Manage IE events in IFRAMEs
+ const ui=keymanweb.ui = new UIFloat();
- if(!params['isActivating']) ui.HideInterface();
-
- return true;
- });
-
- /**
- * Function _Resize
- * Scope Private
- * @param {Object} e event object
- * @return {boolean}
- * Description Display KMW OSK at specified position (returns nothing)
- */
- ui._Resize = function(e)
- {
- if(ui.outerDiv.style.display =='block')
- {
- var elem = keymanweb['getLastActiveElement']();
- if(ui.floatRight) // I1296
- ui.ShowInterface(util['getAbsoluteX'](elem) + elem.offsetWidth + 1, util['getAbsoluteY'](elem) + 1);
- else
- ui.ShowInterface(util['getAbsoluteX'](elem) + 1, util['getAbsoluteY'](elem) + elem.offsetHeight + 1);
+ //TODO: had to expose properties of params - what does that do? (focus event doesn't normally include these properties?)
+ keymanweb.addEventListener('controlfocused', (params) => {
+ // ... this check shouldn't need to check _kmwAttachment directly.
+ if(params.activeControl == null || params.activeControl['_kmwAttachment']) {
+ /*if(keymanweb.domManager._IsEditableIframe(Ltarg))
+ Ltarg = Ltarg.defaultView.frameElement;*/
+ if(ui.floatRight) { // I1296
+ ui.ShowInterface(util.getAbsoluteX(params.target) + params.target.offsetWidth + 1, util.getAbsoluteY(params.target) + 1);
+ } else {
+ ui.ShowInterface(util.getAbsoluteX(params.target), util.getAbsoluteY(params.target)
+ - parseInt(util.getStyleValue(ui.outerDiv,'height'),10) - 2);
+ }
}
return true;
+ });
+
+ keymanweb.addEventListener('controlblurred', (params) => {
+ if(!params.event) {
+ return true; // I2404 - Manage IE events in IFRAMEs
+ }
+
+ if(!params.isActivating) {
+ ui.HideInterface();
+ }
+
+ return true;
+ });
+
+ if(window.addEventListener) {
+ window.addEventListener('resize', ui._Resize, false);
}
- if(window.addEventListener)
- window.addEventListener('resize', ui._Resize, false);
-
// but also call initialization when script loaded, which is after KMW initialization for asynchronous script loading
- ui.Initialize();
+ ui.initialize();
+
+ // is/was never actually raised. Note that the `shutdown` method likely fulfills a similar role.
+ // keymanweb.addEventListener('unloaduserinterface', ui._UnloadUserInterface);
} catch(err){}
diff --git a/web/src/app/ui/tsconfig.json b/web/src/app/ui/tsconfig.json
index 84f3b46025..83eef7b7a0 100644
--- a/web/src/app/ui/tsconfig.json
+++ b/web/src/app/ui/tsconfig.json
@@ -9,8 +9,8 @@
},
"extends": "../../tsconfig.base.json",
"files": [
- // "kmwuibutton.ts",
- // "kmwuifloat.ts",
+ "kmwuibutton.ts",
+ "kmwuifloat.ts",
"kmwuitoggle.ts",
"kmwuitoolbar.ts"
],
diff --git a/web/src/test/auto/dom/CI.conf.cjs b/web/src/test/auto/dom/CI.conf.cjs
index c7c9813df7..a96ffebbed 100644
--- a/web/src/test/auto/dom/CI.conf.cjs
+++ b/web/src/test/auto/dom/CI.conf.cjs
@@ -18,7 +18,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- // Can't set in base.conf.js b/c of constant's definition style.
+ // Can't set in base.conf.cjs b/c of constant's definition style.
logLevel: config.LOG_INFO
};
diff --git a/web/src/test/auto/dom/manual.conf.cjs b/web/src/test/auto/dom/manual.conf.cjs
index 88e20d283c..37d982e9b5 100644
--- a/web/src/test/auto/dom/manual.conf.cjs
+++ b/web/src/test/auto/dom/manual.conf.cjs
@@ -18,7 +18,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- // Can't set in base.conf.js b/c of constant's definition style.
+ // Can't set in base.conf.cjs b/c of constant's definition style.
logLevel: config.LOG_INFO
};
diff --git a/web/src/test/auto/integrated/CI.conf.cjs b/web/src/test/auto/integrated/CI.conf.cjs
index 38ee2c97a0..94e94a0fc8 100644
--- a/web/src/test/auto/integrated/CI.conf.cjs
+++ b/web/src/test/auto/integrated/CI.conf.cjs
@@ -1,4 +1,4 @@
-var BASE_CONFIG = require("./base.conf.js");
+var BASE_CONFIG = require("./base.conf.cjs");
var ci_config_adapter = require("../../../../../common/test/resources/karma-browserstack-config.cjs");
module.exports = ci_config_adapter(BASE_CONFIG, "full");
\ No newline at end of file
diff --git a/web/src/test/auto/integrated/cases/basics.js b/web/src/test/auto/integrated/cases/basics.js
index ac99e9f830..c06ce73d38 100644
--- a/web/src/test/auto/integrated/cases/basics.js
+++ b/web/src/test/auto/integrated/cases/basics.js
@@ -73,60 +73,60 @@ Modernizr.on('touchevents', function(result) {
})
});
-// describe('Basic Button UI', function() {
+ describe('Basic Button UI', function() {
-// beforeEach(function() {
-// this.timeout(testconfig.timeouts.uiLoad);
-// fixture.setBase('fixtures');
-// fixture.load('singleInput.html');
+ beforeEach(function() {
+ this.timeout(testconfig.timeouts.uiLoad);
+ fixture.setBase('fixtures');
+ fixture.load('singleInput.html');
-// // Loads two scripts in parallel, but just in case, 2x timeout.
-// return setupKMW('button', testconfig.timeouts.uiLoad);
-// });
+ // Loads two scripts in parallel, but just in case, 2x timeout.
+ return setupKMW('button', testconfig.timeouts.uiLoad);
+ });
-// afterEach(function() {
-// fixture.cleanup();
-// teardownKMW();
-// });
+ afterEach(function() {
+ fixture.cleanup();
+ teardownKMW();
+ });
-// it('The Button UI initializes correctly.', function() {
-// assert(keyman.ui.init, 'Initialization flag is set to false!');
-// })
-// });
+ it('The Button UI initializes correctly.', function() {
+ assert(keyman.ui.init, 'Initialization flag is set to false!');
+ })
+ });
-// describe('Basic Float UI', function() {
+ describe('Basic Float UI', function() {
-// beforeEach(function() {
-// this.timeout(testconfig.timeouts.uiLoad);
-// fixture.setBase('fixtures');
-// fixture.load('singleInput.html');
+ beforeEach(function() {
+ this.timeout(testconfig.timeouts.uiLoad);
+ fixture.setBase('fixtures');
+ fixture.load('singleInput.html');
-// // Loads two scripts in parallel, but just in case, 2x timeout.
-// return setupKMW('float', testconfig.timeouts.uiLoad);
-// });
+ // Loads two scripts in parallel, but just in case, 2x timeout.
+ return setupKMW('float', testconfig.timeouts.uiLoad);
+ });
-// afterEach(function() {
-// fixture.cleanup();
-// teardownKMW();
-// });
+ afterEach(function() {
+ fixture.cleanup();
+ teardownKMW();
+ });
-// it('The Float UI initializes correctly.', function() {
-// assert(keyman.ui.initialized, 'Initialization flag is set to false!');
+ it('The Float UI initializes correctly.', function() {
+ assert(keyman.ui.initialized, 'Initialization flag is set to false!');
-// assert.isNotNull(keyman.ui.outerDiv, 'Failed to create the floating controller element!');
+ assert.isNotNull(keyman.ui.outerDiv, 'Failed to create the floating controller element!');
-// var divs = document.getElementsByTagName("div");
-// var match = false;
+ var divs = document.getElementsByTagName("div");
+ var match = false;
-// for(var i=0; i < divs.length; i++) {
-// if(divs[i] == keyman.ui.outerDiv) {
-// match = true;
-// }
-// }
+ for(var i=0; i < divs.length; i++) {
+ if(divs[i] == keyman.ui.outerDiv) {
+ match = true;
+ }
+ }
-// assert(match, 'Floating controller element has not been added to the page!');
-// })
-// });
+ assert(match, 'Floating controller element has not been added to the page!');
+ })
+ });
describe('Basic Toolbar UI', function() {
diff --git a/web/src/test/auto/integrated/manual.conf.cjs b/web/src/test/auto/integrated/manual.conf.cjs
index 2c9e939f08..1969c40050 100644
--- a/web/src/test/auto/integrated/manual.conf.cjs
+++ b/web/src/test/auto/integrated/manual.conf.cjs
@@ -18,7 +18,7 @@ module.exports = function(config) {
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- // Can't set in base.conf.js b/c of constant's definition style.
+ // Can't set in base.conf.cjs b/c of constant's definition style.
logLevel: config.LOG_INFO
};
diff --git a/web/src/test/manual/web/desktop-ui/button.html b/web/src/test/manual/web/desktop-ui/button.html
index 73f058e494..a52dbfc0c5 100644
--- a/web/src/test/manual/web/desktop-ui/button.html
+++ b/web/src/test/manual/web/desktop-ui/button.html
@@ -23,7 +23,7 @@
-
+
-
+