14. september 2008 - 14:56Der er
68 kommentarer og 1 løsning
Hvorfor stopper min event-handler IE?
Hej, jeg sidder med et stykke kode hvor der indegår to event-handlere, og så vidt jeg kan se, er det oprettelse af den nye event (addEvent) der får IE til at gøre absolut intet - ikke engang reagere på den event der kalder editPhrase - addEvent(pElm, 'click', editPhrase)
Jeg har følgende:
function editPhrase(e) { var phrase = getTarget(e).lastChild.nodeValue; while(getTarget(e).lastChild) getTarget(e).removeChild(getTarget(e).lastChild);
Det skal så lige siges, at måden du aktivere editPhrases funktionen er et trykke på en hvilken som helst sætning på listen, og for at gemme den redigerede sætning, trykker du på whitespace mellem inputfeltet og den grå streg under inputfeltet du redigere sætningen i.
Rolig nu ... vi har også andet at lave! Det er forskellen på at betale E-points og kroner.
Du har under alle omstændigheder et problem omkring navngivningen af dine div. En id må ikke begynde med et tal, men _skal_ begynde med et bogstav eller en underscore.
Om det er årsagen - og IE ikke vil adressere felterne - ved jeg dog ikke. Under alle omstændigheder bør du rette det.
Jeg kan ikke teste så meget på din applikation, da load.php kun kan tilgås med XMLHttpRequests fra dit eget domæne, så prøv selv at teste på hvad somhelst med en alert. Begynd i toppen af den funktion, du mistænker og alert alle variabler, der kan have interesse. Flyt derefter alerten en linje eller to og alert nye variabler og/eller ændrede tilstande/værdier ... fortsæt på denne måde til bunden af funktionen. Gå derefter videre til næste funktion, osv.
Jo, i IE kan jeg åbenbart godt kalde load.php herfra. Det ser ud til, at serveren faktisk kaldes, hvis jeg klikker på et div. Det betyder, at det ikke er din event handler, der fejler noget. Jeg tester lige lidt mere =)
Sorry, men jeg har siddet med denne fejl siden igår, så man bliver lidt frustreret med tiden...
Hvis jeg nu fortæller dig at hvis man fjerner addEvent(getTarget(e), 'click', savePhrase); fra funktionen, så gør IE alt helt perfekt (bortset fra selvfølgelig at tilføje eventen), men lige så snart den tilføjes, sker der intet igen. Jeg har prøvet at debugge shittet, hele dagen, og det var det eneste jeg kunne finde.
Problemet er, at når du sætter event'en i slutningen af editPhrase, er handleEvent ikke færdig med at loope igennem alle event handlers for typen 'click'. Derfor vil din nye event handler ligge som den sidste i array'et - og savePhrase bliver afviklet
Jeg ville nok også lade add- og remove-funktionerne være IE-aware:
function addEvent(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent("on"+type, handler); } else { // assign each event handler a unique ID
- og:
function removeEvent(element, type, handler) { if (element.removeEventListener) { element.removeEventListener(type, handler, false); } else if (element.detachEvent) { element.detachEvent("on"+type, handler); } else { // delete the event handler from the hash table
Yeah, det er er kun et logo der vil være på den, normalt, private side du fik link til, så det går nok;)
Jeg sidder og forestiller mig at løsningen er at finde en killer event-handler samling, i stedet for det jeg kører med der. Har du nogen forslag? Jeg har før fundet et link til en konkurrence om hvem der kunne lave de bedste event handlers og sådan - ret hardcore kode, hvor jeg ikke fatter halvdelen af hvad der står i den, hvilket også er hvorfor jeg har valgt at bruge den jeg kører med nu. Men måske det var et dårligt valg:P
Men hvorfor egentlig al den event gymnastik? Sæt én event handler på alle div. Lad denne handler sætte en attribut på div'et, der skifter hver anden gang, der klikkes. Værdien af attributten afgør så, hvad der skal ske, når der klikkes.
Husk også, at ECMA 262 reserverer tegnet '$' til maskingenereret kode. Det bør du ikke bruge i variabelnavne (selvom det desværre er vældig på mode for tiden)
Det skulle der jo så en helt ny funktion til for at lave, udover den linie der opretter eventen. Det er uden tvivl mere end de 4 linier jeg bruger til at skifte frem og tilbage med events'ne, ved hjælp af den event handler jeg bruger til alle events jeg arbejder med;)
Det med ECMA 242 og '$' må du forklare nærmere - den event handler jeg bruger er en jeg fandt på en blog (i forbindelse med før nævnte konkurrence), som jeg så har bygget videre på og ændret nogen ting som jeg gerne vil have dem til at se ud. Men jeg har aldrig fattet hvad de '$' gør godt for:P
Det jeg mente var bare, at ved at lave det event-toggle-værk du snakkede om, ville der skulle bruges flere linier kode, end de 4 linier jeg bruger nu, til at slette og oprette de nødvendige events.
function clickPhrase(e) { var oElm = getTarget(e); if (getAttribute("editing")!="yes") { var phrase = oElm.lastChild.nodeValue; while(oElm.lastChild) oElm.removeChild(oElm.lastChild);
var edit = document.createElement('input'); edit.setAttribute('type', 'text'); edit.setAttribute('value', phrase); edit.className = 'text'; var css = edit.style; css.width = "509px"; css.fontSize = "12px"; css.marginBottom = "9px"; oElm.appendChild(edit); setAttribute("editing", "yes"); } else { if (oElm.lastChild) { var id = oElm.getAttribute('id'); var phrase = oElm.lastChild.value; while(oElm.lastChild) oElm.removeChild(oElm.lastChild);
var savedPhrase = document.createTextNode(phrase); oElm.appendChild(savedPhrase);
function clickPhrase(e) { var oElm = getTarget(e); if (oElm.getAttribute("editing")!="yes") { var phrase = oElm.lastChild.nodeValue; while(oElm.lastChild) oElm.removeChild(oElm.lastChild);
var edit = document.createElement('input'); edit.setAttribute('type', 'text'); edit.setAttribute('value', phrase); edit.className = 'text'; var css = edit.style; css.width = "509px"; css.fontSize = "12px"; css.marginBottom = "9px"; oElm.appendChild(edit); oElm.setAttribute("editing", "yes"); } else { if (oElm.lastChild) { var id = oElm.getAttribute('id'); var phrase = oElm.lastChild.value; while(oElm.lastChild) oElm.removeChild(oElm.lastChild);
var savedPhrase = document.createTextNode(phrase); oElm.appendChild(savedPhrase);
Det med style i tagget er fordi jeg stadig arbejder på at fixe et problem der hedder at firefox ikke gider style edit-feltet når det er blevet oprettet, så jeg smed bare et hurtigt style på som en løsning, indtil jeg fik løst IE problemet.
- og hvad '$' angår, så er JavaScript underlagt ECMA's standard for scriptsprog - og som for tiden hedder ECMA 262. Denne standard reserverer '$' til maskingenereret kode. Med det forstås f.eks:
style er i javascript DOM-binding et objekt-property på et html-element og ikke en attribut, og så er det ret væsentligt, selvom der findes en cssText-ting i visse browsere (som nødvendigvis skal sættes meget forsigtigt, da den jo erstatter, præcis son en setAttribute jo vil gøre !-)
$ har i javascript ikke en egentlig betydning, og vil i mange tilfælde være gyldig til en hel del ting, men er i ECMA-script-rekommendationen reserveret til at bruges i 'maskin-genereret' kode, det bedste eksempel, jeg kender handler om matches i regExps:
var x = "Jeg er et kvaj"; var reg = /\s(e)/g; var txt = x.replace(reg,"_$1") alert(txt);
"Så det vil sige jeg kan bruge reserverede ord som variabel navne, ved at sætte '$' foran?" >> Nej, det har du helt misforstået. Men i princippet kan du jo sette et hvilket somhelst bogstav foran et reserveret ord - for så er det jo et andet ord =)
'$' er desværre kommet på mode blandt visse kodere som begyndelsesbogstav på funktionsnavne - men det er ikke nogen særlig god idé, da '$' er reserveret til anden brug
Nu er der så et andet problem - hvis du klikker i et edit felt efter at have "startet edit-mode" så vil både ie og ff komme med en fejl. Det prøvede jeg så at ordne med if(!oElm.lastChild) return; hvilket også virkede i alle browsere bortset fra ie, da ie returnere event-target som HTMLInputElement ligemeget om du faktisk trykker på edit-feltet eller bare i selve div-element som input elementet ligger i.
"nej, for som sagt ser IE altid event-target som input feltet, ligegyldigt hvor i div'n du trykker." >> Nej, det er ikke korrekt. Det, jeg foreslog før, virker i hvertfald i IE (kan som sagt ikke teste i andet)
Ahh, nu har jeg identificeret insektet - IE tager margenen på et element med som en del af elementet, så hvis man trykker på margenen, er det det samme som at trykke på element. Og i så fald virker mit eksempel (if(!oElm.lastChild) return;) også perfekt... Det var da egentligt en dum opfattelse af elementer IE har -.-
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.