matthes042: Onresize-Event triggert nicht nach setzen eines Ankers.

Guten Tag,

ich wollte nie etwas mit Webentwicklung zu tun haben, nun muss ich mich berufsbedingt aber doch damit auseinander setzen und stoße ab und an auf ein Problem. Dieses hier ist das erste, welches mir google nicht beantworten konnte. Dementsprechend ist es mein erster Beitrag hier und ich hoffe ihr seid so freundlich und weißt mich im freundlichen Ton auf Fehler hin. ;)

Zur Sache: Ich soll eine Navigation mittels JS dazu bringen nach links und rechts mittels Buttons und ohne Scrollbar zu scrollen. Hilfe dazu habe ich hier gefunden und das funktioniert. Da man für diese Art einen div-Container erstellen muss, der eine feste Breite besitzt um overflow:hidden nutzen zu können ist man aber bei der Darstellung sehr eingeschränkt. Habe das nun ebenfalls mittels JS umgesetzt und lasse es onload berechnen und setzen. Bei einem resize-Event jedoch lasse ich die Seite neu laden (vllt. gibt es dafür eine bessere Lösung), um die Navigation wieder anzupassen. Problem 1, dass dadurch entsteht ist, dass evtl. vorgenommene Eingaben natürlich weg sind. Das zweite Problem ist, dass ich die Buttons mit einem Anker versehen habe, da sonst die Position des DIVs nicht gespeichert wird, wenn ich die Navigation scrolle. Nachdem ich jedoch einen Anker gesetzt habe reagiert weder der IE noch der Firefox auf das onresize-Event.

Code lasse ich jetzt erst einmal weg, vllt. reicht es das Thema theoretisch zu behandeln oder ich habe die falschen Schlagworte bei der Suche verwendet.

Jedenfalls danke ich schon einmal für eure Hilfe. :)
Viele Grüße,
Matthes

  1. Hallo,

    Code lasse ich jetzt erst einmal weg

    Aus deiner Beschreibung werde ich leider nicht schlau über die Anforderungen sowie deine gegenwärtige Implementierung. Bitte zeige den Code und am besten ein funktionsfähiges Beispiel, aus dem ersichtlich wird, was das Ziel und das Problem ist.

    vllt. reicht es das Thema theoretisch zu behandeln

    Theoretisch lässt sich dazu nur folgendes sagen: Das »Setzen eines Ankers« – ich vermute, du meinst damit, dass die Adresse zu foo.html#anker geändert wird und der Browser ein Element mit der ID »anker« fokussiert – hat keine Auswirkungen auf das Feuern von resize-Events. Vermutlich erweckt bloß irgendetwas in deinem Code den Anschein, dass es so wäre.

    Mathias

    1. Hi,

      ich habe gerade meinen Posting nochmal durchgelesen und kann nachvollziehen, dass du mich nicht verstanden hast. :D

      Ich hoffe, dass ich den Code so richtig eingefügt habe. Da ich mich als Anfänger empfinde freue ich auch über Tipps und Verbesserungsvorschläge, die über das eigentliche Thema hinaus gehen.

      Hier also der Code:

        
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
      <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">  
        
      <head>  
      <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />  
      <title>index</title>  
      <meta name="description" content="Descripton" />  
      <style type="text/css">  
        
      .menu {  
      	background-color: #99CC33;  
      	width: 200px;  
      	color: #006633;  
      	float: left;  
      <!--	top: 20px;-->  
      <!--	left: 20px;-->  
      <!--	padding: 5px;-->  
      	position: absolute;  
      }  
        
      #block {  
      	width: 1000px;  
      	overflow: hidden;  
      }  
        
      #block2 {  
      	width: 10000px;  
      }  
        
      </style>  
        
      <script type="text/javascript">  
        
      var Navigation = new Object();  
      Navigation.buttonbreite = 50;  
      Navigation.buttonpressed = 0;  
      Navigation.breite = 0;  
        
        
      function moveItRight()  
      {  
        var el = document.getElementById("block"),  
            st = el.scrollLeft;  
        
        go();  
        function go()  
         {  
      	 if(Navigation.buttonpressed==1) {  
      	     st = st + 10;  
      	     if(st < Navigation.breite - document.body.offsetWidth - Navigation.buttonbreite)  
      	      {  
      	        el.scrollLeft = st;  
      	        setTimeout(go, 10);  
      	      }  
      	    else  
      	      el.scrollLeft = Navigation.breite - document.body.offsetWidth - Navigation.buttonbreite;  
      	 }  
         }  
      }  
        
      function moveItLeft()  
      {  
        var el = document.getElementById("block"),  
            st = el.scrollLeft;  
        
        go();  
        function go()  
         {  
      	 if(Navigation.buttonpressed==1) {  
      	     st = st - 10;  
      	     if(st > -1)  
      	      {  
      	        el.scrollLeft = st;  
      	        setTimeout(go, 10);  
      	      }  
      	    else  
      	      el.scrollLeft = 0;  
      	 }  
         }  
      }  
        
      function getFensterweite() {  
      	return document.body.offsetWidth;  
      }  
        
      window.onload = function() {  
      	var all_obj;  
      	if(document.all) {  
      		all_obj=document.all;  
      	}  
      	else if(document.getElementsByTagName && !document.all) {  
      		all_obj=document.getElementsByTagName("*");  
      	}  
      	for(i=0; i<all_obj.length;i++) {  
      		if(all_obj[i].className == "menu") {  
      			Navigation.breite = Navigation.breite + all_obj[i].offsetWidth;  
      		}  
      	}  
      	document.getElementById("block").style.width = document.body.offsetWidth - Navigation.buttonbreite + "px";  
      	document.getElementById("buttons").style.width = Navigation.buttonbreite + "px";  
      }  
        
      function doResize() {  
      	location.href = location.href;  
      }  
        
        
      window.onresize = doResize;  
        
      </script>  
      </head>  
      <body>  
        
      <table border="0" cellpadding="0" cellspacing="0">  
      	<tr>  
      		<td>  
      			<div id="block">  
      				<div id="block2">  
      					<div class="menu">Navigation1</div >  
      					<div class="menu">Navigation1</div >  
      					<div class="menu">Navigation1</div >  
      					<div class="menu">Navigation1</div >  
      					<div class="menu">Navigation1</div >  
      					<div class="menu">Navigation1</div >  
      				</div>  
      			</div>  
      		</td>  
      		<td >  
      			<div id="buttons">  
          			<a href="#" onmousedown="Navigation.buttonpressed=1;moveItLeft()" onmouseup="Navigation.buttonpressed=0">left</a>&nbsp;<a href="#" onmousedown="Navigation.buttonpressed=1;moveItRight()" onmouseup="Navigation.buttonpressed=0">right</a>  
      			</div>  
      		</td>  
      	</tr>  
      </table>  
        
        
      </body>  
      </html>  
        
      
      
      1. @@Matthes042:

        nuqneH

        .menu {
        background-color: #99CC33;
        width: 200px;
        color: #006633;
        float: left;
        <!-- top: 20px;-->
        <!-- left: 20px;-->
        <!-- padding: 5px;-->
        position: absolute;
        }

        BTW, das ist falsch. <http://de.selfhtml.org/css/formate/einbinden.htm#kommentare@title=Kommentare in CSS>.

        Qapla'

        --
        Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
        (Mark Twain)
        1. BTW, das ist falsch. <http://de.selfhtml.org/css/formate/einbinden.htm#kommentare@title=Kommentare in CSS>.

          Qapla'

          Ah, danke. :) Wieder etwas gelernt. Hatte es vorher mit // probiert, aber das ging auch nicht. /* */ kenne ich zwar, bin aber nicht auf die Idee gekommen das zu probieren und Eclipse hat bei strg+shift+c <!-- --> draus gemacht.

          1. Om nah hoo pez nyeetz, Matthes!

            Ah, danke. :) Wieder etwas gelernt. Hatte es vorher mit // probiert, aber das ging auch nicht. /* */ kenne ich zwar, bin aber nicht auf die Idee gekommen das zu probieren und Eclipse hat bei strg+shift+c <!-- --> draus gemacht.

            Was ja für HTML auch stimmt. Woher soll Eclipse denn wissen, dass du in einem HTML-Dokument CSS-Code unterbringen möchtest?

            Also (aber nicht deshalb) CSS auslagern.

            Matthias

            --
            1/z ist kein Blatt Papier. http://www.billiger-im-urlaub.de/kreis_sw.gif
            1. Om nah hoo pez nyeetz, Matthes!

              Ah, danke. :) Wieder etwas gelernt. Hatte es vorher mit // probiert, aber das ging auch nicht. /* */ kenne ich zwar, bin aber nicht auf die Idee gekommen das zu probieren und Eclipse hat bei strg+shift+c <!-- --> draus gemacht.

              Was ja für HTML auch stimmt. Woher soll Eclipse denn wissen, dass du in einem HTML-Dokument CSS-Code unterbringen möchtest?

              Also (aber nicht deshalb) CSS auslagern.

              Matthias

              Ja, das ist natürlich richtig, wie ich schon sagte ist es nur ein kleiner Test für mich gewesen.

              Leider komme ich hier auch nicht weiter, von euch hat also auch keiner ne Ahnung was bei mir falsch läuft?

              1. Om nah hoo pez nyeetz, Matthes!

                Leider komme ich hier auch nicht weiter, von euch hat also auch keiner ne Ahnung was bei mir falsch läuft?

                zunächst einmal hast du unsemantisches HTML (Div-Suppe) auf dein JS hab ich nicht geschaut, hier wäre ein Online-Beispiel sinnvoll. Eine Navigation ist eine Liste.

                Matthias

                --
                1/z ist kein Blatt Papier. http://www.billiger-im-urlaub.de/kreis_sw.gif
                1. Om nah hoo pez nyeetz, Matthes!

                  Leider komme ich hier auch nicht weiter, von euch hat also auch keiner ne Ahnung was bei mir falsch läuft?

                  zunächst einmal hast du unsemantisches HTML (Div-Suppe) auf dein JS hab ich nicht geschaut, hier wäre ein Online-Beispiel sinnvoll. Eine Navigation ist eine Liste.

                  Matthias

                  Hi, danke für deine Antwort. Hatte durch dieses kleine Beispiel einen Ahaaaa-Effekt. Das ist das erste Mal, dass mir klar wird wie nützlich css sein kann.

                  Jedoch habe ich nun das Problem, dass overflow:hidden nicht funktioniert. Mit den Divs habe ich das nur hinbekommen, weil ich einen weiteren Div darunter gesetzt habe, der eine größere Größe hat, da sonst auf Grund von float:left die Einträge umgebrochen wurden.

                  Wenn es nötig ist Divs in der Liste zu setzen macht es eine Liste ja nicht übersichtlicher, so dass ich davon ausgehe etwas falsch zu machen?

                  Ebenfalls Matthias... :)

                  1. Om nah hoo pez nyeetz, Matthes!

                    Jedoch habe ich nun das Problem, dass overflow:hidden nicht funktioniert. Mit den Divs habe ich das nur hinbekommen, weil ich einen weiteren Div darunter gesetzt habe, der eine größere Größe hat, da sonst auf Grund von float:left die Einträge umgebrochen wurden.

                    Aus welchem Grund benötigst du overflow hidden?

                    Gib es einfach der Liste oder den Listenelementen.

                    Matthias

                    --
                    1/z ist kein Blatt Papier. http://www.billiger-im-urlaub.de/kreis_sw.gif
                    1. Aus welchem Grund benötigst du overflow hidden?

                      Gib es einfach der Liste oder den Listenelementen.

                      Darum dreht sich Matthes’ Ursprungsfrage. Er will per JavaScript in einer Navigation scrollen. Daher ein Container mit overflow: hidden und darin ein Element mit einer Breite, die die des Containers überragt. scrollLeft des Containers wird per JS gesetzt. Siehe mein Beispiel.

                      Mathias

                      1. Om nah hoo pez nyeetz, molily!

                        Darum dreht sich Matthes’ Ursprungsfrage. Er will per JavaScript in einer Navigation scrollen.

                        Jetzt hab ich das denn auch verstanden :)

                        Der ul overflow: hidden; und vom ersten Listenelement das margin-left ändern sollte auch Erfolg versprechend sein.

                        Matthias

                        --
                        1/z ist kein Blatt Papier. http://www.billiger-im-urlaub.de/kreis_sw.gif
          2. @@Matthes:

            nuqneH

            Hatte es vorher mit // probiert

            Gibt’s in CSS leider nicht.

            Eclipse hat bei strg+shift+c <!-- --> draus gemacht.

            So intelligent ist Eclipse wohl nicht zu wissen, dass es in einem HTML-Dokument(!) Bereiche (CSS, JavaScript) geben kann, für die gänzlich andere Regeln gelten.

            Mit einem externen Stylesheet (CSS-Datei) wär das nicht passiert.

            Qapla'

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

              nuqneH

              So intelligent ist Eclipse wohl nicht zu wissen, dass es in einem HTML-Dokument(!) Bereiche (CSS, JavaScript) geben kann, für die gänzlich andere Regeln gelten.

              Mit einem externen Stylesheet (CSS-Datei) wär das nicht passiert.

              Oh, zweiter!

              Qapla'

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

              nuqneH

              So intelligent ist Eclipse wohl nicht zu wissen, dass es in einem HTML-Dokument(!) Bereiche (CSS, JavaScript) geben kann, für die gänzlich andere Regeln gelten.

              Die hiesige Forumsoftware übrigens auch nicht. Zum richtigen Syntaxhighlighting müssten die [cod⁠e]-Bereiche verschachtelt werden:

              [cod⁠e lang=html]<!DOCTYPE html>
              <html …>
                <head>
                  ⋮
                  <style>
              [cod⁠e lang=css]body
              {
                font-family: Calibri, Optima, sans-serif;
              }[/cod⁠e]
                  </style>
                  <script>
              [cod⁠e lang=javascript]document.documentElement.className += ' js';[/cod⁠e]
                  </script>
                </head>
                ⋮
              </html>[/cod⁠e]

              ergibt:

              <!DOCTYPE html>  
              <html >  
                <head><style>  
              [code lang=css]body  
              {  
                font-family: Calibri, Optima, sans-serif;  
              }
              

              </style>
                  <script>
              document.documentElement.className += ' js';
                  </script>
                </head>
                ⋮
              </html>[/code]

              Qapla'

              --
              Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
              (Mark Twain)
            3. Eclipse hat bei strg+shift+c <!-- --> draus gemacht.

              So intelligent ist Eclipse wohl nicht [...]

              Für eine IDE in diesem Umfang (> 100 MiB) aber ziemlich schwach.

              1. @@suit:

                nuqneH

                So intelligent ist Eclipse wohl nicht [...]
                Für eine IDE in diesem Umfang (> 100 MiB) aber ziemlich schwach.

                Warum sollten die Eclipse-Entwickler auch auf die Idee kommen, ein Webentwickler könnte auf die Idee kommen, CSS- oder JavaScript-Code in einem HTML-Dokument zu notieren?

                Qapla'

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

                  Warum sollten die Eclipse-Entwickler auch auf die Idee kommen, ein Webentwickler könnte auf die Idee kommen, CSS- oder JavaScript-Code in einem HTML-Dokument zu notieren?

                  Weil Webentwickler eben auf Ideen kommen, auf die keiner kommt? Und deswegen sollte ein Programmprogrammierer auf mehr Ideen kommen! Oder einen Kurs besuchen: Psychologie des Users vom DAU bis zum Experte...

                  Aber es gibt sogar Webagenturen, die CSS richtig auslagern. So richtig aus dem <head>-Bereich, meine ich ;)

                  Link bei Interesse, meine »Erfahrungen mit Webdesign-Agenturen« haste vielleicht eh schon gelesen...

                  Adiou.

                  --
                  Ich bin eigentlich ganz anders, aber ich komme so selten dazu. - Ödön von Horwáth
                  Ist Rudi Carrell Gott? Oder George Harrison Ford?
                  Ich bin faul und das ist gut so.
                  1. Aber es gibt sogar Webagenturen, die CSS richtig auslagern. So richtig aus dem <head>-Bereich, meine ich ;)

                    Wo findet man sowas? :) Nein, ernsthaft - hier im Haus wird das auch gemacht.

                    Aber es gibt durchas Fälle wo das nicht möglich - irgendwelche embedded-Webserver wo du nur 1 File hast, welches als Info-Seite ausgeliefert wird und du kannst nur das bearbeiten usw.

                    1. Bounjoun suit,

                      Aber es gibt sogar Webagenturen, die CSS richtig auslagern. So richtig aus dem <head>-Bereich, meine ich ;)
                      Wo findet man sowas? :) Nein, ernsthaft - hier im Haus wird das auch gemacht.

                      Ihr tut die CSS-Anweisungen irgendwo im body unterbringen?

                      Aber es gibt durchas Fälle wo das nicht möglich - irgendwelche embedded-Webserver wo du nur 1 File hast, welches als Info-Seite ausgeliefert wird und du kannst nur das bearbeiten usw.

                      Das meine ich nicht. Ein <style>-Block ist zwar suboptimal, aber besser als CSS-Notationen irgendwo zwischen div und p ;)

                      Adiou.

                      --
                      Ich bin eigentlich ganz anders, aber ich komme so selten dazu. - Ödön von Horwáth
                      Ist Rudi Carrell Gott? Oder George Harrison Ford?
                      Ich bin faul und das ist gut so.
            4. Tach,

              Eclipse hat bei strg+shift+c <!-- --> draus gemacht.

              So intelligent ist Eclipse wohl nicht zu wissen, dass es in einem HTML-Dokument(!) Bereiche (CSS, JavaScript) geben kann, für die gänzlich andere Regeln gelten.

              doch eigentlich ist Eclipse so intelligent, das Syntaxhighlighting, die kontextsensitive Ergänzung u.ä. wechselt und er zeigt mir in einem Script-Block auch gleich an, dass ich mit dem hinzugefügten Kommentar einen Fehler mache (in CSS logischerweise nicht, da ist das ja kein Syntaxfehler). Aber die Kommentare bleiben gleich.

              mfg
              Woodfighter

      2. Hallo,

        nach einigen Änderungen habe ich endlich verstanden, was das Script tun soll. Allgemein machst du es dir sehr kompliziert und es ließe sich vereinfachen.

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

        In der Sprachangabe sollte wahrscheinlich »de« stehen für Deutsch.

        .menu {
        background-color: #99CC33;
        width: 200px;
        color: #006633;
        float: left;
        <!-- top: 20px;-->
        <!-- left: 20px;-->
        <!-- padding: 5px;-->
        position: absolute;
        }

        Den position-Kram habe ich entfernt, sonst liegen die Navigationseinträge nicht nebeneinander, sondern übereinander.

        var Navigation = new Object();
        Navigation.buttonbreite = 50;
        Navigation.buttonpressed = 0;
        Navigation.breite = 0;

        Kurzschreibweise:

        var Navigation = {
           buttonbreite: 50,
           buttonpressed: 0,
           breite: 0
        };

        buttonpressed sollte ein Boolean-Wert sein, also true oder false.

        if(Navigation.buttonpressed==1) {
             st = st + 10;
             if(st < Navigation.breite - document.body.offsetWidth - Navigation.buttonbreite)

        Ich würde hier nicht mit document.body.offsetWidth arbeiten. Dieser Wert ist weitesgehend uninteressant, dich interessiert die Breite der Navigation selbst.

        window.onload = function() {
        var all_obj;
        if(document.all) {
        all_obj=document.all;
        }
        else if(document.getElementsByTagName && !document.all) {
        all_obj=document.getElementsByTagName("*");
        }
        for(i=0; i<all_obj.length;i++) {
        if(all_obj[i].className == "menu") {
        Navigation.breite = Navigation.breite + all_obj[i].offsetWidth;
        }
        }

        Das ist unnötig umständlich. Hole dir das Navigationselement, das die Menü-Einträge umschließt, und durchlaufe mit .getElementsByTagName('li') seine Kinder.

        document.getElementById("block").style.width = document.body.offsetWidth - Navigation.buttonbreite + "px";
        document.getElementById("buttons").style.width = Navigation.buttonbreite + "px";

        Das kannst du alles mit CSS-Positionierung lösen.
        Lediglich die maximalen Scrollwert muss man mit JavaScript berechnen.

        function doResize() {
        location.href = location.href;
        }

        window.onresize = doResize;

        Beim Resize musst du nicht neu laden, sondern lediglich einige Breiten neu berechnen, wie du es beim onload auch tust.

        <table border="0" cellpadding="0" cellspacing="0">

        Layouttabellen sind überflüssig, verwende CSS zur Positionierung.

          		<div id="block2">  
          			<div class="menu">Navigation1</div >  
          			<div class="menu">Navigation1</div >  
          			<div class="menu">Navigation1</div >  
          			<div class="menu">Navigation1</div >  
          			<div class="menu">Navigation1</div >  
          			<div class="menu">Navigation1</div >  
          		</div>  
        

        Das sollte eine Liste mit ul/li oder ol/li werden.

          	<div id="buttons">  
        

        <a href="#" onmousedown="Navigation.buttonpressed=1;moveItLeft()" onmouseup="Navigation.buttonpressed=0">left</a>&nbsp;<a href="#" onmousedown="Navigation.buttonpressed=1;moveItRight()" onmouseup="Navigation.buttonpressed=0">right</a>
        </div>

        Hier fehlt das Unterdrücken der Standard-Ereignisbehandlung des click-Events, um zu verhindern, dass der Browser # anspringt.

        Außerdem solltest du Event-Handler mit JavaScript registrieren, am besten so, dass mehrere Event-Handler eines Typs registriert werden können (Unobtrusive JavaScript).

        Hier ein Gegenvorschlag zur Strukturierung:

        http://jsfiddle.net/VgxXZ/2/

        Schau dir den Aufbau mal genauer an.

        Beim Laden wird erst einmal init aufgerufen. Darin werden die benötigten Elemente geholt und beim Navigation-Object gespeichert. Außerdem werden die Event-Handler registriert:

            n.addEvent(window, 'resize', n.setupWidths);  
          
            n.container = document.getElementById('navigation-container');  
            n.element = document.getElementById('navigation');  
          
            var buttonLeft = document.getElementById('button-left');  
            n.addEvent(buttonLeft, 'mousedown', n.buttonLeftDown);  
            n.addEvent(buttonLeft, 'click', n.buttonUp);  
          
            var buttonRight = document.getElementById('button-right');  
            n.addEvent(buttonRight, 'mousedown', n.buttonRightDown);  
            n.addEvent(buttonRight, 'click', n.buttonUp);
        

        Schließlich wird setupWidths aufgerufen, welches auch beim Resize wieder aufgerufen wird:

            // Container-Breite  
            n.containerWidth = n.container.offsetWidth;  
          
            // Summe der Breite aller Navigations-Items  
            n.width = 0;  
            var lis = n.element.getElementsByTagName('li');  
            for (var i = 0, l = lis.length; i < l; i++) {  
              n.width += lis[i].offsetWidth;  
            }  
            n.element.style.width = n.width + 'px';  
          
            // Beides wird für die maximale Scroll-Position benötigt  
            n.maxScrollLeft = n.width - n.containerWidth;
        

        Der Rest sind Event-Handler für die Button-Klicks sowie die beiden scrollLeft- und scrollRight-Funktionen. Neu hinzugekommen ist eigentlich nur buttonUp als click-Handler bei den Buttons:

          buttonUp: function (e) {  
            Navigation.buttonPressed = false;  
            if (e.preventDefault) {  
              e.preventDefault();  
            } else {  
              e.returnValue = false;  
            }  
          },
        

        Darin wird wie gesagt verhindert, dass der Browser # anspringt.

        Mathias

        1. Hallo!!

          Ich bin begeistert, nicht nur, dass du die Aufgabe sehr schön gelöst hast, vor allem auch weil ich anhand dieser viel lernen konnte! Ich danke dir für die Mühe, die du dir gegeben hast!

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

          In der Sprachangabe sollte wahrscheinlich »de« stehen für Deutsch.

          Stimmt, das Grundgerüst war ursprünglich kopiert und wurde mit wachsendem Verständnis verändert.

          var Navigation = new Object();
          Navigation.buttonbreite = 50;
          Navigation.buttonpressed = 0;
          Navigation.breite = 0;

          Kurzschreibweise:

          var Navigation = {
             buttonbreite: 50,
             buttonpressed: 0,
             breite: 0
          };

          Das kenne ich, habe ich auch so versucht, jedoch hat das nur mit dem Firefox (Version 6) funktioniert und nicht mit dem IE (Version 8)?

          buttonpressed sollte ein Boolean-Wert sein, also true oder false.

          Stimmt.

          if(Navigation.buttonpressed==1) {  
               st = st + 10;  
               if(st < Navigation.breite - document.body.offsetWidth - Navigation.buttonbreite)  
          

          Ich würde hier nicht mit document.body.offsetWidth arbeiten. Dieser Wert ist weitesgehend uninteressant, dich interessiert die Breite der Navigation selbst.

          Die Breite der Navigation war unter Verwendung von Divs die Breite des Fensters (offsetWidth) minus die Breite der Buttons, die daneben angebracht wurden. Habe hier aber noch einen Fehler, da Klammern um offsetWidth und buttonbreite fehlen. In deinem Code hast du das aber anders gemacht, schaue ich mir gleich an. :)

          window.onload = function() {
          var all_obj;
          if(document.all) {
          all_obj=document.all;
          }
          else if(document.getElementsByTagName && !document.all) {
          all_obj=document.getElementsByTagName("*");
          }
          for(i=0; i<all_obj.length;i++) {
          if(all_obj[i].className == "menu") {
          Navigation.breite = Navigation.breite + all_obj[i].offsetWidth;
          }
          }

          Das ist unnötig umständlich. Hole dir das Navigationselement, das die Menü-Einträge umschließt, und durchlaufe mit .getElementsByTagName('li') seine Kinder.

          Ah, ByTagName war mir bisher nicht bekannt, auch wäre ich nicht auf die Idee gekommen, dass man getElement (was natürlich logisch ist) auf jedes Element des htmls anwenden kann und nicht nur auf document.

          document.getElementById("block").style.width = document.body.offsetWidth - Navigation.buttonbreite + "px";  
          document.getElementById("buttons").style.width = Navigation.buttonbreite + "px";  
          

          Das kannst du alles mit CSS-Positionierung lösen.
          Lediglich die maximalen Scrollwert muss man mit JavaScript berechnen.

          Hier denke ich noch falsch. Habe das gemacht, damit ich für die Breite der Buttons nur eine Variable ändern brauche. Unnötig kompliziert, ob ich sie in einem JS umsetze, was man sicherlich vermeiden sollte, oder lieber in einer css, was eindeutig geschickter ist...

          Die Containerbreite für die Navigation hast du gesetzt, indem du im CSS den Abstand nach oben, links und rechts gesetzt hast, den Rest macht der Browser selbst?! Oh man, manchmal denke ich wirklich langsam, das macht Sinn so!

          function doResize() {
          location.href = location.href;
          }

          window.onresize = doResize;

          Beim Resize musst du nicht neu laden, sondern lediglich einige Breiten neu berechnen, wie du es beim onload auch tust.

          Ah, das ist sehr gut, löst das Problem, dass gemachte Eingaben gelöscht werden. :)

          <table border="0" cellpadding="0" cellspacing="0">

          Layouttabellen sind überflüssig, verwende CSS zur Positionierung.

            		<div id="block2">  
            			<div class="menu">Navigation1</div >  
            			<div class="menu">Navigation1</div >  
            			<div class="menu">Navigation1</div >  
            			<div class="menu">Navigation1</div >  
            			<div class="menu">Navigation1</div >  
            			<div class="menu">Navigation1</div >  
            		</div>  
          

          Das sollte eine Liste mit ul/li oder ol/li werden.

          Wäre es mein Projekt würde ich deiner Empfehlung sofort nachgehen, es soll aber in einem bestehenden Projekt benutzt werden und da wird alles mit divs gehandhabt...

            	<div id="buttons">  
          

          <a href="#" onmousedown="Navigation.buttonpressed=1;moveItLeft()" onmouseup="Navigation.buttonpressed=0">left</a>&nbsp;<a href="#" onmousedown="Navigation.buttonpressed=1;moveItRight()" onmouseup="Navigation.buttonpressed=0">right</a>
          </div>

          Hier fehlt das Unterdrücken der Standard-Ereignisbehandlung des click-Events, um zu verhindern, dass der Browser # anspringt.

          Außerdem solltest du Event-Handler mit JavaScript registrieren, am besten so, dass mehrere Event-Handler eines Typs registriert werden können (Unobtrusive JavaScript).

          So, das habe ich halb verstanden beim ersten Durchlesen. Ich hoffe mit deinem Beispiel, dass ich mir nun genauer ansehen werde, werde ich das genauer verstehen.

          Noch einmal: Ich danke dir, nicht nur für die Lösung des Problems, sondern auch weil ich mir gern einen vernünftigen Programmierstil aneignen möchte und dein Beispiel mir sehr gut gefällt.

          PS: jsfiddle ist ja ne tolle Sache. Sollte ich noch einmal eine Frage haben werde ich auch darauf zurückgreifen.

          1. So, da bin ich wieder. :)

            Ich habe noch ein wenig damit rumgespielt und festgestellt, dass ich zwei Navigationsleisten ansteuern soll. Ich fand es unschön das Skript zu kopieren. Da ich aus der objektorientierten Entwicklung komme, bin ich über die Konstruktorfunktionen gestolpert. Das funktioniert auch sehr gut. Meine Frage betrifft also kein Problem, sondern eher allgemeines Verständnis JavaScript betreffend:

            Worin unterscheiden sich

            1. var Navigation = { ... }

            und

            2. function Navigation(Argumente) { ... }

            ?

            Von 1. kann man immer nur ein Objekt gleichzeitig haben, oder? Von zweitem kann man durch var nav = new Navigation(Argumente) soviele erzeugen wie man benötigt? Gibt es dabei etwas bestimmtes zu beachten?

            Ich möchte den Code einmal bei Fiddle hinterlegen und deine Meinung dazu hören. Wenn ich es richtig verstanden habe ist var that = this nötig, sobald man eine weitere (innere) Funktion betritt, da der Kontext von this dann auf window steht?
            Meine jetzige Implementierung hat glaube ich ausschließlich globale Funktionen? Sollte man sowas vermeiden? Mit privaten hat der Code leider nicht mehr funktioniert. Habe dort nur addEvent global gelassen, da dort ja von außen zugegriffen wird, funktionierte aber nicht.

            Hier der Fiddle-Link:

            http://jsfiddle.net/mXvrw/

            Viele Grüße,
            Matthias

            1. Hallo,

              Worin unterscheiden sich

              1. var Navigation = { ... }

              das erzeugt ein Objekt mit dem Namen Navigation und den Eigenschaften und Werten, die du in der geschweiften Klammer definierst.

              1. function Navigation(Argumente) { ... }

              Das ist eine Funktion.

              Du willst jetzt nicht wirklich fragen, was der Unterschied zwischen einem Objekt und einer Funktion (oder Methode) ist? Oder war dir einfach die Objekt-Notation unter 1. nicht geläufig?

              Von 1. kann man immer nur ein Objekt gleichzeitig haben, oder?

              Nein. Du kannst z.B. ein Array gleichartiger Objekte haben, oder mehrere gleichartige Objekte mit verschiedenen Namen.

              Von zweitem kann man durch var nav = new Navigation(Argumente) soviele erzeugen wie man benötigt? Gibt es dabei etwas bestimmtes zu beachten?

              Ach, daher weht der Wind. Ja, dann betrachtest du die Funktion quasi als Konstruktor, der in Verbindung mit dem new-Operator neue Objekte erzeugt. Das geht auch.

              Ich möchte den Code einmal bei Fiddle hinterlegen und deine Meinung dazu hören. Wenn ich es richtig verstanden habe ist var that = this nötig, sobald man eine weitere (innere) Funktion betritt, da der Kontext von this dann auf window steht?

              Nein. Wenn du eine Funktion als Konstruktor aufrufst, ist this eine Referenz auf das neue Objekt, das beim Eintritt in die Funktion noch keine Eigenschaften hat. Oder habe ich nicht verstanden, was du meinst?

              So long,
               Martin

              --
              Dem Philosoph ist nichts zu doof.
              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            2. Worin unterscheiden sich

              1. var Navigation = { ... }

              und

              1. function Navigation(Argumente) { ... }

              ?

              Von 1. kann man immer nur ein Objekt gleichzeitig haben, oder? Von zweitem kann man durch var nav = new Navigation(Argumente) soviele erzeugen wie man benötigt?

              Ja, richtig.

              Gibt es dabei etwas bestimmtes zu beachten?

              Anstatt »Navigation« musst du immer »this« verwenden - bei Event-Handlern und Co. ist es nicht immer einfach, Zugriff auf das Instanzobjekt zu bekommen, weil »this« nicht automatisch an dieses gebunden wird. Das ist leider nicht ganz so trivial:
              http://molily.de/js/organisation-instanzen.html
              und speziell
              http://molily.de/js/organisation-verfuegbarkeit.html

              Ich möchte den Code einmal bei Fiddle hinterlegen und deine Meinung dazu hören. Wenn ich es richtig verstanden habe ist var that = this nötig, sobald man eine weitere (innere) Funktion betritt, da der Kontext von this dann auf window steht?

              Ja, das funktioniert - vorausgesetzt, die Methoden werden im Konstruktor verschachtelt und damit für jede Instant neu angelegt. Das ist kein Problem, solange man eh nur zwei Instanzen erzeugt. Wenn man tausende Instanzen erzeugen würde, sollte man die Methoden lieber am Prototyp erzeugen und dann binden (die dortige bind-Funktion haben viele Browser mittlerweile schon nativ implementiert, ich muss das mal aktualisieren).

              Meine jetzige Implementierung hat glaube ich ausschließlich globale Funktionen? Sollte man sowas vermeiden? Mit privaten hat der Code leider nicht mehr funktioniert.

              Wirkliche private Methoden gibt es nicht. Man kann lediglich lokale Funktionen im Konstruktor schachteln, ohne diese am Instanzobjekt zu speichern, siehe http://molily.de/js/organisation-instanzen.html#private-objekte. Das heißt, man kann dann auch nicht über das Instanzobjekt darauf zugreifen. Wahrscheinlich hattest du das versucht und dabei kommt natürlich nichts.

              Habe dort nur addEvent global gelassen, da dort ja von außen zugegriffen wird, funktionierte aber nicht.

              Im Prinzip kannst du sämtliche Funktionen lokal notieren, ohne sie ans Instanzobjekt zu hängen. Dein Code ist ja bisher in sich abgeschlossen.

              Hier der Fiddle-Link:

              http://jsfiddle.net/mXvrw/

              Das sieht sehr gut aus!
              Dort sind dir zwei »var« abhanden gekommen in den Methoden scrollRight und scrollLeft. Den »el«-Shortcut kann man sich jetzt sparen und direkt »container« verwenden.
              Außerdem solltest du Zeilen mit »;« anstatt »,« beenden (ist wahrscheinlich ein Copy-n-Paste-Fehler vom alten Code). Das Komma ist ein Operator und dient nur in var-Statements oder Objekt-Literalen dazu, einzelne Einträge zu trennen. Wenn man das anstelle vom Semikolon verwendet, kann es auch schnell zum Problem werden.

              Hier noch mal ein Beispiel, bei dem sätmliche Funktionen »privat« sind (also keine richtigen Methoden am Instanzobjekt sind). Zudem habe ich alles in eine weitere selbstausführende anonyme Funktion verpackt, damit die Variablen Navigation, navigationFirst und navigationSecond nicht global werden.

              http://jsfiddle.net/molily/ENNrH/1/

              Ansonsten hat sich die Funktionalität nicht geändert – es zeigt nur, dass man die Kapselung noch weiter treiben kann. Diese Instanz ist schlicht ein leeres Objekt. Man kann natürlich darüber streiten, ob man in solchen Fällen noch einen Konstruktor braucht, den man mit »new« aufruft.

              Grüße,
              Mathias

              1. Hi,

                puh, danke, so langsam kann ich mich für Webentwicklung erwärmen. Deine JavaScript-Dokumentation liest sich übrigens sehr gut, habe angefangen sie einmal von vorn durchzugehen.

                Hier noch mal ein Beispiel, bei dem sätmliche Funktionen »privat« sind (also keine richtigen Methoden am Instanzobjekt sind). Zudem habe ich alles in eine weitere selbstausführende anonyme Funktion verpackt, damit die Variablen Navigation, navigationFirst und navigationSecond nicht global werden.

                http://jsfiddle.net/molily/ENNrH/1/

                Ansonsten hat sich die Funktionalität nicht geändert – es zeigt nur, dass man die Kapselung noch weiter treiben kann. Diese Instanz ist schlicht ein leeres Objekt. Man kann natürlich darüber streiten, ob man in solchen Fällen noch einen Konstruktor braucht, den man mit »new« aufruft.

                Hmm, ok, das verwirrt mich nun doch ein wenig. Ich denke, wenn ich in deiner Dokumentation weiter vorrangekommen bin, werde ich verstehen was eine "selbstausführende anonyme Funktion" ist. ;)
                Du benutzt hier gar kein this und that mehr, wäre es bei meinem Code ebenfalls möglich den einfach wegzulassen? Nein, da es keine lokalen Funktionen sind, oder?

                This bzw. that in Zusammenhang mit lokalen Funktionen funktioniert nicht, oder? Daran könnte es gelegen haben, dass es bei mir nicht funktioniert, ich glaube ich habe sowas wie that.addEvent = function() {...} geschrieben.

                Matthias. :)

                1. Ich denke, wenn ich in deiner Dokumentation weiter vorrangekommen bin, werde ich verstehen was eine "selbstausführende anonyme Funktion" ist. ;)

                  Ich sehe gerade, das habe ich auch hier beschrieben: ;)
                  http://molily.de/js/organisation-module.html#scope

                  Du benutzt hier gar kein this und that mehr, wäre es bei meinem Code ebenfalls möglich den einfach wegzulassen? Nein, da es keine lokalen Funktionen sind, oder?

                  Richtig.

                  Im einen Fall sind es Eigenschaften/Methoden eines Objekts – es Instanzobjekts eben. Also muss man immer über objekt.eigenschaft darauf zugreifen. Da hat man das Problem, dass man immer das Instanzobjekt zu Fassen bekommen muss.

                  Im anderen Fall sind es einfach lokale Variablen des Konstruktors, die in den darin verschachtelten Funktionen verfügbar sind (Fachbegriff dafür: Closures). Also nennt man die Variablen einfach direkt beim Namen. Der JavaScript-Interpreter steigt durch die verschachtelten Funktionen nach oben und findet sie anhand des Namens (Fachbegriff dafür: Scope-Chain).

                  This bzw. that in Zusammenhang mit lokalen Funktionen funktioniert nicht, oder?

                  Richtig, denn sie sind keine Eigenschaften der Instanz.

                  Deswegen sind es keine »richtigen« privaten Eigenschaften – so etwas gibt es in JavaScript nicht. Man nutzt stattdessen verschachtelte Funktionen und deren Variablen-Gültigkeitsbereiche, um Kapselung und »Privatheit« herzustellen.

                  Man kann, vor allem bei Methoden, natürlich beides kombinieren: Die Funktion erst lokal notieren und sie dann *zusätzlich* an die Instanz hängen.
                  Das hat den Vorteil, dass man sie innerhalb einfach bei ihrem Namen nennen kann und nicht this.methode oder that.methode schreiben braucht:

                  function Konstruktor () {  
                    function funktion () {  
                      alert('hallo');  
                    }  
                    function andereFunktion () {  
                      funktion();  
                    }  
                    this.methode1 = funktion;  
                    this.methode2 = andereFunktion;  
                  }  
                  var instanz = new Konstruktor();  
                  instanz.methode1();  
                  instanz.methode12();
                  

                  Mathias

              2. @@molily:

                nuqneH

                Das Komma ist ein Operator und dient nur in var-Statements oder Objekt-Literalen dazu, einzelne Einträge zu trennen.

                Ergänzung: Auch in for-Schleifen kann der ','-Operator sinnvoll eingesetzt werden:

                for (var i = 0, node =; i < 42 && node.nextSibling; i++, node = node.nextSibling)

                Qapla'

                --
                Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
                (Mark Twain)
                1. Das Komma ist ein Operator und dient nur in var-Statements oder Objekt-Literalen dazu, einzelne Einträge zu trennen.

                  Ergänzung: Auch in for-Schleifen kann der ','-Operator sinnvoll eingesetzt werden:

                  Ja. Das »nur« bezog sich auf das Trennen von Einträgen im Sinne von: In diesen Fällen ist es kein Operator. Wobei diese Aufzählung nicht vollständig war, das »nur« also falsch, z.B. hatte ich Array-Literale und Parameterlisten nicht genannt.

                  Der Komma-Operator als solcher hat tatsächlich viele nützliche Anwendungszwecke, siehe auch http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/.

                  Mathias

              3. Hi nochmal,

                habe nun ein wenig weiter gelesen und wollte trotzdem noch einmal nachhören, ob ich es richtig verstanden habe:

                Hier noch mal ein Beispiel, bei dem sätmliche Funktionen »privat« sind (also keine richtigen Methoden am Instanzobjekt sind). Zudem habe ich alles in eine weitere selbstausführende anonyme Funktion verpackt, damit die Variablen Navigation, navigationFirst und navigationSecond nicht global werden.

                http://jsfiddle.net/molily/ENNrH/1/

                Beim Einbinden des .js wird die anonyme Funktion durch die beiden letzten () direkt ausgeführt. In deiner Umsetzung gibt es nun nichts globales mehr, es wird also nichts ans window-Object angehangen. Die Funktionalität für die Navigation ist gewährleistet, hat man jedoch einen Fall, wo man später noch auf NavigationFirst zugreifen möchte, ist diese Umsetzung nicht geeignet, da man keinen Zugriffspunkt mehr hat?

                Ansonsten hat sich die Funktionalität nicht geändert – es zeigt nur, dass man die Kapselung noch weiter treiben kann. Diese Instanz ist schlicht ein leeres Objekt. Man kann natürlich darüber streiten, ob man in solchen Fällen noch einen Konstruktor braucht, den man mit »new« aufruft.

                Hmm... was bedeutet leeres Objekt und weshalb benötigt man nicht zwingend einen new Aufruf?

                Viele Grüße,
                Matthias