Per aumentare l'usabilità dobbiamo aggiungere una tastiera a video.
Questo richiede un nuovo oggetto, che chiameremo con molta fantasia Keyboard.
Inoltre, viste le maggiori dimensioni del box, la grafica deve permettere risoluzioni fino a 1600x1200
L'oggetto Keyboard
function _keyboard()
{
this.activeInputField
this.FieldId=-1
this.chars = new Array ('789','456','123','0');
this.keyboardTable
}
Questo è l'oggetto; è collegato all'oggetto HTML contenente i tasti dalla proprietà
_msgBox.prototype.checkKeyboard = function ()
{
if (!this.Keyboard)
{
this.Keyboard = new _keyboard()
this.divKeyboard.appendChild(this.Keyboard.show())
}
}
_msgBox.prototype.showKeyboard = function ()
{
/* In base al campo selezionato visualizzerò la tastiera più opportuna */
this.checkKeyboard()
this.divKeyboard.style.display = 'block';
}
La tabella che conterrà la tastiera deve essere costruita con il DOM se vogliamo che gli eventi passino correttamente in tutti i browser.
_keyboard.prototype.show = function () {
var kTable = document.createElement("table");
kTable.className = 'keyb';
kTable.id = 'table_keyboard';
msgBoxInstance.collegaEvento(kTable, 'click', this.handleClick)
var kRow
var kCell
for (var i=0; i<this.chars.length; i++)
{
aRow = this.chars[i];
kRow = kTable.insertRow(-1);
for (var j=0; j<aRow.length; j++)
{
kCell = kRow.insertCell(-1)
kCell.unselectable="on"
kCell.appendChild(document.createTextNode(aRow.charAt(j)))
kCell.className='key';
kCell.value = aRow.charAt(j)
}
}
this.keyboardTable = kTable;
return kTable
}
Il metodo handleClick dell'oggetto _keyboard identifica il tasto che ha originato l'evento click e ne utilizza la proprietà value.
_keyboard.prototype.handleClick = function (e) {
{
/*
gestisce l'input da tastiera virtuale (per modifica articolo)
leggi anche http://www.quirksmode.org/js/introevents.html
*/
var td
try
{
if (e instanceof Object)
{ // firefox
td = (e.target?e.target:e) // gestisco anche che venga
// passato direttamente l'oggetto come parametro
}
else
td = event.srcElement;
// td è l'oggetto cliccato - si spera con un carattere come attributo "value"...
while ((td) && (td.className!='key'))
{
td = td.parentElement;
}
if (td)
{
var k = msgBoxInstance.Keyboard;
k.replaceSelection (k.activeInputField, td.value)
msgBoxInstance.fields[k.FieldId].value = k.activeInputField.value
}
else
log1('handleClick: object not found');
}
catch(ex) {
log1('errore: ' + ex)
}
}
}
La posizione del cursore
Cercherò di essere breve.
Il funzionamento per Firefox è piuttosto lineare. Invece in Internet Explorer abbiamo difficoltà maggiori.
In particolare la differenza è che mentre firefox ricorda la posizione del cursore all'interno di un campo anche se questo campo non ha il focus, altrettanto non vale per IE.
Il codice usato qui è preso dal valido esempio pubblicato http://www.faqts.com/knowledge_base/view.phtml/aid/13562 ed usa lo stesso "trucchetto" per evitare questo problema: aggiungere a tutti gli elementi che potrebbero "rubare" il focus dal nostro campo input la proprietà unselectable=true.
Un'altra strada praticabile e più pulita è - solo per IE - di salvare il range corrente in una proprietà dinamica input.lastRange = input.createTextRange _prima_ che questo perda il focus (evento - proprietario IE - onlosecapture)
Quindi all'interno dell'oggetto Keyboard definisco alcune funzioni per gestire il focus:
setSelectionRange imposta l'area selezionata (oppure, se selectionStart = selectionEnd, posiziona il cursore alla posizione indicata)
_keyboard.prototype.setSelectionRange = function (input, selectionStart, selectionEnd) {
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(selectionStart, selectionEnd);
}
else if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
}
}
e replaceSelection: sostituisce la selezione oppure aggiunge alla posizione corrente.
_keyboard.prototype.replaceSelection = function (input, replaceString) {
if (input.setSelectionRange) {
var selectionStart = input.selectionStart;
var selectionEnd = input.selectionEnd;
input.value = input.value.substring(0, selectionStart)
+ replaceString
+ input.value.substring(selectionEnd);
this.setCaretToPos(input, selectionStart + replaceString.length);
}
else if (document.selection) {
var range = document.selection.createRange();
if (range.parentElement() == input) {
// ovvero c'è una selezione nel nostro input box.
var isCollapsed = (range.text == '');
range.text = replaceString;
}
else
{
// fallback in caso il focus sia stato preso da un altro campo
// (in tal caso selection.createRange() non fa riferimento a input)
input.value += replaceString;
}
}
else
{
// fallback per altri browsers
input.value += replaceString;
}
}
Ora rivediamo come usare questa funzionalità (dal nostro file msgBox.html):
function request()
{
msgBox_Edit.virtualKeyboard = true;
msgBox_Edit.clearFields()
msgBox_Edit.addField('Nick', 'nick', 'Nemo')
msgBox_Edit.addField('e-Mail', 'email', 'Questo indirizzo email è protetto dagli spambots. È necessario abilitare JavaScript per vederlo.')
msgBox_Edit.request('Ma chi sei?',elaboraRispostaRequest,
'un\'altra domanda di cultura generale', -1)
}
E nella callback potremo semplicemente elencare i campi e vederne i valori:
function elaboraRispostaRequest(msgResult)
{
var txl = document.getElementById('textlog');
txl.value = 'risultato msgBox: '+ msgResult+'\n'
+ 'attiva: '+ msgBoxAttiva
+ '\nId: ' + msgBoxInstance.id_msgBox ;
var aField
for (var i=0; i< msgBox_Edit.fields.length; i++)
{
aField = msgBox_Edit.fields[i]
txl.value += '\nCampo '+i+' ('+aField.desc+')= '+aField.value
}
}
Nelle prossime puntate vedremo di rendere più potente questa funzione, fornendo sia tastiere dedicate che alcuni tasti standard; e aggiungeremo la validazione essenziale dei campi.
I file descritti in questo articolo si possono scaricare dall'introduzione