Azami: While-Schleife bricht nach erstem durchlauf ab

Hallöchen,

ich habe mich mal wieder ein wenig in Javascript versucht um für unser Firmen Intranetseite eine Art Verfallsdatum für links zu generieren.
Dafür habe ich mir aus einigen Codeschnippseln und ein wenig eigenem Wissen (Betonung liegt auf wenig) dieses "Ding" hier zusammen gebastelt

<html>  
<body>  
<br />  
   <div align="center" text-align="center">  
      <a href="Link1" target="_blank" date="27.01.2012">Link1</a><hr />  
      <a href="Link2" target="_blank">Link2</a><hr />  
      <a href="Link3" target="_blank" date="26.01.2012">Link3</a><hr />  
      <a href="Link4" target="_blank">Link4</a><hr />  
      <a href="Link5" target="_blank" date="01.01.2012">Link5</a><hr />  
   </div>  
<script type="text/Javascript">  
besuch = new Date();  
i = 0  
datum = ""  
  
while (i <= document.links.length) {  
   datum = document.links[i].date;  
   datum = datum.toString();  
   datum = datum.split(".");  
   datum[0] = parseInt(datum[0],10);  
   datum[1] = parseInt(datum[1],10)-1;  
   if (datum[2].length == 2) datum[2] = "20" + datum[2];  
   var kontrolldatum = new Date(datum[2],datum[1],datum[0]);  
   restzeit = Math.round((new Date(kontrolldatum.getTime() + 7 * 24 * 60 * 60 * 1000) - besuch) / 1000 / 60 / 60 / 24);  
   if(restzeit >0) {  
      document.links[i].style.fontWeight = "bold";  
   }  
   i++;  
   alert(i);  
   alert(document.links.length);  
}  
</script>  
</body>  
</html>

Der ganze HTML Teil ist nicht wirklich w3c-konform aber da es sich hier rein um eine interne Seite handelt ist das ja mehr oder weniger egal.

Die Alert sind nur drin um zu prüfen nach welchem Durchlauf die Schleife abbricht.

Wäre schön wenn sich das mal jemand anschauen könnte.
Grüße
Merlin

  1. Moin Moin!

    Firefox Error Console sagt: datum is undefined file:///F:/murks.html Line 18

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
    1. Moin Moin!

      Firefox Error Console sagt: datum is undefined file:///F:/murks.html Line 18

      Alexander

      Nabend,

      der IE sagt mir hier nichts anderes, aber warum?

      1. Hallo,

        Nabend,

        der IE sagt mir hier nichts anderes, aber warum?

        Woher weiß die while-SChleife denn, was document.links ist?

        LG
        PAtty

        1. Hi,

          Woher weiß die while-SChleife denn, was document.links ist?

          ich stehe wohl auf dem Schlauch, denn ich verstehe deine Frage nicht. http://de.selfhtml.org/javascript/objekte/links.htm@title=document.links sollte dem Browser bekannt sein.

          Bis die Tage,
          Matti

      2. Firefox Error Console sagt: datum is undefined file:///F:/murks.html Line 18
        der IE sagt mir hier nichts anderes, aber warum?

        evtl. weil jeder 2te Link kein entsprechendes Attribut date hat?

        1. Moin Moin!

          Firefox Error Console sagt: datum is undefined file:///F:/murks.html Line 18
          der IE sagt mir hier nichts anderes, aber warum?

          evtl. weil jeder 2te Link kein entsprechendes Attribut date hat?

          Exakt!

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          1. Interessant, wenn alle ein Date haben läuft die Schleife wunderbar durch, aber wieso?
            Ansich ist die Bedingung für die While-Schleife ja nicht erfüllt wenn er auf den ersten "a" ohne ein date trifft.
            Oder nimmt es Javascript mit dem Errorhandling so genau?...

            Naja egal, es funktioniert ja jetzt aber wie kann ich es umgehen, dass ich in jedem Link ein date einfügen muss? Ich will ja nicht alle Links mit einem Date versehen. Würde da ein reines if (date="") reichen? Dürfte ja eigentlich nicht da er das Date nicht findet und dann wieder mit einem Error abbricht.

            Grüße und danke
            Merlin

            1. Moin Moin!

              Interessant, wenn alle ein Date haben läuft die Schleife wunderbar durch, aber wieso?

              Ansich ist die Bedingung für die While-Schleife ja nicht erfüllt wenn er auf den ersten "a" ohne ein date trifft.

              Nö, wieso? Die Laufbedingung für die while-Schleife ist i<=document.links.length, wobei i für jeden Link hochgezählt wird. (Ganz nebenbei: Du willst i nur bis document.links.length-1 laufen lassen.) Von irgendeiner Prüfung, ob das Link-Element irgendwelche Attribute hat, steht da nichts.

              Der zweite Link hat kein "date"- bzw. "data-date"-Attribut, das führt dazu, dass die Variable datum nach der Zuweisung datum=document.links[i].date bzw. datum=document.links[i].getAttribute("data-date") undefiniert ist. Und auf undefinierten Werten kann man nicht toString() aufrufen.

              Oder nimmt es Javascript mit dem Errorhandling so genau?...

              Javascript arbeitet wie alle anderen Sprachen, mit denen Du einen Computer programmierst. Sie tun das, was Du geschrieben hast, nicht das, was Du meinst. Auch wenn Javascript in der Regel interpretiert wird, heißt das nicht, dass der Computer rät, was Du willst.

              Naja egal, es funktioniert ja jetzt aber wie kann ich es umgehen, dass ich in jedem Link ein date einfügen muss? Ich will ja nicht alle Links mit einem Date versehen. Würde da ein reines if (date="") reichen? Dürfte ja eigentlich nicht da er das Date nicht findet und dann wieder mit einem Error abbricht.

              So in der Art. Dir fehlt so etwas wie if (!datum) continue;, was bei fehlendem Datumswert weiterspringt, bzw. if (datum) { arbeite mit datum }. Weil Du die übliche for-Schleife unbedingt durch while ersetzen mußtest, wird der einfachere Weg mit continue nicht funktionieren, weil i dann nicht erhöht wird. Und Du willst i nicht an zwei verschiedenen Stellen erhöhen.

              Versuch's mal mit for und continue, das halte ich für die sauberste Variante:

                
              for (i=0; i<document.links.length; i++) {  
                  datum=document.links[i].getAttribute("data-date");  
                  if (!datum) continue;  
                  /* restliches Gebastel mit datum, toString, split, parseInt, style usw. */  
                  /* i++ findet hier NICHT statt, dass macht for ganz oben! */  
              }  
              
              

              Alexander

              --
              Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
              1. Ansich ist die Bedingung für die While-Schleife ja nicht erfüllt wenn er auf den ersten "a" ohne ein date trifft.

                Nö, wieso? Die Laufbedingung für die while-Schleife ist i<=document.links.length, wobei i für jeden Link hochgezählt wird. (Ganz nebenbei: Du willst i nur bis document.links.length-1 laufen lassen.) Von irgendeiner Prüfung, ob das Link-Element irgendwelche Attribute hat, steht da nichts.

                Moin,

                was anderes habe ich ja auch nicht gesagt, dadurch das da ein Error kommt ist die Bedingung ja immer noch nicht erfüllt. Deshalb ja auch "While-Schleife ja NICHT erfüllt".

                Aber Wurst, jetzt funktioniert alles so wie ich es möchte und absolut zu meiner zufriedenheit. Jetzt nur noch ein überprüfung einbauen wie lange die Links gültig und das manche Links auch immer gültig sind und alles ist Perfekt.

                Bin ich wieder ein wenig schlauer geworden!

                Danke und bis zum nächsten mal
                Merlin

  2. Hi,

    <html>

    Ergänze hier bitte noch einen Dokument-Typ (DOCTYPE).

    <br />

    Dieses br-Element scheint mir sinnlos. Um einen Abstand vom oberen Rand zu bekommen, weise per CSS dem body-Element einen Innenabstand (oben) zu.

    <div align="center" text-align="center">

    Dieses div scheint eine Liste zu beinhalten. Lass es doch eine Liste (ul oder ol) sein.

    <a href="Link1" target="_blank" date="27.01.2012">Link1</a><hr />
          <a href="Link2" target="_blank">Link2</a><hr />
          <a href="Link3" target="_blank" date="26.01.2012">Link3</a><hr />
          <a href="Link4" target="_blank">Link4</a><hr />
          <a href="Link5" target="_blank" date="01.01.2012">Link5</a><hr />

    Die hr-Elemente kannst du entsorgen, und dem a-Elementen (oder den Listen-Elementen, s.o.) einen unteren Rahmen zuweisen. Außerdem gibt es IMHO kein @date-Attribut bei a-Elementen. HTML5-Konform schreibt sich das @data-date.

    besuch = new Date();
    i = 0
    datum = ""

    Hier fehlen zwei Semikolons. Es gibt irgendwelche Regeln, nach denen man Semikolons weglassen darf, und vielleicht hast du Glück und hast eine erwischt (obwohl Alexanders Beitrag so aussieht, als sei dies nicht der Fall). Aber ich merke mir diese Regeln nicht, sondern schreibe die Semikolons immer. Das würde ich dir auch empfehlen. Auch solltest du dir angewöhnen, deine Variablen "privat" zu machen, d.h. ein "var" davorschreiben. Die Variable datum benötigst du nur innerhalb der Schleife, die kannst du hier also weglassen.

    while (i <= document.links.length) {
       datum = document.links[i].date;

    Falls du meinen Ratschlag bzgl. "data-date" beherzigt, heißt dies hier dann document.links[i].getAttribute('data-date'), auch hier ein var vor die Variable.

    Deine Logik habe ich nicht auf Korrektheit geprüft.

    if(restzeit >0) {
          document.links[i].style.fontWeight = "bold";
       }

    Hier empfehle ich dir, dem Element document.links[i] eine Klasse zuzuweisen, welche die gewünschte Formatierung trägt.

    Ich teste gerade selbst ein wenig herum. Mein Favorit ist es, eine CSS-Regel dynamisch einzuführen, welche das Attribut data-date mit dem entsprechenden Wert (dem heutigen Datum) tragen. Alternativ einfach allen Elementen mit dem passenden Attribut-Wert die entsprechende Klasse zuzuweisen. Das ist mit jQuery ein Einzeiler.
    Bis die Tage,
    Matti

    1. Hi,

      <html>
      Ergänze hier bitte noch einen Dokument-Typ (DOCTYPE).

      <br />
      Dieses br-Element scheint mir sinnlos. Um einen Abstand vom oberen Rand zu bekommen, weise per CSS dem body-Element einen Innenabstand (oben) zu.

      <div align="center" text-align="center">
      Dieses div scheint eine Liste zu beinhalten. Lass es doch eine Liste (ul oder ol) sein.

      <a href="Link1" target="_blank" date="27.01.2012">Link1</a><hr />
            <a href="Link2" target="_blank">Link2</a><hr />
            <a href="Link3" target="_blank" date="26.01.2012">Link3</a><hr />
            <a href="Link4" target="_blank">Link4</a><hr />
            <a href="Link5" target="_blank" date="01.01.2012">Link5</a><hr />

      Die hr-Elemente kannst du entsorgen, und dem a-Elementen (oder den Listen-Elementen, s.o.) einen unteren Rahmen zuweisen. Außerdem gibt es IMHO kein @date-Attribut bei a-Elementen. HTML5-Konform schreibt sich das @data-date.

      besuch = new Date();
      i = 0
      datum = ""
      Hier fehlen zwei Semikolons. Es gibt irgendwelche Regeln, nach denen man Semikolons weglassen darf, und vielleicht hast du Glück und hast eine erwischt (obwohl Alexanders Beitrag so aussieht, als sei dies nicht der Fall). Aber ich merke mir diese Regeln nicht, sondern schreibe die Semikolons immer. Das würde ich dir auch empfehlen. Auch solltest du dir angewöhnen, deine Variablen "privat" zu machen, d.h. ein "var" davorschreiben. Die Variable datum benötigst du nur innerhalb der Schleife, die kannst du hier also weglassen.

      while (i <= document.links.length) {
         datum = document.links[i].date;
      Falls du meinen Ratschlag bzgl. "data-date" beherzigt, heißt dies hier dann document.links[i].getAttribute('data-date'), auch hier ein var vor die Variable.

      Deine Logik habe ich nicht auf Korrektheit geprüft.

      if(restzeit >0) {
            document.links[i].style.fontWeight = "bold";
         }
      Hier empfehle ich dir, dem Element document.links[i] eine Klasse zuzuweisen, welche die gewünschte Formatierung trägt.

      Ich teste gerade selbst ein wenig herum. Mein Favorit ist es, eine CSS-Regel dynamisch einzuführen, welche das Attribut data-date mit dem entsprechenden Wert (dem heutigen Datum) tragen. Alternativ einfach allen Elementen mit dem passenden Attribut-Wert die entsprechende Klasse zuzuweisen. Das ist mit jQuery ein Einzeiler.
      Bis die Tage,
      Matti

      Danke für deine ausführlichen Ratschläge.

      Die Formatierungen etc. mit HR, dem BR und den A als Liste habe ich nur gemacht, da ich erstmal nur in einer reinen "Testumgebung" bastel, also komplett ohne CSS etc. In der richtigen Page hab ich das natürlich vernünftiger gemacht ;)

      Ich habe mal die date durch deine @data-date ersetzt und auch die abfrage soweit geändert und natürlich auch die Semikolon hinzugefügt *facepalm*

      Leider läuft die schleife jetzt erst garnicht mehr an und IE spuckt mir wie immer diesen Fehler aus:
      [code language=html]
      Details zum Fehler auf der Webseite

      Benutzer-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
      Zeitstempel: Mon, 30 Jan 2012 12:20:05 UTC

      Meldung: 'datum' ist Null oder kein Objekt
      Zeile: 18
      Zeichen: 2
      Code: 0
      URI: file:///C:/***/test.htm
      [/code]

      jQuery, Mootools etc kommt hier leider nicht in frage...Sicherheitsbestimmungen -.-

      Grüße
      Merlin

    2. @@Matti Mäkitalo:

      nuqneH

      Hier fehlen zwei Semikolons. Es gibt irgendwelche Regeln, nach denen man Semikolons weglassen darf, und vielleicht hast du Glück und hast eine erwischt

      Ja, hat er. Mit Glück hat das aber wenig zu tun.

      Falls du meinen Ratschlag bzgl. "data-date" beherzigt, heißt dies hier dann document.links[i].getAttribute('data-date')

      Nicht wirklich. Eigentlich heißt es dann document.links[i].dataset.date, das verstehen nur einige alte Browser noch nicht.

      Qapla'

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

        Hier fehlen zwei Semikolons. Es gibt irgendwelche Regeln, nach denen man Semikolons weglassen darf, und vielleicht hast du Glück und hast eine erwischt

        Ja, hat er. Mit Glück hat das aber wenig zu tun.

        Ich habe beim Schreiben damit gerechnet, dass so ein Kommentar kommt. Ich wollte damit ausdrücken: ich weiß, dass Regeln zum Weglassen der Semikolons existieren, ich kenne sie aber nicht und ich will sie auch nicht kennen, da ich dieses Feature für gefährlich halte. Das gebräuchliche Beispiel:

          
        function bla() {  
          return  
            {  
              id : 1,  
              val : 2  
            };  
        }  
        
        

        Die Funktion bla() liefert bekanntlicherweise nicht mein Objekt.

        Für mich (ohne Kenntnis der Weglass-Regeln) ist es daher Glück, ob das Weglassen eines Semikolons gerade erlaubt ist oder nicht. Natürlich könnte ich nachschlagen, aber dass will ich aus guten Gründen gerade nicht tun.

        Falls du meinen Ratschlag bzgl. "data-date" beherzigt, heißt dies hier dann document.links[i].getAttribute('data-date')

        Nicht wirklich. Eigentlich heißt es dann document.links[i].dataset.date, das verstehen nur einige alte Browser noch nicht.

        Sind das "äquivalente" Schreibweisen (d.h.: liefern sie bei Implementierung von dataset immer das gleiche Ergebnis) oder gibt es da einen Unterschied, den ich nicht sehe? Das das mit dataset die HTML5-Schreibweise ist, ist mir soweit klar, nur warum sollte deswegen die getAttribute-Variante nicht funktionieren (und dies implizierst du mit "Nicht wirklich.").

        Bis die Tage,
        Matti

        1. @@Matti Mäkitalo:

          nuqneH

          Nicht wirklich. Eigentlich heißt es dann document.links[i].dataset.date, das verstehen nur einige alte Browser noch nicht.

          Sind das "äquivalente" Schreibweisen (d.h.: liefern sie bei Implementierung von dataset immer das gleiche Ergebnis) oder gibt es da einen Unterschied, den ich nicht sehe?

          Vielleicht ist der Zugriff über das dataset-Objekt performanter? Und man kann die Eigenschaften lesen und schreiben ohne zwei getrennte Methoden getAttribute() und setAttribute() zu benötigen.

          Das das mit dataset die HTML5-Schreibweise ist, ist mir soweit klar, nur warum sollte deswegen die getAttribute-Variante nicht funktionieren (und dies implizierst du mit "Nicht wirklich.").

          So war’s nicht gemeint. Sondern dass das dataset-Objekt dafür gedacht ist. Und wenn man der WHATWG unterstellt, sich wirklich was dabei gedacht zu haben, dann sollte man das vielleicht auch verwenden. Wenn’s denn auch in älteren Browsern funktionieren muss, mit

          var link = document.links[i], datum = link.dataset ? link.dataset.date : link.getAttribute('data-date');

          Qapla'

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

            nuqneH

            var link = document.links[i], datum = link.dataset ? link.dataset.date : link.getAttribute('data-date');

            Hm, besonders performant ist das auch nicht gerade. Und unnötig, in der Schleife bei jedem Link zu prüfen, ob ein dataset-Objekt vorhanden ist. Das sollte einmal genügen

            var hasDataset = !!document.documentElement.dataset;

            In der Schleife dann

            var datum = hasDataset ? document.links[i].dataset.date : document.links[i].getAttribute('data-date');

            Qapla'

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