Dr.Colossos: options in selectfeld einfügen - FireFox Bug

Hi,

ich würde gerne ein Select-Feld dynamisch mit Optionen erweitern.

Meine derzeitige Lösung ersetzt dazu einfach das innerHTML-Attribut des jeweiligen Selectfeldes (hab gerade gesehen, im IE geht das auch ned wegen einem Bug).

Nun gut, ich habe aber im Firefox noch ein anderes Problem.

Die Optionen werden korrekt eingetragen, aber nachdem ich auf das Feld klicke, ist die Box, die den gewählten Eintrag zeigt, leer ... öffne ich das Feld, sind alle Optionen da, nur die selektierte wird nicht im Feld gezeigt.

Anbei ein Beispiel, statisch.

Weiss wer ob man das fixen kann?

Danke

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <title>dynamic select field</title>
  <script language="javascript" type="text/javascript">
   function refreshSelect(selectField)
   {
    selectField.innerHTML = '<option value="55">new 55</option>'
           + '<option value="66">new 66</option>'
           + '<option value="77">new 77</option>'
           + '<option value="88" selected="selected">new 888888</option>'
           + '<option value="99">new 99</option>'
           + '<option value="1223">originally selected</option>';

}
  </script>
 </head>
 <body>
  <select onmclick="refreshSelect(this)">
   <option selected="selected" value="1223">originally selected</option>
  </select>
 </body>
</html>

  1. Hi,

    <script language="javascript" type="text/javascript">
       function refreshSelect(selectField)
       {
        selectField.innerHTML = '<option value="55">new 55</option>'

    Daß das "option>'" bereits außerhalb des script-Elements steht, ist Dir bewußt?

    <select onmclick="refreshSelect(this)">

    soll das ein Multi-Click-Eventhandler sein?

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hi,

      wie gesagt, dass is hier nur ein statisches Beispiel, und ich weiss ehrlich noch nicht mal was du mir eigentlich sagen willst ..?

      Probier's im FF 2.0 aus und du siehst was ich meine.

      Es geht mir hier nur um die leere Auswahl, obwohl ein Eintrag gewählt ist wenn ich das Feld öffne.

      Work-Around?

      Danke

  2. n'abend,

    function refreshSelect(selectField)
       {
        selectField.innerHTML = '<option value="55">new 55</option>'
               + '<option value="66">new 66</option>'
               + '<option value="77">new 77</option>'
               + '<option value="88" selected="selected">new 888888</option>'
               + '<option value="99">new 99</option>'
               + '<option value="1223">originally selected</option>';

    }

    Gott gab uns das DOM und sprach: »Dies sei eure neue Religion«.

    /**  
     * Befülle eine Auswahlliste mit neuen Optionen  
     * @param field Node, deren Kinder entfernt werden sollen  
     * @param options Array von Optionen: [ {text:"Bezeichnung", value:"Wert", selected:true}, … ]  
     * @return field-node aus der Eingabe  
     */  
    function addOptions( field, options )  
    {  
      for( var i=0, option; option = options[i]; i++ )  
      {  
        // neues <option> Element erstellen  
        var opt = document.createElement( 'option' );  
      
        // <option value="xyz"> zuweisen  
        opt.value = option.value;  
      
        // <option selected> zuweisen  
        // option.selected könnte nicht gesetzt sein, wäre also "undefined", das ist hier nur just in case...  
        opt.selected = option.selected ? true : false;  
      
        // <option>xyz</option> zuweisen  
        opt.appendChild( document.createTextNode( option.text ) );  
      
        // neue Option ins <select> einklinken  
        field.appendChild( opt );  
      }  
      
      // zur Verkettung von Aufrufen  
      return field;  
    }  
      
    /**  
     * Lösche alle Option-Elemente einer Auswahlliste  
     * @param field Node, deren Kinder entfernt werden sollen  
     * @return field-node aus der Eingabe  
     */  
    function emptyOptions( field )  
    {  
      while( field.childNodes.length > 0 )  
        field.removeChild( field.childNodes[0] );  
      
      // zur Verkettung von Aufrufen  
      return field;  
    }
    

    Wenn du nun also deine Liste aktualisieren möchtest, kannst du einfach das folgende ausführen:

    function refreshSelect( field )  
    {  
      // bestehende Optionen löschen  
      emptyOptions( field );  
      // neue Options hinzufügen  
      addOptions( field, [  
        { text:"new 55", value:"55" },  
        { text:"new 66", value:"66" },  
        { text:"new 77", value:"77" },  
        { text:"new 888888", value:"88", selected:true},  
        { text:"new 99", value:"99" },  
        { text:"originally selected", value:"1223" }  
      
      ] );  
      
      return field;  
    }
    

    natürlich kannst du vor dem Löschen der Optionen schauen welche Option ausgewählt war und die eine oder andere Option speichern, damit sie neu eingetragen wird, etc. etc.

    <select onmclick="refreshSelect(this)">

    ist das ein Tippfehler, oder ein mir nicht bekannter EventHandler »onmclick«?

    </html>

    weiterhin schönen abend...

    --
    #selfhtml hat ein Forum?
    sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
    1. Hi Struppi, globe,

      ja, hatte ich auch schon so (bzw. analog, da ich prototype nutze in meinem Projekt).

      Das Problem is aber das gleiche. Im FF 2.0 sind SelectFelder in denen ich Optionen dynamisch hinzufüge "leer" nach dem Hinzufügen ... "leer" meint dabei nicht das keine Einräge in der Auswahlliste sind, sondern dass der feldwert zwar markiert ist wenn ich das Feld öffne, aber der Inhalt wird von FF 2.0 nicht "repainted".

      _______________
      |_Eintrag__|_V_|   <-- original

      |
         |   hinzufügen
         V
      _______________
      |__________|_V_|   <-- leer

      |
         |   aufklappen
         V
      _______________
      |__________|_V_|
      |___Eintag0____|
      |___Eintag_____|
      |___Eintag1____|
      |___Eintag2____|

      versteht ihr was ich meine? Ist es nachvollziehbar.

      Wie bereits erwähnt war es nicht anders als ich die Optionen als DOM-Objekte erstellt habe, und dem SelectFeld hinzugefügt habe - selbes Problem im FF 2.0 (3.0 nicht getestet). In allen anderen Broowsern funktioniert es wunderbar ... wie bereits öfter erwähnt ist das Hinzufügen ja auch nicht das Problem, sondern das repaint() des FF.

      Der Grund es nun mit innerHTML zu machen ist der das erstens die new Option()-Methode auch nicht funktionierte, und die innerHTML Variante wie so oft schneller ist ... wenn auch nicht so schön, aber auf das pfeif ich wenn es anders performater ist!

      Danke

      1. versteht ihr was ich meine? Ist es nachvollziehbar.

        Nein.

        Struppi.

        1. Hi,

          ja, das funktioniert, sehr richtig.

          Aber du fügst nur options an, ich will sie auch ersetzen, ggf. auch die selektierte, und ich denke das is das FF 2.0 Problem.

          Probier mal diesen Code, dann siehst du was ich meine (siehe unten).

          Okay, ich denke das entfernen/ersetzen der 'seleteced' option is das was FireFox-Probleme bereitet.

          Zum Hintergrund, warum ich das mache. Mein Programm zeigt u.U. lange Listen an (+1000 Zeilen), die u. a. select-Felder beinhalten (+20) => 20.000 Selectfelder. Ich will den Code bei Seitenaufbau minimieren, und zeige daher nur die selektierten Werte an. Klickt der User auf eine Selectbox, werden die anderen verfügbaren Optionen nachgeladen (ja, eine Filter Möglichkeit besteht, um nicht alle +1000 Zeilen anzuzeigen, aber wir kennen alle User die darauf pfeifen, und sagen, ich will ALLES sehen).

          Okay, nun könnt ich einfach die neuen Optionen anfügen, das geht (wie dein Beispiel zeigt), aber die Optionen sind sortiert (z.B. alphabetisch). Dann würde die original selektierte Option immer ganz oben erscheinen, ggf. gegen die Sortierung.

          D.h. ich müsste Optionen vor das orignale setzen (im Beispiel vor den Eintrag mit Wert "originally selected"). Sobald ich das probiere, ist der Bereich der die elektierte Option zeigen soll leer, obwohl die Optionen im Feld verfügbar sind, und auch die gewählte farbig hinterlegt ist ... nur eben erscheint sich nicht in der Box.

          Verständlich?
          Lösung?
          Danke!

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
          <html>
           <head>
             <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
            <title>dynamic select field</title>
            <script type="text/javascript">
          function refreshSelect(selectField)
          {
           if(selectField.options.length > 1)
            return;

          // entferne alle aktuellen Optionen
           for(var i = 0; i < selectField.options.length; i++)
            selectField.options[i] = null;

          // füge neue and
           addOpt(selectField, 55, 'new 55');
           addOpt(selectField, 66, 'new 66');
           addOpt(selectField, 77, 'new 77');
           addOpt(selectField, 88, 'new 88', false, false);
           addOpt(selectField, 99, 'new 9');

          // das ist der zuvor selektierte Eintrag
           addOpt(selectField, 1223, 'originally selected', true, true);
          }
          function addOpt(el, val, text, def, sel) {
           if(!text) text = val;
           var o = new Option(val, text, !!def, !!sel);
           el.options[el.options.length] = o;
          }

          </script>
          </head>
           <body>
            <select onclick="refreshSelect(this)">

          <option selected="selected" value="1223">originally selected</option>
            </select>
           </body>
          </html>

          1. Probier mal diesen Code, dann siehst du was ich meine (siehe unten).

            OK, sieht nach einem Bug aus. Mir fällt auch kein workaround ein, aber das gewählte Option wird trotzdem übertragen.

            var o = new Option(val, text, !!def, !!sel);

            Ich hab hier die Felder vertauscht.
            var o = new Option(text, val, !!def, !!sel);

            Struppi.

            1. Hi,

              gut, ich bin doch (noch) nicht wahnsinnig :)

              Ich habe inzwischen work-arounds.

              Man darf anscheinend die selektierte Option nicht löschen!

              Ich vergleiche nun einfach ob eine neueinzufügende Option bereits besteht und ob diese selektiert ist. Wenn dem so ist, behalte ich einen Verweis auf diese Option, und füge statt ihr kein neues Element ein, sondern den Verweis (mit appendChild).

              Da appendChild in diesem Fall einen Verweis auf eine bereits existierende DOM-Node bekommt, wird diese nur verschoben im Baum -> Sortierung stimmt, und korrekte Optionen sind selektiert.

              Nun muss man nur noch erreichen, dass auch diese Option in der Box dargestellt wird.

              Durch ...

              [...]
              if(alternative1)
              {
                  field.size = 2;
                  field.size = 1;
              }
              else if(alternative2)
              {
                  field.multiple = 'multiple';
                  field.multiple = '';
              }
              [...]

              ... wird jeweils ein repaint() "getriggered", und die korrekte Option erscheint.

              Aber leider führt der repaint()-Aufruf dazu, dass wenn das Feld angeklickt wird, die Auswahlliste sofort wieder geschlossen wird. Folglich braucht man zwei Klicks ... ärgerlich.

              So, und wer meint jez immernoch dass das trivial ist ..?

              Wenn ich mich dazu durchgerungen habe das tatsächlich sauber zu codieren (wenn man hier von sauber reden kann), dann poste ich das auch hier.

              Danke für die Hilfe ... wem was besseres einfällt ... würd mich freuen dass zu sehen!

              1. Man darf anscheinend die selektierte Option nicht löschen!

                Das kann ich nicht nachvollziehen.

                Nun muss man nur noch erreichen, dass auch diese Option in der Box dargestellt wird.

                Durch ...

                Ich hab eine andere Variante, die aber auch dazu führt:

                Aber leider führt der repaint()-Aufruf dazu, dass wenn das Feld angeklickt wird, die Auswahlliste sofort wieder geschlossen wird. Folglich braucht man zwei Klicks ... ärgerlich.

                Struppi.

                1. Hi,

                  Das kann ich nicht nachvollziehen.

                  Meinst du dass nicht der Grund ist, oder dass es nicht nachzuvollziehen ist warum sich FF so verhält?

                  Egal ... blur() war auch ein Ansatz von mir, wodurch bei onblur der selectedIndex erneut gesetzt wurde ...

                  tmp = feld.selectedIndex;
                  feld.selectedIndex = 0;
                  feld.selectedIndex = feld.options.length - 1;
                  feld.selectedIndex = tmp;

                  Macht effektiv nix, aber sorgt auch dafür dass die richtige Option dargestellt wird.

                  Alles nicht zufriedenstellend ...

                  Das ganze in einem neuem Select-Feld zu machen funktioniert übrigens ...

                  neu = createElement('select');
                  addOptions(neu);
                  doc.body.append(neu);

                  Ansonsten ich bin am Ende mit meinen Ideen ... und Nerven.

                  CLOSED?

    2. Hi globe,

      ja, aber es ergibt sich hier genau das gleich Problem. Wenn ich die Optionen lösche, d.h. insbesondere die selektierte, dann muckt FF 2.0.

      Genau das ist das von mir beschriebene Verhalten, und es spielt keine Rolle wie man das Feld nun aktualiesert, obe mit new Option, createElement oder dem hässlichen doch schnelleren innerHTML.

      Oder tritt das Problem bei euch nicht auf?

      Danke

  3. ich würde gerne ein Select-Feld dynamisch mit Optionen erweitern.

    selfhtml zeigt dir wie.

    Meine derzeitige Lösung ersetzt dazu einfach das innerHTML-Attribut des jeweiligen Selectfeldes ...

    ist die denkbar ungünstigste.

    Struppi.