Sebo: createElement, checkbox und der IE

Hallo!

Ich hab eine Frage zum erstellen einer Checkbox mit JavaScript. Vielleicht kann mir ja jemand helfen.
Im FF und Opera funktioniert es auch ohne Fehlermeldungen. Nur der IE macht mal wieder Sorgen.

Hier das Stück JS:

var formular = document.getElementById('form');  
var checkbox = document.createElement('input');  
formular.appendChild(checkbox);  
checkbox.setAttribute('type', 'checkbox');

Jetzt habe ich gelesen, dass der IE "checkbox" nicht als "type" kennt, sondern dass ich das setAttribute weglassen und createElement('<input type="checkbox">') notieren muss.

Das funktioniert mit dem IE auch so wie beschrieben.
Jetzt würde ich beide Varianten gern für die jeweiligen Browser anbieten,
ich komm mit den Conditional Compilations des IE nicht klar.

Wie schreib ich eine Browserweiche in JS damit ich dem IE seine extra-Wurst braten kann?

Sebo

  1. @@Sebo:

    nuqneH

    Jetzt habe ich gelesen, dass der IE "checkbox" nicht als "type" kennt

    ?? Doch, tut er.

    sondern dass ich das setAttribute weglassen

    Guter Plan. setAttribute() bereitet im IE immer wieder Probleme. Du notierst Attribute besser als Eigenschaft des Elementobjekts:

    var checkbox = document.createElement('input');  
    checkbox.type = 'checkbox';
    

    und createElement('<input type="checkbox">') notieren muss.

    ?? Was soll das denn?

    Jetzt würde ich beide Varianten gern für die jeweiligen Browser anbieten,

    Nö, du würdest gen eine Variante für alle Browser anbieten. Das Problem ist hier die Reihenfolge: Erst checkbox.type = 'checkbox' setzen, dann ins DOM hängen:

    checkbox.type = 'checkbox';  
    formular.appendChild(checkbox);
    

    Wobei auch das funktioniert:

    checkbox.setAttribute('type', 'checkbox');  
    formular.appendChild(checkbox);
    

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
    1. und createElement('<input type="checkbox">') notieren muss.

      ?? Was soll das denn?

      Das habe ich hier gefunden.

      Nö, du würdest gen eine Variante für alle Browser anbieten. Das Problem ist hier die Reihenfolge: Erst checkbox.type = 'checkbox' setzen, dann ins DOM hängen:

      Es lag also nur an der Reihenfolge. Gut, dann muss ich für den IE nichts extra schreiben. Danke!

      1. @@Sebo:

        nuqneH

        Das habe ich hier gefunden.

        Soso, der gute alte wahsaga. ;-) Bei solchen Postings im Archiv hätte ich mich auch umbenannt. >;-> SCNR.

        Da hat Micha das also her. Nun, wir können auch anders.

        Qapla'

        --
        Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
        (Mark Twain)
        1. Hallo Gunnar Bittersmann,

          Da hat Micha das also her. Nun, wir können auch anders.

          Ja, da habe ich es her und seitdem setzte ich diesen Schnipsel immer ein, wenn Input-Elemente erzeugt werden sollen. ;-)
          Im IE8 kann ich nach einem kurzen Test bestätigen, dass es unnötig zu sein scheint. Gilt das auch für ältere IEs?

          Mit freundlichem Gruß
          Micha

          1. Im IE8 kann ich nach einem kurzen Test bestätigen, dass es unnötig zu sein scheint. Gilt das auch für ältere IEs?

            Ja (getestet bis IE 6).

            Das type-Attribut kann ganz normal gesetzt werden, bevor das input-Element eingehängt ist. Danach ist es nur lesbar.

            Problematisch ist das name-Attribut. Aber auch nur insofern, dass input.name = "..." nicht dazu führt, dass das Element über die http://de.selfhtml.org/javascript/objekte/elements.htm@title=elements-Collection über dessen Namen oder ID erreichbar ist.

            Will man das unbedingt, so ist die proprietäre Aufrufweise von createElement nötig:

            <!DOCTYPE html>  
            <html><body>  
              
            <form><p id="target"></p></form>  
              
            <script>  
            [code lang=javascript](function () {  
            	var input = document.createElement('input');  
            	input.type = 'checkbox';  
            	input.name = 'eins';  
            	document.getElementById('target').appendChild(input);  
              
            	input = document.createElement('<input type="checkbox" name="zwei">');  
            	document.getElementById('target').appendChild(input);  
              
            	alert(document.forms[0].elements.eins);  
            	alert(document.forms[0].elements.zwei);  
            })();
            

            </script>

            </body></html>[/code]

            Das ist seit IE 8 gefixt, betrifft also zumindest IE 6 und 7.

            Credits: Struppi und JürgenB, SELFHTML Forum.

            Mathias

  2. Hallo Sebo,

    Im FF und Opera funktioniert es auch ohne Fehlermeldungen. Nur der IE macht mal wieder Sorgen.

    Wenn ich mich recht entsinne, besitzt das type-Attribut einen read-only Status und kann eigentlich nicht überschrieben werden. Wir haben das wie folgt gelöst:

    try {  
    	el = document.createElement(tagName);  
    	el.type = type;  
    }  
    catch(err) {  
    	el = document.createElement('<'+tagName+' type="'+type+'">');  
    }
    

    Mit freundlichem Gruß
    Micha

    1. try {

      el = document.createElement(tagName);
      el.type = type;
      }
      catch(err) {
      el = document.createElement('<'+tagName+' type="'+type+'">');
      }

        
      Wie gesagt ist das unnötig. Für welche tagName und type ist es deiner Meinung nach nötig?  
      Für die Eingabewerte "input" und "checkbox" springen IE 6, 7, 8 und 9 \*nicht\* in den Catch-Block.  
        
      Mathias
      
      1. Hallo molily,

        Wie gesagt ist das unnötig.

        Okay, dann werde ich das mal anpassen. Warum ich das Problem damals hatte, kann ich so nicht mehr nachvollziehen. Wenn ich mir diesen Beitrag so ansehe, würde ich meinen, dass ich den selben /Fehler/ gemacht habe wie Sebo. Also das Input-Element erstellt, dem Dokument hinzugefügt und *dann* erst die Attribute gesetzt. Genau sagen kann ichs Dir aber nicht mehr - dennoch Danke für Deinen Hinweis.

        Mit freundlichem Gruß
        Micha

      2. [latex]Mae  govannen![/latex]

        try {

        el = document.createElement(tagName);  
        el.type = type;  
        

        }
        catch(err) {
        el = document.createElement('<'+tagName+' type="'+type+'">');
        }

        
        >   
        > Wie gesagt ist das unnötig. Für welche tagName und type ist es deiner Meinung nach nötig?  
          
        input / button.  
          
        Bei irgendeinem IE (ich glaube es war 6, aber frag mich nicht nach der genauen Version, bin nicht am entsprechenden Computer) ist hier letztens ein Script abgebrochen worden, weil ich ein Button-Element auf die herkömmliche Weise (wie im try-Block) erzeugt habe. Mit der „alternativen“ createElement-Schreibweise funktioniert es.  
          
        Stur lächeln und winken, Männer!  
        Kai
        
        -- 
        Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken  
        in Richtung "Mess up the Web".([suit](https://forum.selfhtml.org/?t=197497&m=1324775))  
        [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)
        
        1. [latex]Mae  govannen![/latex]

          input / button

          Oder war es das button-Element? Habe gerade Zweifel.

          Stur lächeln und winken, Männer!
          Kai

          --
          Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
          in Richtung "Mess up the Web".(suit)
          SelfHTML-Forum-Stylesheet
        2. [latex]Mae  govannen![/latex]

          Wie gesagt ist das unnötig. Für welche tagName und type ist es deiner Meinung nach nötig?

          input / button.

          Es war das button-Element.

          var pfd = document.createElement('button');  
          pfd.type = 'button';
          

          versagt mindestens noch im IE7, auf diesem Computer hab ich keinen IE8, kann daher nicht testetn.

          Stur lächeln und winken, Männer!
          Kai

          --
          Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
          in Richtung "Mess up the Web".(suit)
          SelfHTML-Forum-Stylesheet
          1. @@Kai345:

            nuqneH

            var pfd = document.createElement('button');

            pfd.type = 'button';

            
            >   
            > versagt mindestens noch im IE7, auf diesem Computer hab ich keinen IE8, kann daher nicht testetn.  
              
            Versagt auch, aber  
              
            ~~~javascript
            var pfd = document.createElement('button');  
            pfd.setAttribute('type', 'button');
            

            tut im 8er seinen Dienst (nicht im 7er).

            Die Empfehlung, auf setAttribute() zu verzichten, kann man also so allgemein doch nicht stehen lassen; manchmal ist setAttribute() geradezu vonnöten.

            BTW, auch in anderen Browsern, die 'dataset' noch nicht beherrschen:

            if (foo.dataset) foo.dataset.barBaz = quz;  
            else foo.setAttribute('data-bar-baz', 'quz');
            

            Qapla'

            --
            Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
            (Mark Twain)
            1. [latex]Mae  govannen![/latex]

              Versagt auch, aber

              var pfd = document.createElement('button');

              pfd.setAttribute('type', 'button');

              
              >   
              > tut im 8er seinen Dienst (nicht im 7er).  
              >   
              > Die Empfehlung, auf `setAttribute()`{:.language-javascript} zu verzichten, kann man also so allgemein doch nicht stehen lassen; manchmal ist `setAttribute()`{:.language-javascript} geradezu vonnöten.  
                
              Man tauscht also die potentiellen Probleme der einen Technik gegen die der anderen Technik... da ist mir ein kleiner try-catch-Fallschirm irgendwie lieber. Ich denke mal, Clients, die \*das\* nicht verstehen, dürften inzwischen in freier Wildbahn nicht mehr anzutreffen sein.  
                
                
              Stur lächeln und winken, Männer!  
              Kai
              
              -- 
              Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken  
              in Richtung "Mess up the Web".([suit](https://forum.selfhtml.org/?t=197497&m=1324775))  
              [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)
              
            2. var pfd = document.createElement('button');

              pfd.type = 'button';

              
              >   
              > ~~~javascript
              
              var pfd = document.createElement('button');  
              
              > pfd.setAttribute('type', 'button');
              
              

              Danke für diese Ergänzungen. Das kann ich bestätigen.

              Die Empfehlung, auf setAttribute() zu verzichten, kann man also so allgemein doch nicht stehen lassen; manchmal ist setAttribute() geradezu vonnöten.

              BTW, auch in anderen Browsern, die 'dataset' noch nicht beherrschen:

              if (foo.dataset) foo.dataset.barBaz = quz;

              else foo.setAttribute('data-bar-baz', 'quz');

                
              Wieso braucht man da notwendig setAttribute?  
              foo['data-bar-baz'] = 'quz'; ginge theoretisch auch, müssten die Browser auch schlucken.  
              Wobei eigentlich nichts dagegen spricht, in Browsern, die ohnehin nicht dataset unterstützen, die Camel-Case-Schreibweise zu verwenden. Also einfach als Alternative  
              foo.dataBarBaz = 'quz';  
              Kommt ja letztlich auf dasselbe heraus; beim Element werden Daten gespeichert. Wobei ich in diesen Browsern eher ein System einsetzen würde, wie es jQuery verwendet. Dabei wird nur ein Key am Element gespeichert und die Nutzdaten in einem von jQuery verwalteten zentralen Objekt. Das erleichtert das Aufräumen und das Verhindern von Memory-Leaks.  
                
              Mathias  
                
              
              
      3. Hallo molily,

        Für welche tagName und type ist es deiner Meinung nach nötig?

        Die Umsetzung im ganzen sieht so aus bei mlf. Besagter Code reagiert also auf INPUT und BUTTON Elemente in einer Helfer-Funktion (createInputElementWithAttributes):

        document.createInputElementWithAttributes = function(tagName, att, par) {  
        	if (tagName.toLowerCase() != "input" && tagName.toLowerCase() != "button")  
        		return;  
          
        	var type = false;  
        	var el = false;  
        	for (var i=0; i<att.length; i++) {  
        		if (att[i][0].toLowerCase() == "type") {  
        			type = att[i][1];  
        			break;  
        		}  
        	}  
        	  
        	if (type) {  
        		try {  
        			el = document.createElement(tagName);  
        			el.type = type;  
        		}  
        		catch(err) {  
        			el = document.createElement('<'+tagName+' type="'+type+'">');  
        		}  
        	}  
        	el = el || document.createElement(tagName);  
          
        	for (var i=0; i<att.length; i++) {  
        		if (att[i][0].toLowerCase() != "type")  
        			el[att[i][0]] = att[i][1];  
        	}  
        	if (par)  
        		par.appendChild(el);  
        	return el;  
        };  
          
        document.createElementWithAttributes = function(tagName, att, par) {  
        	if (tagName.toLowerCase() == "input" || tagName.toLowerCase() == "button")  
        		return document.createInputElementWithAttributes(tagName, att, par);  
        	  
        	var el = document.createElement(tagName);  
        	for (var i=0; i<att.length; i++)  
        		el[att[i][0]] = att[i][1];  
        	if (par) {  
        		par.appendChild(el);  
        	}  
        	return el;  
        };
        

        Mit freundlichem Gruß
        Micha

        1. Hallo,

          Die Umsetzung im ganzen sieht so aus bei mlf. Besagter Code reagiert also auf INPUT und BUTTON Elemente in einer Helfer-Funktion (createInputElementWithAttributes)

          Ok, aber was ist jetzt mit molilys Einwand, dass der catch-Block u.U. nicht zum Zug kommt?

          Und wäre es statt try-catch mit

            
          el = document.createElement(tagName);  
          el.type = type;  
          el.type === type || (el = document.createElement('<'+tagName+' type="'+type+'">');  
          
          

          nicht auch getan? Wahrscheinlich nicht, denn das sieht nach normaler Objekt-Erweiterung aus, so dass vielleicht der IE trotz (el.type === type) === true die type-Eigenschaft nicht als Attribut ansieht.

          Tipp: Wenn man die Attribute nicht als zweidimensionales Array sondern als Objekt übergibt, entfällt die Frickelei mit att[0][1].

          Gruß, Don P

          1. [latex]Mae  govannen![/latex]

            Und wäre es statt try-catch mit

            el = document.createElement(tagName);
            el.type = type;
            el.type === type || (el = document.createElement('<'+tagName+' type="'+type+'">');

            
            >   
            > nicht auch getan? Wahrscheinlich nicht, denn  
              
            ... das Script bricht schon bei el.type = type; ab.  
              
            
            > Tipp: Wenn man die Attribute nicht als zweidimensionales Array sondern als Objekt übergibt, entfällt die Frickelei mit att[0][1].  
              
            Ack.  
              
            Stur lächeln und winken, Männer!  
            Kai
            
            -- 
            Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken  
            in Richtung "Mess up the Web".([suit](https://forum.selfhtml.org/?t=197497&m=1324775))  
            [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)
            
            1. Hallo,

              Und wäre es statt try-catch mit
              [...]
              nicht auch getan? Wahrscheinlich nicht, denn

              ... das Script bricht schon bei el.type = type; ab.

              Ok, aber wenn halt trotzdem kein catch zum Zug kommen sollte, ist das suboptimal.
              Umgekehrt müsste es jedenfalls klappen, z.B. geht folgendes im IE8 und auch im FF problemlos:

              try { /* IE-Extrawurst */  
                
               var el = document.createElement( '<input type="checkbox">' );  
                
              }  
              catch(err){  
                
               el = document.createElement('input'); el.type = 'checkbox';  
                
              }  
              
              

              Der FF springt nämlich in den catch-block :).

              Gruß, Don P

          2. Hallo Don P,

            Tipp: Wenn man die Attribute nicht als zweidimensionales Array sondern als Objekt übergibt, entfällt die Frickelei mit att[0][1].

            Ich wollte kurze Aufrufe haben und finde es hier nicht *so* unübersichtlich:

            document.createElementWithAttributes("a", [["class", "foo"], ["href", "#"]], null);

            Trotzdem Danke für den Hinweis.

            Mit freundlichem Gruß
            Micha

            1. [latex]Mae  govannen![/latex]

              Tipp: Wenn man die Attribute nicht als zweidimensionales Array sondern als Objekt übergibt, entfällt die Frickelei mit att[0][1].

              Ich wollte kurze Aufrufe haben und finde es hier nicht *so* unübersichtlich:

              document.createElementWithAttributes("a", [["class", "foo"], ["href", "#"]], null);

              document.createElementWithAttributes("a", {"class": "foo", "href": "#"}, null);

              ist meiner meinung nach viel übersichtlicher und in der Funktion auch leichter zu verarbeiten.

              Stur lächeln und winken, Männer!
              Kai

              --
              Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
              in Richtung "Mess up the Web".(suit)
              SelfHTML-Forum-Stylesheet
              1. document.createElementWithAttributes("a", [["class", "foo"], ["href", "#"]], null);

                document.createElementWithAttributes("a", {"class": "foo", "href": "#"}, null);

                ist meiner meinung nach viel übersichtlicher und in der Funktion auch leichter zu verarbeiten.

                Ja, Bibliotheken sind schon nicht dumm. Man kann von ihnen lernen, was API-Design angeht.

                Mathias

              2. Hallo Kai345,

                document.createElementWithAttributes("a", {"class": "foo", "href": "#"}, null);
                ist meiner meinung nach viel übersichtlicher und in der Funktion auch leichter zu verarbeiten.

                Stimmt! Sieht überzeugend gut aus, muss ich sagen. Ich werde es mal im Hinterkopf behalten und bei Gelegenheit abändern. Vielen Dank.

                Mit freundlichem Gruß
                Micha

  3. <snip>

    Hier das Stück JS:

    var formular = document.getElementById('form');

    var checkbox = document.createElement('input');
    formular.appendChild(checkbox);
    checkbox.setAttribute('type', 'checkbox');

      
    Erst type ändern, dann ins Dokument einfügen.
    
    1. @@bonzo400:

      nuqneH

      Erst type ändern, dann ins Dokument einfügen.

      Erst Thread lesen, dann antworten. ;-)

      Qapla'

      --
      Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
      (Mark Twain)