			var kLetAlfaNum = [ ' 0','1','abc2','def3','ghi4','jkl5','mnńo6','pqrs7','tuv8','wxyz' ]
			var kLetNum = [ '0','1','2','3','4','5','6','7','8','9' ]
			var kLetAlfa = [ ' ','','abc','def','ghi','jkl','mnńo','pqrs','tuv','wxyz' ]
			var kLetNumBlank = [ '0 ','1','2','3','4','5','6','7','8','9' ]

			var kBuf = [ ''  ,'',''   ,''   ,''   ,''   ,''    ,''    ,''   ,'' ]
			var index = 0
			var nowTime = new Date().valueOf()
			var keyStroke = ''
			var timeOutMsecs = 1000
			var timer = null
			
			// activa el field indicado en nField del form indicado por nForm
			function focusField( nForm, nField ) {
				document.forms[nForm].elements[nField].focus()
				return false			
			} 

			// función de atención al teclado
			// parámetros (todos opcionales
			// 1 = array de caracteres asignados a cada tecla DTMF
			// 2 = true si validar el field valida el formulario
			// 3 = función de validación del formulario
			function tecla() {
				if ( event.keyCode == 0 )
					return

				var nField = document.getElementById(event.srcElement.id).name
				var nForm = document.getElementById(event.srcElement.id).form.name

				// arg 1 = máscara de teclado
				if ( arguments.length > 0 && arguments[0] != null )
					kLet = arguments[0]
				else
					kLet = kLetAlfaNum

				// arg 2 = true si el field es validador
				if ( arguments.length > 1 && arguments[1] != null )
					var validate = arguments[1]
				else
					var validate = false
					
				// arg 3 = función de validación, si el field es validador
				
				///////////////////////////////////////////////////////////////////////////////
				
				var field = document.forms[nForm].elements[nField]
				var texto = field.value
				var code = parseInt(event.keyCode)
								
				if ( code>=48 && code<=57 )
					var iKeyStroke = code-48
				else
					var iKeyStroke = -1
				
				switch(iKeyStroke) {
					case 0:
					case 2:
					case 3:
					case 4:
					case 5:
					case 6:
					case 7:
					case 8:
					case 9:
						if ( timer != null ) {
							clearTimeout( timer )
							timer = null
							var field = document.forms[nForm].elements[nField]
							var iCurrent = field.tabIndex
							if ( iCurrent >= document.forms[nForm].elements.length )
								iCurrent = 0
							focusField( nForm, iCurrent )
						}

						var now = new Date().valueOf()
						if ( (now - nowTime) > timeOutMsecs && keyStroke != '' ) {
							kBuf = [''  ,'',''   ,''   ,''   ,''   ,''    ,''    ,''   ,''    ]
							index++	
						}	
						else {
							if ( code != keyStroke && keyStroke != '' ) {
								kBuf = [''  ,'',''   ,''   ,''   ,''   ,''    ,''    ,''   ,''    ]
								index++	
							}
						}

						if ( kBuf[iKeyStroke] == '' || kBuf[iKeyStroke].length == kLet[iKeyStroke].length )
							kBuf[iKeyStroke] = kLet[iKeyStroke].charAt(0)
						else
							kBuf[iKeyStroke] += kLet[iKeyStroke].charAt(kBuf[iKeyStroke].length)
						letter = kBuf[iKeyStroke].charAt(kBuf[iKeyStroke].length-1).toUpperCase()
						field.value = texto.substr(0,index) + letter
							
						keyStroke = code
						nowTime = now
						break
					default:
						switch( code ) {
							case 49:  // 1
							case 42:	// asterisco
								if ( timer != null ) {
									clearTimeout( timer )
									timer = null
								}
								if ( index > 0 ) {
									field.value = field.value.substr(0,field.value.length-1) 
									index = field.value.length
								}
								else {
									field.value = ''
									index = 0
								}
								kBuf = [''  ,'',''   ,''   ,''   ,''   ,''    ,''    ,''   ,''    ]
								keyStroke=''
								nowTime = new Date().valueOf()
								break
							case 35: // almohadilla
							case 45: // almohadilla simulador
							case 97: // almohadilla plataforma
							case 13: // enter
								if ( validate && timer != null ) {
									clearTimeout( timer )
									timer = null
									event.keyCode = null
									document.forms[nForm].submit()
									return false
								}
								
								if ( validate ) {
										if ( arguments.length > 2 && arguments[2] != null ) {
											var errMsg = arguments[2]()
											if ( errMsg == '' ) {
												timer = setTimeout('nextField("' + nForm + '","' + nField + '")'	,2000);
												event.keyCode = null
												return false
											}
											else
												alert('Errores: ' + errMsg )
										}
										else {
												timer = setTimeout('nextField("' + nForm + '","' + nField + '")'	,2000);
												event.keyCode = null
												return false
										}
								}

								if ( !validate || (now - nowTime) > timeOutMsecs ) {
									var iCurrent = field.tabIndex
									if ( iCurrent >= document.forms[nForm].elements.length )
										iCurrent = 0
									focusField( nForm, iCurrent )

									index = 0
									kBuf = [''  ,'',''   ,''   ,''   ,''   ,''    ,''    ,''   ,''    ]
									keyStroke = ''
								}
								else
									keyStroke = code

								nowTime = new Date().valueOf()
								event.keyCode = null
								return false
								break
							default:
								if ( timer != null ) {
									clearTimeout( timer )
									timer = null
								}
								break
						}
						break
				}
				field.focus()
				event.keyCode = null
			}	

			// función para cambio al field siguiente, si se pulsa una sola vez # en un field
			// de validación
			function nextField( nForm, nField ) {
				var field = document.forms[nForm].elements[nField]
				var iCurrent = field.tabIndex
				if ( iCurrent >= document.forms[nForm].elements.length )
					iCurrent = 0
				focusField( nForm, iCurrent )
			
				index = 0
				kBuf = [''  ,'',''   ,''   ,''   ,''   ,''    ,''    ,''   ,''    ]
				keyStroke = ''
				clearTimeout( timer )
				timer = null
				return false
			}
