[JS] Option list bouwen

Pagina: 1
Acties:
  • 165 views sinds 30-01-2008
  • Reageer

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Als ik in PHP een option list wil maken, doe ik iets als
PHP:
1
2
3
4
5
6
7
8
$options = array('a' => 'Appels', 'b' => 'Boter', 'c' => 'Cake');
$selected = 'b';

foreach ($options as $value => $text) {
  $selected = ($value == $selected) ? 'selected' : '';
  $list.= '<option value="' . $value . ' ' . $selected . '">' . $text . '</option>';
}
echo sprintf("<select>%s</select>", $list);

Het resultaat is dan een keurige option list:
HTML:
1
2
3
4
5
<select>
  <option value="a">Apples</option>
  <option value="b" selected>Boter</option>
  <option value="c">Cake</option>
</select>

Nu wil ik hetzelfde in Javascript fabriceren. Ik heb eea gelezen over associatieve array's in javascript, en bedacht dat de volgende array zou moeten werken:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
var options = new Array();
var selected = 'b';

options['a'] = 'Appels';
options['b'] = 'Boter';
options['c'] = 'Cake';

for (var i = 0; i < options.length; i++) {
  selected = (options[i] == selected) ? 'selected' : '';
  list += '<option value="'+options[i]+' '+selected+'">'+options[i].value+'</option>';
}
document.write('<select>'+list+'</select>');

Toch werkt dit niet. Het begint al bij het feit dat options.length, nul is. Toch zeggen diverse pagina's die ik las, dat dit een goede manier is om een javascript array te bouwen. Wat doe ik verkeerd?

[ Voor 22% gewijzigd door Reveller op 29-05-2006 22:11 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

JavaScript:
1
2
3
4
5
6
7
for (var property in options)
{
  if (options.hasOwnProperty(property))
  {
    alert(property + ': ' + options[property]);
  }
}

(IE < 6 kent hasOwnProperty niet dus behoeft een work-around)
alternatief is om wel een genummerde array te gebruiken met 2 items; een value en text-pair:
JavaScript:
1
2
3
4
var options = [];
options[0] = ['a', 'Appels'];
options[1] = ['b', 'Boter'];
options[2] = ['c', 'Cake'];


en verdiep je aub in DOM methoden om dynamisch elementen aan te maken; document.write is gewoon smerig...

[ Voor 61% gewijzigd door crisp op 29-05-2006 22:21 ]

Intentionally left blank


  • BtM909
  • Registratie: Juni 2000
  • Niet online

BtM909

Watch out Guys...

Als je geen numerieke array opbouwt dan blijft de length altijd 0. Je zou eventueel een 2 dimensionale array kunnen maken waarin je de value en de text in stopt. Die kan je vervolgens dus wel gewoon met lenght aflopen en je select opbouwen.

Mooier is nog om te kijken hoe je dat middels de DOM methode doet. Nu met document.write is eigenlijk heel vies en daarnaast (mocht je XHTML gaan gebruiken) niet eens werkend te krijgen.

Ace of Base vs Charli XCX - All That She Boom Claps (RMT) | Clean Bandit vs Galantis - I'd Rather Be You (RMT)
You've moved up on my notch-list. You have 1 notch
I have a black belt in Kung Flu.


  • user109731
  • Registratie: Maart 2004
  • Niet online
crisp schreef op maandag 29 mei 2006 @ 22:17:
JavaScript:
1
2
3
4
5
6
7
for (var property in options)
{
  if (options.hasOwnProperty(property))
  {
    alert(property + ': ' + options[property]);
  }
}

<small>(IE < 6 kent hasOwnProperty niet dus behoeft een work-around)</small>
Wat is het nut van hasOwnProperty boven dit:
JavaScript:
1
2
3
for (var property in options) {
    alert(property + " : " + options[property]);
}

Lijkt mij dat het te maken heeft met prototyping ed, maar heeft het verder nog nut?
(zomaar een interesse-vraag :))

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Via het alternatief dat Crisp aanbood, ben ik gekomen tot
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
var options = [];
var selected = 'b';

options[0] = ['a', 'Appels'];
options[1] = ['b', 'Boter'];
options[2] = ['c', 'Cake'];

for (var i = 0; i < options.length; i++) {
  select = (options[i][0] == selected) ? 'selected' : '';
  list  += '<option value="' + options[i][0] + ' ' + select + '">' + options[i][1] + '</option>';
}

document.write('<select>' + list + '</select>');


Dat werkt perfect, maar:
crisp schreef op maandag 29 mei 2006 @ 22:17:
document.write is gewoon smerig...
Dus toen gezocht en eea gevonden en geprutst:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
var options = [];
var selected = 'b';

options[0] = ['a', 'Appels'];
options[1] = ['b', 'Boter'];
options[2] = ['c', 'Cake'];

var box = document.getElementById('box');

for (var i = 0; i < options.length; i++) {
  box.options[i] = new Option(options[i], options[i + 1]);
}
</script>

<select id="box"></select>

Ik krijg nu alleen de error "box has no properties". Dat klopt, maar die wil ik juist toch daarna viade DOM toevoegen?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Grote prutser schreef op maandag 29 mei 2006 @ 22:36:
[...]

Wat is het nut van hasOwnProperty boven dit:
JavaScript:
1
2
3
for (var property in options) {
    alert(property + " : " + options[property]);
}

Lijkt mij dat het te maken heeft met prototyping ed, maar heeft het verder nog nut?
(zomaar een interesse-vraag :))
JavaScript:
1
2
3
4
5
6
var a = [];
a['a'] = 'a';
a['b'] = 'b';
Array.prototype.foo = 'bar';

for (var p in a) alert(p);

hasOwnProperty is dus een manier om de prototyped method te onderscheiden van de 'eigen' properties.

[ Voor 10% gewijzigd door crisp op 29-05-2006 22:50 ]

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
JavaScript:
1
2
3
myOption = document.createElement('option');
myOption.value = options[i][0];
box.appendChild(myOption);

zoiets?

Hou er ook rekening mee dat de box pas aangemaakt word nadat je code doorlopen is.
Dus de box er boven zetten of (netter) de functie pas aanroepen nadat je pagina geladen is.

@crisp:thnx

[ Voor 71% gewijzigd door user109731 op 29-05-2006 23:01 . Reden: domme fout :( ]


  • Fuzzillogic
  • Registratie: November 2001
  • Laatst online: 01-07-2025
Probeer dit eens:
JavaScript:
1
box.options.push(new Option(options[i][0], options[i][1]));


(jouw new Option(options[i], options[i + 1]) klopt sowieso al niet ;))

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Nexxennium schreef op maandag 29 mei 2006 @ 22:50:
Probeer dit eens:
JavaScript:
1
box.options.push(new Option(options[i][0], options[i][1]));


(jouw new Option(options[i], options[i + 1]) klopt sowieso al niet ;))
De options collection is geen array; hoe kom je erbij dat het dan wel de push-method zou ondersteunen :?

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Ik heb hier de oplossing neergezet. Nog even de javascript-code los:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var options = {
    "a" : "Appels",
    "b" : "Boter",
    "c" : "Cake"
}

var selected = "b";

var selectBox = document.createElement("select");
for(var key in options)
{
    var optionNode = document.createElement("option");
    optionNode.value = key;
    if(key==selected)
    {
        optionNode.selected = true;
    }
    optionNode.appendChild(document.createTextNode(options[key]));
    selectBox.appendChild(optionNode);
}
var optionContainer = document.getElementById("optionContainer");
optionContainer.appendChild(selectBox);


Meer informatie over het DOM: Gecko DOM Reference, een van de beste DOM references die ik ken.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

JavaScript:
1
Object.prototype.foo = function() { alert('nu gaat er iets mis'); }

:P

Intentionally left blank


  • Fuzzillogic
  • Registratie: November 2001
  • Laatst online: 01-07-2025
crisp schreef op maandag 29 mei 2006 @ 22:53:
[...]

De options collection is geen array; hoe kom je erbij dat het dan wel de push-method zou ondersteunen :?
Hmm, me bad, maar schijnbaar werkt het wel. Dat artikel is nogal oud alleen. Maar het geeft m.i. de onnavolgbare chaos weer aan waar Javascript uit opgebouwd is.

HTMLSelectElement::add() is blijkbaar de nettere oplossing. Zie DOM level 1. Misschien dat de array-methode nog een relikwie van DOM level 0.. Even zoeken.

[edit]
Bingo.. Bah, smerig legacy-geneuzel.

[ Voor 11% gewijzigd door Fuzzillogic op 29-05-2006 23:08 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Nexxennium schreef op maandag 29 mei 2006 @ 23:04:
[...]

Hmm, me bad, maar schijnbaar werkt het wel. Dat artikel is nogal oud alleen. Maar het geeft m.i. de onnavolgbare chaos weer aan waar Javascript uit opgebouwd is.

HTMLSelectElement::add() is blijkbaar de nettere oplossing. Zie DOM level 1. Misschien dat de array-methode nog een relikwie van DOM level 0.. Even zoeken.
Nope, push() doesn't work - wordt zelfs in dat artikel van PPK niet over gerept.
Dat heeft verder ook weinig met javascript te maken maar puur met DOM EcmaScriptBindings en staat dus los van de taal zelf.
Het is een collection en je kan dus met numerieke references werken en er is een length property, maar daar houd elke vergelijking met een array wel mee op - en ja, ik vind het logisch.
De reference die je aanhaalt gebruikt gewoon de verkeerde term, het is geen array, het is een HTMLCollection oftewel een node-list

[ Voor 11% gewijzigd door crisp op 29-05-2006 23:16 ]

Intentionally left blank


  • Fuzzillogic
  • Registratie: November 2001
  • Laatst online: 01-07-2025
Het was dus in "DOM level 0" wel degelijk een array. En de Netscape reference gebruikt het ook precies zo. Dat .push dan niet werkt vind ik dan weer onlogisch.

Achja, ik heb er geloof ik nog nooit een geheim van gemaakt dat ik Javascript een vervelend taaltje vind. De weak-typed-ellende en steekt ook hier weer de kop op.

Enough of that.De methode van Chris oogt wat omslachtig. Waarom maak je niet gewoon een JS Option element aan en voegt die met HTMLSelectElement::add() aan je select box toe?

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

DOM level 0 is ook geen bestaande standaard ;)

vwb add(); ik heb eerlijk gezegd geen idee hoe het zit met de ondersteuning daarvan in IE < 6, ik ga meestal voor safe en kies dan voor een 'DOM level 0' approach:
JavaScript:
1
2
var s = document.createElement('select');
s.options[s.options.length] = new Option('text', 'value');


offtopic:
en weak-typing is niet noodzakelijk ellende; het is een feature en alleen voor mensen die daar niet mee om kunnen gaan is het ellende :P (javascript 2.0 zal waarschijnlijk optional static-type checking krijgen)

[ Voor 105% gewijzigd door crisp op 29-05-2006 23:37 ]

Intentionally left blank


  • Fuzzillogic
  • Registratie: November 2001
  • Laatst online: 01-07-2025
crisp schreef op maandag 29 mei 2006 @ 23:22:
DOM level 0 is ook geen bestaande standaard ;)
Vandaar mijn quotes. Het was wel een defacto standaard, en vanwege alle legacy-support die de hele webomgeving met zich meezeult verbaast het me als het nu niet meer werkt.
vwb add(); ik heb eerlijk gezegd geen idee hoe het zit met de ondersteuning daarvan in IE < 6, ik ga meestal voor safe en kies dan voor een 'DOM level 0' approach:
IE<6? Kom an zeg, waar leg jij de grens?
en weak-typing is niet noodzakelijk ellende; het is een feature en alleen voor mensen die daar niet mee om kunnen gaan is het ellende :P (javascript 2.0 zal waarschijnlijk optional static-type checking krijgen)
Als we op de man gaan spelen (met of zonder smiley): weak typing is voor hobbyisten die nooit een grote applicatie hebben gemaakt.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Nexxennium schreef op maandag 29 mei 2006 @ 23:54:
[...]

Vandaar mijn quotes. Het was wel een defacto standaard, en vanwege alle legacy-support die de hele webomgeving met zich meezeult verbaast het me als het nu niet meer werkt.
het is meer een mix van zaken die bestonden in IE en Netscape op het moment dat het W3C geformeerd werd.
IE<6? Kom an zeg, waar leg jij de grens?
Bij IE5.5 meestal op dit moment ;)
Als we op de man gaan spelen (met of zonder smiley): weak typing is voor hobbyisten die nooit een grote applicatie hebben gemaakt.
Ik heb in het verleden toch zat aan grote applicaties gewerkt en in veel verschillende (vaak ook strong-typed) talen. Ik vind weak-typed in bepaalde omgevingen toch wel handig en ook in grote applicaties kan je daar nog prima mee uit de voeten. Alsof een taal pas 'serieus genomen kan worden' als het strong-typed is... 8)7

Intentionally left blank


Verwijderd

Nexxennium schreef op maandag 29 mei 2006 @ 23:54:
Als we op de man gaan spelen (met of zonder smiley): weak typing is voor hobbyisten die nooit een grote applicatie hebben gemaakt.
:D Ik vind dat zo'n uitspraak iets meer toelichting verdient!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Laten we ons nou niet druk maken over strong vs. weak typing, als strong typing echt beter was geweest dan weak typing waren er al lang geen weak-typed talen meer en vice versa. En onzin dat er nog nooit een grote applicatie gemaakt is met weak-typing, zo gebruikt Google ontzettend veel python, is Oracle met een groot web-framework bezig is (ADF Faces) en zijn er producten als Backbase.

Als het een grapje is: prima, maar zet er dan een smiley bij :p

  • admiral866
  • Registratie: April 2000
  • Laatst online: 14:48

admiral866

The King Personality Disorder

ik had ook zoiets gemaakt, "dynamisch" selectboxes vullen. Maar op een of andere duistere reden kreeg ik soms een lege option erbij.

kon de oorzaak niet vinden, oplossing was deze naderhand weer te verwijderen :P
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
var arElements = document.form.elements;
for(i=0;i<arElements.length;i++){
        if(arElements[i].type == "select-one"){
            el = arElements[i];
            for(k=0;k<el.options.length;k++){
                option = el.options[k];                 
                if(option.text == ""){
                    el.options[k] = null;
                    k--;
                }
            }       
        }
    }

  • SuperRembo
  • Registratie: Juni 2000
  • Laatst online: 20-08-2025
crisp schreef op maandag 29 mei 2006 @ 22:17:
(IE < 6 kent hasOwnProperty niet dus behoeft een work-around)
Is daar een eenvoudige work-around voor?

| Toen / Nu


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

SuperRembo schreef op dinsdag 30 mei 2006 @ 23:10:
[...]

Is daar een eenvoudige work-around voor?
Ja, bijvoorbeeld de method zelf prototypen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (!Object.prototype.hasOwnProperty)
{
    Object.prototype.hasOwnProperty = function(property)
    {
        try
        {
            var prototype = this.constructor.prototype;
            while (prototype)
            {
                if (prototype[property] == this[property])
                {
                    return false;
                }
                prototype = prototype.prototype;
            }
        }
        catch (e) { }

        return true;
    }
}

of op een alternatieve manier:
JavaScript:
1
2
3
4
5
6
7
for (prop in array)
{
  if (!Array.prototype[prop])
  {
    // not a prototyped method
  }
}


de eerste is volledig, maar de tweede simpele check zal in de praktijk voor 99,99% al voldoen ;)

[ Voor 8% gewijzigd door crisp op 30-05-2006 23:27 ]

Intentionally left blank


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik heb nu onderstaande functie, maar krijg de foutmelding "options is not defined". Als ik regel 6 en 7 naar onderen verplaats (naar regel 20 / 21), verandert hier niets aan. Wat doe ik verkeerd?
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function templateList() {
  var options = {"a" : "Appels", "b" : "Boter", "c" : "Cake"}
  var selected = 'b';
  var selectBox = document.createElement("select");

  goto = new Function("e", "location.href='cms?' + options[selectBox.selectedIndex].value");
  selectBox.onchange = goto;

  for(var key in options) {
    var optionNode = document.createElement("option");
    optionNode.value = key;
    if (key == selected) {
      optionNode.selected = true;
    }
    optionNode.appendChild(document.createTextNode(options[key]));
    selectBox.appendChild(optionNode);
  }
  var optionContainer = document.getElementById("optionContainer");
  optionContainer.appendChild(selectBox);
}

Nog een opmerking: het valt mij op dat met deze functie eerst de pagina ingeladen wordt, en dat een fractie van een seconde de select box aan de pagina wordt toegevoegd. Als ik de functie uit de TS gebruik (met document.write), staat de select box er meteen. Blijkbaar vereist de oplossing hierboven wat meer resources van de client. Wat is dan eigenlijk het grote voordeel (behalve dat je netjes de DOM aanpast ipv een "dom" stukje gegenereerde html insert?)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Het grote voordeel is dat je netjes de DOM gebruikt.

Verder gaat dit niet werken, want waar moet die "goto" functie de options vandaan halen? Die functie kan niet zomaar bij die variabelen in templateList. Wat je moet doen is een object maken, daar stop je deze functie in, daar sla je de selectBox op, en je kan er weer bij.

Ik heb m'n voorbeeldje even aangepast. Zie options.html en de source:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 var SelectBox = {

    selectElement: null,

    init: function()
    {
        var options = {
            "http://gathering.tweakers.net" : "GoT",
            "http://tweakers.net" : "Tweakers.net",
            "http://slashdot.org" : "Slashdot"
        }

        var selected = "http://slashdot.org";

        var selectElement = document.createElement("select");
        for(var key in options)
        {
            var optionNode = document.createElement("option");
            optionNode.value = key;
            if(key==selected)
            {
                optionNode.selected = true;
            }
            optionNode.appendChild(document.createTextNode(options[key]));
            selectElement.appendChild(optionNode);
        }
        var optionContainer = document.getElementById("optionContainer");
        optionContainer.appendChild(selectElement);

        selectElement.onchange = SelectBox.onchange;

        SelectBox.selectElement = selectElement;
    },

    onchange: function()
    {
        window.location = SelectBox.selectElement.value;
    }

}

window.onload = SelectBox.init;

[ Voor 12% gewijzigd door chris op 03-06-2006 10:02 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

dit kan ook prima hoor, geen closures nodig:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
function goto()
{
  window.location = 'cms?' + this.options[this.selectedIndex].value;
}

function templateList()
{
...
  selectBox.onchange = goto;
...
}

of gewoon:
JavaScript:
1
selectBox.onchange = function() { window.location = 'cms?' + this.options[this.selectedIndex].value; }

;)

chris: met jouw functie kan je maar 1 instance van die selectBox hebben, als je het een beetje netjes aanpast dan kan je dit soort dingen doen:
JavaScript:
1
2
var select1 = new SelectBox(options);
var select2 = new SelectBox(otheroptions);

in je onchange function kan je dan verwijzen naar this.selectElement

[ Voor 64% gewijzigd door crisp op 03-06-2006 11:44 ]

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
crisp: Ja, natuurlijk, maar daar gaat het niet om. Als ik met prototype ga gooien wordt het weer zo ingewikkeld voor de TS. Ik denk dat dit wel laat zien wat ts wil. En ik zou ook dit herschrijven:
JavaScript:
1
  this.options[this.selectedIndex].value

naar:
JavaScript:
1
  this.value


Dat werkt ook prima :)

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

chris schreef op zaterdag 03 juni 2006 @ 11:58:
crisp: Ja, natuurlijk, maar daar gaat het niet om. Als ik met prototype ga gooien wordt het weer zo ingewikkeld voor de TS. Ik denk dat dit wel laat zien wat ts wil. En ik zou ook dit herschrijven:
JavaScript:
1
  this.options[this.selectedIndex].value

naar:
JavaScript:
1
  this.value


Dat werkt ook prima :)
Niet in oudere browsers ;)

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Hier nog even de laatste: options2.html.

JavaScript:
1
2
3
4
5
6
7
8
9
var options = {
    "http://gathering.tweakers.net" : "GoT",
    "http://tweakers.net" : "Tweakers.net",
    "http://slashdot.org" : "Slashdot"
}
var selected = "http://slashdot.org";
var targetNode = document.getElementById("optionContainer");

new SelectBox(options, selected, targetNode);

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Iets andere approach:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var SelectBox = function(options, selected, targetNode)
{
    this.selectNode = null;
    this.init(options, selected, targetNode);
}

SelectBox.prototype =
{
    init: function(options, selected, targetNode)
    {
        var selectNode = document.createElement('select'), optionNode;
        for (var key in options)
        {
            if (options.hasOwnProperty(key))
            {
                optionNode = document.createElement('option');
                optionNode.value = key;
                if (key == selected)
                {
                    optionNode.defaultSelected = true;
                }
                optionNode.appendChild(document.createTextNode(options[key]));
                selectNode.appendChild(optionNode);
            }
        }
        targetNode.appendChild(selectNode);
        selectNode.onchange = this.onchange;
        this.selectNode = selectNode;
    },
    onchange: function()
    {
        //-- 'this' referes to the select-element itself when called from a handler, else to the object instance
        var selectNode = this.selectNode ? this.selectNode : this;
        window.location = selectNode.options[selectNode.selectedIndex].value;
    }
}

window.onload = function()
{
    var options = {
        'http://gathering.tweakers.net' : 'GoT',
        'http://tweakers.net' : 'Tweakers.net',
        'http://slashdot.org' : 'Slashdot'
    }
    var selected = 'http://slashdot.org';
    var targetNode = document.getElementById('optionContainer');

    var foo = new SelectBox(options, selected, targetNode);
}

note het gebruik van hasOwnProperty en hoe ik de onchange functie refereer in plaats van voor elke instance opnieuw aanmaak (dit geeft ook de mogelijkheid om direct onchange() op je object aan te roepen).

Overigens zou ik onload nooit op deze manier overschrijven; ik zou normaliter onload ws niet eens gebruiken juist vanwege de vertraging ;)

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Hm, ik vind die onchange een beetje verwarrend. In jouw geval zal this altijd die node zijn. Maak er dan een callback van met apply ofzo :)

En die hasOwnProperty is echt niet nodig bij goed geschreven javascript, je moet gewoon niet dingen als Object.prototype en Array.prototype gaan aanpassen. Misschien moet ik er maar eens een artikel over gaan schrijven: Object.prototype considered harmful.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

chris schreef op zaterdag 03 juni 2006 @ 13:21:
Hm, ik vind die onchange een beetje verwarrend. In jouw geval zal this altijd die node zijn. Maak er dan een callback van met apply ofzo :)

En die hasOwnProperty is echt niet nodig bij goed geschreven javascript, je moet gewoon niet dingen als Object.prototype en Array.prototype gaan aanpassen. Misschien moet ik er maar eens een artikel over gaan schrijven: Object.prototype considered harmful.
Daar zijn al artikelen over geschreven maar er zijn domweg wel situaties waarbij je Object of Array zou willen prototypen; bijvoorbeeld als je toSource() wilt gebruiken in IE of andere manieren om javascript objecten te serializen.
Voor Array geldt dat nog meer bij gebrek aan bijvoorbeeld push en pop in IE < 5.5 en indexOf in IE <= 7 (maar arrays zou je niet als hashmap moeten gebruiken).
Ik zou er dan eerder voor pleiten om je options als gewone array met objecten mee te geven:
JavaScript:
1
2
3
4
5
var options = [
    {key: 'http://gathering.tweakers.net', value: 'GoT'},
    {key: 'http://tweakers.net', value: 'Tnet'},
    {key: 'http://slashdot.org', value: 'Slashdot'}
];



En nee, 'this' is niet altijd de node; het ligt eraan hoe je 'm aanroept: vanuit de handler is 'this' de node, maar als je dit doet:
JavaScript:
1
2
var foo = new SelectBox(...);
foo.onchange();

dan is 'this' je object instance.
Een callback kan natuurlijk altijd en heb je ook nodig op het moment dat je bij je object initialisatie een custom handler wilt kunnen meegeven.

[ Voor 21% gewijzigd door crisp op 03-06-2006 13:34 ]

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
crisp schreef op zaterdag 03 juni 2006 @ 13:29:
[...]

Daar zijn al artikelen over geschreven maar er zijn domweg wel situaties waarbij je Object of Array zou willen prototypen; bijvoorbeeld als je toSource() wilt gebruiken in IE of andere manieren om javascript objecten te serializen.
True, het kan ontzettend handig zijn, maar dan pleit ik voor een base-class waar je je object van af laat stammen, die wel die functionaliteit heeft. Dus b.v. een BaseObject.
Voor Array geldt dat nog meer bij gebrek aan bijvoorbeeld push en pop in IE < 5.5 en indexOf in IE <= 7 (maar arrays zou je niet als hashmap moeten gebruiken).
Ik weet precies wat je bedoelt, en er is geen "beste" oplossing. Ik wil gewoon door m'n Arrays met for(key in arr) kunnen lopen, maar ik wil inderdaad ook push en pop in alle browsers kunnen gebruiken. Beide oplossingen hebben hun nadelen.
Ik zou er dan eerder voor pleiten om je options als gewone array met objecten mee te geven:
JavaScript:
1
2
3
4
5
var options = [
    {key: 'http://gathering.tweakers.net', value: 'GoT'},
    {key: 'http://tweakers.net', value: 'Tnet'},
    {key: 'http://slashdot.org', value: 'Slashdot'}
];
Maar dat is ook gewoon helemaal niet hoe het bedoeld is :)
En nee, 'this' is niet altijd de node; het ligt eraan hoe je 'm aanroept: vanuit de handler is 'this' de node, maar als je dit doet:
JavaScript:
1
2
var foo = new SelectBox(...);
foo.onchange();

dan is 'this' je object instance.
Ik zeg dus ook, in jouw geval zal 'this' altijd de node zijn. Ik zou het raar vinden om die onchange als event handler te gebruiken maar ook nog eens als "normale" methode :) Maar volgens mij snappen we elkaar wel :p

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Het is juist handig om onchange ook als method van je object instance te kunnen gebruiken; stel dat ik een situatie heb waarbij een onchange op selectB ook de onchange op selectA moet triggeren ;)

En verder: Array is geen hashmap; for - in over een array is gewoon evil. Object is ook geen hashmap maar is beter als hashmap te gebruiken dan Array (maar hasOwnProperty blijft nodig).

Vwb serialization wil je juist ook primitive objects kunnen serializen en niet alleen custom objects, en om nu voor elk custom object een serialize() implementatie te schrijven is ook weer zoiets...

[ Voor 4% gewijzigd door crisp op 03-06-2006 13:51 ]

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
De eerste twee punten heb je helemaal gelijk :)

Laatste punt:
je kan natuurlijk ook nog altijd iets doen als:
JavaScript:
1
var s = (new Serializer(object)).serialize();

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

true, maar mijn punt is dat Object ook geen Hashmap is en dat het gewoon good practice is om er rekening mee te houden dat het prototyped methods kan hebben ;)

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:33

crisp

Devver

Pixelated

Ik heb toch laatst even zitten kijken naar mijn manier van serializen van javascript objects naar een PHP-serialized format. Inmiddels heb ik de prototyped methods vervangen door de volgende functie:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function serialize(obj)
{
    if (typeof obj == 'undefined')
        return '';
    else if (obj === null)
        return 'N;';

    var serialized = '';
    switch (obj.constructor)
    {
        case Array:
            serialized = 'a:';
        case Object:
            if (serialized == '') serialized = 'o:';
            var item, count = 0, value, content = '';
            for (item in obj)
            {
                if ((value = serialize(obj[item])) != '')
                {
                    content += serialize(isNaN(item)?item:parseInt(item,10)) + value;
                    count++;
                }
            }
            serialized += count + ':{' + content + '}';
            break;
        case String:
            obj = obj.replace(/\r\n|\r|\n/g, '\r\n');
            serialized = 's:' + obj.length + ':"' + obj + '";';
            break;
        case Number:
            serialized = (Math.floor(obj) == obj ? 'i' : 'd') + ':' + obj + ';';
            break;
        case Boolean:
            serialized = 'b:' + (obj == true ? 1 : 0) + ';';
            break;
    }

    return serialized;
}

De scherpe lezer ziet dat ik hier voor zowel arrays als objects een for-in construct gebruik zonder afvraging of iets een prototyped method of property is, maar dat is by design: Function objects zijn sowieso niet supported en andere prototyped properties wil je waarschijnlijk toch mee serialized hebben ;)

Intentionally left blank


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Ziet er netjes uit, handig gebruik van obj.constructor :). Toch ben ik me nog steeds aan het afvragen wat nou de beste manier is om door een HashMap heen te lopen. Volgens mij is (for..in) er wel voor bedoeld, maar bij objecten met rare dingen in hun prototype werkt dat toch niet helemaal goed samen. Misschien is dit inderdaad wel de manier.

  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-01 16:11
offtopic:
Damn, het niveau is hier wel omhoog gegaan vanaf mijn laatste bezoek! :*)

Kan verder niet veel nuttigs bijdragen nu, sorry ;)

[ Voor 26% gewijzigd door r0bert op 12-06-2006 12:05 ]

Pagina: 1