der sker intet når jeg trykker på knappen, jeg har prøvet onclick/onClick både med setAttribute og med button.onClick/click jeg har prøvet at lave en funktion der ingen argumenter tog og så gøre det således:
button.setAttribute("onClick", testFunc);
ligeledes både med stort og lille 'c' og setAttribute og button.
jeg har lige tjekket w3schools.com (http://w3schools.com/htmldom/dom_obj_pushbutton.asp) og der synes jeg ikke at jeg kan finde noget. kan det virkelig passe at man ikke kan sætte onclick på en button vha. DOM?
Nøøøhhh ... w3schools.com er ikke mange døde fluer værd! Får man endelig navigeret sig udenom de værste fejl og misforståelser, kommer man til alle sitets mangler og udeladelser :o|
den har problemer med argumenter når man gør det på den måde. man skal bruge noget preventDefault men jeg har aldrig rigtig forstået pricippet. laver oftest mine ting således jeg kan undgå argumenter netop derfor
-> w13 - ja altså jeg har en funktion der får noget info fra en php-fil i json-"format" og denne json bliver gennemløbet og der bliver genereret en tabel med de data jeg får, i hver linje er der en knap, som bruges til at slette den pågældende linje fra databasen, det er den knap der skal køre funktionen deleteProduktType som logisk nok skal bruge id'et på den pågældende række...
det virker nogenlunde, bortset fra at alle knapperne sletter den sidste række i tabellen, så hver gang jeg laver en addEvent på button, gør den det på alle knapperne...
Det kræver rigtig god forståelse af mange principper at skrive god DOM-kode. Således risikerer man meget let at havne på dybt vand med crashende browsere flydende mellem bøjerne, når man bruger Ajax og event handlers.
Når man sætter anonyme funktioner som event handlers, får man meget ofte lavet cirkullære refrencer mellem JavaScript og DOM'en. Sker det, kan IE ikke frigive hukommelsen igen, når elementerne fjernes og null'es ... selv når der skiftes side, fejler IE ofte med at frigive hukommelsen!
Prøv f.eks. at åbne din Task Manger og load dette dokument i en IE. Læg mærke til, hvordan hukommelsesforbruget er drastisk stigende med hvert klik på knappen:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>TITLE</title> </head> <body>
<button onclick="bar()">TEST</button>
<div id="gnu"></div>
<script type="text/javascript"> var oPar = document.getElementById("gnu"); var oo = null; function addEvent(oElm, sType, fn) { oElm.attachEvent("on"+sType, fn); } function foo(nInx) { var el = document.createElement("div"); oPar.appendChild(el); el.appendChild( document.createTextNode("Div_" + nInx) ); addEvent(el, "click", function() {alert("clicked")}); addEvent(el, "mouseover", function() {alert("over")}); addEvent(el, "mouseout", function() {alert("out")}); } function bar() { var i, j; for (i=0; i<20; i++) { // Opret 500 elementer og indsæt dem i div'et 'gnu' for (j=0; j<500; j++) { foo(j); } // - og slet dem igen while (oPar.firstChild) { oo = oPar.firstChild; oPar.removeChild(oo); oo = null; } oo = null; } } </script>
- og så må du i øvrigt aldrig tildele et element en event handler, før elementet er indsat i dokumentets DOM-træ. Ellers spilder IE taber også hukommelse :o|
Nu vil nogle nok indevende, at mit eksempel indsætter 10.000 elementer og derfor er urealistisk. Det er absolut ikke tilfældet.
Jeg kender f.eks. en bruger på Eksperten, der lavede en 'Eksperten-reader', som hele tiden stod og tjekkede visse af E's kategorier for nye spørgsmål/indlæg. På et tidspunkt, hvor vi tilfældig kom til at tale om emnet i en tråd, gik det pludseligt op for ham, hvorfor browseren med den pågældende applikation hele tiden crashede! ;o)
-> ole - hold da op, den æder lige godt 120mb hver gang :0 - det er jo vildt!
okay, jeg var ikke klar over at man kunne tildele noget til et element efter det var blevet indsat i dokumentet, altså jeg troede at alt der skulle laves ifb et element skulle gøres inden man tilføjede det. men så er det vel derfor at jeg har problemet med at alle button får tildelt den samme eventhandler, altså den sidste der bliver tildelt, bliver tildelt til alle knapperne?
Jeg forstår ikke, hvad 'button' refererer til i kommentaren (27/05-2008 18:25:53). Jeg kan ikke se, du opretter en reference til noget. Jeg kan kun se, du lige pludselig prøver at tildele 'button' en event handler og noget tekstindhold ... men hvad er 'button', og hvor kommer den fra?
og dette står inde i en for løkke som løber min json-streng igennem
okay, det er ikke mig der har fået det forkert ind, det vil være rigtigt nok at generere en tabel med knapper i en for-løkke, for samtidig at tildele knapperne id'er og så derefter løber knapperne igennem og tildele eventhandlers til dem en efter en?
hvad mener du med problemer? det undrer mig at jeg ikke kan skrive json.types[i].type.id i deleteProduktType-kaldet, men at jeg er nødt til at smide den over i en variabel og så bruge den i kaldet.
men "anonym" funktion, går jeg ud fra at du mener:
men problemet er stadig det samme, den tildeler eventhandlers til alle de forgående knapper, så alle knapperne kalder funktionen deleteProductType med samme id som argument...
Nu har jeg ikke gennemlæst spørgsmålet så grundigt, men kan du ikke bruge new Function("blabla"+var+"blabla") i stedet for function(){blabla} til at sammensætte en funktion med i stringform?
-> w13 - jeg er ikke lige med, jeg kan lige prøve at ridse problemet op:
jeg genererer en tabel, med data fra database, og på hver linje skal der være en knap der kalder en funktion som sletter den pågældende række i db'en, denne funktion skal natruligvis have et id med som argument. når jeg tilføjer eventhandlers til knapperne, gør den det hele tiden til alle de forgående knapper, så når den er færdig, vil den sidste linje blive slettet uanset hvilken knap du trykker på...
endnu en ting der undrer mig, som jeg ligger mærke til nu, er at den add'er en event igen efter den sidste knap er tilføjet, for den skulle alert'e "hej: "+i - hvor i er samme tal som den knap man trykker på, og da det ikke virker korrekt, ville jeg mene at alle knapper skulle alert'e "hej: 4", da den sidste knap hedder btn_4, men de alert'er "hej: 5".. ?
Nej, jeg har ikke givet op, men har haft travlt med andre ting =)
Når du gennemløber løkken, bliver værdien af 'i' forhøjet med én for hvert gennemløb. Når den anonyme funktion kaldes, anvender denne den værdi, som variablen 'i' har på det pågældende tidspunkt ... ikke værdien af 'i' på det tidspunkt, hvor event handleren sættes.
Hvis du opbygger koden proceduralt, kan du f.eks. gøre sådan:
function findTag(oSrcElm, sTag) { var oBody = document.getElementsByTagName("body")[0]; while (oSrcElm!=oBody) { if (oSrcElm.nodeName.toLowerCase()==sTag) return oSrcElm; oSrcElm = oSrcElm.parentNode; } return null; }
function foo(e) { var e = e ? e : event; var oSrcElm = e.target ? e.target : event.srcElement; oSrcElm = findTag(oSrcElm, "button"); alert(oSrcElm.getAttribute("elmInx")); }
function doDom(){ body = document.getElementsByTagName('body')[0]; for (var i=0; i < 5; i++) { var btn = document.createElement('button'); btn.appendChild(document.createTextNode('btn_'+i)); body.appendChild(btn); btn.setAttribute("elmInx", i); addEvent(btn, "click", foo); btn = null; } } </script>
Årsagen til 'findTag' er, at brugeren kunne klikke på et nested element. Event objektets target eller srcElement ville i så være det nestede element - ikke det element, handleren er sat på.
Personligt ville jeg nok opbygge det objekt orienteret, men det gør absolut ikke problemerne omkring IE's hukommelsestab mindre!
Har du brug for at tilknytte en værdi fra det øjeblik, handleren sættes, kan du sætte den som attribut på elementet.
Dog er det bedre kodestil at oprette et abstrakt element og sætte værdier som properties på dét - og så udelukkende bruge HTML elementet som interface. I andre programmerings miljøer er det et must at opbygge alt som abstraktioner, så applikationen/logikken er komplet adskilt fra 'display' og 'håndtag'.
Funktionalitet på WWW kom humpende ind fra venstre i Netscape 2.0 browseren - og blev klistret ovenpå et paragraf- og tabelværk, beregnet til opstilling og syndikering af videnskabelige måledata (HTML). Derfra har teknologien i rekordtempo udviklet sig bl.a. til et udviklingsmiljø, hvor man kan bygge store, komplekse business løsninger.
Af hensyn til bagudkompatibilitet halter både sprogene og browserne, der skal afvikle applikationerne, voldsomt bagud i forhold til ønskerne omkring udviklingen. Samtidig er indlæringskurven for webteknologierne ganske lav. Det gør, at rigtig mange af de kodere, der skriver websites og -applikationer, ikke har nogen teoretisk uddannelse i programmering. En situation, der yderligere sinker udviklingen og 'opstramningen' af sprogene.
Både www's unge alder og dets historie/kultur gør således, at vi har en masse møllesten at slæbe på. Selvom webprogrammering er yderst let at gå til, er det - når tingene bliver komplekse - ofte vanskeligere at have med at gøre end mere 'langhårede' miljøer/sprog/teknologier. Forholdene bliver forhåbentligt bedre med tiden ;o)
-- er det dig eller mig, der har en fotografisk hukommelse, for den der addEvent ser godt nok ens ud (bortset fra et 'n' i evnt, og jeg har den i hvert fald ud fra en tidligere gennemgang af problematikken !-)
hej ole, det er helt i orden, det var osse bare for sjov :)
så det vil sige at på en måde kan man sige at der hele tiden står "i" i den tildelte eventhandler, og så når den bliver kaldt, finder den ud af hvad værdien af "i" er? så giver det mere mening jo.
jeg vil også gerne opbygge det objekt orienteret, men det rækker min viden desværre ikke til på nuværende tidspunkt :( - så jeg starter med at prøve dit eksempel.
jeg har ikke, som sådan, brug for at vide hvilket element der sender eventen, det var bare hvis det var en bedre løsning (eller den eneste) - jeg forstår ikke helt det med det abstrakte du snakker om :S
og tak for en lille historie om www :)
-> roenving - det er "din" kode han bruger i eksemplet, jeg går ud fra at han har c/p fra mit link 29/5-20:52 - det er bare mig der har ændret lidt på det du kom med tidligere :)
roenving >> Som du måske husker, indeholder min mail-signatur følgende linjer:
-------------------------------------------------------------------------------------------- Everyone has a photographic memory .... some just don't have film
Hehe ... næhhh, det var såmænd helt som splazz skriver: copy/paste ;o)
splazz >> "funktionen "foo", går den ikke ind og ser på" - jo.
- og det er helt legalt at bruge custom attributter, når de sættes/læses af script. Derimod giver det ingen mening at sætte f.eks. target attributten under html 4.01 Strict med det formål at få browseren til at åbne et nyt vindue (HTML 4.01 Strict indeholder som bekendt ikke target attributten)
Det er et stykke tid siden(lille år) jeg rodede med den eval under add/attachevent og kunne ikke selv huske hvorfor jeg egentlig endte op med den ... (http://www.eksperten.dk/spm/833495)
- Dit spørgsmål her minder mig om det. Jeg bryder mig ikke selv om at bruge eval for meget (overdrevet), men når jeg kigger på foo, findtag og det ekstra holder attribut tror jeg, at jeg beholder den lille eval, det er jo ikke en stor streng eller kompliceret sammensætning af funktioner jeg eval'er...
Jeg ville nok ikke bruge eval, men jeg tør ikke lægge hovedet på blokken i forhold til den faktiske forskel i performance ved denne specifikke problematik. Jeg har dog en klar formodning ;o)
Linjen: oSrcElm = findTag(oSrcElm, "button");
- er medtaget af generelle grunde. Det betyder ikke så meget ved et button element. Forestil dig, du i stedet for en knap lavede denne konstruktion: <div>Noget tekst og noget <b>fed tekst</b>, der kan klikkes på</div>
- og satte en onclick handler på divet, som kører funktionen foo. Så kunne du indføre et par alerts i foo:
function foo(e) { var e = e ? e : event; var oSrcElm = e.target ? e.target : event.srcElement; alert(oSrcElm.nodeName); // <-- Her ... oSrcElm = findTag(oSrcElm, "div"); alert(oSrcElm.nodeName); // <-- og her alert(oSrcElm.getAttribute("elmInx")); }
Hvis du så klikker på den fede tekst, vil den første alert returnere 'B' og den anden 'DIV'. Klikker du derimod udenfor den fede tekst, vil begge alerts returnere 'DIV'. Derfor ... =)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1"><title>dom4.htm</title>
function doDom(){ body = document.getElementsByTagName('body')[0]; for (var i=0; i < 5; i++) { var btn = document.createElement('div'); btn.appendChild(document.createTextNode('Noget tekst og noget ')); var btn2 = document.createElement('b'); btn2.appendChild(document.createTextNode('fed tekst '+i)); btn.appendChild(btn2); btn.appendChild(document.createTextNode(', der kan klikkes på')); body.appendChild(btn); addEvent(btn, "click", "alert('hej: "+i+"');"); btn = btn2 = null; } }
function findTag(oSrcElm, sTag) { var oBody = document.getElementsByTagName("body")[0]; while (oSrcElm!=oBody) { if (oSrcElm.nodeName.toLowerCase()==sTag) return oSrcElm; oSrcElm = oSrcElm.parentNode; } return null; }
function foo(e) { var e = e ? e : event; var oSrcElm = e.target ? e.target : event.srcElement; oSrcElm = findTag(oSrcElm, "div"); alert('hej' +oSrcElm.getAttribute("elmInx")); }
function doDom(){ body = document.getElementsByTagName('body')[0]; for (var i=0; i < 5; i++) {
var btn = document.createElement('div'); btn.appendChild(document.createTextNode('Noget tekst og noget ')); var btn2 = document.createElement('b'); btn2.appendChild(document.createTextNode('fed tekst '+i)); btn.appendChild(btn2); btn.appendChild(document.createTextNode(', der kan klikkes på'));
det ser ud til at begge løsninger har hver deres fordele og ulemper, så jeg tror jeg prøver mig frem, og finder ud af hvilken jeg skal bruge til mit projekt, det kan jo være jeg får brug for dem begge.
mclemens >> Jeg må desværre dømme din 'event handler ting' som værende dårlig og rystende overflødig. F.eks. kan der kun medsendes strenge som variabler - og det er i hvertfald for mig komplet ubrugeligt.
Medsender jeg et array som ["et", "to"], ender jeg øjensynligt op med strengen "et, to". Medsender jeg objektet {"one":"en", "two":"to"}, ender jeg op med et tomt objekt. Desuden skal enkelte apostroffer i strenge escapes med to backslashes: "blabla \\'noget i gåseøjne\\' blabla bla" - hvilket også er noget rod.
I forbindelse med mere avanceret kode - ikke mindst OOP - er løsningen komplet håbløs, da der ikke kan medsendes referencer og der ikke kan scopes!
Jeg forstår ikke begrundelsen for dine snørklede veje for at konstruere en måde at sætte event handlers på, men udfra teksten i din artikel at dømme, må det skyldes manglende forståelse for JS - og måske scoping i JS.
Det giver som bekendt ikke mening at diskutere koden i en artikel i kommenrafelterne under artiklen - og jeg har forlængst opgivet at arbejde seriøst med E's forfatter interface til artiklerne - men jeg vil prøve at strikke en artikel sammen om emnet på www.dengodekode.dk. Jeg har pokkers travlt lige for tiden, så det varer nok et par uger =)
Umiddelbart kan jeg godt sende et array eller object... - Men grunden til jeg skrev mit oprindelige om var egentlig at jeg manglede en måde at fjerne funktioner fra event'en.
Grunden til at jeg ikke bruger foo og findtag er at IE, som du selv er inde på, ikke refererer over til this på samme måde som FF gør. Det gør så at man skal fange elementet for at få adgang til et obj med gemte variabler eller evt. en variabel der henviser til et globalt object ...
- det er ikke altid et fast element tag der skal søges efter i findtag, og det kan være svært at vide om man rammer den rigtige div med flere div's i hinanden.
Jeg er enig i dig i at det ikke er optimalt - jeg plejer nu kun at bruge det jeg brugte før til at rette op på "this" problemet. Det vil være rart hvis du finder en smutvej der gør det muligt uden eval (jeg synes ikke rigtig at jeg kunne finde andet end det du foreslog i 29/05-2008 23:47:14)
Hmm, du mener nok et array eller obj der er defineret i forvejen ... den eneste måde jeg lige kan se det på er:
var tmp;
function addalerts(){ tmp={'one':'en', 'two':'to'}; element=document.getElementById("testelement"); ael(element, "click", "forward(tmp);"); }
function forward(obj){ for(i in obj)alert(i+": "+obj[i]); }
(men det er jo heller ikke optimalt, der kan dog også sættes en attribut på elementet og så have et globalt obj istedet og så læse i funktionen efter attributen og hente objectet fra det globale object ... men igen lidt snørklet)
- Hvordan sender du dit array eller obj med via en almindelig addeventlistener?
Nej, jeg mener ikke et globalt defineret objekt (og det går jeg udfra, du mener i dit eksempel, selvom du erklærer variablen med 'var') - men et objekt, der er lokalt defineret i en funktions scope og ønskes medsendt til handleren ved en event.
Det er der være flere måder at gøre på, men det kunne f.eks. være sådan: var a = ["et", "to"]; oObject.addEventListener("click", function(){myFunc(a)}, false);
Løsningen kan under ingen omstændigheder bruges, hvis arrays og objects skal være globale for at virke. Det (og en del andet) gør den komplet ubrugelig i forbindelse med OOP.
Du kan ikke få FF til at overholde standarden omkring this, men hvis man gør det korrekt, er der heller ingen problemer i dén retning. Det handler om scopes, men det er for lang en omgang at kaste sig ud i her, så du må vente på artiklen =)
Desuden kører du en bunke kode, hvergang du kalder funktionen. Alle dine if-sætninger skal således evalueres ved hvert kald af funktionen - og det er jo vildt overkill. If-sætningerne bør vel kun køres én gang - så der tages højde for broweren én gang for alle i dét dokument ;o)
Jeg ser frem til artiklen, når du skriver den vil det være rart hvis du lige kom forbi removeeventlistener også - (jeg synes at jeg har problemer med at fjerne den anonyme funktion i ovenstående)
function addalerts(){ var a = ["et", "to"]; oObject=document.getElementById("testelement"); oObject.addEventListener("click", function(){myFunc(a)}, false); oObject.removeEventListener("click", function(){myFunc(a)}, false);
Den vil jeg også kikke igennem på et tidspunkt ;o)
Du skal iøvrigt lige vide, at de værste problemer omkring IE's memory leaks ser ud til at være løst. Det er efterhånden et stykke tid siden, MS udgav en sikkerhedsopdatering, som tager hånd om dette problem. De har formodentlig været hårdt presset Ajax' hastige udbredelse ;o)
Synes godt om
Ny brugerNybegynder
Din løsning...
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.