2009-04-14 9 views
5

He leído una serie de publicaciones sobre esto, pero ninguna con una respuesta sólida. Aquí está mi código:setAttribute, onClick y compatibilidad de navegador cruzado

// button creation 
onew = document.createElement('input'); 
onew.setAttribute("type", "button"); 
onew.setAttribute("value", "hosts"); 
onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // ie 
onew.setAttribute("onclick", "fnDisplay_Computers('" + alines[i] + "')"); // mozilla 
odiv.appendChild(onew); 

Ahora, el método setAttribute() (con el comentario de Mozilla) funciona bien en Mozilla, pero sólo si se trata después de la línea por encima de ella. Por lo tanto, en otras palabras, parece que solo se establece el valor predeterminado para el que se establezca en último lugar. El método .onclick (con el comentario ie) no funciona en ningún caso, ¿lo estoy usando incorrectamente?

De cualquier manera, no puedo encontrar una manera de hacer que esto funcione en IE, y mucho menos en ambos. Cambié la llamada a la función cuando usé el método .onclick y funcionó bien usando solo una simple llamada a una función de alerta, por lo que creo que mi sintaxis es incorrecta.

Para abreviar, no puedo hacer que el parámetro onclick funcione de manera consistente entre IE/Mozilla.

- Nicholas

Respuesta

6

que suelen utilizar algo como:

onew.onclick = new Function("fnDisplay_Computers('" + alines[i] + "')"); 

esto debería funcionar tanto en IE e Firefox.

+0

Esto funciona perfectamente, se puede explicar por qué su puesta en marcha como una "nueva función" (a pesar de que los fnDisplay_Computers función()" ya está definido, resuelve el problema? –

+0

Creo que es un problema del tipo de datos involucrados y la referencia a la "nueva Función" asociada con el nuevo método onclick ... pero realmente no sé la respuesta exacta, lo siento! –

+0

Hermoso! Gracias! Tuve problemas con IE7 esto lo resolvió perfectamente –

1

Utilice la función addEventListener() con "click" para el argumento type para los navegadores basados ​​en Mozilla, y attachEvent() función con "onclick" como el argumento sEvent para IE; Me parece que es mejor utilizar una sentencia try/catch, por ejemplo:

try { 
    onew.attachEvent("onclick", //For IE 
        function(){fnDisplay_Computers("'" + alines[i] + "'"); }); 
} 
catch(e) { 
    onew.addEventListener("click", //For Mozilla-based browsers 
        function(){fnDisplay_Computers("'" + alines[i] + "'"); }, 
        false); 
} 
15

onew.setAttribute ("tipo", "botón");

Nunca use setAttribute en documentos HTML. IE consigue muy mal en muchos casos, y las propiedades DOM-HTML son más cortos, más rápido y más fácil de leer:

onew.type= 'button'; 

onew.onclick = function() {fnDisplay_Computers ("'" + alines [i ] + "'"); }; // ie

¿Qué es 'alines'? ¿Por qué lo está convirtiendo en una cadena y rodeándolo con comillas simples? Parece que estás tratando de hacer algo atroz que implica la evaluación de código en una cadena (que es lo que estás haciendo a continuación en la versión 'onew.setAttribute'). La evaluación del código JavaScript en cadenas es casi siempre lo incorrecto; evitarlo como la peste. En el caso anterior, IE debería hacer lo mismo que Firefox: no debería funcionar.

Si 'alines [i]' es una cadena, supongo que lo que intenta hacer es recordar esa cadena construyendo una cadena de código que evaluará en JavaScript la cadena original. Pero:

"'" + alines[i] + "'" 

es insuficiente. ¿Qué sucede si 'alines [i]' tiene un apóstrofo adentro, o una barra invertida?

'O'Reilly' 

usted tiene un error de sintaxis y posible agujero de seguridad.Ahora, se podría hacer algo laborioso y molesto como:

"'" + alines[i].split('\\').join('\\\\').split("'").join("\\'") + "'" 

para tratar de escapar de la cadena, pero es feo y no va a funcionar para otros tipos de datos. Incluso se puede pedir JavaScript para hacerlo por usted:

uneval(alines[i]) 

Pero no todos los objetos, incluso se pueden convertir en evaluable cadenas de código JavaScript; básicamente todo el enfoque está condenado al fracaso.

Lo normal hacer si lo que desea es tener la devolución de llamada onclick llamar a una función con un parámetro es escribir el código en la forma sencilla:

onew.onclick= function() { 
    fnDisplay_Computers(alines[i]); 
}; 

Generalmente esto funcionará y es lo que quiere . Hay, sin embargo, una pequeña arruga que puede haber golpeado aquí, que podría ser lo que le confunde al considerar el enfoque loco con las cuerdas.

A saber, si 'i' en este caso es la variable de un bucle 'para' adjunto, la referencia a 'alines [i]' no hará lo que usted piensa que hace. La función de devolución de llamada accederá a la 'i' cuando ocurra el clic, que es después de que haya terminado el ciclo. En este punto, la variable 'i' quedará con el valor que tenga al final del ciclo, por lo que 'alines [i]' siempre será el último elemento de 'alines', independientemente de en qué 'onew' se haya hecho clic.

(Véase, por ejemplo. How to fix closure problem in ActionScript 3 (AS3) por alguna discusión sobre esto. Es una de las mayores causas de la confusión con cierres en JavaScript y Python, y realmente debe fijarse en un nivel de lengua algún día.)

Puede sortear el problema de bucle encapsulando el cierre en su propia función, así:

function callbackWithArgs(f, args) { 
    return function() { f.apply(window, args); } 
} 

// ... 

onew.onclick= callbackWithArgs(fnDisplay_Computers, [alines[i]]); 

Y en una versión posterior de JavaScript, podrás decir simplemente:

onew.onclick= fnDisplay_Computers.bind(window, alines[i]); 

Si le gustaría ser capaz de utilizar 'Function.bind()' en los navegadores de hoy en día, se puede obtener una implementación del marco Prototype, o simplemente utilizar:

if (!('bind' in Function.prototype)) { 
    Function.prototype.bind= function(owner) { 
     var that= this; 
     var args= Array.prototype.slice.call(arguments, 1); 
     return function() { 
      return that.apply(owner, 
       args.length===0? arguments : arguments.length===0? args : 
       args.concat(Array.prototype.slice.call(arguments, 0)) 
      ); 
     }; 
    }; 
} 
+1

EXCELENTE respuesta, wow cubriste todas las bases. Afortunadamente las cadenas están todas desinfectadas antes de que siempre se haga referencia a alines [x] y los valores entrantes son parte de un matriz definida de todos modos por lo que no hay necesidad de preocuparse. –

+0

¿Es seguro decir lo siguiente: onclick es un controlador de eventos y NO un atributo y, por lo tanto, establecerlo como un atributo no creará el controlador de eventos necesario para que funcione al menos bajo IE? –

+1

Sí. En realidad, es una propiedad de gestor de eventos de script nativo (de tipo Function) * y * un atributo de nivel de documento (de tipo String), pero dado que IE <8 no comprende cómo funcionan los atributos, intenta establecer el controlador de eventos en el Cadena en lugar de una función compilada a partir de ella, que no funciona. – bobince

0

Creo # 3 protesteth demasiado . En muchas situaciones estoy construyendo una tabla dinámicamente y necesito pasar parámetros a la función de devolución de llamada. No es un problema de tipo seguro ya que mi parm variable es un índice entero de la fila de la tabla en cuestión. Aquí está el código tanto con una variable y parámetro fijo que parece ser compatible con los navegadores:

for (i = 0; i < arrTableData.length; i++) { 
    eleTR = objTable.insertRow(i + 1); 
    cell = eleTR.insertCell(0); 
    cell.width = "21"; 
    var myElement = document.createElement('img'); 
    myElement.setAttribute('src', 'images/button_down.gif'); 
    myElement.setAttribute('alt', 'Move item down'); 
    myElement.onclick = new Function('moveItem(' + i + ',0)'); 
    cell.appendChild(myElement); 
} 
Cuestiones relacionadas