2009-04-14 11 views
5

Ho letto un numero di post su questo ma nessuno con una risposta valida. Qui è il mio codice:setAttribute, onClick e compatibilità cross browser

// 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); 

Ora, il metodo setAttribute() (con il commento di Mozilla) funziona bene in Mozilla, ma solo se si tratta dopo la linea di sopra di esso. Quindi, in altre parole, sembra semplicemente l'impostazione predefinita per l'ultima volta impostata. Il metodo .onclick (con il commento cioè) non funziona in entrambi i casi, lo sto usando in modo errato?

In entrambi i casi non riesco a trovare un modo per farlo funzionare a IE, per non parlare di entrambi. Ho cambiato la chiamata alla funzione quando utilizzo il metodo .onclick e ha funzionato correttamente usando solo una semplice chiamata a una funzione di avviso, motivo per cui ritengo che la mia sintassi non sia corretta.

Per farla breve, non riesco a far funzionare il parametro onclick in modo coerente tra IE/Mozilla.

- Nicholas

risposta

6

Io di solito uso qualcosa di simile:

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

questo dovrebbe funzionare sia in IE e Firefox.

+0

Questo funziona perfettamente, si può spiegare il motivo per cui la sua creazione come un "nuova funzione" (anche se i fnDisplay_Computers function()" è già definito, risolve il problema? –

+0

Penso che sia un problema del tipo di dati coinvolto e il riferimento alla "nuova funzione" associata al nuovo metodo onclick ... ma davvero non conosco la risposta esatta, scusa! –

+0

Bello! Grazie! Ho avuto problemi con IE7 questo lo ha risolto perfettamente –

1

Utilizzare la funzione addEventListener() con "click" per l'argomento type per i browser basati su Mozilla, e attachEvent() funzione con "onclick" come argomento sEvent per IE; Trovo che sia meglio utilizzare un'istruzione try/catch, per esempio:

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", "pulsante");

Non utilizzare mai setAttribute su documenti HTML. IE ottiene male male, in molti casi, e le proprietà DOM-HTML sono più brevi, più veloce e più facile da leggere:

onew.type= 'button'; 

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

Che cosa sono le "aline"? Perché lo converti in una stringa e la circondi con virgolette singole? Sembra che tu stia cercando di fare qualcosa di atroce che coinvolge la valutazione del codice in una stringa (che è ciò che stai facendo qui sotto nella versione 'onew.setAttribute'). La valutazione del codice JavaScript nelle stringhe è quasi sempre la cosa sbagliata; Evitalo come la peste. Nel caso precedente, IE dovrebbe fare lo stesso di Firefox: non dovrebbe funzionare.

Se "alines [i]" è una stringa, suppongo che quello che stai cercando di fare sia ricordare quella stringa costruendo una stringa di codice che valuterà in JavaScript la stringa originale. Ma:

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

non è sufficiente. Cosa succede se 'alines [i]' ha un apostrofo o una barra rovesciata?

'O'Reilly' 

hai un errore di sintassi e un possibile buco di sicurezza.Ora, si potrebbe fare qualcosa di faticoso e fastidioso come:

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

per cercare di sfuggire alla stringa, ma è brutto e non funzionerà per gli altri tipi di dati. Si potrebbe anche chiedere Javascript per farlo per voi:

uneval(alines[i]) 

Ma non tutti gli oggetti possono anche essere convertiti in stringhe valutabili sorgente JavaScript; fondamentalmente l'intero approccio è destinato al fallimento.

La cosa normale da fare se si vuole solo avere il callback onclick chiamare una funzione con un parametro è quello di scrivere il codice in modo diretto:

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

Generalmente questo funzionerà ed è ciò che si vuole . C'è, tuttavia, una leggera ruga che potresti aver colpito qui, il che potrebbe essere ciò che ti confonde nel considerare l'approccio stravagante con le stringhe.

Vale a dire, se 'i' in questo caso è la variabile di un ciclo 'per' che racchiude, il riferimento a 'alines [i]' non farà ciò che si pensa che faccia. Si accede alla funzione "i" mediante la funzione di richiamata quando avviene il clic, ovvero dopo il il ciclo è terminato. A questo punto la variabile "i" rimarrà con qualsiasi valore avesse alla fine del ciclo, quindi "alines [i]" sarà sempre l'ultimo elemento di "alines", indipendentemente da quale "onew" è stato fatto clic.

(vedi ad es. How to fix closure problem in ActionScript 3 (AS3) per qualche discussione di questo. E 'una delle principali cause di confusione con chiusure in JavaScript e Python, e in realtà dovrebbe essere fissato ad un livello di linguaggio, un giorno.)

Puoi aggirare il problema del ciclo incapsulando la chiusura nella sua propria funzione, in questo modo:

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

// ... 

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

E in una versione successiva di JavaScript, sarete in grado di dire semplicemente:

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

Se vuoi essere in grado di utilizzare 'Function.bind()' nei browser di oggi, è possibile ottenere un'implementazione del quadro Prototype, o semplicemente usare:

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

risposta ECCELLENTE, wow hai coperto tutte le basi. Fortunatamente le stringhe sono tutte sanificate prima che alines [x] sia mai referenziato e i valori in entrata fanno parte di un array definito comunque, quindi non c'è bisogno di preoccuparsi lì. –

+0

È sicuro dire quanto segue: onclick è un gestore di eventi e NON un attributo e pertanto impostandolo come attributo non creerà il gestore di eventi necessario affinché funzioni almeno in IE? –

+1

Sì. In realtà è sia una proprietà del gestore di eventi di script nativo (di tipo Function) * sia un attributo a livello di documento (di tipo String), ma poiché IE <8 non comprende come funzionano gli attributi che tenta di impostare il gestore di eventi Stringa invece di una funzione compilata da esso, che non funziona. – bobince

0

credo # 3 protesteth troppo . In molte situazioni sto costruendo una tabella in modo dinamico e ho bisogno di passare parametri alla funzione di callback. Non è un problema di tipo typesafe poiché la mia variabile parm è un indice intero della riga della tabella in questione. Ecco il codice con sia una variabile e parametro fisso che sembra essere cross-browser compatibile:

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); 
} 
Problemi correlati