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

[JS] SetAttribute (DOM) geeft geen goed resultaat (IE6)

Pagina: 1
Acties:

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Update: Nieuw probleem beschreven in post 10, onclick false returnen om de link te cancelen

Ik gebruik de volgende code voor een testcase:

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>

<head>
    <script type="text/javascript">
        attachAtt = function(oEl)
        {   oEl.setAttribute( 'id' , 'testId' );
            oEl.setAttribute( 'param', 'valueArg' );
            
            alert('Outer: ' + oEl.outerHTML + "\n" + 'Inner: ' + oEl.innerHTML);
            
            return oEl;
        }
    </script>
</head>

<body>
<input type="button" value="do" onclick="attachAtt(document.createElement('testElement'));" />
</html>

Voorbeeld

De output is twee keer leeg, terwijl ik de boel naar mijn idee toch echt correct aanmaak? Ik een soortgelijke testcase voeg ik ook twee keer een attribuut toe, maar blijft er maar één bestaan in de output. Iemand enig idee waar dit vandaan kan komen?

[ Voor 5% gewijzigd door r0bert op 12-08-2008 12:27 ]


Verwijderd

Waarom wil je DOM en outer/innerHTML samen gebruiken? Dat is sowieso al een zonde.

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Dat gebruik ik enkel om het resultaat inzichtelijk te maken in de alert-box. Op zich is dat niet van belang, mag ook op een andere manier. Het gaat om 'setAttribute' wat blijkbaar niet functioneerd, waar dus het probleem ligt. Ik heb wat gezocht, maar helaas nog niets voldoenends kunnen vinden.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:21

crisp

Devver

Pixelated

IE is inderdaad een ramp als het neerkomt op het (correct) ondersteunen van het DOM, dat is algemeen bekend. Vermijdt dus gewoon het gebruik van setAttribute zoveel mogelijk als IE-ondersteuning belangrijk is.

Intentionally left blank


  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Ja, IE en FF. Spijtig. Maar ik ga in ieder geval op zoek naar een nette workaround (lekker tegenstrijdig :)).
Waarom wil je DOM en outer/innerHTML samen gebruiken? Dat is sowieso al een zonde.
Ik heb gezocht naar een goed alternatief voor outerHTML, maar niet kunnen vinden.
Vermijdt dus gewoon het gebruik van setAttribute zoveel mogelijk als IE-ondersteuning belangrijk is.
Op welke manier kan ik dat doen? Het gaat om het construeren van een SOAP-message waarin helaas wel attribute gebruikt moeten worden.

[ Voor 99% gewijzigd door r0bert op 10-08-2008 19:29 ]


Verwijderd

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
    <head>
        <script type="text/javascript">
            function blaat()
            {
                var obj=document.createElement("div");
                obj.setAttribute("id","testId");
                obj.setAttribute("param","valueArg");
                document.body.appendChild(obj);
            }
        </script>
        <style type="text/css">#testId{ background-color:red; height:20px; width:100px; }</style>
    </head>
    <body>
        <input onclick="javascript:blaat();" type="button" value="Test"/>
    </body>
</html>


Als ik dit uitprobeer, dan wordt er wel degelijk een element aangemaakt en ingevoegd, zowel in FF als in IE6.0.

Als ik dan het type element verander naar iets anders, bijv testElement, dan zie ik in firebug het element gewoon verschijnen. Volgens mij werkt setAttribute ook wel, maar om één of andere reden geeft outerHTML niet het gewenste resultaat (ook niet met gewone html elementen).

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Verwijderd schreef op maandag 11 augustus 2008 @ 10:22:
Volgens mij werkt setAttribute ook wel, maar om één of andere reden geeft outerHTML niet het gewenste resultaat (ook niet met gewone html elementen).
Volgens mij niet. Als ik obj.getAttribute('param') doe krijg ik ook 'null'.

Ik ga iets proberen met DOMDocument, daar werkt de setAttribute wel. Blijkbaar wordt in een XHTML document niet toegestaan om eigen elementen toe te voegen, maar alleen de set die XHTML daarin verschaft (en dan zelfs nog buggy). In een eigen XML document via DOMDocument leek het geen probleem te zijn (kreeg een goede alert terug (MSXML2.DomDocument.3.0).

Verwijderd

Ik weet niet of bijv IE een extra check doet of een element wel een geldig element is. Setattribute werkt in ieder geval zeker met een div element zoals in mijn voorbeeld.

FF doet setattribute zeker goed, dit is gewoon te controleren met firebug.

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
    <head>
        <script type="text/javascript">
            function blaat()
            {
                var obj=document.createElement("testElement");
                obj.setAttribute("id","testId");
                obj.setAttribute("param","valueArg");
                document.body.appendChild(obj);
                alert("outerHTML="+obj.outerHTML);
                alert("innerHTML="+obj.innerHTML);
                alert("p="+obj.getAttribute("param"));
            }
        </script>
        <style type="text/css">#testId { background-color:red; height:20px; width:100px; }</style>
    </head>
    <body>
        <input onclick="javascript:blaat();" type="button" value="Test"/>
    </body>
</html>


Dit geeft bij mij zowel onder FF 2.0.0.12 als onder IE 6.0.2900.2180 de juiste waarde bij getAttribute. Krijg je geen script fout in je logs? Anders moet je eens firebug downloaden & installeren als je dat nog niet hebt.

edit:
typefoutje

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Bij mij gaat dat dus niet goed :? Ik zal de boel eens installeren, wie weet kan ik wat meer achterhalen.

Vooralsnog gebruik ik een DOMDocument (misschien wel mooier ook). Implementatie verdient geen schoonheidsprijs, maar er komen SOAP messages uit uiteindelijk:
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
var isIe = /MSIE [56789]/.test(navigator.userAgent.toLowerCase());

// ### DEFINING IT .. ###############
                        
DOMDocument = function()
{   this.dom = this.__construct();
    this.dom = 
        this.loadString
            ('<soap:Envelope \
                        xmlns:soap="http://www.w3.org/2001/12/soap-envelope" \
                        xmlns="http://www.w3.org/2001/12/soap-envelope" \
                    />\
                ',
                'text/xml'
            );  
    
    return this;
}


DOMDocument.prototype.__construct = function()
{   if (isIe)
    {
        aActiveXDOM = [
                                        'MSXML4.DOMDocument', 
                                        'MSXML4.DOMDocument.4.0', 
                                        'MSXML3.DOMDocument',
                                        'MSXML3.DOMDocument.3.0',                                       
                                        'MSXML2.DOMDocument', 
                                        'MSXML2.DOMDocument.3.0',
                                        'MSXML.DOMDocument', 
                                        'Microsoft.XmlDom'
                                    ];

        for (var iActX = 0; iActX < aActiveXDOM.length; iActX++)
        {   try 
            {   return new ActiveXObject(aActiveXDOM[iActX]);
            } catch (eActiveXException) { /* Do nothing */  
            }     
        }
    
        return false;
    }
    else
        return new DOMParser();
}


DOMDocument.prototype.getXML = function()
{   return this.dom.xml || (new XMLSerializer()).serializeToString(this.dom);
}


if (isIe)
{   DOMDocument.prototype.loadString = function(sXML, sMime)
    {   this.dom.loadXML(sXML);

        return this.dom;
    }
}
else
{   DOMDocument.prototype.loadString = function (sXML, sMime)
    {   return this.dom.parseFromString(sXML, sMime);
    }
}


// ### USING IT .. ########################


oDOMDoc = (oDom = new DOMDocument()).dom;

oDOMDoc.documentElement.setAttribute('id','testId');
oDOMDoc.documentElement.setAttribute('param','testParam');

alert(oDom.getXML());

                                        
String.prototype.ltrim  = function ()   { return this.replace(/^ */,"");     };
String.prototype.rtrim  = function ()   { return this.replace(/ *$/,"");     };
String.prototype.trim    = function ()  { return this.ltrim().rtrim();      };

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Met bovenstaande code loop ik tegen het vreemde probleem dat door het ActiveX-object in IE er geen

JavaScript:
1
domdoc.createTextNode('value')

ondersteund wordt :?

Is daar iets over bekend? Google geeft me een aantal voorbeelden, maar die werken gewoon niet (in IE).

Update: Inmiddels gelukt. Moest uitgegaan worden van een element.

[ Voor 28% gewijzigd door r0bert op 12-08-2008 12:28 . Reden: Tijdelijke link verwijderd. ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Ik heb een nieuw probleem.

Mijn links verwijzen naar het creeeren van een XHR. Die XHR duurt even om te laden. In die tijd, wil ik niet dat de link naar de 'href' gaat navigeren - wel wil ik javascript/de browser graag vrijgeven in de laadtijd, dus async. Normaal return ik hiervoor bij de onclick 'false' maar krijg dat nu niet voor elkaar.

Ik gebruik deze code om de events aan de links te plakken:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
rewriteLinks = function()
{   onlLinks = document.getElementsByTagName('a');

    for (var iLink = 0; iLink < onlLinks.length; iLink++)
    {   oLink = onlLinks.item(iLink);

        if (document.addEventListener)
            oLink.addEventListener('click', soapMessage, false);    // FF
        else if (window.attachEvent)
            oLink.attachEvent('onclick', soapMessage);          // IE
        else
            oLink.onclick = soapMessage;                // Rand
    }
}


De functie soapMessage returned (altijd) 'false'. Helaas blijkt dat niet voldoende, want de pagina in de 'href' wordt gewoon geladen. Ik heb ook geprobeerd met
JavaScript:
1
function(){soapMessage(this); return false;}

maar dat werkt niet - en maakt eigenlijk ook weinig verschil met de return false uit 'soapMessage'.

Hoe speel ik dit klaar? Ik had veel zoekresultaten, maar nergens dit probleem.

Firefox kan ik overigens stoppen door in de functie 'soapMessage' deze code toe te passen:
JavaScript:
1
this.setAttribte('href', 'javascript:void(0);');

Maar dat werkt niet voor IE6 en IE7.

[ Voor 10% gewijzigd door r0bert op 12-08-2008 12:35 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:21

crisp

Devver

Pixelated

Daar heb je e.preventDefault() voor (in het geval van W3 Event model)

Maar gezien je code maak je niet echt gebruik van specifieke features die addEventListener/attachEvent bieden. IE's attachEvent heeft ook nog als nadeel dat de handler in de global scope wordt uitgevoerd ipv met de link in scope - dat verklaart waarom je this.setAttribute()* daar niet werkt. Ik vraag me dus af waarom je niet gewoon zo doet:

JavaScript:
1
2
3
4
5
6
7
8
9
rewriteLinks = function()
{
    onlLinks = document.getElementsByTagName('a');

    for (var iLink = 0; iLink < onlLinks.length; iLink++)
    {
            onlLinks[iLink].onclick = soapMessage;
    }
}


note dat .item() gebruiken feitelijk puur overhead is en niet nodig bij dit soort iteraties.
* mbt setAttribute(): ook daarvan vraag ik me af waar die voorkeur vandaan komt om echt overal set/getAttribute the gebruiken terwijl element.property = value in de meeste gevallen net zo goed werkt...

[ Voor 123% gewijzigd door crisp op 12-08-2008 12:59 ]

Intentionally left blank


  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Oké, ik dacht dat alle 3 de methodes ondersteunen meer compatibiliteit op zou leveren.

Ik zal zo (eerst even eten) zoeken op preventDevault. Die was ik al tegengekomen, maar ik weet niet precies hoe ik het event af zal moeten vangen.

Ook is het volgens mij voldoende om iets als
JavaScript:
1
onlLinks[iLink].onclick = return soapMessage; 

te kunnen produceren, maar ik weet niet hoe - want dit lijkt niet te werken.

Alleen te beperken tot de onclick werkt in ieder geval voor IE7 en FF.
IE6 werkt niet maar dat heeft dan mogelijk een andere reden.

[ Voor 16% gewijzigd door r0bert op 12-08-2008 13:00 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:21

crisp

Devver

Pixelated

r0bert schreef op dinsdag 12 augustus 2008 @ 12:58:
Oké, ik dacht dat alle 3 de methodes ondersteunen meer compatibiliteit op zou leveren.

Ik zal zo (eerst even eten) zoeken op preventDevault. Die was ik al tegengekomen, maar ik weet niet precies hoe ik het event af zal moeten vangen.

Ook is het volgens mij voldoende om iets als
JavaScript:
1
onlLinks[iLink].onclick = return soapMessage; 

te kunnen produceren, maar ik weet niet hoe - want dit lijkt niet te werken.
Je zegt dat soapMessage van zichzelf altijd al false returned, dus is dit voldoende:
JavaScript:
1
onlLinks[iLink].onclick = soapMessage;

een eventhandler verwacht een functie-reference. de returnvalue van die functie wordt teruggegeven aan de handler. In het geval dat evalueert naar een boolean false zorgt dat er in het geval van een inline handler voor dat een eventuele default actie niet uitgevoerd wordt.

[ Voor 16% gewijzigd door crisp op 12-08-2008 13:03 ]

Intentionally left blank


  • foliant
  • Registratie: Juli 2007
  • Laatst online: 19-01-2022
offtopic:
Tip: using the right msxml version
http://blogs.msdn.com/xml...in-internet-explorer.aspx
r0bert schreef op maandag 11 augustus 2008 @ 14:11:

[code=js]

aActiveXDOM = [
'MSXML4.DOMDocument',
'MSXML4.DOMDocument.4.0',
'MSXML3.DOMDocument',
'MSXML3.DOMDocument.3.0',
'MSXML2.DOMDocument',
'MSXML2.DOMDocument.3.0',
'MSXML.DOMDocument',
'Microsoft.XmlDom'
];

for (var iActX = 0; iActX < aActiveXDOM.length; iActX++)
{ try
{ return new ActiveXObject(aActiveXDOM[iActX]);
} catch (eActiveXException) { /* Do nothing */
}
}
Pagina: 1