Olaf Schneider: Anker als Eindeutige Links missbrauchen

Hallo,

ich möchte meine Fotogallerie um Ajax erweitern. Warum?

Das Switchen von einem Bild zum nächsten sieht einfach nicht so schön aus und ich würde den Browsen, die opacity unterstützen sowie IE mit seinem dusseligen Filterkonzept gerne ein Überblenden spendieren.

Da die vorhandenen Links für die Seitennavigation für Nicht-Javascript-Clients vorhanden bleiben und die Seite damit bedienbar bleibt, sehe ich eigentlich auch keine Probleme ausser …

… den Bookmarks.

Meine Idee war jetzt, zu jedem Ajaxrequest einen nicht vorhandenen Anker anzuspringen.

location.href = '#id=' + siteId;

Jetzt gibt es vier Möglichkeiten des Aufrufs:

www.example.org/ -> gehe zur Startseite
www.example.org/?id=8 -> gehe zur Seite 8
www.example.org/#id=13 -> gehe zur Seite 13
www.example.org/?id=8#id=13 -> gehe zur Seite 13 (Die Startseite war 8, aber 13 die letzte aktuelle Seite)

Letztendlich ist in der URL aber immer noch ein Sprung auf einen (nicht vorhandenen) Anker definiert. Kann dieses Probleme machen oder gibt es bessere Lösungen?

Gruß
Olaf

  1. Hi,

    Meine Idee war jetzt, zu jedem Ajaxrequest einen nicht vorhandenen Anker anzuspringen.

    das Ding in der URL nennt sich "Fragment Identifier", also sinngemäß "Teil-Identifikator". Der Name sagt nichts darüber aus, dass irgend etwas angesprungen werden würde. In der Tat wird der Fragment Identifer außerhalb der HTML-Welt auch für ähnliche Zwecke verwendet, wie Du sie hier vorhast.

    location.href = '#id=' + siteId;

    Ich empfehle Dir aber, als FragId auch tatsächlich einen Identifier zu verwenden, anstatt irgend eine Fremdsyntax zu simulieren (z.B. die von URL-Parametern).

    www.example.org/ -> gehe zur Startseite
    www.example.org/?id=8 -> gehe zur Seite 8
    www.example.org/#id=13 -> gehe zur Seite 13
    www.example.org/?id=8#id=13 -> gehe zur Seite 13 (Die Startseite war 8, aber 13 die letzte aktuelle Seite)

    Hm, das erscheint mir nicht logisch. Definiere die Bedeutung des Parameters und die der FragId eindeutig, z.B. Parameter=>"der Start ist" und FragId=>"aktuell ist".

    Kann dieses Probleme machen oder gibt es bessere Lösungen?

    Das Verhalten der aktuellen Browser beim vermeintlichen Sprung an nicht existente Anker ist bekannt, das Verhalten kommender Browser halte ich für klar. Mir persönlich ist jedoch nicht bekannt, wie die einzelnen Browser mit (als Ankername) ungültigen Werten umgehen - daher meine obige Empfehlung, valide ID-Werte zu verwenden. Damit hast Du dann ein vorhersehbares Verhalten. Wenn Dir dies genügt, hast Du ein umsetzbares Konzept.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo Cheatah,

      Danke für Deine Antwort.

      [code type=javascript]location.href = '#id=' + siteId;[/code]

      Ich empfehle Dir aber, als FragId auch tatsächlich einen Identifier zu verwenden, anstatt irgend eine Fremdsyntax zu simulieren (z.B. die von URL-Parametern).

      Da hast Du natürlich recht, das = fliegt raus.

      www.example.org/ -> gehe zur Startseite
      www.example.org/?id=8 -> gehe zur Seite 8
      www.example.org/#id=13 -> gehe zur Seite 13
      www.example.org/?id=8#id=13 -> gehe zur Seite 13 (Die Startseite war 8, aber 13 die letzte aktuelle Seite)

      Hm, das erscheint mir nicht logisch. Definiere die Bedeutung des Parameters und die der FragId eindeutig, z.B. Parameter=>"der Start ist" und FragId=>"aktuell ist".

      Genau das ist gemeint. Die Idee war folgende:

      Wenn der User Javascript aktiviert hat, wird der XmlHttpRequest abgesetzt und der Fragment Identifier der URL geändert. Die Seiten-ID steht dann im Fragment Identifier.

      Wennd der User kein Javascript hat, werden die normalen Links benutzt und die Seiten-ID steht im geänderten id-Parameter der URL.

      Jetzt kann es sein, dass ein Nicht-js-User einen Link an einen Kumpel schickt, der js aktiv hat, zwei Bilder weiterschaltet und dann wiederum von dieser Seite ein Lesezeichen anlegt. Diese URL hat dann zwei IDs codiert: Einmal die nicht mehr relevante vom Kumpel geschickte und die durch js erzeugte neue.

      Fazit: Die ID im Fragment Identifier gewinnt immer.

      Ein kleiner Nachteil ist dann bei diesem eher seltenen Szenario natürlich, dass die URL zwei IDs enthält, von der eine nutzlos ist. Zu dieser Unschönheit ist mir noch keine Lösung eingefallen.

      Gruß
      Olaf

      1. Hi,

        Ein kleiner Nachteil ist dann bei diesem eher seltenen Szenario natürlich, dass die URL zwei IDs enthält, von der eine nutzlos ist. Zu dieser Unschönheit ist mir noch keine Lösung eingefallen.

        warum? Laut Deiner Definition (bzw. der Bestätigung der meinen ;-)) haben beide Werte eine Bedeutung. Ob die URL "schön" ist sei mal dahin gestellt - sie muss die Ressource eindeutig identifizieren, das ist alles. Dies tut sie gerade mal dann nicht, wenn eine URL mit FragId auf einem System ohne JavaScript aufgerufen wird. Ist dieser Mangel vertretbar?

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hallo Cheatah,

          Ob die URL "schön" ist sei mal dahin gestellt - sie muss die Ressource eindeutig identifizieren, das ist alles. Dies tut sie gerade mal dann nicht, wenn eine URL mit FragId auf einem System ohne JavaScript aufgerufen wird. Ist dieser Mangel vertretbar?

          Die FragId wird serverseitig ausgewertet und bekommt Vorrang gegenüber der per GET übertragenden id. Daher wird auch bei diesem Fall die korrekte Seite ausgeliefert:

          if fragId exists
              id = fragId
          elseif getId exists
              id = getId
          else
              id = 1 // erste Seite
          end

          Gruß
          Olaf

          1. Nachtrag:

            in meinem Konzept steckt ein Denkfehler. Der Fragment Identifier wird nicht per http übertragen und steht somit auch dem Server nicht zur Auswertung zur Verfügung.

            Schade auch. Zurück ans Zeichenbrett …

            Gruß
            Olaf

            1. Hi,

              in meinem Konzept steckt ein Denkfehler. Der Fragment Identifier wird nicht per http übertragen

              richtig :-)

              Schade auch. Zurück ans Zeichenbrett …

              Es ist natürlich Deine Entscheidung, aber wie groß ist der potenzielle Verlust?

              Cheatah

              --
              X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
              X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
              X-Will-Answer-Email: No
              X-Please-Search-Archive-First: Absolutely Yes
              1. Hallo Cheatah,

                in meinem Konzept steckt ein Denkfehler. Der Fragment Identifier wird nicht per http übertragen

                Es ist natürlich Deine Entscheidung, aber wie groß ist der potenzielle Verlust?

                was mich stört, ist, dass erst die Seite anhand der getId geladen wird und dann, wenn die fragId unterschiedlich ist, dierekt ein zweiter Request abgesetzt wird, um eine neue Seite anhand der fragId zu laden.

                ---

                Ansatz 2 (noch nicht recherchiert und geprüft)

                Per

                location.href = '?status=204&id=' + id

                wird tatsächlich eine neue Seite aufgerufen, allerdings gibt der Server, wenn status == 204 ist, nur ein "204 No Content" zurück. Das href-Attribut im Link verweist dagegen nur auf ?id=0815 und der neue Content wird zurückgegeben.

                So habe ich noch nicht gearbeitet und ich muss erst einmal checken, wie das die verschiedenen Browser überhaupt aufnehmen.

                Gruß
                Olaf

                1. […] allerdings gibt der Server, wenn status == 204 ist, nur ein "204 No Content" zurück.

                  bzw. ein "304 Not Modified".

                  1. Hi,

                    bzw. ein "304 Not Modified".

                    das kann nur dann funktionieren, wenn der Client eine frühere Version vorliegen hat - was bei einer neuen URL absolut unmöglich ist. Interpretations-Schwierigkeiten wegen des (vermutlich) fehlenden If-Modified-Since-Headers sind zusätzlich abzusehen.

                    Cheatah

                    --
                    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
                    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
                    X-Will-Answer-Email: No
                    X-Please-Search-Archive-First: Absolutely Yes
                    1. Hallo Cheatah,

                      ich bin auch aus anderen Gründen der Nichtpraktikabilität schon wieder ab davon.

                      Danke noch einmal für Dein Feedback.

                      Später vielleicht mehr …

                      Gruß
                      Olaf

                2. Hi,

                  was mich stört, ist, dass erst die Seite anhand der getId geladen wird und dann, wenn die fragId unterschiedlich ist, dierekt ein zweiter Request abgesetzt wird, um eine neue Seite anhand der fragId zu laden.

                  soweit ist das verständlich. Aber wie groß ist der Verlust, der daraus entsteht? Ist das - aus Nutzer- und Betreibersicht - tragbar? Wenn ja, dann denke daran: Gut ist besser als perfekt.

                  Ansatz 2 (noch nicht recherchiert und geprüft)
                  Per
                  location.href = '?status=204&id=' + id
                  wird tatsächlich eine neue Seite aufgerufen,

                  Beim Absetzen des Requests gilt die aktuelle Seite zunächst als vernichtet. Das macht sich u.a. im Stoppen von Grafik-Animationen und JavaScripts bemerkbar. Wie der Response ausgewertet und verwendet wird, ist erst in zweiter Linie von Relevanz.

                  Cheatah

                  --
                  X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
                  X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
                  X-Will-Answer-Email: No
                  X-Please-Search-Archive-First: Absolutely Yes