Avatar billede kjeldsted Novice
21. januar 2012 - 19:20 Der er 20 kommentarer og
1 løsning

onmousedown ved getElementById()

Hejsa.

Jeg er støt på et lille problem i forbindelse med en side jeg ville lave lidt dynamisk. I den forbindelse har jeg brug for at vide hvornår der med musen bliver trykket på en bestemt boks. Jeg gik ud fra jeg blot skulle benytte document.getElementById("boks").onmousedown, men jeg kan jo konstatere at dette kun virker uden getElemntById("boks"), og så er jeg lidt lige vidt.
Hvad skal jeg lige gøre for at kunne registrere dette?

På forhånd tak, og fortsat god weekend :)
Avatar billede olebole Juniormester
21. januar 2012 - 19:51 #1
<ole>

Jeg tror, alle browsere understøtter:

function foo() {
    alert("Foo");
}
document.getElementById("boks").onmousedown = foo;

- men ellers kan du f.eks. skrive:

function foo() {
    alert("Foo");
}

var elm = document.getElementById("boks");
if (elm.addEventListener) elm.addEventListener("click", foo, false);
else if (elm.attachEvent) elm.attachEvent("onclick", foo);

/mvh
</bole>
Avatar billede olebole Juniormester
21. januar 2012 - 19:56 #2
- eller du kan bruge en X-browser wrapper:

var setEvent = (function() {
    if (window.addEventListener) return function(elm, sType, fn) {
        elm.addEventListener(sType, fn, false);
    }
    else if (window.attachEvent) return function(elm, sType, fn) {
        elm.attachEvent("on"+sType, fn);
    }
})();
function foo() {
    alert("Foo");
}

setEvent(document.getElementById("boks"), "click", foo);
Avatar billede kjeldsted Novice
21. januar 2012 - 20:00 #3
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
    body {
        margin:0px;   
    }
    #boks {
        position:absolute;
        background-color:#F00;
        height:200px;
        width:200px;
        margin-left:245px;   
    }
</style>
<script type="text/javascript">
function foo() {
    alert("Foo");
}
document.getElementById("boks1").onmousedown = foo;
</script>
</head>
<body>
    <div id="overallContainer">
        <div id="boks">bar</div>
    </div>   
</body>
</html>


Ja, lidt overflødigt meget kode. Men ovenstående kan jeg i hvert fald ikke få til at virke i hvert FF eller Safari...

Og jeg kan heller ikke få den til at virke med dit andet forslag, Ole...
Er det mig eller min computer der er blevet syg? ;o
Avatar billede olebole Juniormester
21. januar 2012 - 20:02 #4
Når du skriver: "Jeg er støt på et lille problem i forbindelse med en side jeg ville lave lidt dynamisk", får jeg den tanke, at det kunne være elementer, du opretter - og evt. sletter - dynamisk med JS.

I så fald vil jeg nok fraråde at lægge event handlers på de oprettede elementer, men lægge en enkelt handler på det omkransende element. Så kan du spørge på event'ens srcElement eller target - alt efter, hvad browseren understøtter - og udføre handlingen, hvis det er et af de ønskede elementer
Avatar billede olebole Juniormester
21. januar 2012 - 20:02 #5
Kik i fejlmeddelserne  *o)
Avatar billede kjeldsted Novice
21. januar 2012 - 20:06 #6
Pt. bliver elementerne ikke oprettet dynamisk... Men det skulle de gerne kunne komme til senere.

Og lille kommentar til #3. Jeg ved godt jeg skriver "boks" et sted og "boks1" et andet. Men det står der nu kun ved #3, og er rette i selve koden. Uden det hjalp :(

Og Fejlkonsolen i FF skriver at document.getElementById("boks") is NULL
Avatar billede claes57 Ekspert
21. januar 2012 - 20:20 #7
javascriptlinjen
document.getElementById("boks").onmousedown = foo;
skal kaldes efter feltet er tegnet i html - dvs placer et javascriptkald efter
<div id="boks">bar</div>
der kører den linje.
Avatar billede kjeldsted Novice
21. januar 2012 - 20:20 #8
Og hvis vi nu antager at jeg har en opsætning med en <div> der hedder "overallContainer", hvori der er en række bokse kaldet boks1, boks2, boks3 osv. som skal kunne fjernes/tilføjes/flyttes dynamisk.

Hvis jeg så ligge en handler på overallContainer hvor jeg gerne vil kunne flytte boks1, hvordan skal jeg så rent praktisk hive fat i den child der så hedder boks1?
Avatar billede kjeldsted Novice
21. januar 2012 - 20:24 #9
#7: Hm... Jeg synes da nu ikke før at have oplevet at den ikke kan finde oplysninger om elementer der ligger under selve scriptet....
Men det ser vist ud til at være svaret...
Avatar billede kjeldsted Novice
21. januar 2012 - 20:26 #10
Ah... Fandt lidt om det hér: http://help.dottoro.com/ljahrnvn.php

Tror jeg vil prøve at give mig i kast med dét...
Avatar billede kjeldsted Novice
21. januar 2012 - 20:33 #11
Nå, men tak til jer begge. Jeg tror jeg vil lade jer dele de points, hvis det er i orden :)

I har jo sådan set begge løst mit problem og jeg kommer til at benytte både #7 samt #4. Så smid nogle svar.
Avatar billede olebole Juniormester
21. januar 2012 - 21:46 #12
Jeg samler ikke point, så det løser sig selv  =)

Med hensyn til #9: Det er jo egentlig ganske logisk. Browseren læser ikke koden anderledes, end du selv gør ... oppefra og ned. Hvis du kalder et element, der endnu ikke 'er født', vil det ikke give mening for browseren - hvorfor den smider en fejl om, at referencen er null.

Hvordan du skal delegere dine events, kan jeg fortælle dig. Det afhænger af den kode, det skal virke i. Hvad jeg ikke fik skrevet ovenfor, er, at du efter al sandsynlighed får skabt en bunke memory leaks, hvis du lægger handlers på de dynamisk oprettede elementer. Det kræver et meget godt kendskab til både JS, DOM og ikke mindst de forskellige browsere (og deres versioners) garbage collection
Avatar billede olebole Juniormester
21. januar 2012 - 21:50 #13
PS: Scriptet behøver ikke ligge under/efter elmentet i koden. Selve kaldet må bare ikke foretages, før elementet er renderet - f.eks. lige efter window objektets onload event bliver fyret af
Avatar billede kjeldsted Novice
21. januar 2012 - 21:52 #14
#12. Det er da også rigtigt at du ikke samler på points. Så må claes57 nyde dem :)

Og, ja. Det er jo selvfølgelig rigtigt nok at det jo burde hænge sådan sammen.

Og så er jeg da ked af at læse Det kræver et meget godt kendskab til både JS, DOM og ikke mindst de forskellige browsere (og deres versioners) garbage collection. Nu er min viden om JS og DOM stadig meget begrænset, da jeg pt. kun har beskæftiget mig med meget simple JS ting og først nu rigtigt går i gang med de mere "interessante" ting. Men vil da kaste mig over garbage collection i min O'Reilly bog om JS. Så må vi se om jeg kan blive lidt klogere ;)
Avatar billede kjeldsted Novice
21. januar 2012 - 21:59 #15
Hm... O'Reilly konkludere at "You need to know only enough about garbage collection to trust that it works"...
Han skriver blot kort hvordan det fungere og at det ikke er noget programmøren behøver tænke over.

Men hvad skal man så vide om det?
Avatar billede olebole Juniormester
21. januar 2012 - 22:17 #16
Nu er det nok ikke Tim O'Reilly selv, der har skrevet bogen (mon det skulle være den legendariske 'The Rhino Book'?) - og det er i hvertfald totalt forvrøvlet i en virkelighed med komplicerede dynamiske sider, som ví har set dem siden Ajax så dagens lys.

Konklusionen holdt meget godt i perioden fra 1992 til midten af nullerne, men er totalt i hegnet i dag! Faktisk var garbage collection på det tidspunkt nærmest på et komisk stade på det tidspunkt, men der var heller ikke så meget at bruge det til - siderne blev skiftet længe inden, memory leaks kunne blive et problem.

Kun de største ignoranter tager ikke den slags ind som meget alvorlige overvejelser i planlægningen af en moderne webapplikation!

Det betyder langtfra, det ikke sker, at udviklere ikke tænker i memory leaks. Bag nettet er hullerne mellem kompetence ofte enorme  *o)
Avatar billede kjeldsted Novice
21. januar 2012 - 22:44 #17
Nej, okay. Det er ikke ham selv der er skrevet den. Kun udgivet den ;) Og, jo. Det må være The Rihno.
Ellers synes jeg da at det jeg har læst i bogen pt. virker ganske fornuftigt. Selvom den er tilbage fra 2007.

Men hvor findes der information om dette emne som man kan blive lidt klogere på?
Avatar billede olebole Juniormester
22. januar 2012 - 00:35 #18
Kanon bog(!), men den må så være skrevet i 2005/6. Den er en anelse yngre end De Ti Bud!  *o)

Det er et kæmpe emne, som omfatter mange forskellige problematikker i forskellige browsere og deres forskellige versioner - ikke mindst IE. Specielt har IE haft meget svært ved at rydde ordentligt op - eller rettere, at koordinere oprydningen af JavaScript med oprydningen af DOM'en og omvendt. IE har således haft enormt svært ved at opløse cirkulære referencer mellem JavaScript scopes og DOM elementer, hvilket dog er blevet væsentligt forbedret i de seneste 2-3 versioner.

Det er dog ikke kun fejl og uhensigtsmæssigheder i browserne, der skaber problemer. Ligeså ofte skyldes problemer omkring memory leaks manglende forståelse for DOM og JavaScript - og såmænd også mangel på grundlæggende forståelse for programmering og programmel.

I den følgende kode oprettes en reference til to DIVonload. Derefter farver jeg det inderste DIV gult og indsætter et P element med innerHTML, når der trykkes på den første knap.

Et klik på den anden knap prøver at farve det inderste DIV rødt, men hvad sker der?

Tredie knap prøver at sammenligne referencen, jeg oprettede på onload med det DIV, der ligger i dokumentet. Hvad sker?

<script type="text/javascript">
var elmInner = null,
elmOuter = null;

function foo() {
    elmInner.style.background = "#ff0";
    elmOuter.innerHTML += "<p>Et P-tag, indsat med innerHTML</p>";
}
function bar() {
    // Dette virker ikke
    elmInner.style.background = "#f00";
}
function baz() {
    // Er elmInner og vores DIV 'inner' det samme?
    alert(document.getElementById("inner") == elmInner);
}

window.onload = function() {
    elmInner = document.getElementById("inner");
    elmOuter = document.getElementById("outer");
}
</script>

<div id="outer">
    <div id="inner">Dette er DIV'et "inner"</div>
</div>

<p>
    <button onclick="foo()">Tilføj og farv 'inner' gul</button>
    <button onclick="bar()">Farv 'inner' rød</button>
    <button onclick="baz()">Er de ens?</button>
</p>

Når vi skriver noget til i det yderste DIV's innerHTML, overskriver vi i virkeligheden denne med en kopi af sig selv - plus det nye. Derfor er det inderste DIV ikke længere det samme, som det, vi lavede en reference til på onload.

Det ligger til gengæld i hukommelsen - og er ildrødt  *o)

Faktisk kan du prøve at sætte det ind igen med:

function fooBar() {
    elmOuter.appendChild(elmInner);
    alert(elmOuter.innerHTML)
}
- og:

<button onclick="fooBar()">Indsæt igen</button>

Alert'en er kun til, fordi DIV'et i hukommelsen er tomt i IE og derfor ikke bliver vist ... men det ligger der. Alle andre browsere viser DIV'et med oprindeligt indhold.

En enkelt reference, der bliver liggende i hukommelsen, betyder ikke noget, men i moderne objekt orienterede, dynamiske, ajax drevne applikationer kan det pludselig blive rigtig meget hukommelse, der ikke frigives.

Et andet eksempel er manglende brug af nøgleordet this i event handlers. Et eksempel kunne være:

var oXHR = new XMLHttpRequest();
oXHR.open("post", sUrl, true);
oXHR.setRequestHeader("Content-Type: application/x-www-form-urlencoded; charset=utf-8");
oXHR.onreadystatechange = function() {
    if (oXHR.readyState<4) return;
    doSomeThing(oXHR.responseText);
};
oXHR.send("contxt=getUsers");

Her oprettes en cirkulær reference mellem JS og XHR-objektet, fordi variabelnavnet 'oXHR' benyttes indenfor handlerens closure. Denne reference opløses ikke ved funktionens udløb i IE - i hvertfald ikke op til og med version 8. Det siges, det skulle være rettet helt i version 9, men jeg har ikke selv fået testet.

Løsningen er at bruge this i stedet for oXHR indenfor handleren - hvilket også er i langt bedre overensstemmelse med almindelig OOP-tankegang.

Der ligger enkeltartikler om emnet her og der på nettet, men husk at tjekke for alderen. Der er kæmpe forskel på specielt IE6-9 - med mange mellemstadier.

Meget af det grunder dog som sagt i forståelse af virkemåden af browseren , DOM'en og JavaScript - samt programmering, generelt. Webkodning har en flad indlæringskurve. Ligesom det i sløjdsalen er forholdsvis let at få lavet noget brugbart, kan man også skrive alm. websider med noget serverdrevet dynamik.

Når man skal i gang med at skrive dynamiske webapps med Ajax og masser af DOM manipulation, kommer man til det punkt, hvor møbelsnedkeren skiller sig ud fra sløjdsalen. Moderne webudvikling er et fag  *o)
Avatar billede kjeldsted Novice
22. januar 2012 - 01:10 #19
Puha, da, for et indlæg. Først og fremmest mange tak for hjælpen :)

Når jeg tænker mig om var udgaven af bogen jo næsten lige udkommet da jeg købte den i sin tid ('06. Kan se den er udgiver august '06 og ikke '07 som jeg skrev ;) ), men der er jo selvfølgelig sket en del siden. Jeg har da også bemærket antallet af referencer til IE6.

Men jeg kan da godt se at det ikke altså er den bedste løsning blot at tage saven i hånden og save løs. Man skal måske vide en del om det på forhånd, inden man for alvor slår sig løs.

Tror jeg læser det hele igennem i morgen når jeg er lidt mere frisk. For det kræver vist man er lidt vågen.
Avatar billede kjeldsted Novice
24. januar 2012 - 16:23 #20
Claes57, ville du have lidt points for dette?
Avatar billede kjeldsted Novice
25. januar 2012 - 16:51 #21
Har endnu ikke lige fået det nærlæst. Men i hvert fald mange tak for hjælpen til jer begge.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester