mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
Refactored setupDesktopPage() to allow for setup of dynamically-added inputs after page initialization, added setup for solving #29.
Includes present code for testing the issue.
This commit is contained in:
parent
b3d7fe6ce3
commit
15939a34a9
5 changed files with 290 additions and 9 deletions
99
testing/issues-29-63.html
Normal file
99
testing/issues-29-63.html
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
|
||||
<!-- Set the viewport width to match phone and tablet device widths -->
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no" />
|
||||
|
||||
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
||||
<!-- Enable IE9 Standards mode -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>KeymanWeb Sample Page - Uncompiled Source</title>
|
||||
|
||||
<!-- Your page CSS -->
|
||||
<style type='text/css'>
|
||||
body {font-family: Tahoma,helvetica;}
|
||||
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
|
||||
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
|
||||
#KeymanWebControl {width:50%;min-width:600px;}
|
||||
</style>
|
||||
|
||||
<!-- Insert uncompiled KeymanWeb source scripts -->
|
||||
<script src="../source/kmwstring.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwbase.js" type="application/javascript"></script>
|
||||
<script src="../source/keymanweb.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwosk.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwnative.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwcallback.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwkeymaps.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwlayout.js" type="application/javascript"></script>
|
||||
<script src="../source/kmwinit.js" type="application/javascript"></script>
|
||||
|
||||
<!--
|
||||
For desktop browsers, a script for the user interface must be inserted here.
|
||||
|
||||
Standard UIs are toggle, button, float and toolbar.
|
||||
The toolbar UI is best for any page designed to support keyboards for
|
||||
a large number of languages.
|
||||
-->
|
||||
<script src="../source/kmwuitoggle.js"></script>
|
||||
|
||||
<!-- Initialization: set paths to keyboards, resources and fonts as required -->
|
||||
<script>
|
||||
var kmw=window.tavultesoft.keymanweb;
|
||||
kmw.init({
|
||||
resources:'resources'
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Add keyboard management script for local selection of keyboards to use -->
|
||||
<script src="./issues-29-63.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<!-- Sample page HTML -->
|
||||
<body onload='loadKeyboards();'>
|
||||
<h2>KeymanWeb Sample Page - Uncompiled Source</h2>
|
||||
|
||||
<div id='DynamicTextboxes'>
|
||||
<!--
|
||||
The following DIV is used to position the Button or Toolbar User Interfaces on the page.
|
||||
If omitted, those User Interfaces will appear at the top of the document body.
|
||||
(It is ignored by other User Interfaces.)
|
||||
-->
|
||||
<div id='KeymanWebControl'></div>
|
||||
|
||||
<!--<h3>Type in your language in this text area:</h3>
|
||||
<textarea id='ta1' class='test' placeholder='Type here'></textarea>
|
||||
|
||||
<h3>or in this input field:</h3>
|
||||
<input id='in1' class='test' placeholder='or here'/>-->
|
||||
<hr>
|
||||
</div>
|
||||
<input type='button' id='btn1' onclick='addInputs();' value='Create Inputs!' />
|
||||
<h3><a href="../samples/index.html">Return to testing home page</a></h3>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
<!--
|
||||
*** DEVELOPER NOTE -- FIREFOX CONFIGURATION FOR TESTING ***
|
||||
*
|
||||
* If the URL bar starts with <b>file://</b>, Firefox may not load the font used
|
||||
* to display the special characters used in the On-Screen Keyboard.
|
||||
*
|
||||
* To work around this Firefox bug, navigate to <b>about:config</b>
|
||||
* and set <b>security.fileuri.strict_origin_policy</b> to <b>false</b>
|
||||
* while testing.
|
||||
*
|
||||
* Firefox resolves website-based CSS URI references correctly without needing
|
||||
* any configuration change, so this change should only be made for file-based testing.
|
||||
*
|
||||
***
|
||||
-->
|
||||
</html>
|
||||
116
testing/issues-29-63.js
Normal file
116
testing/issues-29-63.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// JavaScript Document samplehdr.js: Keyboard management for KeymanWeb demonstration pages
|
||||
|
||||
/*
|
||||
The keyboard name and/or ISO language code must be specified for each keyboard that is to be available.
|
||||
If the same keyboard is used for several languages, it must be listed for each
|
||||
language, but the keyboard itself will only be loaded once.
|
||||
If two (or more) keyboards are to be available for a given language, both must be listed.
|
||||
Any number of keyboards may be specified in one or more calls.
|
||||
Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path.
|
||||
The actual keyboard object will be downloaded asynchronously when first selected for use.
|
||||
|
||||
Each argument to addKeyboards() is a string, for example:
|
||||
european2 loads the current version of the Eurolatin 2 keyboard (for its default language)
|
||||
european2@fra loads the current version of the Eurolatin 2 keyboard for French
|
||||
european2@fra@1.2 loads version 1.2 of the Eurolatin 2 keyboard for French
|
||||
|
||||
Argument syntax also supports the following extensions:
|
||||
@fra load the current version of the default keyboard for French
|
||||
@fra$ load all available keyboards (current version) for French
|
||||
|
||||
Each call to addKeyboards() requires a single call to the remote server,
|
||||
(unless all keyboards listed are local and fully specified) so it is better
|
||||
to use multiple arguments rather than separate function calls.
|
||||
|
||||
Calling addKeyboards() with no arguments returns a list of *all* available keyboards.
|
||||
The Toolbar (desktop browser) UI is best suited for allowing users to select
|
||||
the appropriate language and keyboard in this case.
|
||||
|
||||
Keyboards may also be specified by language name using addKeyboardsForLanguage()
|
||||
for example:
|
||||
keymanweb.addKeyboardsForLanguage('Burmese');
|
||||
|
||||
Appending $ to the language name will again cause all available keyboards for that
|
||||
language to be loaded rather than the default keyboard.
|
||||
|
||||
The first call to addKeyboardsForLanguage() makes an additional call to the
|
||||
keyman API to load the current list of keyboard/language associations.
|
||||
|
||||
In this example, the following function loads the indicated keyboards,
|
||||
and is called when the page loads.
|
||||
*/
|
||||
|
||||
function loadKeyboards()
|
||||
{
|
||||
var kmw=tavultesoft.keymanweb;
|
||||
|
||||
// The first keyboard added will be the default keyboard for touch devices.
|
||||
// For faster loading, it may be best for the default keybaord to be
|
||||
// locally sourced.
|
||||
kmw.addKeyboards({id:'us',name:'English',language:{id:'eng',name:'English'},
|
||||
filename:'./us-1.0.js'});
|
||||
|
||||
// Add more keyboards to the language menu, by keyboard name,
|
||||
// keyboard name and language code, or just the ISO 639 language code.
|
||||
kmw.addKeyboards('french','european2@swe','european2@nor','@heb');
|
||||
|
||||
// Add a keyboard by language name. Note that the name must be spelled
|
||||
// correctly, or the keyboard will not be found. (Using ISO codes is
|
||||
// usually easier.)
|
||||
kmw.addKeyboardsForLanguage('Dzongkha');
|
||||
|
||||
// Add a fully-specified, locally-sourced, keyboard with custom font
|
||||
kmw.addKeyboards({id:'lao_2008_basic',name:'Lao Basic',
|
||||
language:{
|
||||
id:'lao',name:'Lao',region:'Asia',
|
||||
font:{family:'LaoWeb',source:['../font/saysettha_web.ttf','../font/saysettha_web.woff','../font/saysettha_web.eot']}
|
||||
},
|
||||
filename:'./lao_2008_basic.js'
|
||||
});
|
||||
|
||||
// The following two optional calls should be delayed until language menus are fully loaded:
|
||||
// (a) a specific mapped input element input is focused, to ensure that the OSK appears
|
||||
// (b) a specific keyboard is loaded, rather than the keyboard last used.
|
||||
//window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500);
|
||||
//window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fra');},3000);
|
||||
|
||||
// Note that locally specified keyboards will be listed before keyboards
|
||||
// requested from the remote server by user interfaces that do not order
|
||||
// keyboards alphabetically by language.
|
||||
}
|
||||
|
||||
{
|
||||
var inputCounter = 1;
|
||||
}
|
||||
|
||||
function addInputs()
|
||||
{
|
||||
var masterDiv = document.getElementById('DynamicTextboxes');
|
||||
|
||||
var newTextArea = document.createElement("textarea");
|
||||
|
||||
var i = inputCounter++;
|
||||
|
||||
newTextArea.id = 'ta' + i;
|
||||
newTextArea.className = 'test';
|
||||
newTextArea.placeholder = "Dynamic area!";
|
||||
|
||||
var newInput = document.createElement("input");
|
||||
newInput.id = 'in' + i;
|
||||
newInput.className = 'test';
|
||||
newInput.placeholder = "Dynamic area!";
|
||||
|
||||
masterDiv.appendChild(newTextArea);
|
||||
masterDiv.appendChild(newInput);
|
||||
|
||||
// keymanweb.inputList = [];
|
||||
// keymanweb.setupDesktopPage();
|
||||
// keymanweb._AttachToControls(newTextArea);
|
||||
// keymanweb._AttachToControls(newInput);
|
||||
|
||||
keymanweb.setupDesktopElement(newTextArea);
|
||||
keymanweb.setupDesktopElement(newInput);
|
||||
keymanweb.attachToControl(newTextArea);
|
||||
keymanweb.attachToControl(newInput);
|
||||
keymanweb.listInputs();
|
||||
}
|
||||
1
testing/lao_2008_basic.js
Normal file
1
testing/lao_2008_basic.js
Normal file
File diff suppressed because one or more lines are too long
1
testing/us-1.0.js
Normal file
1
testing/us-1.0.js
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1028,18 +1028,37 @@
|
|||
var ipList=document.getElementsByTagName(k==0?'INPUT':'TEXTAREA');
|
||||
for(var n=0;n<ipList.length;n++)
|
||||
{
|
||||
if(ipList[n].className.indexOf('kmw-disabled') < 0 && !ipList[n].readOnly )
|
||||
keymanweb.inputList.push(ipList[n]);
|
||||
if(ipList[n].className)
|
||||
ipList[n].className=ipList[n].className+' keymanweb-font';
|
||||
else
|
||||
ipList[n].className='keymanweb-font';
|
||||
keymanweb.setupDesktopElement(ipList[n]);
|
||||
// if(ipList[n].className.indexOf('kmw-disabled') < 0 && !ipList[n].readOnly )
|
||||
// keymanweb.inputList.push(ipList[n]);
|
||||
// if(ipList[n].className)
|
||||
// ipList[n].className=ipList[n].className+' keymanweb-font';
|
||||
// else
|
||||
// ipList[n].className='keymanweb-font';
|
||||
}
|
||||
}
|
||||
//TODO: sort list by y, x position on page
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function setupDesktopElement
|
||||
* Scope Private
|
||||
* Description Setup one element for non-touch devices and add it to the inputList if it is an input element (desktop browsers)
|
||||
* @return {boolean}
|
||||
*/
|
||||
keymanweb.setupDesktopElement = function(Pelem)
|
||||
{
|
||||
// If it's not one of these, we don't need to hook the OSK into it.
|
||||
if(!(Pelem.tagName == "INPUT" || Pelem.tagName == "TEXTAREA")) return false;
|
||||
|
||||
// TODO: Fix potential issue - We might have an issue if, for some reason, an element is re-added later.
|
||||
if(Pelem.className.indexOf('kmw-disabled') < 0 && !Pelem.readOnly)
|
||||
keymanweb.inputList.push(Pelem);
|
||||
if(Pelem.className)
|
||||
Pelem.className=Pelem.className+' keymanweb-font';
|
||||
else
|
||||
Pelem.className='keymanweb-font';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user-specified (or default) font for the first mapped input or textarea element
|
||||
* before applying any keymanweb styles or classes
|
||||
|
|
@ -1765,7 +1784,7 @@
|
|||
var ro=Pelem.attributes['readonly'],cn=Pelem.className;
|
||||
if(typeof ro == 'object' && ro.value != 'false' ) return;
|
||||
if(typeof cn == 'string' && cn.indexOf('kmw-disabled') >= 0) return;
|
||||
|
||||
|
||||
if(Pelem.tagName.toLowerCase() == 'iframe')
|
||||
keymanweb._AttachToIframe(Pelem);
|
||||
else
|
||||
|
|
@ -3155,6 +3174,8 @@
|
|||
* Description Local function to get list of editable controls
|
||||
*/
|
||||
var LiTmp = function(_colon){return Pelem.getElementsByTagName(_colon);};
|
||||
|
||||
// If the element Pelem has any child elements, we wish to analyze those.
|
||||
var Linputs = LiTmp('INPUT'),
|
||||
Ltextareas = LiTmp('TEXTAREA'),
|
||||
Lframes = LiTmp('IFRAME'),
|
||||
|
|
@ -3537,6 +3558,49 @@
|
|||
// Restore and reload the currently selected keyboard
|
||||
keymanweb.restoreCurrentKeyboard();
|
||||
|
||||
/* Setup of handlers for dynamically-added and (eventually) dynamically-removed elements.
|
||||
* Reference: https://developer.mozilla.org/en/docs/Web/API/MutationObserver
|
||||
*
|
||||
* We place it here so that it loads after most of the other UI loads, reducing the MutationObserver's overhead.
|
||||
*/
|
||||
|
||||
keymanweb.observationTarget = document.querySelector('body');
|
||||
keymanweb.mutationObserver = new MutationObserver(function(mutations)
|
||||
{
|
||||
var dirtyFlag = false; // Notes if we need to recompute our .sortedInputs array.
|
||||
//console.log(mutations);
|
||||
|
||||
console.log(mutations.length);
|
||||
|
||||
for(i=0; i < mutations.length; i++)
|
||||
{
|
||||
mutation = mutations[i];
|
||||
|
||||
for(j = 0; j < mutation.addedNodes.length; j++)
|
||||
{
|
||||
var addedNode = mutation.addedNodes[j];
|
||||
|
||||
// Will need to handle this in case of child elements in a newly-added element with child elements.
|
||||
// if(mutation.addedNode.getElementsByTagName) console.log(mutation.target.getElementsByTagName('INPUT'));
|
||||
|
||||
if(addedNode.tagName == 'INPUT' || addedNode.tagName == 'TEXTAREA')
|
||||
{
|
||||
dirtyFlag = true;
|
||||
//TODO: Make this a function call that does the real work!
|
||||
//console.log(addedNode, " - ", mutation);
|
||||
}
|
||||
}
|
||||
|
||||
// There also exists a 'mutation.removedNodes' array. We'll need to address that for issue #63.
|
||||
|
||||
// After all mutations have been handled, we need to recompile our .sortedInputs array.
|
||||
if(dirtyFlag) keymanweb.listInputs();
|
||||
}
|
||||
});
|
||||
|
||||
keymanweb.observationConfig = { childList: true, subtree: true };
|
||||
keymanweb.mutationObserver.observe(keymanweb.observationTarget, keymanweb.observationConfig);
|
||||
|
||||
// Set exposed initialization flag to 2 to indicate deferred initialization also complete
|
||||
keymanweb['initialized']=2;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue