= 0 ? 'block' : 'none');
else if(typeof(layerId) == 'string')
layer.style.display=(layout.layer[Ln].id == layerId ? 'block' : 'none');
else
layer.style.display=(Ln == 0 ? 'block' : 'none');
}
}
else
{
kbd.innerHTML="No "+formFactor+" layout is defined for "+PKbd['KN']+".
";
}
// Add a faint border
kbd.style.border='1px solid #ccc';
return kbd;
}
/**
* Adjust the absolute height of each keyboard element after a rotation
*
**/
osk.adjustHeights=function()
{
if(!osk._Box || !osk._Box.firstChild || !osk._Box.firstChild.firstChild || !osk._Box.firstChild.firstChild.childNodes) return;
var layers=osk._Box.firstChild.firstChild.childNodes,
nRows=layers[0].childNodes.length,
oskHeight=osk.getHeight(),
rowHeight=Math.floor(oskHeight/(nRows == 0 ? 1 : nRows)),
nLayer,nRow,rs,keys,nKeys,nKey,key,ks,j,pad,fs=1.0;
if(device.OS == 'Android' && 'devicePixelRatio' in window)
rowHeight = rowHeight/window.devicePixelRatio;
oskHeight=nRows*rowHeight;
var b=osk._Box,bs=b.style;
bs.height=bs.maxHeight=(oskHeight+3)+'px';
b=b.firstChild.firstChild; bs=b.style;
bs.height=bs.maxHeight=(oskHeight+3)+'px';
if(device.formFactor == 'phone') fs=0.6;
// TODO: Logically, this should be needed for Android, too - may need to be changed for the next version!
if(device.OS == 'iOS')
fs=fs/util.getViewportScale();
bs.fontSize=fs+'em';
var resizeLabels=(device.OS == 'iOS' && device.formFactor == 'phone' && util.landscapeView());
for(nLayer=0;nLayer 0)) key.childNodes[0].style.fontSize='6px';
}
}
}
}
/**
* Create a control bar with title and buttons for the desktop OSK
*/
osk.controlBar = function()
{
var bar=util._CreateElement('DIV'),title='';
bar.id='keymanweb_title_bar';
bar.className='kmw-title-bar';
bar.onmousedown=osk._VMoveMouseDown;
if(keymanweb.keyboardManager.activeKeyboard) {
title=keymanweb.keyboardManager.activeKeyboard['KN'];
}
var Ltitle=util._CreateElement('SPAN');
Ltitle.className='kmw-title-bar-caption';
Ltitle.innerHTML=title;
bar.appendChild(Ltitle);
var Limg=osk.closeButton=util._CreateElement('DIV');
Limg.id='kmw-close-button';
Limg.className='kmw-title-bar-image';
Limg.onmousedown=osk._CancelMouse;
Limg.onclick=function(){osk._Hide(true);}
bar.appendChild(Limg);
Limg=osk.helpImg=util._CreateElement('DIV');
Limg.id='kmw-help-image';
Limg.className='kmw-title-bar-image';
Limg.title='KeymanWeb Help';
Limg.onclick=function()
{
var p={}; util.callEvent('osk.helpclick',p);
if(window.event) window.event.returnValue=false;
return false;
}
Limg.onmousedown=osk._CancelMouse;
bar.appendChild(Limg);
Limg=osk.configImg=util._CreateElement('DIV');
Limg.id='kmw-config-image';
Limg.className='kmw-title-bar-image';
Limg.title='KeymanWeb Configuration Options';
Limg.onclick=function()
{
var p={}; util.callEvent('osk.configclick',p);
if(window.event) window.event.returnValue=false;
return false;
}
Limg.onmousedown=osk._CancelMouse;
bar.appendChild(Limg);
Limg=osk.pinImg=util._CreateElement('DIV'); //I2186
Limg.id='kmw-pin-image';
Limg.className='kmw-title-bar-image';
Limg.title='Pin the On Screen Keyboard to its default location on the active text box';
Limg.onclick=function()
{
osk.loadCookie(); osk.userPositioned=false; osk.saveCookie();
osk._Show();
osk.doResizeMove(); //allow the UI to respond to OSK movements
if(osk.pinImg) osk.pinImg.style.display='none';
if(window.event) window.event.returnValue=false;
return false;
}
Limg.onmousedown=osk._CancelMouse;
bar.appendChild(Limg);
return bar;
}
/**
* Display build number
*/
osk.showBuild = function()
{
util.alert('KeymanWeb Version '+keymanweb['version']+'.'+keymanweb['build']+'
'
+'Copyright © 2017 SIL International');
}
/**
* Create a bottom bar with a resizing icon for the desktop OSK
*/
osk.resizeBar = function()
{
var bar=util._CreateElement('DIV');
bar.className='kmw-footer';
bar.onmousedown=osk._CancelMouse;
// Add caption
var Ltitle=util._CreateElement('DIV');
Ltitle.className='kmw-footer-caption';
Ltitle.innerHTML='KeymanWeb';
Ltitle.id='keymanweb-osk-footer-caption';
// Display build number on shift+double click
util.attachDOMEvent(Ltitle,'dblclick',function(e){if(e && e.shiftKey)osk.showBuild();},false);
// Prevent selection of caption (IE - set by class for other browsers)
if('onselectstart' in Ltitle) Ltitle.onselectstart= util.selectStartHandler; //IE (Build 360)
bar.appendChild(Ltitle);
var Limg = util._CreateElement('DIV');
Limg.className='kmw-footer-resize';
Limg.onmousedown=osk._VResizeMouseDown;
Limg.onmouseover=Limg.onmouseout=osk._VResizeMouseOut;
bar.appendChild(Limg);
osk.resizeIcon=Limg;
//TODO: the image never appears in IE8, have no idea why!
return bar;
}
/**
* Function _VKbdMouseOver
* Scope Private
* @param {Object} e event
* Description Activate the KMW UI on mouse over
*/
osk._VKbdMouseOver = function(e)
{
keymanweb.uiManager.setActivatingUI(true);
}
/**
* Function _VKbdMouseOut
* Scope Private
* @param {Object} e event
* Description Cancel activation of KMW UI on mouse out
*/
osk._VKbdMouseOut = function(e)
{
keymanweb.uiManager.setActivatingUI(false);
}
/**
* Function _VResizeMouseOver, _VResizeMouseOut
* Scope Private
* @param {Object} e event
* Description Process end of resizing of KMW UI
*/
osk._VResizeMouseOver = osk._VResizeMouseOut = function(e)
{
e = keymanweb._GetEventObject(e); // I2404 - Manage IE events in IFRAMEs
if(!e) return false;
if(e && e.preventDefault) e.preventDefault();
var r=osk.getRect();
osk.width=r.width; osk.height=r.height;
e.cancelBubble = true;
return false;
}
/**
* Function _VResizeMouseDown
* Scope Private
* @param {Object} e event
* Description Process resizing of KMW UI
*/
osk._VResizeMouseDown = function(e)
{
keymanweb.uiManager.justActivated = true;
e = keymanweb._GetEventObject(e); // I2404 - Manage IE events in IFRAMEs
if(!e) return true;
osk.resizing = 1;
var Lposx,Lposy;
if (e.pageX) {
Lposx = e.pageX; Lposy = e.pageY;
}
else if(e.clientX) {
Lposx = e.clientX + document.body.scrollLeft;
Lposy = e.clientY + document.body.scrollTop;
}
osk._ResizeMouseX = Lposx;
osk._ResizeMouseY = Lposy;
if(document.onmousemove != osk._VResizeMouseMove && document.onmousemove != osk._VMoveMouseMove) // I1472 - Dragging off edge of browser window causes muckup
{
osk._VPreviousMouseMove = document.onmousemove;
osk._VPreviousMouseUp = document.onmouseup;
}
osk._VPreviousCursor = document.body.style.cursor;
osk._VPreviousMouseButton = (typeof(e.which)=='undefined' ? e.button : e.which);
osk._VOriginalWidth = osk._DivVKbd.offsetWidth;
osk._VOriginalHeight = osk._DivVKbd.offsetHeight;
document.onmousemove = osk._VResizeMouseMove;
document.onmouseup = osk._VResizeMoveMouseUp;
if(document.body.style.cursor) document.body.style.cursor = 'se-resize';
if(e && e.preventDefault) e.preventDefault();
e.cancelBubble = true;
return false;
}
/**
* Function _VResizeMouseMove
* Scope Private
* @param {Object} e event
* Description Process mouse movement during resizing of OSK
*/
osk._VResizeMouseMove = function(e)
{
var Lposx,Lposy;
e = keymanweb._GetEventObject(e); // I2404 - Manage IE events in IFRAMEs
if(!e) return true;
osk.resizing = 1;
if(osk._VPreviousMouseButton != (typeof(e.which)=='undefined' ? e.button : e.which)) // I1472 - Dragging off edge of browser window causes muckup
{
return osk._VResizeMoveMouseUp(e);
}
else
{
if (e.pageX) {
Lposx = e.pageX; Lposy=e.pageY;
}
else if (e.clientX) {
Lposx = e.clientX + document.body.scrollLeft;
Lposy = e.clientY + document.body.scrollTop;
}
var newWidth=(osk._VOriginalWidth + Lposx - osk._ResizeMouseX),
newHeight=(osk._VOriginalHeight + Lposy - osk._ResizeMouseY);
// Set the smallest and largest OSK size
if(newWidth < 0.2*screen.width) newWidth = 0.2*screen.width;
if(newHeight < 0.1*screen.height) newHeight = 0.1*screen.height;
if(newWidth > 0.9*screen.width) newWidth=0.9*screen.width;
if(newHeight > 0.5*screen.height) newWidth=0.5*screen.height;
// Set OSK width
osk._DivVKbd.style.width=newWidth+'px';
// Explicitly change OSK height and font size - cannot safely rely on scaling from font
osk._DivVKbd.style.height=newHeight+'px';
osk._DivVKbd.style.fontSize=(newHeight/8)+'px';
if(e && e.preventDefault) e.preventDefault();
e.cancelBubble = true;
return false;
}
}
/**
* Function _VMoveMouseDown
* Scope Private
* @param {Object} e event
* Description Process mouse down on OSK
*/
osk._VMoveMouseDown = function(e)
{
var Lposx, Lposy;
keymanweb.uiManager.justActivated = true;
e = keymanweb._GetEventObject(e); // I2404 - Manage IE events in IFRAMEs
if(!e) return true;
osk.resizing = 1;
if (e.pageX)
{ Lposx = e.pageX; Lposy = e.pageY; }
else if (e.clientX)
{ Lposx = e.clientX + document.body.scrollLeft; Lposy = e.clientY + document.body.scrollTop; }
if(document.onmousemove != osk._VResizeMouseMove && document.onmousemove != osk._VMoveMouseMove) // I1472 - Dragging off edge of browser window causes muckup
{
osk._VPreviousMouseMove = document.onmousemove;
osk._VPreviousMouseUp = document.onmouseup;
}
osk._VPreviousCursor = document.body.style.cursor;
osk._VPreviousMouseButton = (typeof(e.which)=='undefined' ? e.button : e.which);
osk._VMoveX = Lposx - osk._Box.offsetLeft;
osk._VMoveY = Lposy - osk._Box.offsetTop;
if(keymanweb.keyboardManager.isCJK()) osk.pinImg.style.left='15px';
document.onmousemove = osk._VMoveMouseMove;
document.onmouseup = osk._VResizeMoveMouseUp;
if(document.body.style.cursor) document.body.style.cursor = 'move';
if(e && e.preventDefault) e.preventDefault();
e.cancelBubble = true;
return false;
}
/**
* Process mouse drag on OSK
*
* @param {Object} e event
*/
osk._VMoveMouseMove = function(e)
{
var Lposx, Lposy;
e = keymanweb._GetEventObject(e); // I2404 - Manage IE events in IFRAMEs
if(!e) return true;
if(osk.noDrag) return true;
osk.resizing = 1;
osk.userPositioned = true;
osk.pinImg.style.display='block';
if(osk._VPreviousMouseButton != (typeof(e.which)=='undefined' ? e.button : e.which)) // I1472 - Dragging off edge of browser window causes muckup
{
return osk._VResizeMoveMouseUp(e);
}
else
{
if (e.pageX)
{ Lposx = e.pageX; Lposy = e.pageY; }
else if (e.clientX)
{ Lposx = e.clientX + document.body.scrollLeft; Lposy = e.clientY + document.body.scrollTop; }
osk._Box.style.left = (Lposx-osk._VMoveX)+'px';
osk._Box.style.top = (Lposy-osk._VMoveY)+'px';
if(e && e.preventDefault) e.preventDefault();
var r=osk.getRect();
osk.width=r.width;osk.height=r.height;
e.cancelBubble = true;
return false;
}
}
/**
* Function _VResizeMoveMouseUp
* Scope Private
* @param {Object} e event
* Description Process mouse up during resizing of KMW UI
*/
osk._VResizeMoveMouseUp = function(e)
{
e = keymanweb._GetEventObject(e); // I2404 - Manage IE events in IFRAMEs
if(!e) return true;
osk.resizing = 0; osk.currentKey=null;
document.onmousemove = osk._VPreviousMouseMove;
document.onmouseup = osk._VPreviousMouseUp;
if(document.body.style.cursor) document.body.style.cursor = osk._VPreviousCursor;
keymanweb.domManager.focusLastActiveElement();
if(e && e.preventDefault) e.preventDefault();
keymanweb.uiManager.justActivated = false;
keymanweb.uiManager.setActivatingUI(false);
if(osk._DivVKbd) {
osk._VOriginalWidth = osk._DivVKbd.offsetWidth;
osk._VOriginalHeight = osk._DivVKbd.offsetHeight;
}
osk.doResizeMove();
e.cancelBubble = true;
osk.saveCookie();
return false;
}
/**
* Function userPositioned
* Scope Public
* @return {(boolean|number)} true if user located
* Description Test if OSK window has been repositioned by user
*/
osk['userLocated'] = function()
{
return osk.userPositioned;
}
/**
* Description Display KMW OSK (at position set in callback to UI)
* Function show
* Scope Public
* @param {(boolean|number)=} bShow True to display, False to hide, omitted to toggle
*/
osk['show'] = function(bShow)
{
if(arguments.length > 0)
{
osk._Enabled=bShow;
if(bShow) osk._Show(); else osk._Hide(true);
}
else
{
if(osk._Visible) osk._Hide(true); else osk._Show();
}
}
/**
* Allow UI to respond to OSK being shown (passing position and properties)
*
* @param {Object=} p object with coordinates and userdefined flag
* @return {boolean}
*
*/
osk.doShow = function(p)
{
return util.callEvent('osk.show',p);
}
/**
* Allow UI to update respond to OSK being hidden
*
* @param {Object=} p object with coordinates and userdefined flag
* @return {boolean}
*
*/
osk.doHide = function(p)
{
return util.callEvent('osk.hide',p);
}
/**
* Allow UI to update OSK position and properties
*
* @param {Object=} p object with coordinates and userdefined flag
*
*/
osk.doResizeMove = function(p)
{
return util.callEvent('osk.resizemove',p);
}
/**
* Display KMW OSK at specified position (returns nothing)
*
* @param {number=} Px x-coordinate for OSK rectangle
* @param {number=} Py y-coordinate for OSK rectangle
*/
osk._Show = function(Px, Py)
{
// Do not try to display OSK if undefined, or no active element
if(osk._Box == null || keymanweb.domManager.getActiveElement() == null) return;
// Never display the OSK for desktop browsers unless KMW element is focused, and a keyboard selected
if((!device.touchable) && (keymanweb.keyboardManager.activeKeyboard == null || !osk._Enabled)) return;
var Ls = osk._Box.style;
// Do not display OSK until it has been positioned correctly
if(device.touchable && Ls.bottom == '') Ls.visibility='hidden';
// The following code will always be executed except for externally created OSK such as EuroLatin
if(osk.ddOSK)
{
// Enable the currently active keyboard layer and update the default nextLayer member
var n,nLayer=-1,b=osk._DivVKbd.childNodes[0].childNodes;
for(n=0; n= 0) //probably never happens, legacy support only
{
Ls.left = Px + 'px'; Ls.top = Py + 'px';
}
else
{
if(osk.userPositioned)
{
Ls.left=osk.x+'px'; Ls.top=osk.y+'px';
}
else
{
var el=keymanweb.domManager.getActiveElement();
if(osk.dfltX != '')
Ls.left=osk.dfltX;
else if(typeof el != 'undefined' && el != null)
Ls.left=util._GetAbsoluteX(el)+'px';
if(osk.dfltY != '')
Ls.top=osk.dfltY;
else if(typeof el != 'undefined' && el != null)
Ls.top=(util._GetAbsoluteY(el)+el.offsetHeight)+'px';
}
}
osk._Enabled=1; osk._Visible=1;
if(osk._DivVKbd)
{
osk.width=osk._DivVKbd.offsetWidth; osk.height=osk._DivVKbd.offsetHeight;
}
osk.saveCookie();
var pin=osk.pinImg;
if(typeof pin != 'undefined' && pin != null)
pin.style.display=osk.userPositioned?'block':'none';
}
// If OSK still hidden, make visible only after all calculation finished
if(Ls.visibility == 'hidden')
window.setTimeout(function(){osk._Box.style.visibility='visible';},0);
// Allow desktop UI to execute code when showing the OSK
if(!device.touchable)
{
var Lpos={};
Lpos['x']=osk._Box.offsetLeft;
Lpos['y']=osk._Box.offsetTop;
Lpos['userLocated']=osk.userPositioned;
osk.doShow(Lpos);
}
}
/**
* Adjust the width of the last cell in each row for length differences
* due to rounding percentage widths to nearest pixel.
*
* @param {number} nLayer Index of currently visible layer
*/
osk.adjustRowLengths = function(nLayer)
{
if(nLayer >= 0) return; //TODO: TEST ONLY - remove code if not needed
var maxWidth,layers=osk._DivVKbd.childNodes[0].childNodes;
if(nLayer < 0 || nLayer >= layers.length || layers[nLayer].aligned) return;
// Do not try and align if not visible!
if(layers[nLayer].style.display != 'block') return;
// Set max width to be 6 px less than OSK layer width (allow for inter-key spacing)
// TODO: Adjustment needs to be device and orientation specific
maxWidth=osk._DivVKbd.childNodes[0].offsetWidth-6;
if(device.OS == 'Windows')
{
maxWidth -= util.landscapeView() ? 4: 40;
}
var i,rows=layers[nLayer].childNodes,keys,nKeys,lastKey,xMax;
for(i=0; i= 0 && nLayer < layers.length)
{
// Special function keys will always be in bottom row (must modify code if not)
rows=layers[nLayer].childNodes;
keys=rows[rows.length-1].childNodes;
for(k=0; k= 0) return;
}
osk._Visible = 0;
if(osk._Box && device.touchable && osk._Box.offsetHeight > 0) // I3363 (Build 301)
{
var os=osk._Box.style,h=osk._Box.offsetHeight;
//Firefox doesn't transition opacity if start delay is explicitly set to 0!
if(typeof(os.MozBoxSizing) == 'string')
os.transition='opacity 0.8s linear';
else
os.transition=os.msTransition=os.WebkitTransition='opacity 0.5s linear 0';
// Cannot hide the OSK smoothly using a transitioned drop, since for
// position:fixed elements transitioning is incompatible with translate3d(),
// and also does not work with top, bottom or height styles.
// Opacity can be transitioned and is probably the simplest alternative.
// We must condition on osk._Visible in case focus has since been moved to another
// input (in which case osk._Visible will be non-zero)
window.setTimeout(function()
{
var os=osk._Box.style;
if(osk._Visible)
{
// Leave opacity alone and clear transition if another element activated
os.transition=os.msTransition=os.MozTransition=os.WebkitTransition='';
}
else
{
// Set opacity to zero, should decrease smoothly
os.opacity='0';
// Actually hide the OSK at the end of the transition
osk._Box.addEventListener('transitionend',osk.hideNow,false);
osk._Box.addEventListener('webkitTransitionEnd',osk.hideNow,false);
}
},200); // Wait a bit before starting, to allow for moving to another element
}
else
{
if(osk._Box) osk._Box.style.display = 'none';
}
// Allow UI to execute code when hiding the OSK
var p={}; p['HiddenByUser']=hiddenByUser;
osk.doHide(p);
// If hidden by the UI, be sure to restore the focus
if(hiddenByUser) keymanweb.domManager.focusLastActiveElement();
}
/**
* Function hideNow
* Scope Private
* Description Hide the OSK unconditionally and immediately, cancel any pending transition
*/
osk.hideNow = function() // I3363 (Build 301)
{
osk._Box.removeEventListener('transitionend',osk.hideNow,false);
osk._Box.removeEventListener('webkitTransitionEnd',osk.hideNow,false);
var os=osk._Box.style;
os.display='none';
os.opacity='1';
osk._Visible=0;
os.transition=os.msTransition=os.mozTransition=os.WebkitTransition='';
// Remove highlighting from hide keyboard key, if applied
if(osk.hkKey && typeof(osk.hkKey) != 'undefined') osk.highlightKey(osk.hkKey.firstChild,false);
}
// First time initialization of OSK
osk.prepare = function()
{
// Defer loading the OSK until KMW code initialization complete
if(!keymanweb['initialized'])
{
window.setTimeout(osk.prepare,200);
return;
}
// OSK initialization - create DIV and set default styles
if(!osk.ready)
{
osk._Box = util._CreateElement('DIV'); // Container for OSK (Help DIV, displayed when user clicks Help icon)
document.body.appendChild(osk._Box);
// Install the default OSK stylesheet
util.linkStyleSheet(keymanweb.getStyleSheetPath('kmwosk.css'));
// For mouse click to prevent loss of focus
util.attachDOMEvent(osk._Box,'mousedown', function(){keymanweb.uiManager.setActivatingUI(true);});
// And to prevent touch event default behaviour on mobile devices
// TODO: are these needed, or do they interfere with other OSK event handling ????
if(device.touchable) // I3363 (Build 301)
{
util.attachDOMEvent(osk._Box,'touchstart',function(e){keymanweb.uiManager.setActivatingUI(true); e.preventDefault();e.stopPropagation();});
util.attachDOMEvent(osk._Box,'touchend',function(e){e.preventDefault(); e.stopPropagation();});
util.attachDOMEvent(osk._Box,'touchmove',function(e){e.preventDefault();e.stopPropagation();});
util.attachDOMEvent(osk._Box,'touchcancel',function(e){e.preventDefault();e.stopPropagation();});
// Can only get (initial) viewport scale factor after page is fully loaded!
osk.vpScale=util.getViewportScale();
}
}
osk.loadCookie();
osk.ready=true;
}
/**
* Function _Load
* Scope Private
* Description OSK initialization when keyboard selected
*/
osk._Load = function() // Load Help
{
var activeKeyboard = keymanweb.keyboardManager.activeKeyboard;
// If _Load called before OSK is ready, must wait and call again
if(osk._Box == null)
{
if(osk.loadRetry >= 99) return; // fail silently, but should not happen
window.setTimeout(osk._Load,100);
osk.loadRetry++;
return;
}
osk.loadRetry = 0;
if(keymanweb._TitleElement) keymanweb._TitleElement.innerHTML = 'KeymanWeb'; // I1972
osk._Visible=0; // I3363 (Build 301)
osk.layerId='default';
var s=osk._Box.style;
s.zIndex='9999'; s.display='none'; s.width='auto';
s.position = (device.formFactor == 'desktop' ? 'absolute' : 'fixed');
// Use smaller base font size for mobile devices
//if(screen.availHeight < 500) s.fontSize='10pt';
//else if(screen.availHeight < 800) s.fontSize='11pt';
//else s.fontSize='12pt';
if(device.formFactor == 'phone') s.fontSize='1.6em';
osk._DivVKbd = osk._DivVKbdHelp = null; // I1476 - Handle SELECT overlapping
osk._Box.innerHTML = '';
osk._Box.onmouseover = osk._VKbdMouseOver;
osk._Box.onmouseout = osk._VKbdMouseOut;
// TODO: find out and document why this should not be done for touch devices!!
// (Probably to avoid having a null keyboard. But maybe that *is* an option, if there remains a way to get the language menu,
// such as a minimized menu button?)
if(activeKeyboard == null && !device.touchable)
{
var Ldiv=util._CreateElement('DIV');
Ldiv.className = "kmw-title-bar";
Ldiv.appendChild(osk._TitleBarInterior());
Ldiv.onmousedown = osk._VMoveMouseDown;
osk._Box.appendChild(Ldiv);
Ldiv = util._CreateElement('DIV');
Ldiv.className='kmw-osk-none';
osk._Box.appendChild(Ldiv);
}
else
{
var Lviskbd=null,layouts=null,layout=null,Lhelp='';
osk._Box.className = "";
if(activeKeyboard != null)
{
Lviskbd=activeKeyboard['KV']; Lhelp=activeKeyboard['KH'];
// Check if dynamic layout is defined within keyboard
layouts=activeKeyboard['KVKL'];
// If any keyboard layout file is provided, use that to override the generated layout
if(typeof layouts != 'undefined' && layouts != null)
{
layout=layouts[device.formFactor];
// Use the layout for the device, if defined, otherwise use the desktop (default) layout
if(typeof layout == 'undefined' || layout == null)
{
if(device.formFactor == 'phone') layout=layouts['tablet'];
else if(device.formFactor == 'tablet') layout=layouts['phone'];
if(typeof layout == 'undefined' || layout == null) layout=layouts['desktop'];
}
}
}
// Test if Visual keyboard is simply a place holder, set to null if so
if(Lviskbd != null && Lviskbd['BK'] != null)
{
var keyCaps=Lviskbd['BK'],noKeyCaps=true;
{
for(var i=0; i 0)
{
noKeyCaps = false; break;
}
}
}
if(noKeyCaps) Lviskbd=null;
}
// Generate a visual keyboard from the layout (or layout default)
// TODO: this should probably be unconditional now
if(Lviskbd != null || Lhelp == '' || device.touchable) // I3363 (Build 301)
{
// TODO: May want to define a default BK array here as well
if(Lviskbd == null) Lviskbd={'F':'Tahoma','BK':dfltText}; //DDOSK
osk._GenerateVisualKeyboard(Lviskbd, Lhelp, layout, keymanweb.keyboardManager.getKeyboardModifierBitmask());
}
else //The following code applies only to preformatted 'help' such as European Latin
{
osk.ddOSK = false;
Ldiv=util._CreateElement('DIV');
Ldiv.className = "kmw-title-bar";
Ldiv.appendChild(osk._TitleBarInterior());
Ldiv.onmousedown = osk._VMoveMouseDown;
osk._Box.appendChild(Ldiv);
//Add content
var Ldiv = util._CreateElement('DIV');
Ldiv.className='kmw-osk-static';
Ldiv.innerHTML = Lhelp;
osk._Box.appendChild(Ldiv);
if(activeKeyboard['KHF']) activeKeyboard['KHF'](osk._Box);
}
if(keymanweb._TitleElement)
{
keymanweb._TitleElement.innerHTML = ""
+ activeKeyboard['KN'] + ' - ' + keymanweb._TitleElement.innerHTML; // I1972 // I2186
keymanweb._TitleElement.className=''; keymanweb._TitleElement.style.color='#fff';
}
}
// Create the key preview (for phones)
osk.createKeyTip();
// Correct the classname for the (inner) OSK frame (Build 360)
var innerFrame=osk._Box.firstChild,
kbdClass=' kmw-keyboard-'+(activeKeyboard ? activeKeyboard['KI'].replace('Keyboard_','') : '');
if(innerFrame.id == 'keymanweb_title_bar') innerFrame=innerFrame.nextSibling;
innerFrame.className='kmw-osk-inner-frame'+kbdClass;
// Append a stylesheet for this keyboard for keyboard specific styles
// or if needed to specify an embedded font
osk.appendStyleSheet();
if(osk._Enabled) osk._Show();
}
/**
* Append a style sheet for the current keyboard if needed for specifying an embedded font
* or to re-apply the default element font
*
**/
osk.appendStyleSheet = function() {
var activeKeyboard = keymanweb.keyboardManager.activeKeyboard;
var activeStub: com.keyman.KeyboardStub = keymanweb.keyboardManager.activeStub;
// Do not do anything if a null stub
if(activeStub == null) {
return;
}
// First remove any existing keyboard style sheet
if(osk.styleSheet) {
util.removeStyleSheet(osk.styleSheet);
}
var i, kfd=activeStub['KFont'], ofd=activeStub['KOskFont'];
// Add style sheets for embedded fonts if necessary (each font-face style will only be added once)
util.addFontFaceStyleSheet(kfd); util.addFontFaceStyleSheet(ofd);
// Temporarily hide duplicated elements on non-desktop browsers
keymanweb.alignInputs(false);
// Build the style string and append (or replace) the font style sheet
// Note: Some browsers do not download the font-face font until it is applied,
// so must apply style before testing for font availability
// Extended to allow keyboard-specific custom styles for Build 360
var customStyle=osk.addFontStyle(kfd,ofd);
if( activeKeyboard != null && typeof(activeKeyboard['KCSS']) == 'string') // KMEW-129
customStyle=customStyle+activeKeyboard['KCSS'];
osk.styleSheet = util.addStyleSheet(customStyle); //Build 360
// Wait until font is loaded then align duplicated input elements with page elements
if(osk.waitForFonts(kfd,ofd)) keymanweb.alignInputs(true);
}
/**
* Add or replace the style sheet used to set the font for input elements and OSK
*
* @param {Object} kfd KFont font descriptor
* @param {Object} ofd OSK font descriptor (if any)
* @return {string}
*
**/
osk.addFontStyle = function(kfd,ofd)
{
// Get name of font to be applied
var fn=keymanweb.baseFont;
if(typeof(kfd) != 'undefined' && typeof(kfd['family']) != 'undefined') fn=kfd['family'];
// Unquote font name in base font (if quoted)
fn = fn.replace(/\u0022/g,'');
// Set font family chain for mapped elements and remove any double quotes
var rx=new RegExp('\\s?'+fn+',?'), ff=keymanweb.appliedFont.replace(/\u0022/g,'');
// Remove base font name from chain if present
ff = ff.replace(rx,''); ff = ff.replace(/,$/,'');
// Then replace it at the head of the chain
if(ff == '') ff=fn; else ff=fn+','+ff;
// Re-insert quotes around individual font names
ff = '"' + ff.replace(/\,\s?/g,'","') + '"';
// Add to the stylesheet, quoted, and with !important to override any explicit style
var s='.keymanweb-font{\nfont-family:' + ff + ' !important;\n}\n';
// Set font family for OSK text
if(typeof(ofd) != 'undefined')
s=s+'.kmw-key-text{\nfont-family:"'+ofd['family'].replace(/\u0022/g,'').replace(/,/g,'","')+'";\n}\n';
else if(typeof(kfd) != 'undefined')
s=s+'.kmw-key-text{\nfont-family:"'+kfd['family'].replace(/\u0022/g,'').replace(/,/g,'","')+'";\n}\n';
// Store the current font chain (with quote-delimited font names)
keymanweb.appliedFont = ff;
// Return the style string
return s;
}
/**
* Function _Unload
* Scope Private
* Description Clears OSK variables prior to exit (JMD 1.9.1 - relocation of local variables 3/9/10)
*/
osk._Unload = function()
{
osk._VShift = osk._DivVKbd = osk._VKeySpans = osk._Box = 0;
}
/**
* Save size, position, font size and visibility of OSK
*/
osk.saveCookie = function()
{
var c = util.loadCookie('KeymanWeb_OnScreenKeyboard');
var p=osk.getPos();
c['visible'] = osk._Enabled ? 1 : 0;
c['userSet'] = osk.userPositioned ? 1 : 0;
c['left'] = p.left; c['top'] = p.top;
if(osk._DivVKbd)
{
c['width'] = osk.width; c['height'] = osk.height;
}
util.saveCookie('KeymanWeb_OnScreenKeyboard',c);
}
/**
* Restore size, position, font size and visibility of desktop OSK
*
* @return {boolean}
*/
osk.loadCookie = function()
{
var c = util.loadCookie('KeymanWeb_OnScreenKeyboard');
if(typeof(c) == 'undefined' || c == null)
{
osk.userPositioned=false; return false;
}
osk._Enabled = util.toNumber(c['visible'],true);
osk.userPositioned = util.toNumber(c['userSet'],false);
osk.x = util.toNumber(c['left'],-1);
osk.y = util.toNumber(c['top'],-1);
// Restore OSK size - font size now fixed in relation to OSK height, unless overridden (in em) by keyboard
var dfltWidth=0.3*screen.width;
//if(util.toNumber(c['width'],0) == 0) dfltWidth=0.5*screen.width;
var newWidth=util.toNumber(c['width'],dfltWidth),
newHeight=util.toNumber(c['height'],0.15*screen.height);
// Limit the OSK dimensions to reasonable values
if(newWidth < 0.2*screen.width) newWidth = 0.2*screen.width;
if(newHeight < 0.1*screen.height) newHeight = 0.1*screen.height;
if(newWidth > 0.9*screen.width) newWidth=0.9*screen.width;
if(newHeight > 0.5*screen.height) newWidth=0.5*screen.height;
if(osk._DivVKbd)
{
osk._DivVKbd.style.width=newWidth+'px';
osk._DivVKbd.style.height=newHeight+'px';
osk._DivVKbd.style.fontSize=(newHeight/8)+'px';
}
// and OSK position if user located
if(osk.x == -1 || osk.y == -1 || (!osk._Box)) osk.userPositioned = false;
if(osk.x < window.pageXOffset-0.8*newWidth) osk.x=window.pageXOffset-0.8*newWidth;
if(osk.y < 0) {osk.x=-1; osk.y=-1; osk.userPositioned=false;}
if(osk.userPositioned && osk._Box) osk.setPos({'left':osk.x,'top':osk.y});
return true;
}
})();
}