Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[JS] Uitlezen informatie dynamisch toegvoegd formulier in IE

Pagina: 1
Acties:

  • Johnny
  • Registratie: December 2001
  • Laatst online: 15-11 13:22

Johnny

ondergewaardeerde internetguru

Topicstarter
Het volgende stukje code dat door alle elementen in een formulier heen loopt en de waarden van de name en value attributen in een nieuw object genaamd data plaatst. Het is een triviaal stukje code wat in iedere moderne browser probleemloos werkt. Mijn verbazing was dan ook groot toen ik het ging testen in een obscure browser genaamd "Internet Explorer" die heden ten dage door een aanzienlijke groep mensen wordt gebruikt om redenen die mij niet helemaal duidelijk zijn.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
var data = {};

for(i in document.forms['myForm'].elements) {

    var el = document.forms['myForm'].elements[i];      

    if(el.name && el.value) {
    
        data[el.name] = el.value;
    }
}


Het uitvoeren van het bovenstaande code geeft in Internet Explorer de volgende foutmelding, waarna de uitvoering van het script ook direct stopt:

code:
1
Regel: 9; Fout: 'name' is leeg of geen object.


Nu ben ik er zelf vrij zeker van dat alle elementen een name attribuut hebben, maar om er helemaal zeker van te zijn wordt er op regel 7 nog gecontroleerd of deze wel echt bestaat. Internet Explorer gaat door deze check heen en klaagt vervolgens dat deze toch niet bestaat.

Een korte zoektocht op het internet leert mij dat dit probleem waarschijnlijk wordt veroorzaakt door het feit dat het formulier myForm niet aanwezig was op de pagina op het moment dat deze werd geladen, maar later met behulp van JavaScript in de pagina is geplaatst. Een van de vele eigenaardigheden van Internet Explorer is om in dat geval de name-attributen niet op te nemen in het DOM, waardoor ze dus niet te benaderen zijn via JavaScript.

Nu heb ik al diverse creatieve, doch ranzige oplossing voor dit probleem proberen te vinden. Maar wat blijkt? Ook het uitlezen van het type en value attribuut geeft de waarde "undefined" waardoor het wel erg lastig wordt om bruikbare informatie uit de formuliervelden te ontrekken. Gek genoeg staan wel alle elementen in de lijst en worden en komen ze in de for-loop allemaal aan de beurt, alleen kan ik er niks mee.

Nu is mijn hoop dat er hier iemand is die vaker met dit bijltje heeft gehakt en me kan helpen met dit probleem ten behoeve van de ons zo geliefde Internet Explorer gebruikers.

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Debuggen...

Is het een probleem dat je 'i' niet netjes initialiseert?
Wat krijg je als je alert(el) in de loop zet?
Wat krijg je als je alert(el.name) in de loop zet?

Zijn er bijvoorbeeld obscure form-elementen die automatisch worden aangemaakt, en die undefined als name zoduen kunnen hebben?

TabCinema : NiftySplit


  • tonyisgaaf
  • Registratie: November 2000
  • Niet online
Johnny schreef op maandag 29 september 2008 @ 20:01:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
var data = {};

for(i in document.forms['myForm'].elements) {

    var el = document.forms['myForm'].elements\[i];      

    if(el.name && el.value) {
    
        data[el.name] = el.value;
    }
}
Is het niet "netter" om het als volgt te doen:
JavaScript:
1
2
3
4
5
6
7
8
9
var el, data = {};
var myForm = document.forms['myForm'];
for (var i = 0; i < myForm.length; i++) {
    el = myForm.elements[i];

    if(el.name && el.value) { 
        data[el.name] = el.value; 
    }
}

Zo weet je tenminste zeker dat i een integer is en declareer je el niet elke keer dat je de for loop execute (for loop geeft geen closure!).
Daarnaast gewoon debuggen idd. Alert een keer wat el is, wat el.name is en wat el.value is. Kijk ook eens of el.id misschien wel bestaat bijv. Of doe een for in loop op el en schrijf het resultaat naar een debug divje oid.

[ Voor 1% gewijzigd door tonyisgaaf op 29-09-2008 23:31 . Reden: var data vergeten, typfouten ]

NL Weerradar widget Euro Stocks widget Brandstofprijzen widget voor 's Dashboard


  • Johnny
  • Registratie: December 2001
  • Laatst online: 15-11 13:22

Johnny

ondergewaardeerde internetguru

Topicstarter
Helaas heb ik geen toegang tot de broncode van Internet Explorer, dus neem ik genoegen met een workaround.
Is het een probleem dat je 'i' niet netjes initialiseert?
Er is niks niet netjes aan deze syntax, en dat gedeelte werkt ook.
tonyisgaaf schreef op maandag 29 september 2008 @ 23:28:
[...]

Is het niet "netter" om het als volgt te doen:
JavaScript:
1
2
3
4
5
6
7
8
9
var el, data = {};
var myForm = document.forms['myForm'];
for (var i = 0; i < myForm.length; i++) {
    el = myForm.elements\[i];

    if(el.name && el.value) { 
        data[el.name] = el.value; 
    }
}

Zo weet je tenminste zeker dat i een integer is en declareer je el niet elke keer dat je de for loop execute (for loop geeft geen closure!).
Daarnaast gewoon debuggen idd. Alert een keer wat el is, wat el.name is en wat el.value is. Kijk ook eens of el.id misschien wel bestaat bijv. Of doe een for in loop op el en schrijf het resultaat naar een debug divje oid.
Hier geldt hetzelfde verhaal, deze details maken geen enkel verschil omdat, het hele principe niet werkt in Internet Explorer.

Ik heb even een testcase gemaakt die wat meet inzicht geeft in het probleem, en het is echt heel erg vaag, het werkt uitstekend in alle browsers behalve in Internet Explorer. Zoals ik al eerder vertelde telt hij wel het aantal elementen juist, te zien aan de lengte van 16, maar in plaats van dat er 16 formulier-elementen in zitten bevat het object 5 generieke eigenschappen. Een alternatieve methode met behulp van getElementsByTagName werkt in andere browsers wederom uitstekend, maar Internet Explorer maakt er weer een andere rotzooi van, ondanks dat de name wel wordt geplaatst in de i variable is de value nog steeds niet te achterhalen.

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


Verwijderd

Heb je toevallig last van elementen met het verkeerde
nodeType?

[ Voor 10% gewijzigd door Verwijderd op 30-09-2008 08:53 ]


  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Dit werkt gewoon in Internet Explorer 7:

HTML:
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
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">

<head>
    <title>Test</title>

    <script type="text/javascript">
        function init(){
            buildForm();
            readFormNames();
            injectForm();
            readFormNames();
        }
        
        function buildForm() {
            var div = document.getElementById("formContainer");
            var form = document.createElement("form");
            form.id = "myForm";
            for (var i = 1; i <= 3; i++) {
                var input = document.createElement('input');
                input.name = "myInput"+i;
                form.appendChild(input);
            }
            div.appendChild(form);
        }
        
        function injectForm() {
            var div = document.getElementById("formContainer");
            div.innerHTML = '<form id="myForm"><input name="myInput1" /><input name="myInput2" /><input name="myInput3" /></form>';
        }
        
        function readFormNames() {
            var form = document.forms["myForm"];
            for (var i = 0; i < form.elements.length; i++) {
                alert(form.elements[i].name);
            }
        }
    </script>
</head>

<body onload="init()">
    <div id="formContainer"></div>
</body>
</html>


Output: myInput1, myInput2, myInput3, myInput1, myInput2, myInput3.

Waarom het bij jou niet werkt mag je zelf uitzoeken :P

TabCinema : NiftySplit


  • Crayne
  • Registratie: Januari 2002
  • Laatst online: 17-03 13:41

Crayne

Have face, will travel

Het zit hem in je gebruik van de 'for ... in' constructie. Als je die namelijk vervangt door een simpele for lus zul je zien dat het wel werkt. Waarom dat is moet ik je schuldig blijven, maar ik ben er zelf al vaker tegen aan gelopen dat de 'for ... in' constructie onverwachte elementen lijkt toe te voegen aan arrays.

[ Voor 38% gewijzigd door Crayne op 30-09-2008 15:34 ]

Mijn Library Thing catalogus


Verwijderd

for-in constructies voegen niks toe aan arrays, dat doen een aantal brakke veel gebruikte libraries wel

en vervolgens is form.elements een collection, geen array, en die heeft meer members, die geen "name" property hebben

  • tonyisgaaf
  • Registratie: November 2000
  • Niet online
Johnny schreef op maandag 29 september 2008 @ 23:58:
[...]

Helaas heb ik geen toegang tot de broncode van Internet Explorer, dus neem ik genoegen met een workaround.


[...]

Er is niks niet netjes aan deze syntax, en dat gedeelte werkt ook.


[...]

Hier geldt hetzelfde verhaal, deze details maken geen enkel verschil omdat, het hele principe niet werkt in Internet Explorer.

Ik heb even een testcase gemaakt die wat meet inzicht geeft in het probleem, en het is echt heel erg vaag, het werkt uitstekend in alle browsers behalve in Internet Explorer. Zoals ik al eerder vertelde telt hij wel het aantal elementen juist, te zien aan de lengte van 16, maar in plaats van dat er 16 formulier-elementen in zitten bevat het object 5 generieke eigenschappen. Een alternatieve methode met behulp van getElementsByTagName werkt in andere browsers wederom uitstekend, maar Internet Explorer maakt er weer een andere rotzooi van, ondanks dat de name wel wordt geplaatst in de i variable is de value nog steeds niet te achterhalen.
Je bent wel f*kking koppig he. Verander nou maar eens in je testcase dit:
JavaScript:
1
2
3
4
5
6
7
8
//getElementsByTagName
document.getElementById('info').innerHTML += '<h3>getElementsByTagName</h3>';
var inputs = document.getElementsByTagName('INPUT');
document.getElementById('info').innerHTML += 'length: ' + inputs.length + '<br>';
for(i in inputs) {
    var el = inputs[i];
    document.getElementById('info').innerHTML += i + ' '+ el + ' ' + el.type + ' ' + el.name + ' '+ el.value + '<br>';
}

in dit:
JavaScript:
1
2
3
4
5
6
7
8
//getElementsByTagName
document.getElementById('info').innerHTML += '<h3>getElementsByTagName</h3>';
var inputs = document.getElementsByTagName('INPUT');
document.getElementById('info').innerHTML += 'length: ' + inputs.length + '<br>';
for(var i = 0; i < inputs.length; i++) {
    var el = inputs[i];      
    document.getElementById('info').innerHTML += i + ' '+ el + ' ' + el.type + ' ' + el.name + ' '+ el.value + '<br>';
}

En tada! In IE6 werkt het gewoon.
En je laatste allereigenste testcase: maar nu met bovenstaande wijziging(en).

Volgens de HTML specs is Form.elements inderdaad een HTMLCollection:
code:
1
2
3
4
5
interface HTMLCollection {
  readonly attribute unsigned long   length;
  Node               item(in unsigned long index);
  Node               namedItem(in DOMString name);
};

Dan zou je de Nodes in de element Collection dus "het beste" kunnen benaderen met elements.item(i), ipv elements[i].

[ Voor 9% gewijzigd door tonyisgaaf op 30-09-2008 17:46 . Reden: testcase toegevoegd, html specs elements[] ]

NL Weerradar widget Euro Stocks widget Brandstofprijzen widget voor 's Dashboard

Pagina: 1