Dieter Raber: onblur faken

Hallo,

ich beschaeftige mich gerade mit einer Image-Selectbox. Das ist ein Widget, den ich mit Javascript generiere und der dazu dient, Bilder aus einem gegebenen Verzeichnis auszuwaehlen.

Das Ding sieht so aus

der genrierte Quellcode etwa so:

  
<div class="img-selectbox">  
  <div style="background-image: url(pics/test/pic003.png)">  
    <label>pic003.png</label>  
    <button type="button"></button>  
  </div>  
  <div>  
    <ul>  
      <li style="background-image:url(pics/test/pic001.png)">  
        <label>pic001.png</label>  
      </li>  
      <li style="background-image:url(pics/test/pic002.png)">  
        <label>pic002.png</label>  
      </li>  
      <li style="background-image:url(pics/test/pic003.png)">  
        <label>pic008.png</label>  
      </li>  
      <li style="background-image:url(pics/test/pic050.png)">  
        <label>pic050.png</label>  
      </li>  
    </ul>  
  </div>  
  <input value="pics/test/pic003.png" name="box" id="box" type="hidden">  
</div>  

Das funktioniert bis auf paar kleine Macken auch ganz gut, fuer 2 Probleme habe ich allerdings keine Loesung:
1. die Box mit den 'Options' sollte auch onblur verschwinden, d.h., wenn irgendwo ausserhalb geklickt wird, da es aber in Wirklickeit div, ul, li und label sind, funktioniert onblur hier nicht

2. Wenn ich eine 'Option' mit einem ueberlangen Bildernamen habe, haelt sich FF an die vorgegebene Breite der 'Optionbox', waehrend IE diese entsprechend verbreitert. Allerdings wird nur die betreffende Option breiter. Am liebsten waere mir, wenn wie bei der Original-Selectbox sich alle Options der laengsten anpassen wuerden, dazu braeuchte ich aber eine Methode, die Laenge des Textes in Pixeln herauszufinden. Wenn das nicht geht, muss ich einen Weg finden, IE vom Ausdehnen der Option abzuhalten.

Ich wuerde mich fuer jeden Denkansatz interessieren.

Nebenbei bemerkt, als ich das Bild auf meine Server hochgeladen habe, bin ich wieder ueber das hier gestolpert. Ich habe das schon mal vor gut einem Jahr gepostet, aber finde es immer noch ganz nett.

Gruß,

Dieter

  1. Hallo,

    <div class="img-selectbox">
      <div style="background-image: url(pics/test/pic003.png)">
        <label>pic003.png</label>
        <button type="button"></button>
      </div>

    Äh, du weißt schon, für was das label-Element gedacht ist?

    Das funktioniert bis auf paar kleine Macken auch ganz gut, fuer 2 Probleme habe ich allerdings keine Loesung:

    1. die Box mit den 'Options' sollte auch onblur verschwinden, d.h., wenn irgendwo ausserhalb geklickt wird, da es aber in Wirklickeit div, ul, li und label sind, funktioniert onblur hier nicht

    Überwache alle Fokus- und Klickevents dokumentweit. Wenn deren Zielelement nicht im Widget liegt, klappe zu.

    1. Wenn ich eine 'Option' mit einem ueberlangen Bildernamen habe, haelt sich FF an die vorgegebene Breite der 'Optionbox', waehrend IE diese entsprechend verbreitert. Allerdings wird nur die betreffende Option breiter. Am liebsten waere mir, wenn wie bei der Original-Selectbox sich alle Options der laengsten anpassen wuerden

    Hmm... wieso gibst du eine Breite vor? Alles steckt in einem div, das ohne Vorgabe automatisch so breit wird, wie der Inhalt es erfordert. Kann man damit nicht arbeiten?

    dazu braeuchte ich aber eine Methode, die Laenge des Textes in Pixeln herauszufinden.

    Das ginge auch (offsetWidth o.ä.), erscheint mir aber unnötig umständlich.

    Wenn das nicht geht, muss ich einen Weg finden, IE vom Ausdehnen der Option abzuhalten.

    overflow:hidden, oder ignoriert IE das?

    Mathias

    1. Hallo molily,

      Äh, du weißt schon, für was das label-Element gedacht ist?

      Ja, ich werde das wohl austauschen

      Überwache alle Fokus- und Klickevents dokumentweit.

      Wie mache ich das?

      • Klickevents ist klar
      • Fokus ist mir nicht klar, da ich ja keine passenden Elemente habe

      Wenn deren Zielelement nicht im Widget liegt, klappe zu.

      • Meinst du ueber eine Kombination von Mausposition und Widgetgroesse/position?

      Hmm... wieso gibst du eine Breite vor?
      Alles steckt in einem div, das ohne Vorgabe automatisch so breit wird, wie der Inhalt es erfordert. Kann man damit nicht arbeiten?

      Die auessere Box hat eine bestimmte Groesse, damit der Widget mit anderen Elementen in der Form zusammenpasst

      Das ginge auch (offsetWidth o.ä.), erscheint mir aber unnötig umständlich.

      Wie ginge das im Groben vor sich?

      overflow:hidden, oder ignoriert IE das?

      Du kannst dir vorstellen, dass die generierten Styles relativ komplex sind und ich muss gestehen, dass ich an einem Punkt etwas den Ueberblick verloren habe. Mit andern Worten, ich bin ziemlich sicher, dass IE das ignoriert, aber beschwoeren wuerde ich es nicht.

      Gruß,

      Dieter

      1. Hallo,

        Überwache alle Fokus- und Klickevents dokumentweit.
        Wie mache ich das?

        • Klickevents ist klar
        • Fokus ist mir nicht klar, da ich ja keine passenden Elemente habe

        Du brauchst auch keine passenden Elemente im Widget. Der Punkt ist: Wenn ein Fokus bei Elementen außerhalb des Widgets passiert, dann kann dein Widget zuklappen.

        Wenn deren Zielelement nicht im Widget liegt, klappe zu.

        • Meinst du ueber eine Kombination von Mausposition und Widgetgroesse/position?

        Nein, über das Zielelement des Events. Dafür gibts die target-Eigenschaft des Event-Objektes bzw. im IE srcElement.

        Dann überprüfst du mit contains(), ob das Zielelement im Widget liegt (bzw. in welchem - alle anderen klappst du dann zu, falls es noch mehrere Widgets gibt).

        http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/contains.asp
        http://www.quirksmode.org/blog/archives/2006/01/contains_for_mo.html

        Hmm... wieso gibst du eine Breite vor?
        Die auessere Box hat eine bestimmte Groesse, damit der Widget mit anderen Elementen in der Form zusammenpasst

        Dann kannst du Ausreißer nur abschneiden oder die Breite nachträglich mit JavaScript anpassen.

        Das ginge auch (offsetWidth o.ä.), erscheint mir aber unnötig umständlich.
        Wie ginge das im Groben vor sich?

        Die offsetWidth der entsprechenden Elemente (momentan label) abfragen und gegebenenfalls die Breite des ganzen Widgets auf das breiteste anpassen.

        Mit andern Worten, ich bin ziemlich sicher, dass IE das ignoriert, aber beschwoeren wuerde ich es nicht.

        In meinen einfachen Beispielen setzt er es jedenfalls um.

        Mathias

    2. <div class="img-selectbox">
        <div style="background-image: url(pics/test/pic003.png)">
          <label>pic003.png</label>
          <button type="button"></button>
        </div>

      Äh, du weißt schon, für was das label-Element gedacht ist?

      Okay, so dumm war das gar nicht.

      Ich würde ja auf »progressive enhancement« setzen, indem die ganze JavaScript-Funktionalität ausgelagert wird und automatisch hinzugefügt wird.

      Ausgehen würde ich von solchem Code:

      <ul class="widget-dropdown">  
      <li><label><input type="radio" name="image" value="001.jpg"> 001.jpg</label></li>  
      <li><label><input type="radio" name="image" value="002.jpg"> 002.jpg</label></li>  
      <li><label><input type="radio" name="image" value="003.jpg"> 003.jpg</label></li>  
      <!-- ... -->  
      </ul>
      

      Das wäre zugänglich und man könnte es trotzdem gut mit JavaScript zu einem Widget umarbeiten. Das nur als generelle Anmerkung, ich nehme angesichts deines Codes einmal an, dass Zugänglichkeit und Trennung von JavaScript- und bloßer Formularlogik in dem Fall kein Thema.

      Mathias

    3. Hallo,

      Überwache alle Fokus- und Klickevents dokumentweit. Wenn deren Zielelement nicht im Widget liegt, klappe zu.

      Vergiss, was ich sagte: Klick-Events steigen auf, aber Focus-Events sinnigerweise nicht. Du kannst sie also nicht auf traditionellem Wege in der Bubbling-Phase zentral behandeln.

      Du kannst sie zwar nichtsdestoweniger in der Capture-Phase behandeln, das geht aber nur über DOM Events, womit du IE ausschließt. Doofe Sache, da musst du die Handler für die Überwachung von Links, Formularfeldern und anderen Widgets von Hand vergeben.

      Mathias

      1. Klick-Events steigen auf, aber Focus-Events sinnigerweise nicht. Du kannst sie also nicht auf traditionellem Wege in der Bubbling-Phase zentral behandeln.

        Naja, Opera und Konqueror unterstützen den Event DOMFocusIn, der ist ähnlich dem focus-Event, er bubblet nur.
        Dann blieben Gecko und IE außen vor, auch nicht schön.

        Mathias

    4. Hallo,

      Überwache alle Fokus- und Klickevents dokumentweit. Wenn deren Zielelement nicht im Widget liegt, klappe zu.

      Ein Beispiel:

      http://molily.de/temp/dropdown/

      Da werden jetzt DOMFocusIn und Mousedown zentral und global überwacht, sodass das Widget automatisch zuklappt.

      Um sicher zu sein, müsste man allen fokussierbaren Elementen einen Handler geben, der das Widget zuklappt. Das ginge dann natürlich nicht mehr mit einem zentralen Handler.

      Mathias

      1. Hallo molily,

        Deine Ausfuehrungen sind wie immer sehr hilfreich, danke.

        Ich habe dein Beispiel heruntergeladen und habe noch einige Fragen. Mir ist die Notation von Dropdown nicht so richtig vertraut, auch wenn ich verstehe, was da im einzelnen so passiert.

        Ich wuerde gerne eine beliebige Anzahl von Boxen haben wollen, d.h. die id-Zuweisung innerhalb des Objekts wuerde dann nicht mehr funktionieren. Ich habe versucht Dropdown dafuer in eine Funktion einzupacken, die mir erlaubt, einige Argumente weiterzugeben. Mir ist aber nicht klar, was dann window.onload passieren mueeste. Ich habe etwas rumexperimentiert, habe aber den Eindruck, ich mache da mehr kaputt als gut.

        Gruß,

        Dieter

        1. Hallo,

          Ich habe dein Beispiel heruntergeladen und habe noch einige Fragen. Mir ist die Notation von Dropdown nicht so richtig vertraut, auch wenn ich verstehe, was da im einzelnen so passiert.

          Die Widget-bezogenen Funktionen und Variablen habe ich in einem Object gruppiert.

          Die Schreibweise { ... } ist ein Object-Literal.

          var obj = { eigenschaft : "wert", e2 : "w2" };

          ist dasselbe wie

          var obj = new Object();
          obj.eigenschaft = "wert";
          obj.e2 = "w2";

          Ich wuerde gerne eine beliebige Anzahl von Boxen haben wollen

          Ja, das müsste man anders lösen.

          http://molily.de/temp/dropdown/multiple.html

          Ich werde morgen noch weiter daran arbeiten, erst einmal als Entwurf, gute Nacht. :) Morgen dann mehr.

          Ich habe versucht Dropdown dafuer in eine Funktion einzupacken, die mir erlaubt, einige Argumente weiterzugeben.

          Ja, das geht nicht, weil die Version immer mit dem einen globalen Dropdown-Object arbeitete.

          Mathias

          1. Hallo Mathias,

            So, Wochenende fast rum, Image-Selectbox fertig!
            http://dieterraber.net/selfhtml/imgSelectBox.htm

            Mit deinem letzten Code ('multiple.htm') habe ich mich gleich wesentlich heimicher gefuehlt. Im Grunde hat dieser sich nicht wesentlich von meiner letzten Version entschieden, so dass ich beide Versionen mit vertretbarem Aufwand zusammenfuehren konnte.

            Ich hatte an sich eine ganze Menge Vorstellungen, die ich in meinem Posting nicht erwaehnt hatte. Eine davon war, die ganze Gestaltung des Widgets mit JS zu machen, so dass man in CSS nur die Breite angeben muss. Das habe ich jetzt verwirklicht, wenn es meine Zeit zulaesst, werde ich noch eine Schnittstelle einbauen, die das bequeme Ueberschreiben der Styles per Object von aussen zulaesst.

            Vielen Dank an dieser Stelle fuer Deine Hilfe, du hast mir viel Zeit und Aerger erspart und gelernt hab' ich auch noch was.

            Gruß,

            Dieter

            1. Hallo Dieter.

              So, Wochenende fast rum, Image-Selectbox fertig!
              http://dieterraber.net/selfhtml/imgSelectBox.htm

              Ich trübe deine Freude ja ungern, aber ist dir aufgefallen, dass irgendetwas im aufklappbaren Bereich des „select“–Elementes im Opera 9 und 8.54 zu breit ist und deshalb darin ein horizontaler Scrollbalken entsteht?

              Zudem wird im Safari (1.3) bei aktiviertem JS rein garnichts angezeigt, auch wenn der generierte Code offenbar vollständig ist.

              Einen schönen Sonntag noch.

              Gruß, Mathias

              --
              sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
              „It is required that HTML be a common language between all platforms. This implies no device-specific markup, or anything which requires control over fonts or colors, for example. This is in keeping with the SGML ideal.“
              [HTML Design Constraints: Logical Markup]
              1. Hallo Mathias,

                [...] Opera 9 und 8.54 zu breit ist und deshalb darin ein horizontaler Scrollbalken entsteht?

                Weisst Du zufaellig , ob man Opera sowas wie Overflow X kennt?

                Zudem wird im Safari (1.3) bei aktiviertem JS rein garnichts angezeigt, auch wenn der generierte Code offenbar vollständig ist.

                Damit kann ich gut leben, Safari und Konqueror sind immer delikat. Wenn Du Dir zB. http://dieterraber.net/twElb.htm anschaust, wirst Du mit Safari vermutlich auch nicht sehr weit kommen. Ich schreibe diese Dinger in erster Linie, weil ich sie gerade brauche und meine Kunden nutzen eh fast alle IE oder FF.

                Gruß,

                Dieter

                1. Hallo Dieter.

                  [...] Opera 9 und 8.54 zu breit ist und deshalb darin ein horizontaler Scrollbalken entsteht?
                  Weisst Du zufaellig , ob man Opera sowas wie Overflow X kennt?

                  Ja, leider nicht.

                  Wenn Du Dir zB. http://dieterraber.net/twElb.htm anschaust, wirst Du mit Safari vermutlich auch nicht sehr weit kommen. Ich schreibe diese Dinger in erster Linie, weil ich sie gerade brauche und meine Kunden nutzen eh fast alle IE oder FF.

                  OK, dann ist das ganze verschmerzbar.

                  Einen schönen Sonntag noch.

                  Gruß, Mathias

                  --
                  sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
                  „It is required that HTML be a common language between all platforms. This implies no device-specific markup, or anything which requires control over fonts or colors, for example. This is in keeping with the SGML ideal.“
                  [HTML Design Constraints: Logical Markup]
            2. Hallo Dieter

              So, Wochenende fast rum, Image-Selectbox fertig!
              http://dieterraber.net/selfhtml/imgSelectBox.htm

              Zwei Kleinigkeiten dazu:
              Die Image-Selectbox bleibt ausgeklappt, wenn ich das Browserfenster verlasse, sie sollte sich auch beim Verlassen des Browserfesters schließen.
              Eine Schriftvergrößerung (im Firefox) verträgt sie auch nicht wirklich.

              Auf Wiederlesen
              Detlef

              --
              - Wissen ist gut
              - Können ist besser
              - aber das Beste und Interessanteste ist der Weg dahin!
              1. Hallo Detlef,

                Die Image-Selectbox bleibt ausgeklappt, wenn ich das Browserfenster verlasse, sie sollte sich auch beim Verlassen des Browserfesters schließen.

                Ist gefixt, danke fuer den Hinweis

                Eine Schriftvergrößerung (im Firefox) verträgt sie auch nicht wirklich.

                Nee, lass ich aber so

                Gruß,

                Dieter

            3. Hi Dieter,

              So, Wochenende fast rum, Image-Selectbox fertig!
              http://dieterraber.net/selfhtml/imgSelectBox.htm

              Wenn ich das Widget aufklappe und auf die Scrollbar klicke um zu scrollen, geht es wieder zu. Ich muss also das Mausrad verwenden um zu scrollen. Nur zur Info.

              Liebe Grüße.

              ciao
              romy

              PS: IE 6.0

              1. Hallo romy,

                Wenn ich das Widget aufklappe und auf die Scrollbar klicke um zu scrollen, geht es wieder zu.

                Danke, die Ursache ist der noch etwas unausgegorene Fix fuer https://forum.selfhtml.org/?t=134538&m=873881. Ich hab den jetzt erstmal entfernt, morgen schau mich mal bei MSDN, was die noch so an Loesungen bereithalten

                Gruß,

                Dieter

            4. Hallo Dieter,

              So, Wochenende fast rum, Image-Selectbox fertig!
              http://dieterraber.net/selfhtml/imgSelectBox.htm

              Ich fände es noch toll, wenn das Teil sich gut mit der Tastatur bedienen ließe - aktuell ist das ja bestenfalls etwas "holprig". Ansonsten ist es schonmal ganz nett. :-)

              Viele Grüße,
              Christian

              --
              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
  2. Nebenbei bemerkt, als ich das Bild auf meine Server hochgeladen habe, bin ich wieder ueber das hier gestolpert. Ich habe das schon mal vor gut einem Jahr gepostet, aber finde es immer noch ganz nett.

    Das ist superklasse, danke für den Hinweis.
    Bin immer noch am Schmunzeln ;-)

    Gustl