master_Q: Bilder über onfocus laden

Hallihallo,

ich hab eine schnelle Frage:

Ich habe ein Formular und wenn ein bestimmtes input-Feld aktiviert ist über onfocus, dann sollen in der zweiten Spalte der Website alle dazugehörigen Produktbilder zu diesem input-feld geladen werden.

ich schaffe ein einzelnes Bild zu laden bei onfocus. aber wie lade ich mehrere Bilder untereinander gleichzeitg??

  
  
<!--Image - Preloader -->  
var arrImg = new Array();  
arrImg[0] = new Image();  
arrImg[0].src = "images/produkt1.png";  
  
arrImg[1] = new Image();  
arrImg[1].src = "images/produkt2.png";  
  
arrImg[2] = new Image();  
arrImg[2].src = "images/produkt3.png";  
  
function swapImage(imgName, intImg){  
	document.getElementById(imgName).src = arrImg[intImg].src;  
  
return false;  

  
<img src="" name="start" id="start" width="650px" height="400px">  
<input type="text" name="produkt1" id="produkt1"  onfocus="return swapImage('start', 7)"/>  
  
  
  
  
  

  1. function swapImage(imgName, intImg){
    document.getElementById(imgName).src = arrImg[intImg].src;

    Hier füllst Du die src des Bildes mit der ID "start". Das Bild kann nur eine source haben.

    Verwende mehrere Bilder

    <img src="" name="start1" id="start" width="650px" height="400px">
    <img src="" name="start2" id="start" width="650px" height="400px">
    <img src="" name="start3" id="start" width="650px" height="400px">

    und passe die Funktion und den Funktionsaufruf an.

    Ich bin aber nicht sicher, ob es noch schöner geht.

    Cheers,
    Baba

    1. Lieber Baba,

      Ich bin aber nicht sicher, ob es noch schöner geht.

      klar geht es! Wenn man das Schlüsselwort "this" im onfocus-Attribut notiert, dann bekommt die Funktion als Parameter eine Referenz auf das zu aktualisierende Bild übermittelt.

      <img src="" alt="" onfocus="return loadMe(this, '/images/products/nails.gif')" />

      function loadMe (img, url) {  
          img.src = url;  
          return false;  
      }  
        
      // preload: execute this function at once  
      (function () {  
          var imgs = document.images; // all <img> elements  
          var pre = []; // will contain new Image() objects  
          var regex = new RegExp(".*this, '([^']+)'.*", "i");  
          var i, img;  
        
          // find all onfocus eventhandler attributes in <img> elements  
          for (i = 0; i < imgs.length; i++) {  
        
              // do we have an onfocus attribute?  
              if (imgs[i].getAttributeNode("onfocus")) {  
        
                  // create new image object so the browser loads the image data  
                  img = new Image();  
                  img.src = imgs[i].getAttributeNode(  
                      "onfocus"  
                  ).replace(  
                      regex,  
                      "$1"  
                  );  
                  pre.push(img);  
              }  
          }  
      }());
      

      Der JS-Code ist ungetestet, könnte aber so ähnlich funzen(TM), falls er am Ende(!) des Dokuments eingebunden wird.

      Liebe Grüße,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
      1. Hallo,

        noch ne andere Frage, weil ich's gerade sehe...

        Was  ist den der Unterschied zwischen dieser:

        (function () {
        }());

        und dieser

        function () {
        }();

        Notation?

        Viele Grüße
        Siri

        1. Hi Siri!

          Was  ist den der Unterschied zwischen dieser:

          (function () {
          }());

          und dieser

          function () {
          }();

          Notation?

          Der Unterschied ist, dass die Zweite nicht funktionieren wird. ;)

          \0

          --
          sudo make me a sandwich
          1. Hallo,

            ok, ich denke, der Felix hat sich hier auch vertiptt:

            (function () {
            }());

            (function () {
            })();

            So wär besser.

            Viele Grüße
            Siri

            1. Hi Siri!

              ok, ich denke, der Felix hat sich hier auch vertiptt:

              (function () {
              }());
              (function () {
              })();

              So wär besser.

              Welche der beiden Varianten man benutzt ist technisch egal, es wird lediglich allgemein der Gruppierungs-Operator empfohlen, weil man dabei nicht groß auf die Rückgabewerte achten muss. Die Entwickler bei Facebook benutz(t?)en zum Beispiel gerne !function(){}();, was meiner Meinung nach nur unnötig Bugs provoziert.

              Vielleicht äußert einer der JavaScript-Gurus hier im Forum aber gute Argumente, die für die Nutzung von !, +, -, ~, void, … bei IIFEs sprechen?

              \0

              --
              sudo make me a sandwich
              1. Hallo,

                gute Argumente, die für die Nutzung von !, +, -, ~, void, … bei IIFEs sprechen?

                Es ist soweit ich weiß alles gleichwertig, solange man JavaScript-Dateien vernünftig konkateniert (zu einer größeren Datei zusammenfasst).

                (function() {})() und (function() {}()) geben sich in dieser Hinsicht nichts. Sie sind beide problematisch, wenn die vorherige Datei nicht korrekt mit einem Semikolon abschließt. Dann wird nämlich (…) als Teil der letzten Expression angesehen, und in diesem Kontext ist es ein Funktionsaufruf. Beispiel:

                Datei 1: alert(1)
                Datei 2: (function() {})();
                Zusammengefasst: alert(1)(function() {})();

                Das ist syntaktisch korrekt, aber bei der Ausführung wird es einen Fehler geben, weil alert() undefined und keine Funktion zurückgibt.

                Wenn man unäre Operatoren wie !, ~ oder void verwendet, die den einzigen Operand rechts vom Operator erwarten, so gibt es einen Syntaxfehler:

                Datei 1: alert(1)
                Datei 2: !function() {}();
                Zusammengefasst: alert(1)!function() {}();

                Das ist eher erwünscht, weil es einen schnellen und eindeutigen Fehler liefert.

                Es gibt viele Wege, das zu umgehen. Der einfachste ist, dafür zu sorgen, dass alle Scripte ihre Expression Statements mit einem ; abschließen. Da das bei Third-Party-Scripten nicht unbedingt garantiert werden kann, kann eine Datei auch einfach mit einem Semikolon beginnen:

                ;(function() {})();

                Falls nichts oder ein Semikolon davor kommt, ist das einfach ein leeres Statement. Falls ein nicht geschlossenes Expression Statement devor geklebt wird, so schließt es jenes.

                Intelligente Konkatenierer arbeiten m.W. mti ECMAScript-Parsern, um solche Probleme grundsätzlich zu vermeiden. Sie verstehen die Struktur und sind nicht auf gesetzte Semikola angewiesen; sie fügen sie automatisch hinzu.

                Mathias

  2. Hallo,

    Ich habe ein Formular und wenn ein bestimmtes input-Feld aktiviert ist über onfocus, dann sollen in der zweiten Spalte der Website alle dazugehörigen Produktbilder zu diesem input-feld geladen werden.

    Ich würde alle Bilder ins HTML einbetten und sie standardmäßig verstecken. Die Container-Elemente mit den Bildern bekommen IDs:

    <ul id="bilder1" class="hidden">  
    <li><img src="" alt=""></li>  
    </ul>  
      
    <ul id="bilder2" class="hidden">  
    <li><img src="" alt=""></li>  
    </ul>
    

    Die Input-Elemente wird mit den Bildern über diese ID verknüpft. Die zugehörige ID lässt sich in einem data-Attribut unterbringen:

    <input type="text" class="feld-mit-bildern" data-images-id="bilder1">  
    <input type="text" class="feld-mit-bildern" data-images-id="bilder2">  
    
    ~~~usw.  
      
    Das ganze Event-Handling (beim Fokus tue dieses und jenes) sollte im JavaScript aufgesetzt werden. Das JavaScript am besten am Ende des Dokuments laden, damit das DOM und all seine Elemente verfügbar sind.  
      
    ~~~javascript
    // Kapselung in selbstausführender Funktion  
    (function() {  
      // Speichert das Element mit den aktuell sichtbaren Bildern  
      var activeImages;  
      
      // Event-Handling aufsetzen  
      var initInputImages = function() {  
        // Alle Elemente mit der Klasse »feld-mit-bildern« holen  
        var inputs = document.getElementsByClassName('feld-mit-bildern');  
        for (var i = 0, el; el = inputs[i]; i++) {  
          // Event-Handler registrieren  
          el.onfocus = showImages;  
        }  
      };  
      
      // Der Event-Handler  
      var showImages = function(event) {  
        // Lese data-Attribut aus, um an die zugehörige ID zu kommen  
        var imageClass = event.target.getAttribute('data-images-id');  
        // Verstecke die aktuell sichtbaren Bilder  
        if (activeImages) {  
          activeImages.className = 'hidden';  
        }  
        // Zeige die Bilder, die sichtbar werden sollen  
        // Hole das zugehörige Element  
        activeImages = document.getElementById(imageClass);  
        // Lösche die hidden-Klasse  
        activeImages.className = '';  
      };  
      
      // Start!  
      initInputImages();  
      
    })();
    

    Zum Verstecken wird die Klasse »hidden« verwendet. Die muss im CSS natürlich formatiert werden:

    /* Einfache Variante */  
    .hidden { display: none; }  
      
    /* Bessere Variante (zugänglich) */  
    .hidden {  
      position: absolute;  
      left: -9999px;  
      width: 0;  
      height: 0;  
      overflow: hidden;  
    }
    

    Das Ganze mag auf Anhieb etwas komplex wirken, und es ist auch komplizierter, als man es lösen könnte. Aber das ist eine bessere Herangehensweise als JavaScript-Code direkt im HTML und CSS-Code direkt im JavaScript unterzubringen.

    Man könnte zusätzlich einen Link neben dem Eingabefeld zu den jeweiligen Bildern unterbringen, und die Bilder nur Verstecken, wenn JavaScript verfügbar ist. Dann wäre das Formular auch ohne JavaScript voll bedienbar und ließe sich auch benutzen, wenn z.B. der Bildschirm zu klein ist, um Formular und Bilder nebeneinander darzustellen.

    Viele Grüße,
    Mathias

    1. @@molily:

      nuqneH

      /* Bessere Variante (zugänglich) */

      Ist besser denn gut?

      .hidden {
        position: absolute;
        left: -9999px;
        width: 0;
        height: 0;
        overflow: hidden;

      Wird durch -9999px nicht eine riesige Box erzeugt? [Zeldman]

      Oder sollten Browser etwa so schlau sein und dies für ein 0 × 0 großes Element nicht tun?

      Qapla'

      --
      „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
      1. Hallo,

        Wird durch -9999px nicht eine riesige Box erzeugt? [Zeldman]

        (Der Link bezieht sich auf Image-Replacement, also das Ausblenden von Text innerhalb eines Elements, dessen Box weiter in den angestammten Dimensionen im Viewport liegen soll.)

        Oder sollten Browser etwa so schlau sein und dies für ein 0 × 0 großes Element nicht tun?

        Ich würde behaupten, dass sie das Element nicht zeichnen. Zumindest ist die Off-Left-Methode seit 10 Jahren im Einsatz und Performance-Probleme sind mir nicht zu Ohren gekommen.

        Wobei ich gerade lese, dass meine Anpassung mit width: 0 und height: 0 nicht gut ist und manche Screenreader (VoiceOver wird immer wieder genannt) ein Element der Höhe 0 nicht vorlesen. Insofern ist es durchaus gewollt, dass das Element Off-Screen gezeichnet wird. Der ursprüngliche Off-Left-Hack setzt eine Breite größer als 0 aber kleiner als der left-Wert. Und die Höhe bestimmt sich automatisch nach dem Inhalt.

        Also ja: Es wird gegebenenfalls eine sehr große Box erzeugt, je nachdem, was für ein Inhalt verschoben wird. Das ist anscheinend unvermeidlich.

        Ehrlich gesagt habe ich mich seit Jahren nicht mehr mit dem Thema beschäftigt. Es gibt wohl neuere Methoden, die mit der Größe 1px × 1px arbeiten. Das ist das aktuellste, was ich dazu finden konnte. Ich habe es aber noch nicht in Produktion verwendet.

        Mathias

        1. @@molily:

          nuqneH

          Zumindest ist die Off-Left-Methode seit 10 Jahren im Einsatz und Performance-Probleme sind mir nicht zu Ohren gekommen.

          Performanz auf leistungsschwachen (mobilen) Geräten war vor 10 Jahren wohl auch noch kein Thema.

          Qapla'

          --
          „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
      2. .hidden {
          position: absolute;
          left: -9999px;
          width: 0;
          height: 0;
          overflow: hidden;

        Danke für die Hilfe! So funktionierts :) DANKESCHÖN!!!!

    2. Lieber molily,

      var inputs = document.getElementsByClassName('feld-mit-bildern');

      bei welchen Browsern kann ich getElementsByClassName für das document-Objekt voraussetzen? Anscheinend könnte es mit WindowsXP-Usern Probleme geben...

      Liebe Grüße,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
      1. bei welchen Browsern kann ich getElementsByClassName für das document-Objekt voraussetzen?

        Ist das eine rhetorische Frage? ;)

        Anscheinend könnte es mit WindowsXP-Usern Probleme geben...

        Stimmt, querySelectorAll ist die bessere Wahl, da auch auf IE8 verfügbar.

        IE7 kann ignoriert werden in der von mir beschriebenen Weise: das JavaScript wird einfach nicht aktiv, die Bilder sind immer sichtbar und es existiert ein Link zu den Bildern.

        Mathias