Avatar billede dr_nielsen Nybegynder
16. december 2002 - 23:16 Der er 16 kommentarer

objekter og properties

function oElement( oNode ){
  this.id = oNode;
  this.element = function(){
    var theElement = document.getElementById( oNode )
    return theElement;
  }
}


i dette eks, ønsker jeg at hente/deklarere et objekt der allerede eksistere i dokumentet.
var nodeA = new oElement('nodeAFraHTML')

hvis jeg nu ville teste på om objektet nu eksisterer, vil jeg kunne skrive noget i retning af:
if (nodeA.element){alert(nodeA.element)}, og hvis det eksisterer vil jeg vel få en alert med [object].

men jeg får en alert med funktionen skrevt ud i.

Hvordan gøre jeg dette, er det overhovedet en fornuftig måde at gøre tingene på
Avatar billede erikjacobsen Ekspert
16. december 2002 - 23:19 #1
Jeg kan ikke gennemskue om du mener dette:
if (nodeA.element){alert(nodeA.element())}
Avatar billede dr_nielsen Nybegynder
16. december 2002 - 23:23 #2
Det havde jeg glemt, men bruger jeg nu denne
alert(nodeA.element()) returnerer den null, selvom elementet eksisterer
Avatar billede erikjacobsen Ekspert
16. december 2002 - 23:27 #3
Jeg gider ikke prøve selv ... Hvad med
var theElement = document.getElementById( this.id )
for parameteren er jo længe væk
Avatar billede dr_nielsen Nybegynder
16. december 2002 - 23:33 #4
nope, men kan du se ideen, ved at deklarere elementet og igennem objektet hente al nødvendig info (crossbrowser)
der kunne jo endvidere optræde properties som .style .parentNode etc.

Ideen er at skabe et lag som er en fællesnævner til methods og properties på kryds af browserer
Avatar billede erikjacobsen Ekspert
16. december 2002 - 23:36 #5
Hvorfor funktionen? Vil
  this.obj = document.getElementById( oNode );
ikke skaffe dig en reference til objektet?
Avatar billede olebole Juniormester
17. december 2002 - 02:57 #6
<ole>
Nu, da jeg allerede har svaret på ét spm. idag, napper jeg også lige dette  :)

Det er en temmelig uortodoks objektorientering, du har gang i. Den rigtige måde er som følger:

<html>
<head>
<script type="text/JavaScript">
var d=document;
var ns4 = (d.layers)? true : false;

function oElement( oNode ) {
    this.o = (ns4)? d.layers[oNode] : d.getElementById( oNode );
    this.id = this.o.id;
    this.css = (ns4)? this.o : this.o.style;
    this.bCol = this.css.backgroundColor;
    this.w = this.css.width;
    this.h = this.css.height;
    this.html = (ns4)? "I NS4.X kan du ikke aftaste innerHTML" : this.o.innerHTML;
    return this;
}

window.onload = function() {
    var nodeA = new oElement('ib');
   
    // Eksempler:
    alert("id: " + nodeA.o.id);
    alert("innerHTML: " + nodeA.html);
    alert("backgroundColor: " + nodeA.bCol);
    alert("width: " + nodeA.w);
    alert("height: " + nodeA.h);
}
</script>
</head>
<body>

<div id="ib" style="background-color:#ff0000;width:200px;height:100px;">blabla</div>

</body>
</html>

Jeg checker her kun for ns4 mod alle andre - det bør naturligvis udvides (Opera kan f.eks. heller ikke læse innerHTML). Dette var kun et eksempel.
Vær endvidere opmærksom på, du skal sætte styles på elementet (som inline styles - _ikke_ en class) for at kunne aftaste værdierne. Det har dog ikke noget med OOP at gøre ... det er generelt gældende.
Jeg har ikke testet eksemplet op mod NS4.X - men det burde virke.

/mvh  *<|:o)
</bole>
Avatar billede olebole Juniormester
17. december 2002 - 03:01 #7
Linien:
  this.id = this.o.id;
er naturligvis helt overflødig ... jeg lod mig vist forlede af din egen kode  :)

/mvh
Avatar billede olebole Juniormester
17. december 2002 - 03:16 #8
Du kan også lave metoder, som du knytter til objektet:

<html>
<head>
<script type="text/JavaScript">
var d=document;
var ns4 = (d.layers)? true : false;

function oElement( oNode ) {
    this.o = (ns4)? d.layers[oNode] : d.getElementById( oNode );
    this.css = (ns4)? this.o : this.o.style;
    this.bCol = this.css.backgroundColor;
    this.w = this.css.width;
    this.h = this.css.height;
    this.html = (ns4)? "I NS4.X kan du ikke aftaste innerHTML" : this.o.innerHTML;
    this.setWidth = fnSetWidth;
    return this;
}
function fnSetWidth(w) {
    this.css.width = w;
    this.w = w;
}

var nodeA;
window.onload = function() {
    nodeA = new oElement('ib');
}
</script>
</head>
<body>

<div id="ib" style="background-color:#ff0000;width:200px;height:100px;">blabla</div>

<a href="#" onclick="nodeA.setWidth(400);return false;">Sæt bredde</a><br>
<a href="#" onclick="alert(nodeA.w);return false;">Check bredde</a>

</body>
</html>

Læg mærke til to ting:
1. I det første eksempel deklarede jeg variablen 'nodaA' inde i funktionen på onload-eventen. Det gør, den kun kan 'ses' indefra denne funktion (= temmelig ubrugeligt). Det er rettet i dette eksempel.

2. Check bredden før og efter, du har tykket på linket, der ændrer bredden. Før et tryk på linket får du 'px' efter tallet ... det gør du ikke efter et tryk.
Det hænger sammen med, om du skriver 'px' i henholdsvis din inline-styles (og det bør du!) og i kaldet i linket, der kalder objektets metode.
Man kan blive nødt til at bruge noget parseInt() i visse tilfælde - alt efter, hvordan du påtænker at anvende tallene.

/mvh
Avatar billede olebole Juniormester
17. december 2002 - 03:25 #9
Husk i øvrigt at positionere dit div absolute af hensyn til NS4  ;o)
Avatar billede olebole Juniormester
17. december 2002 - 03:32 #10
Nu, du selv var inde på at anvende en anonym funktion i din constructor, må jeg vel hellere vise, det også kan gøres:

function oElement( oNode ) {
    this.o = (ns4)? d.layers[oNode] : d.getElementById( oNode );
    this.css = (ns4)? this.o : this.o.style;
    this.bCol = this.css.backgroundColor;
    this.w = this.css.width;
    this.h = this.css.height;
    this.html = (ns4)? "I NS4.X kan du ikke aftaste innerHTML" : this.o.innerHTML;
    this.setWidth = function(w) {
        this.css.width = w;
        this.w = w;
    }
    return this;
}

Det giver dog meget hurtigt en rodet og uskøn kode og bruges derfor yderst sjældent  :)

Så ... gå nu i seng, Ole ...!

/mvh
Avatar billede olebole Juniormester
17. december 2002 - 03:48 #11
Rettelse:
Vil du kunne kalde med f.eks: alert(nodeA.id) , er du nødt til at have linien:
  this.id = this.o.id;

Jeg kaldte før med: alert(nodeA.o.id) - hvorfor den ikke var nødvendig.

Det var naturligvis et pædagogisk kunstgreb (*host-host*) for at vise, hvordan du kan kalde properties, der ikke er defineret i din constructor  ;o)

Kan du SÅ komme til køjs, din gamle tumpe ...?!?!?!!!

/mvh
Avatar billede dr_nielsen Nybegynder
17. december 2002 - 20:29 #12
olebole - din ildsjæl, du bliver vist lige nødt til at aflevere et svar her, så du kan få din julegave :)
/Nielsen
Avatar billede olebole Juniormester
17. december 2002 - 21:32 #13
dr_nielsen >> Det ville være synd at spilde pointene på mig, da jeg ikke bruger Eksperten mere. Du har sikkert mere brug for dem selv - men tusind tak  ;o)

På falderebet vil jeg lige forklare dig en enkelt ting, jeg kan huske, drillede mig, da jeg selv begyndte på OOP (det kunne måske også være til hjælp for andre, der måtte dumpe ned her, senere).
Det drejer sig om, hvorfor denne funktion ser ud, som den gør:

function fnSetWidth(w) {
    this.css.width = w;
    this.w = w;
}

...og ikke bare:

function fnSetWidth(w) {
    this.w = w;
}

Årsagen er, at 'OBJEKT.w' refererer til den bredde, objektet har i instantierings øjeblikket (det tidspunkt, du opretter dit objekt).
At ændre denne værdi, ændrer ikke på bredden af det HTML-element, der repræsenteres ved objektet - du ændrer altså kun property'en 'w' på objektet.

For at ændre på bredden, må du tage fat i HTML-elementets style-property (eller dets style-objekt, om du vil. Et HTML-elements style-property har jo form som et objekt med properties som 'width', 'height', 'color', osv).
Denne property repræsenteres ved 'OBJEKT.css' ... derfor linien 'this.css.width = w;'.
Men da 'OBJEKT.w' jo stadig refererer til bredden i instantierings øjeblikket, sættes 'OBJEKT.w' ligeledes til den nye bredde-værdi.

Disse forhold gør sig også gældende, hvis du opretter properties for f.eks. left og top.

En aller sidste ting skal være en lille 'advarsel':
For en mand med en fin, ny hammer kommer alt til at ligne søm  ;o)

Når man begynder at gøre sin kode objektorienteret, gør man sig ofte skyldig i overkill (jeg taler af egen erfaring). Et enkelt element bør du ikke oprette et objekt til - men hvis du har nogle stykker, du skal manipulere, kan det være en voldsom fordel.
Her kan man med fordel gøre således:

// opret et array med id'er på dine divs
var myDivs = new Array( "ib", "gudrun", "karl", "kathinka" );

for ( i=0; i<myDivs.length; i++ ) {
    myDivs[i] = new oElement( myDivs[i] );
}

Nu indeholder array'et myDivs ikke længere id'er, men objekter, som refererer til de pågældende divs.
Objektet med id'en 'karl' kan altså herefter kaldes med myDivs[2] - og man kan ændre på alle eller udvalgte objekter ved at tælle dem igennem med en for-løkke, hvis det skulle være interessant  :)

/mvh
Avatar billede dr_nielsen Nybegynder
02. november 2004 - 19:10 #14
lukker denne
Avatar billede olebole Juniormester
02. november 2004 - 19:20 #15
Spørgsmålet er først lukket, når pointene er uddelt  :)
Avatar billede dr_nielsen Nybegynder
02. november 2004 - 20:03 #16
Ja men der er endnu ikke nogle svar, og så havde jeg lidt på fornemmeren at du ville melde en kommentar ind under solen :)

Smid et svar så jeg ikke skal tage dem retur
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