Leonard: Funktions-Schleife "hängt" nach erster Funktion

Hallöle,

Ich wollte mal was neues ausprobieren, in dem ich einen Link schaffe, der die Hintergrundfarbe auf schwarz und die Textfarbe auf weis ändert UND auch wieder zurück (!).
Nur aus irgendeinem mir nicht ersichtlichen Grund klappt es zwar, das er beim ersten Klick alles schön ändert, doch dann verlässt ihn wohl der Mut, denn beim zweiten Klick macht er gar nichts mehr.

Woran könnte das liegen?

<a href="javascript:daynight();">Tag-/Nacht-Modus</a>

function daynight () {          var style=document.body.style.background;          if (style=='#000000'){              style='#ffffff'          }else{              style='#000000'          }          document.body.style.background=style;          var style=document.body.style.color;          if (style=='#ffffff'){              style='#000000'          }else{              style='#ffffff'          }          document.body.style.color=style; }
  1. Hi,

    Ich wollte mal was neues ausprobieren, in dem ich einen Link schaffe, der die Hintergrundfarbe auf schwarz und die Textfarbe auf weis ändert UND auch wieder zurück (!).

    der Sinn dieser Aufgabe sei dahingestellt, aber zum Üben nicht schlecht.

    Nur aus irgendeinem mir nicht ersichtlichen Grund klappt es zwar, das er beim ersten Klick alles schön ändert, doch dann verlässt ihn wohl der Mut, denn beim zweiten Klick macht er gar nichts mehr.

    Doch, und zwar genau dasselbe wie beim ersten Klick. Weil die Bedingungen noch die gleichen sind.

    Woran könnte das liegen?

    An mangelndem Debugging. Deine Variablen enthalten nicht die Werte, die du erwartest. Einer der Kernaspekte beim Debugging ist: Wenn nicht das passiert, was du erwartest, gehe schrittweise vor. Verfolge den Ablauf z.B. anhand von Kontrollausgaben, in Javascript etwa mit console.log() oder notfalls mit alert().

    function daynight () {          var style=document.body.style.background;          if (style=='#000000'){              style='#ffffff'          }else{              style='#000000'          }

    Stop. Was passiert bis hierher?
    Welche Anweisung (welcher Zweig) wird ausgeführt, welche nicht?
    Um das logisch nachzuvollziehen, solltest du nachprüfen, was in deiner Variablen style steht. Du wirst staunen. Die CSS-Eigenschaft background ist eine Sammeleigenschaft, die in *einem* String *alle* Informationen zum Hintergrund des betrachteten Elements enthält - außer der Farbe also z.B. auch Hintergrundbild(er) und deren Ausrichtung. Der Vergleich mit '#000000' wird also niemals zutreffen!

    Na dann, den nächsten Schritt schaffst du wieder alleine.

    So long,
     Martin

    --
    Ordnung schaffen heißt, das Eigelb vom Dotter zu trennen.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(

    1. Okay, ich merk das ich nichtmehr so hinterherkomme...

      An mangelndem Debugging.
      [...] Verfolge den Ablauf z.B. anhand von Kontrollausgaben, in Javascript etwa mit console.log() oder notfalls mit alert().

      an bitte was???

      Stop. Was passiert bis hierher?

      Es ist doch so:
      if (style=='so wird es sein'){
         style='so ist es'
         }else{
         style='ansonsten so'
         }

      Welche Anweisung (welcher Zweig) wird ausgeführt, welche nicht?
      Um das logisch nachzuvollziehen, solltest du nachprüfen, was in deiner Variablen style steht. Du wirst staunen.

      Habe ich gemacht, bin aber nicht zum staunen gekommen:
      body {
      color: #000000;
      background: #ffffff;
      }

      Die CSS-Eigenschaft background ist eine Sammeleigenschaft, die in *einem* String *alle* Informationen zum Hintergrund des betrachteten Elements enthält - außer der Farbe also z.B. auch Hintergrundbild(er) und deren Ausrichtung. Der Vergleich mit '#000000' wird also niemals zutreffen!

      Okay und warum nicht? Bzw. warum funktioniert es dann im "ersten"-Teil der Funktion?

      Na dann, den nächsten Schritt schaffst du wieder alleine.

      Dat wär schön. Ich geb mir sämtliche mühe mein altes Hirn anzutreiben, aber ich komm nicht hinterher.

      Kannst du vielleicht einfacher erklären was du meinst?

      1. Hallo,

        Stop. Was passiert bis hierher?

        Es ist doch so:
        if (style=='so wird es sein'){
           style='so ist es'
           }else{
           style='ansonsten so'
           }

        Philosophieren bringt uns hier nicht weiter. Ich habe ganz bewusst empfohlen, dass du den Inhalt von 'style' überprüfen solltest. Nicht *mutmaßen*, sondern *nachprüfen*.

        Welche Anweisung (welcher Zweig) wird ausgeführt, welche nicht?
        Um das logisch nachzuvollziehen, solltest du nachprüfen, was in deiner Variablen style steht. Du wirst staunen.

        Habe ich gemacht, ...

        Hast du nicht.

        ... bin aber nicht zum staunen gekommen:
        body {
        color: #000000;
        background: #ffffff;
        }

        Das ist anscheinend ein Auszug aus deinem Stylesheet. Aber nicht der Inhalt von document.body.style.background. Abgesehen davon, dass du im Stylesheet auch schon die Sammeleigenschaft background verwendest, obwohl du eigentlich nur background-color meinst.

        Die CSS-Eigenschaft background ist eine Sammeleigenschaft, die in *einem* String *alle* Informationen zum Hintergrund des betrachteten Elements enthält - außer der Farbe also z.B. auch Hintergrundbild(er) und deren Ausrichtung. Der Vergleich mit '#000000' wird also niemals zutreffen!

        Okay und warum nicht? Bzw. warum funktioniert es dann im "ersten"-Teil der Funktion?

        Es funktioniert einmal, weil style eben *nicht* gleich '#000000' ist, also wird der else-Zweig ausgeführt. Das ist aber beim nächsten Mal immer noch so.

        So long,
         Martin

        --
        Niemand ist überflüssig: Er kann immer noch als schlechtes Beispiel dienen.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(

        1. Philosophieren bringt uns hier nicht weiter. Ich habe ganz bewusst empfohlen, dass du den Inhalt von 'style' überprüfen solltest. Nicht *mutmaßen*, sondern *nachprüfen*.

          Ich wollte hier auch nicht philosophieren, es war meine Annahme da ich es nie gelernt habe. Und ich es jetzt ausprobiere um es zu lernen.

          Abgesehen davon, dass du im Stylesheet auch schon die Sammeleigenschaft background verwendest, obwohl du eigentlich nur background-color meinst.
          Die CSS-Eigenschaft background ist eine Sammeleigenschaft, die in *einem* String *alle* Informationen zum Hintergrund des betrachteten Elements enthält - außer der Farbe also z.B. auch Hintergrundbild(er) und deren Ausrichtung.

          Ja meinte ich. Habe es jetzt in *background-color* (im Stylesheet) bzw. *backgroundColor* im JavaScript) geändert.

          Der Vergleich mit '#000000' wird also niemals zutreffen!

          Okay und warum nicht? Bzw. warum funktioniert es dann im "ersten"-Teil der Funktion?

          Es funktioniert einmal, weil style eben *nicht* gleich '#000000' ist, also wird der else-Zweig ausgeführt. Das ist aber beim nächsten Mal immer noch so.

          Wie bereits gesagt ich weis (bzw. wusste bis du es mir gesagt hast) nicht das style nicht gleich #000000 ist. Doch wenn das nicht zutrifft was ist dann der style-Wert oder brauch ich einen anderen?

          Wäre es vielleicht eine angenehmere lösung mit dem zweiten klick eine art reset auszulösen?

          1. Lieber Leonard,

            was um Himmelswillen hat Dich daran gehindert mit alert(style) zu prüfen, was in style tatsächlich abgespeichert ist??

            Liebe Grüße,

            Felix Riesterer.

            -- ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
            1. was um Himmelswillen hat Dich daran gehindert mit alert(style) zu prüfen, was in style tatsächlich abgespeichert ist??

              das wissen wie das funktioniert, aber danke jetzt hab ich es hingekriegt.

              Ist schon interessant wie hier mit Leuten umgegangen wird die auf Grund mangelnder Kenntnis etwas nicht verstehen. Und das in einem HilfsForum....

              1. Lieber Leonard,

                was um Himmelswillen hat Dich daran gehindert mit alert(style) zu prüfen, was in style tatsächlich abgespeichert ist??

                das wissen wie das funktioniert,

                ??? Muss ich das jetzt verstehen?

                aber danke jetzt hab ich es hingekriegt.

                Na prima!

                Ist schon interessant wie hier mit Leuten umgegangen wird die auf Grund mangelnder Kenntnis etwas nicht verstehen. Und das in einem HilfsForum....

                Naja, manchmal ist es schon erstaunlich wie sich manche Leute anstellen, wenn man sie mit der Nase auf Dinge stößt. Und das immer wieder in einem HilfsForum...

                Liebe Grüße,

                Felix Riesterer.

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

                  Naja, manchmal ist es schon erstaunlich wie sich manche Leute anstellen, wenn man sie mit der Nase auf Dinge stößt. Und das immer wieder in einem HilfsForum...

                  Und in diesem Hilfeforum merken manchmal fragende nichtmal mit ner blutigen Nase, wenn sie direkt drauf gestossen wurden. Schmerzresistent würde ich da sagen.

                  --
                  42

                2. Lieber Felix

                  Naja, manchmal ist es schon erstaunlich wie sich manche Leute anstellen, wenn man sie mit der Nase auf Dinge stößt. Und das immer wieder in einem HilfsForum...

                  Der Lehrer erklärt, der Schüler versteht nicht.
                  Der Lehrer erklärt erneut, der Schüler versteht wieder nicht.
                  Der Lehrer erklärt nochmals …
                  … und versteht plötzlich selbst.

                  Mit besten Grüssen Richard

  2. Hallo,

    du musst zwei Sachen unterscheiden:

    1. Inline-Styles
    2. Computed Styles (berechnete Formatierung) und Computed Values (berechnete Werte)

    Inline-Style lassen sich über das style-Attribut oder über die style-Eigenschaft in JavaScript setzen.

    Wenn du keine Inline-Styles gesetzt hast, sind die Eigenschaften unterhalb von style erst einmal leer! (Leere Strings, also "".)

    alert(document.body.style.color) ergibt einen leeren String, wenn du nicht <body style="color: …"> notiert oder vorher document.body.style.color = '…' gesetzt hast.

    Siehe Direktformatierung über das style-Objekt.

    Inline-Styles stehen in der Hierarchie der Stylesheets ganz unten. Darüber stehen die Regeln des Autorenstylesheets. Siehe auch:

    http://wiki.selfhtml.org/wiki/CSS/Kaskade
    http://www.mediaevent.de/css/css-kaskade.html

    Nun zu den Computed Styles. Das sind die tatsächlich verwendeten CSS-Formatierungen. Der Computed Value ist entsprechend der tatsächlich verwendete Wert einer CSS-Eigenschaft. Wie sich der ergibt, regelt die Kaskade. Wenn du z.B. diese CSS-Regel hast …

    body { color: red; }

    … und sonst keine Angaben diese Regel überschreiben, so ist der berechnete Wert der color-Eigenschaft logischerweise "red".

    Den berechneten Wert kannst du nicht mit document.body.style.color auslesen! Denn das spiegelt nur die gesetzten Inline-Styles wider. Den berechneten Wert kannst du mit getComputedStyle(document.body).color auslesen. Siehe CSS-Eigenschaften auslesen.

    Jetzt musst du noch beachten, dass der berechnete Wert nicht unbedingt in dem Format vorliegt, in dem die CSS-Eigenschaft gesetzt wurde. Das liegt daran, dass es in CSS z.B. dutzende Möglichkeiten gibt, eine Farbe zu setzen. Anstatt »black«, »#000«, »#000000« kann der Browser »rgb(0, 0, 0)« zurückgeben. Daher ist es schwierig, die Bedingung »Ist der Hintergrund gerade schwarz?« zu formulieren.

    Was dein Script angeht, so kannst du durchaus mit document.body.style.color bzw. backgroundColor arbeiten. Allerdings prüfe nicht auf einen bestimmten Wert, sondern nur, ob die Eigenschaft gesetzt wurde. Wenn sie gesetzt wurde, weißt du, dass dein Script schon einmal gelaufen ist. Jetzt musst du natürlich noch wissen, was die Ausgangssituation ist (Tag oder Nacht). Sagen wir einmal, Tag ist die Ausgangssituation. Dann reicht der Test:

    var backgroundColor = document.body.style.backgroundColor; if (backgroundColor) {   // Farbe schon gesetzt, also ist Nacht. Es werde Licht!   // Und zwar, indem wir den Inline-Style entfernen. Dadurch greifen wieder die Regeln aus dem Stylesheet.   // Gut, wir könnten hier auch einfach   backgroundColor = ''; } else {   // Inline-Style nicht gesetzt bzw. leer. Es muss Tag sein. Verdunkle die Sonne!   backgroundColor = '#000000'; } document.body.style.background = backgroundColor;

    (ungetestet)

    Soweit klar geworden?

    Eine andere Möglichkeit wäre natürlich, den Tag-/Nacht-Status in einer eigenen Boolean-Variable zu speichern – damit sparst du dir die fehleranfälligen Prüfungen.

    Grüße
    Mathias

    -- Chaplin - JavaScript Application Architecture Using Backbone.js
    1. Hi,

      Jetzt musst du noch beachten, dass der berechnete Wert nicht unbedingt in dem Format vorliegt, in dem die CSS-Eigenschaft gesetzt wurde. Das liegt daran, dass es in CSS z.B. dutzende Möglichkeiten gibt, eine Farbe zu setzen. Anstatt »black«, »#000«, »#000000« kann der Browser »rgb(0, 0, 0)« zurückgeben. Daher ist es schwierig, die Bedingung »Ist der Hintergrund gerade schwarz?« zu formulieren.

      Wenn man aber wirklich mal den Fall hat, dass man den Farbwert vergleichen muss, kann man dazu ein Test-Element nutzen, dem man die Farbe setzt und dann den computed value ausliest (davon, dass ein Browser Farbwerte immer im gleichen Format liefert, kann man nach meinen Tests ausgehen).

      Dieses Testelement kann per visibility:hidden bzw. absoluter Positionierung oberhalb der linken oberen Ecke versteckt werden – display:none geht natürlich nicht, denn dann gibt’s idR. keine Style-Informationen auszulesen. Und erst per JS erzeugt werden kann das Element natürlich auch.

      MfG ChrisB

      --
      RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?

    2. @@molily:

      nuqneH

      Inline-Style lassen sich über das style-Attribut oder über die style-Eigenschaft in JavaScript setzen.

      An der Stelle fehlt der gerade für Anfänger wichtige Hinweis, das man weder das eine noch das andere tun sollte.

      Inline-Styles stehen in der Hierarchie der Stylesheets ganz unten.

      Höchste Priorität ist nicht das, was ich „ganz unten“ nennen würde.

      Qapla'

      -- „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
      1. Inline-Style lassen sich über das style-Attribut oder über die style-Eigenschaft in JavaScript setzen.

        An der Stelle fehlt der gerade für Anfänger wichtige Hinweis, das man weder das eine noch das andere tun sollte.

        Ein solcher Hinweis fehlt, weil ich nicht dieser pauschalen Meinung bin.

        Mathias

        -- Chaplin - JavaScript Application Architecture Using Backbone.js
        1. @@molily:

          nuqneH

          An der Stelle fehlt der gerade für Anfänger wichtige Hinweis, das man weder das eine noch das andere tun sollte.

          Ein solcher Hinweis fehlt, weil ich nicht dieser pauschalen Meinung bin.

          Schade.

          Natürlich gibt es Fälle, wo man um das Setzen von style-Eigenschaften per JavaScript nicht drumrum kommt. Beispiele sind die Übernahme einer Farbe aus einem Farbwähler oder eine JavaScript-Animation (sofern für solche ein Grund besteht, das nicht mit CSS zu realisieren).

          Ein solcher Fall liegt hier nicht vor.

          Qapla'

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

            Ich halte es ebenfalls für sinnvoller, hier mit Klassen zu arbeiten. Ich habe mich in meinem Posting um Inline-Styles gekümmert, damit dem OP erst einmal der beobachtete Effekt und damit der konkrete Fehler im Programm erklärt wird. Der Tenor der vorherigen Postings war, dass der OP bloß ein bisschen debuggen müsse. Das alleine hätte nicht erklärt, warum das Programm nicht wie gewünscht funktioniert. Dein Posting halte ich für eine gute Ergänzung.

            Mathias

            -- Chaplin - JavaScript Application Architecture Using Backbone.js
  3. @@Leonard:

    nuqneH

    Ich wollte mal was neues ausprobieren, in dem ich einen Link schaffe, der die Hintergrundfarbe auf schwarz und die Textfarbe auf weis ändert UND auch wieder zurück (!).

    Das solltest du nicht (direkt) mit JavaScript tun. Layout-Informationen gehören nicht in den JavaScript-Code.

    Was, wenn du dich entschließt, etwas weniger Kontrast vorzusehen, also nicht Schwarz und Weiß, sondern Dunkelgrau und Hellgrau zu verwenden? Dann müsstest du bei einer Layoutänderung dein JavaScript ändern. Das sollte man unbedingt vermeiden! Stattdessen Dokumentstruktur (HTML), Präsentation (CSS) und Verhalten (JavaScript) sauber voneinander trennen.

    Das einzige, was dein JavaScript tun sollte, ist, im DOM (Dokumentstruktur nach dem Parsen des HTML) die Information zu hinterlassen, ob der Tag- oder der Nachtmodus gerade aktiv ist.

    <a href="javascript:daynight();">Tag-/Nacht-Modus</a>

    Das sollte kein Link sein (da zu einer anderen Ressource gegangen wird), sondern ein Button. Dieser bekommt einen Eventhandler, der die Funktion aufruft. Quick and dirty („herkömmlich“) per Eventhandler-Attribut:

    <button onclick="daynight();">Tag-/Nacht-Modus</button>

    Wie man’s richtig macht, siehe molilys Einführung in JavaScript.

    Die Funktion daynight() könnte nun dem html-Element eine Klasse "night" verpassen bzw. diese entfernen:

    function daynight() {   if document.documentElement.className === "night"   {     document.documentElement.className = "";   }   else   {     document.documentElement.className = "night";   } }

    was sich kürzer schreiben lässt als

    function daynight() {   document.documentElement.className = document.documentElement.className === "night" ? "" : "night"; }

    *Wie* die beiden Zustände dargestellt werden, steht im Stylesheet:

    body {   background: white;   color: black; } .night body {   background: black;   color: white; }

    Nun lassen sich Änderungen in Dunkelgrau/Hellgrau problemlos vollziehen, ohne dass das JavaScript dazu angefasst werden muss.

    Problematisch daran: Eventuell vorhandene andere Klassen des html-Elements werden überschrieben. Das möchte man nicht. Abhilfe schafft das classList-Objekt:

    function daynight() {   if document.documentElement.classList.contains("night")   {     document.documentElement.classList.remove("night");   }   else   {     document.documentElement.classList.add("night");   } }

    was man ganz einfach haben kann:

    function daynight() {   document.documentElement.classList.toggle("night"); }

    Eine andere Möglichkeit wäre, keine Klasse, sondern ein data-Attribut zu verwenden:

    function daynight() {   document.documentElement.dataset.isNight = document.documentElement.dataset.isNight === "true" ? "" : "true"; }

    (für ältere Browser müsste man das mit getAttribute()/setAttribute() machen) und im Stylesheet

    body {   background: white;   color: black; } [data-isNight="true"] body {   background: black;   color: white; }

    Qapla'

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