mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 16:35:33 +00:00
744 lines
26 KiB
TypeScript
744 lines
26 KiB
TypeScript
// Includes KMW-added property declaration extensions for HTML elements.
|
|
/// <reference path="kmwexthtml.ts" />
|
|
// Defines the web-page interface object.
|
|
/// <reference path="singleton.ts" />
|
|
// Extends KeyboardInterface with DOM-oriented offerings.
|
|
/// <reference path="text/domKbdInterface.ts" />
|
|
// Defines the web-page interface object.
|
|
/// <reference path="dom/domManager.ts" />
|
|
// Includes KMW-added property declaration extensions for HTML elements.
|
|
/// <reference path="kmwutils.ts" />
|
|
// Defines keyboard management classes.
|
|
/// <reference path="keyboards/kmwkeyboards.ts" />
|
|
// Defines KMW's hotkey management object.
|
|
/// <reference path="kmwhotkeys.ts" />
|
|
// Defines the ui management code that tracks UI activation and such.
|
|
/// <reference path="kmwuimanager.ts" />
|
|
// Defines OSK management code.
|
|
/// <reference path="osk/anchoredOskView.ts" />
|
|
/// <reference path="osk/floatingOskView.ts" />
|
|
/// <reference path="osk/inlinedOskView.ts" />
|
|
// Defines the model manager.
|
|
/// <reference path="text/prediction/modelManager.ts" />
|
|
|
|
/***
|
|
KeymanWeb 14.0
|
|
Copyright 2017-2021 SIL International
|
|
***/
|
|
namespace com.keyman {
|
|
|
|
export enum SpacebarText {
|
|
KEYBOARD = 'keyboard',
|
|
LANGUAGE = 'language',
|
|
LANGUAGE_KEYBOARD = 'languageKeyboard',
|
|
BLANK = 'blank'
|
|
};
|
|
|
|
export interface OptionType {
|
|
root?: string;
|
|
resources?: string;
|
|
keyboards?: string;
|
|
fonts?: string;
|
|
attachType?: 'auto' | 'manual' | ''; // If blank or undefined, attachType will be assigned to "auto" or "manual"
|
|
ui?: string;
|
|
setActiveOnRegister?: string; // TODO: Convert to boolean. Option loader needs to be able to receive this as a string or boolean
|
|
|
|
// Determines the default text shown on the spacebar, if undefined, LANGUAGE_KEYBOARD
|
|
spacebarText?: SpacebarText;
|
|
|
|
// Determines whether or not KeymanWeb should display its own alert messages
|
|
useAlerts?: boolean;
|
|
}
|
|
|
|
export class KeymanBase {
|
|
_MasterDocument = null; // Document with controller (to allow iframes to distinguish local/master control)
|
|
_HotKeys = []; // Array of document-level hotkey objects
|
|
warned = false; // Warning flag (to prevent multiple warnings)
|
|
baseFont = 'sans-serif'; // Default page font (utilized by the OSK)
|
|
appliedFont = ''; // Chain of fonts to be applied to OSK elements
|
|
srcPath = ''; // Path to folder containing executing keymanweb script
|
|
rootPath = ''; // Path to server root
|
|
protocol = ''; // Protocol used for the KMW script.
|
|
mustReloadKeyboard = false;// Force keyboard refreshing even if already loaded
|
|
globalKeyboard = null; // Indicates the currently-active keyboard for controls without independent keyboard settings.
|
|
globalLanguageCode = null; // Indicates the language code corresponding to `globalKeyboard`.
|
|
isEmbedded = false; // Indicates if the KeymanWeb instance is embedded within a mobile app.
|
|
// Blocks full page initialization when set to `true`.
|
|
refocusTimer = 0; // Tracks a timeout event that aids of OSK modifier/state key tracking when the document loses focus.
|
|
|
|
initialized: number; // Signals the initialization state of the KeymanWeb system.
|
|
isHeadless = false; // Indicates that KMW lacks any access to the DOM. Nothing yet implemented for '= true'.
|
|
'build' = 300; // TS needs this to be defined within the class.
|
|
_BrowserIsSafari: boolean; // A legacy browser-check variable.
|
|
|
|
// Used as placeholders during initialization.
|
|
// The corresponding class properties should be dropped after a refactor;
|
|
// this is an intermediate solution while doing the big conversion.
|
|
static _srcPath: string;
|
|
static _rootPath: string;
|
|
static _protocol: string;
|
|
|
|
// Internal objects
|
|
['util']: Util;
|
|
['osk']: com.keyman.osk.OSKView;
|
|
['ui']: any;
|
|
keyboardManager: keyboards.KeyboardManager;
|
|
domManager: dom.DOMManager;
|
|
hotkeyManager: HotkeyManager;
|
|
uiManager: UIManager;
|
|
core: text.InputProcessor;
|
|
modelManager: text.prediction.ModelManager;
|
|
|
|
touchAliasing: dom.DOMEventHandlers;
|
|
|
|
// Defines default option values
|
|
options: OptionType = {
|
|
root: '',
|
|
resources: '',
|
|
keyboards: '',
|
|
fonts: '',
|
|
attachType: '',
|
|
ui: null,
|
|
setActiveOnRegister: 'true', // TODO: convert to boolean
|
|
spacebarText: SpacebarText.LANGUAGE_KEYBOARD,
|
|
|
|
// Determines whether or not KeymanWeb should display its own alert messages
|
|
useAlerts: true
|
|
};
|
|
|
|
// Stub functions (defined later in code only if required)
|
|
setDefaultDeviceOptions(opt: OptionType){}
|
|
getStyleSheetPath(s){return s;}
|
|
getKeyboardPath(f, p?){return f;}
|
|
KC_(n, ln, Pelem){return '';}
|
|
handleRotationEvents(){}
|
|
/**
|
|
* Legacy API function for touch-alias issue workarounds
|
|
* Touch-aliases have been eliminated, though.
|
|
*
|
|
* This function is deprecated in 16.0, with plans for removal in 17.0.
|
|
*/
|
|
['alignInputs'](eleList?: HTMLElement[]){}
|
|
namespaceID(Pstub) {};
|
|
preserveID(Pk) {};
|
|
|
|
setInitialized(val: number) {
|
|
this.initialized = this['initialized'] = val;
|
|
}
|
|
|
|
refreshElementContent = null;
|
|
|
|
// -------------
|
|
|
|
constructor() {
|
|
// Allow internal minification of the public modules.
|
|
this.util = this['util'] = new Util(this);
|
|
this.ui = this['ui'] = {};
|
|
|
|
this.keyboardManager = new keyboards.KeyboardManager(this);
|
|
this.domManager = new dom.DOMManager(this);
|
|
this.hotkeyManager = new HotkeyManager(this);
|
|
this.uiManager = new UIManager(this);
|
|
|
|
// I732 START - Support for European underlying keyboards #1
|
|
var baseLayout: string;
|
|
if(typeof(window['KeymanWeb_BaseLayout']) !== 'undefined') {
|
|
baseLayout = window['KeymanWeb_BaseLayout'];
|
|
} else {
|
|
baseLayout = 'us';
|
|
}
|
|
this._BrowserIsSafari = (navigator.userAgent.indexOf('AppleWebKit') >= 0); // I732 END - Support for European underlying keyboards #1
|
|
|
|
this.core = new text.InputProcessor(this.util.device.coreSpec, {
|
|
baseLayout: baseLayout,
|
|
variableStoreSerializer: new dom.VariableStoreCookieSerializer()
|
|
});
|
|
|
|
// Used by the embedded apps.
|
|
this['interface'] = this.core.keyboardInterface;
|
|
|
|
this.modelManager = new text.prediction.ModelManager();
|
|
this.osk = this['osk'] = null;
|
|
|
|
// Load properties from their static variants.
|
|
this['build'] = Number.parseInt(com.keyman.KEYMAN_VERSION.VERSION_PATCH, 10);
|
|
this.srcPath = KeymanBase._srcPath;
|
|
this.rootPath = KeymanBase._rootPath;
|
|
this.protocol = KeymanBase._protocol;
|
|
|
|
this['version'] = com.keyman.KEYMAN_VERSION.VERSION_RELEASE;
|
|
this['helpURL'] = 'http://help.keyman.com/go';
|
|
this.setInitialized(0);
|
|
|
|
// Signals that a KMW load has occurred in order to prevent double-loading.
|
|
this['loaded'] = true;
|
|
}
|
|
|
|
delayedInit() {
|
|
// Track the selected Event-handling object.
|
|
this.touchAliasing = this.util.device.touchable ? this.domManager.touchHandlers : this.domManager.nonTouchHandlers;
|
|
}
|
|
|
|
/**
|
|
* Reset context when entering or exiting the active element.
|
|
* Will also trigger OSK shift state / layer reset.
|
|
**/
|
|
pageFocusHandler = () => {
|
|
if(!this.uiManager.isActivating && this.osk?.vkbd) {
|
|
this.core.resetContext(null);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Triggers a KeymanWeb engine shutdown to facilitate a full system reset.
|
|
* This function is designed for use with KMW unit-testing, which reloads KMW
|
|
* multiple times to test the different initialization paths.
|
|
*/
|
|
['shutdown']() {
|
|
// Disable page focus/blur events, which can sometimes trigger and cause parallel KMW instances in testing.
|
|
this.util.detachDOMEvent(window, 'focus', this.pageFocusHandler, false);
|
|
this.util.detachDOMEvent(window, 'blur', this.pageFocusHandler, false);
|
|
|
|
this.domManager.shutdown();
|
|
this.osk.shutdown();
|
|
this.util.shutdown();
|
|
this.keyboardManager.shutdown();
|
|
this.core.languageProcessor.shutdown();
|
|
|
|
if(this.ui && this.ui.shutdown) {
|
|
this.ui.shutdown();
|
|
}
|
|
|
|
dom.DOMEventHandlers.states = new dom.CommonDOMStates();
|
|
}
|
|
|
|
/**
|
|
* Returns a generalized metadata object about the state of KMW for use with error reporting.
|
|
*/
|
|
['getDebugInfo']() {
|
|
let metadata = {
|
|
attachType: this.options.attachType,
|
|
device: this.util.device,
|
|
initialized: this.initialized,
|
|
isEmbedded: this.isEmbedded,
|
|
ui: this.ui ? this.ui.name : null
|
|
}
|
|
|
|
if(this.util.device.touchable) {
|
|
metadata.ui = 'touch';
|
|
}
|
|
|
|
return metadata;
|
|
}
|
|
|
|
/**
|
|
* Function addEventListener
|
|
* Scope Public
|
|
* @param {string} event event to handle
|
|
* @param {function(Event)} func event handler function
|
|
* @return {boolean} value returned by util.addEventListener
|
|
* Description Wrapper function to add and identify KeymanWeb-specific event handlers
|
|
*/
|
|
['addEventListener'](event: string, func): boolean {
|
|
return this.util.addEventListener('kmw.'+event, func);
|
|
}
|
|
|
|
/**
|
|
* Function _push
|
|
* Scope Private
|
|
* @param {Array} Parray Array
|
|
* @param {*} Pval Value to be pushed or appended to array
|
|
* @return {Array} Returns extended array
|
|
* Description Push (if possible) or append a value to an array
|
|
*/
|
|
_push<T>(Parray: T[], Pval: T) {
|
|
if(Parray.push) {
|
|
Parray.push(Pval);
|
|
} else {
|
|
Parray=Parray.concat(Pval);
|
|
}
|
|
return Parray;
|
|
}
|
|
|
|
// Base object API definitions
|
|
|
|
/**
|
|
* Function attachToControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Element to which KMW will be attached
|
|
* Description Attaches KMW to control (or IFrame)
|
|
*/
|
|
['attachToControl'](Pelem: HTMLElement) {
|
|
this.domManager.attachToControl(Pelem);
|
|
}
|
|
|
|
/**
|
|
* Function detachFromControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Element from which KMW will detach
|
|
* Description Detaches KMW from a control (or IFrame)
|
|
*/
|
|
['detachFromControl'](Pelem: HTMLElement) {
|
|
this.domManager.detachFromControl(Pelem);
|
|
}
|
|
|
|
/**
|
|
* Exposed function to load keyboards by name. One or more arguments may be used
|
|
*
|
|
* @param {any[]} args keyboard name string or keyboard metadata JSON object
|
|
* @returns {Promise<(KeyboardStub|ErrorStub)[]>} Promise of added keyboard/error stubs
|
|
*
|
|
*/
|
|
['addKeyboards'](...args: any[]) :
|
|
Promise<(com.keyman.keyboards.KeyboardStub|com.keyman.keyboards.ErrorStub)[]> {
|
|
if (!args || !args[0] || args[0].length == 0) {
|
|
// Get the cloud keyboard catalog
|
|
return this.keyboardManager.keymanCloudRequest('',false).catch(error => {
|
|
console.error(error);
|
|
return Promise.reject([{error: error}]);
|
|
});
|
|
} else {
|
|
let x: (string|com.keyman.keyboards.KeyboardStub)[] = [];
|
|
if (Array.isArray(args[0])) {
|
|
args[0].forEach(a =>
|
|
x.push(a));
|
|
} else if (Array.isArray(args)) {
|
|
args.forEach(a =>
|
|
x.push(a));
|
|
} else {
|
|
x.push(args);
|
|
}
|
|
return this.keyboardManager.addKeyboardArray(x);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add default keyboards for given language(s)
|
|
*
|
|
* @param {string|string[]} arg Language name (multiple arguments allowed)
|
|
* @returns {Promise<(KeyboardStub|ErrorStub)[]>} Promise of added keyboard/error stubs
|
|
**/
|
|
['addKeyboardsForLanguage'](arg: string[]|string) : Promise<(com.keyman.keyboards.KeyboardStub|com.keyman.keyboards.ErrorStub)[]> {
|
|
if (typeof arg === 'string') {
|
|
return this.keyboardManager.addLanguageKeyboards(arg.split(',').map(item => item.trim()));
|
|
} else {
|
|
return this.keyboardManager.addLanguageKeyboards(arg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call back from cloud for adding keyboard metadata
|
|
*
|
|
* @param {Object} x metadata object
|
|
**/
|
|
['register'](x) {
|
|
this.keyboardManager.register(x);
|
|
}
|
|
|
|
/**
|
|
* Build 362: removeKeyboards() remove keyboard from list of available keyboards
|
|
*
|
|
* @param {string} x keyboard name string
|
|
* @param {boolean} force When true, also drops the cached keyboard object
|
|
*
|
|
*/
|
|
['removeKeyboards'](x, force?) {
|
|
return this.keyboardManager.removeKeyboards(x);
|
|
}
|
|
|
|
/**
|
|
* Allow to change active keyboard by (internal) keyboard name
|
|
*
|
|
* @param {string} PInternalName Internal name
|
|
* @param {string} PLgCode Language code
|
|
*/
|
|
['setActiveKeyboard'](PInternalName: string, PLgCode: string): Promise<void> {
|
|
return this.keyboardManager.setActiveKeyboard(PInternalName,PLgCode);
|
|
}
|
|
|
|
/**
|
|
* Function getActiveKeyboard
|
|
* Scope Public
|
|
* @return {string} Name of active keyboard
|
|
* Description Return internal name of currently active keyboard
|
|
*/
|
|
['getActiveKeyboard'](): string {
|
|
return this.keyboardManager.getActiveKeyboardName();
|
|
}
|
|
|
|
/**
|
|
* Function getActiveLanguage
|
|
* Scope Public
|
|
* @param {boolean=} true to retrieve full language name, false/undefined to retrieve code.
|
|
* @return {string} language code
|
|
* Description Return language code for currently selected language
|
|
*/
|
|
['getActiveLanguage'](fullName?: boolean): string {
|
|
return this.keyboardManager.getActiveLanguage(fullName);
|
|
}
|
|
|
|
['isAttached'](x: HTMLElement): boolean {
|
|
return this.domManager.isAttached(x);
|
|
}
|
|
|
|
/**
|
|
* Function isCJK
|
|
* Scope Public
|
|
* @param {Object=} k0
|
|
* @return {boolean}
|
|
* Description Tests if active keyboard (or specified keyboard script object, as optional argument)
|
|
* uses a pick list (Chinese, Japanese, Korean, etc.)
|
|
* (This function accepts either keyboard structure.)
|
|
*/
|
|
['isCJK'](k0?) {
|
|
var kbd: keyboards.Keyboard;
|
|
if(k0) {
|
|
kbd = new keyboards.Keyboard(k0);
|
|
} else {
|
|
kbd = this.core.activeKeyboard;
|
|
}
|
|
|
|
return kbd && kbd.isCJK;
|
|
}
|
|
|
|
/**
|
|
* Function isChiral
|
|
* Scope Public
|
|
* @param {string|Object=} k0
|
|
* @return {boolean}
|
|
* Description Tests if the active keyboard (or optional argument) uses chiral modifiers.
|
|
*/
|
|
['isChiral'](k0?) {
|
|
var kbd: keyboards.Keyboard;
|
|
if(k0) {
|
|
if(typeof k0 == 'string') {
|
|
const kbdObj = this.keyboardManager.keyboards.find((kbd) => kbd['KI'] == k0);
|
|
if(!kbdObj) {
|
|
throw new Error(`Keyboard '${k0}' has not been loaded.`);
|
|
} else {
|
|
k0 = kbdObj;
|
|
}
|
|
}
|
|
|
|
kbd = new keyboards.Keyboard(k0);
|
|
} else {
|
|
kbd = this.core.activeKeyboard;
|
|
}
|
|
return kbd.isChiral;
|
|
}
|
|
|
|
/**
|
|
* Get keyboard meta data for the selected keyboard and language
|
|
*
|
|
* @param {string} PInternalName Internal name of keyboard
|
|
* @param {string=} PlgCode language code
|
|
* @return {Object} Details of named keyboard
|
|
*
|
|
**/
|
|
['getKeyboard'](PInternalName: string, PlgCode?: string) {
|
|
var Ln, Lrn;
|
|
|
|
var kbdList = this.keyboardManager.getDetailedKeyboards();
|
|
|
|
for(Ln=0; Ln < kbdList.length; Ln++) {
|
|
Lrn = kbdList[Ln];
|
|
|
|
if(Lrn['InternalName'] == PInternalName || Lrn['InternalName'] == "Keyboard_" + PInternalName) {
|
|
if(arguments.length < 2) {
|
|
return Lrn;
|
|
}
|
|
|
|
if(Lrn['LanguageCode'] == PlgCode) {
|
|
return Lrn;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get array of available keyboard stubs
|
|
*
|
|
* @return {Array} Array of available keyboards
|
|
*
|
|
*/
|
|
['getKeyboards']() {
|
|
return this.keyboardManager.getDetailedKeyboards();
|
|
}
|
|
|
|
/**
|
|
* Gets the cookie for the name and language code of the most recently active keyboard
|
|
*
|
|
* Defaults to US English, but this needs to be user-set in later revision (TODO)
|
|
*
|
|
* @return {string} InternalName:LanguageCode
|
|
*/
|
|
['getSavedKeyboard']() {
|
|
return this.keyboardManager.getSavedKeyboard();
|
|
}
|
|
|
|
/**
|
|
* Function Initialization
|
|
* Scope Public
|
|
* @param {Object} arg object array of user-defined properties
|
|
* Description KMW window initialization
|
|
*/
|
|
['init'](arg): Promise<any> {
|
|
return this.domManager.init(arg);
|
|
}
|
|
|
|
/**
|
|
* Function resetContext
|
|
* Scope Public
|
|
* @param {Object} e The element whose context should be cleared. If null, the currently-active element will be chosen.
|
|
* Description Reverts the OSK to the default layer, clears any processing caches and modifier states,
|
|
* and clears deadkeys and prediction-processing states on the active element (if it exists)
|
|
*/
|
|
['resetContext'](e?: HTMLElement) {
|
|
let elem = e;
|
|
if(!elem) {
|
|
elem = this.domManager.activeElement;
|
|
}
|
|
let outputTarget = dom.Utils.getOutputTarget(elem);
|
|
if(outputTarget) {
|
|
outputTarget.resetContext();
|
|
}
|
|
this.core.resetContext(outputTarget);
|
|
};
|
|
|
|
/**
|
|
* Function setNumericLayer
|
|
* Scope Public
|
|
* Description Set OSK to numeric layer if it exists
|
|
*/
|
|
['setNumericLayer']() {
|
|
this.core.keyboardProcessor.setNumericLayer(this.util.device.coreSpec);
|
|
};
|
|
|
|
/**
|
|
* Function disableControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Element to be disabled
|
|
* Description Disables a KMW control element
|
|
*/
|
|
['disableControl'](Pelem: HTMLElement) {
|
|
this.domManager.disableControl(Pelem);
|
|
}
|
|
|
|
/**
|
|
* Function enableControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Element to be disabled
|
|
* Description Disables a KMW control element
|
|
*/
|
|
['enableControl'](Pelem: HTMLMapElement) {
|
|
this.domManager.enableControl(Pelem);
|
|
}
|
|
|
|
/**
|
|
* Function setKeyboardForControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Control element
|
|
* @param {string|null=} Pkbd Keyboard (Clears the set keyboard if set to null.)
|
|
* @param {string|null=} Plc Language Code
|
|
* Description Set default keyboard for the control
|
|
*/
|
|
['setKeyboardForControl'](Pelem: HTMLElement, Pkbd?: string, Plc?: string) {
|
|
this.domManager.setKeyboardForControl(Pelem, Pkbd, Plc);
|
|
}
|
|
|
|
/**
|
|
* Function getKeyboardForControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Control element
|
|
* @return {string|null} The independently-managed keyboard for the control.
|
|
* Description Returns the keyboard ID of the current independently-managed keyboard for this control.
|
|
* If it is currently following the global keyboard setting, returns null instead.
|
|
*/
|
|
['getKeyboardForControl'](Pelem) {
|
|
this.domManager.getKeyboardForControl(Pelem);
|
|
}
|
|
|
|
/**
|
|
* Function getLanguageForControl
|
|
* Scope Public
|
|
* @param {Element} Pelem Control element
|
|
* @return {string|null} The independently-managed keyboard for the control.
|
|
* Description Returns the language code used with the current independently-managed keyboard for this control.
|
|
* If it is currently following the global keyboard setting, returns null instead.
|
|
*/
|
|
['getLanguageForControl'](Pelem) {
|
|
this.domManager.getLanguageForControl(Pelem);
|
|
}
|
|
|
|
/**
|
|
* Set focus to last active target element (browser-dependent)
|
|
*/
|
|
['focusLastActiveElement']() {
|
|
this.domManager.focusLastActiveElement();
|
|
}
|
|
|
|
/**
|
|
* Get the last active target element *before* KMW activated (I1297)
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
['getLastActiveElement']() {
|
|
return this.domManager.lastActiveElement;
|
|
}
|
|
|
|
/**
|
|
* Set the active input element directly optionally setting focus
|
|
*
|
|
* @param {Object|string} e element id or element
|
|
* @param {boolean=} setFocus optionally set focus (KMEW-123)
|
|
**/
|
|
['setActiveElement'](e: string|HTMLElement, setFocus: boolean) {
|
|
return this.domManager.setActiveElement(e, setFocus);
|
|
}
|
|
|
|
/**
|
|
* Move focus to user-specified element
|
|
*
|
|
* @param {string|Object} e element or element id
|
|
*
|
|
**/
|
|
['moveToElement'](e: string|HTMLElement) {
|
|
this.domManager.moveToElement(e);
|
|
}
|
|
|
|
/**
|
|
* Function addHotkey
|
|
* Scope Public
|
|
* @param {number} keyCode
|
|
* @param {number} shiftState
|
|
* @param {function(Object)} handler
|
|
* Description Add hot key handler to array of document-level hotkeys triggered by key up event
|
|
*/
|
|
['addHotKey'](keyCode: number, shiftState: number, handler: () => void) {
|
|
this.hotkeyManager.addHotKey(keyCode, shiftState, handler);
|
|
}
|
|
|
|
/**
|
|
* Function removeHotkey
|
|
* Scope Public
|
|
* @param {number} keyCode
|
|
* @param {number} shiftState
|
|
* Description Remove a hot key handler from array of document-level hotkeys triggered by key up event
|
|
*/
|
|
['removeHotKey'](keyCode: number, shiftState: number) {
|
|
this.hotkeyManager.removeHotkey(keyCode, shiftState);
|
|
}
|
|
|
|
/**
|
|
* Function getUIState
|
|
* Scope Public
|
|
* @return {Object.<string,(boolean|number)>}
|
|
* Description Return object with activation state of UI:
|
|
* activationPending (bool): KMW being activated
|
|
* activated (bool): KMW active
|
|
*/
|
|
['getUIState'](): UIState {
|
|
return this.uiManager.getUIState();
|
|
}
|
|
|
|
/**
|
|
* Set or clear the IsActivatingKeymanWebUI flag (exposed function)
|
|
*
|
|
* @param {(boolean|number)} state Activate (true,false)
|
|
*/
|
|
['activatingUI'](state: boolean) {
|
|
this.uiManager.setActivatingUI(state);
|
|
}
|
|
|
|
// Functions that might be added later
|
|
['beepKeyboard']: () => void;
|
|
/**
|
|
* @param {number} dn Number of pre-caret characters to delete
|
|
* @param {string} s Text to insert
|
|
* @param {number=} dr Number of post-caret characters to delete
|
|
*/
|
|
['oninserttext']: (dn: number, s: string, dr?: number) => void;
|
|
|
|
/**
|
|
* Create copy of the OSK that can be used for embedding in documentation or help
|
|
* The currently active keyboard will be returned if PInternalName is null
|
|
*
|
|
* @param {string} PInternalName internal name of keyboard, with or without Keyboard_ prefix
|
|
* @param {number} Pstatic static keyboard flag (unselectable elements)
|
|
* @param {string=} argFormFactor layout form factor, defaulting to 'desktop'
|
|
* @param {(string|number)=} argLayerId name or index of layer to show, defaulting to 'default'
|
|
* @return {Object} DIV object with filled keyboard layer content
|
|
*/
|
|
['BuildVisualKeyboard'](PInternalName, Pstatic, argFormFactor, argLayerId): HTMLElement {
|
|
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<keyboardsList.length; Ln++) {
|
|
if(p == keyboardsList[Ln]['KI'].toLowerCase().replace('keyboard_','')) {
|
|
// Requires the Keyboard wrapping object now.
|
|
PKbd = new com.keyman.keyboards.Keyboard(keyboardsList[Ln]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
PKbd = PKbd || this.core.activeKeyboard;
|
|
|
|
// help.keyman.com will (lkudingly) set this function in place to specify the desired
|
|
// dimensions for the documentation-keyboards, so we'll give it priority. One of those
|
|
// "temporary" (but actually permanent) solutions from yesteryear.
|
|
//
|
|
// Note that the main intended use of that function is for embedded KMW on the mobile apps...
|
|
// but they never call `BuildVisualKeyboard`, so it's all good.
|
|
const getOskHeight = this['getOskHeight'];
|
|
let targetHeight = (typeof getOskHeight == 'function' ? getOskHeight() : null) || this.osk.computedHeight || 200;
|
|
|
|
return com.keyman.osk.VisualKeyboard.buildDocumentationKeyboard(PKbd, argFormFactor, argLayerId, targetHeight);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determine path and protocol of executing script, setting them as
|
|
* construction defaults.
|
|
*
|
|
* This can only be done during load when the active script will be the
|
|
* last script loaded. Otherwise the script must be identified by name.
|
|
*/
|
|
var scripts = document.getElementsByTagName('script');
|
|
var ss = scripts[scripts.length-1].src;
|
|
var sPath = ss.substr(0,ss.lastIndexOf('/')+1);
|
|
|
|
import KeymanBase = com.keyman.KeymanBase;
|
|
|
|
KeymanBase._srcPath = sPath;
|
|
KeymanBase._rootPath = sPath.replace(/(https?:\/\/)([^\/]*)(.*)/,'$1$2/');
|
|
KeymanBase._protocol = sPath.replace(/(.{3,5}:)(.*)/,'$1');
|
|
|
|
/**
|
|
* Base code: Declare major component namespaces, instances, and utility functions
|
|
*/
|
|
|
|
// If a copy of the script is already loaded, detect this and prevent re-initialization / data reset.
|
|
if(!window['keyman'] || !window['keyman']['loaded']) {
|
|
|
|
(function() {
|
|
/* The base object call may need to be moved into a separate, later file eventually.
|
|
* It will be necessary to override methods with kmwnative.ts and kmwembedded.ts before the
|
|
* affected objects are initialized.
|
|
*
|
|
* We only recreate the 'keyman' object if it's not been loaded.
|
|
* As this is the base object, not creating it prevents a KMW system reset.
|
|
*/
|
|
window['keyman'] = com.keyman['singleton'] = com.keyman.singleton = new KeymanBase();
|
|
|
|
// TODO: Eliminate the need for this. Will require more refactoring & redesign to drop.
|
|
window['keyman'].core.languageProcessor.init();
|
|
})();
|
|
}
|