Issue #1

Die erweiterte Suche von Gatherer scheint kaputt zu sein, und das schon seit einer Weile (ich schätze mindestens sechs Monate). Ich konnte über Google niemanden finden, der darüber spricht. Ich fragte mich, ob ich etwas falsch gemacht hatte, ob es sonst niemandem aufgefallen war oder ob ich einfach nicht gut genug gesucht hatte, um frühere Diskussionen zu finden. Ich beschloss, ein paar Nachforschungen anzustellen.

Die beiden Hauptprobleme für Gatherer, wie ich sie sehe.

  1. Erstelle eine erweiterte Suche mit zwei oder mehr Kriterien (z.B. eine Suche nach allen blauen, schwarzen und roten Karten. Klicken Sie dann auf der Seite mit den Suchergebnissen auf das Symbol x neben einem dieser Kriterien. Das Kriterium verschwindet aus der Liste, aber die Kartenergebnisse werden nicht aktualisiert.
  2. Führen Sie eine erweiterte Suche mit einem oder mehreren Kriterien durch (z. B. Farbe: Enthält Blau). Klicken Sie dann auf „Suche verfeinern“. Die vorherigen Parameter erscheinen nicht im Feld für die erweiterten Suchkriterien.

Ich glaube mich zu erinnern, dass ich in der Vergangenheit auf ein drittes Problem gestoßen bin, das etwas mit dem Auffüllen der Kriterien auf der Seite der erweiterten Suche zu tun hatte, aber jetzt kann ich mich nicht mehr daran erinnern, was es war.

Ich habe dies in mehreren Browsern getestet (Google Chrome, Mozilla Firefox und Microsoft Edge). Ich habe dies auf mehreren Geräten getestet (einem Laptop, zwei Desktops und einem Telefon). Ich habe dies auf mehreren Betriebssystemen getestet (Windows 10, Ubuntu 16.04, Ubuntu 18.04, Android 8, Android 9).

Wenn ich mir nur den clientseitigen Code ansehe, glaube ich, dass dies ein Problem damit ist, wie die Serverantwort von der Gatherer-Benutzeroberfläche gehandhabt wird (und möglicherweise auch ein Problem damit, wie der Server antwortet).

In AdvancedSearch.js::AdvSearchConditionCallback, Zeile 872, sehen wir, wie die Gatherer-Benutzeroberfläche die Antwort des Servers verarbeiten soll:

var results = eval("(" + transport.responseText + ")");

Die Antwort, die der Server hier sendet, ist JSON. Wenn ich zum Beispiel nach allen blauen, schwarzen und roten Karten suche und dann auf x klicke, um das Kriterium „Enthält Rot“ zu entfernen, erhalte ich folgende Antwort:

{ "LCID": 0, "CommandName": null, "CommandListPath": null, "SearchTerms": null, "SubQueryDelimiter": "Union", "SearchTermDelimiter": "And", "EscapeInputDelimiters": true, "EncodedSerializedQuery": "YwBvAGwAbwByAD0AKwBbAFUAXQArAFsAQgBdAA==", "ExtraSafeKeys": , "IncludeSpecial": false, "Filters": { "color": { "Identifier": "fe329dcb-d64a-4939-bfd6-7af5c102d655", "LogicalOperator": "Intersect", "From": "color", "Terms": ", "LogicalOperator": "And", "State": "+" }, { "Identifier": "b622e49d-87de-439f-ac75-0e99ffee07c6", "FormatString": "color", "Value": "", "LogicalOperator": "And", "State": "+" } ], "State": null, "FormatString": "color", "Value": ", "LogicalOperator": "And", "State": "+" }, { "Identifier": "b622e49d-87de-439f-ac75-0e99ffee07c6", "FormatString": "color", "Value": "", "LogicalOperator": "And", "State": "+" } ] } }, "State": "color=++"} 

Beachten Sie, dass das JSON keine Informationen darüber zu enthalten scheint, welche Karten angezeigt werden sollen, und ich sehe keinen Code in AdvancedSearch.js, der eine Liste von Karten verarbeiten würde.

Der Aufruf von eval("(" + transport.responseText + ")") funktioniert also gut und konvertiert den JSON-String in ein JSON-Objekt. AdvancedSearch.js verwendet dann dieses JSON-Objekt, um die Anzeige des Suchkriterienfeldes zu aktualisieren. Allerdings wird die aktuelle URL nicht aktualisiert (zum Beispiel von „?action=advanced&color=+++“ zu „?action=advanced&color=++“).

Nun ist Prototype.js so konfiguriert, dass es auch versucht, die Antwort auszuwerten. Aber Prototype.js ist nicht so geschrieben, dass es davon ausgeht, dass die Antwort JSON ist. In Prototype.js::respondToReadyState (Zeile 1498) versucht Prototype.js also, eval diese JSON-Zeichenfolge als JavaScript (in evalResponse (Zeile 1533)) auszuwerten, und da die JSON-Zeichenfolge nicht in Klammern eingeschlossen ist, schlägt die Auswertung fehl:

SyntaxError: Unexpected token : at klass.evalResponse (Prototype.js:1533) at klass.respondToReadyState (Prototype.js:1501) at klass.onStateChange (Prototype.js:1436) at XMLHttpRequest.<anonymous> (Prototype.js:291)

Selbst wenn Sie Prototype.js so ändern, dass die Zeichenkette in Klammern eingeschlossen wird, wird die Zeichenkette nur in ein JSON-Objekt umgewandelt und dann nichts damit gemacht. Auch wenn Sie AdvancedSearch.js ändern, um Prototype.js so zu konfigurieren, dass es die Antwort nicht auswertet, macht es einfach weiter und das Endergebnis ist dasselbe.

So, soweit ich das beurteilen kann, gibt es zwei mögliche Probleme:

  1. Die Gatherer UI (und insbesondere AdvancedSearch.js) soll die aktuelle URL ändern und zu den neuen Suchergebnissen navigieren.
  2. Die Gatherer-Benutzeroberfläche soll die zurückgegebene URL im Hintergrund abfragen (oder vielleicht soll der Server alle Karten in die Antwort aufnehmen) und dann die Kartenliste dynamisch aktualisieren.

Wenn dies der Fall ist, wäre die gesamte Logik zur dynamischen Aktualisierung der Suchkriterienliste sinnlos; sobald der Browser zur neuen URL navigiert, wird eine völlig neue Seite geladen, auf der die Kriterienliste bereits ausgefüllt ist und die neuen Karten angezeigt werden. Dies würde auch die erste Abfrage (und die Antwort des Servers) überflüssig machen, da die Benutzeroberfläche bereits über die Informationen verfügt, die der Server zurückgibt, und einfach direkt zu dieser URL navigieren könnte.

Wenn #2 der Fall ist, ist es wahrscheinlich, dass der Server ein Problem hat, bei dem er die resultierende Kartenliste überhaupt zurückgeben soll. Wenn nicht, scheint diese erste Abfrage sinnlos zu sein, da die Antwort nichts enthält, was die Benutzeroberfläche nicht schon hatte. Wie auch immer, die Benutzeroberfläche hat ein Problem, da sie (anscheinend) keinen Code zur dynamischen Aktualisierung der Kartenliste hat.

Dieses Problem ist noch verworrener, weil es nicht immer auftritt. Manchmal, wenn Sie auf „Suche verfeinern“ klicken, funktioniert es richtig. Meistens funktioniert es jedoch nicht. Für diejenigen, die nicht aus der Softwareentwicklungsbranche kommen, ist dies wahrscheinlich eine so genannte „Race Condition“: Zwei Dinge passieren gleichzeitig, und das Endergebnis hängt davon ab, in welcher Reihenfolge sie ausgeführt werden. (Das ist so ähnlich wie der Stapel in der Magie, wo die Reihenfolge zweier Effekte zu drastisch unterschiedlichen Ergebnissen führen kann).

Das ist, was ich als den Kern des Problems ansehe.

Nehmen wir noch einmal unser obiges Beispiel, die Suche nach allen blauen, schwarzen und roten Karten. Wenn Sie die Schaltfläche „Suche verfeinern“ inspizieren, sehen Sie dies:

<a href="/Pages/Advanced.aspx?action=advanced&amp;color=+++" class="refineSearchLink">Refine Search</a>

Das sollte also ziemlich einfach sein. Gehen Sie zurück zur Seite „Erweiterte Suche“ mit denselben Suchkriterien. Das Problem ist nur, was dann tatsächlich passiert. Wenn Sie auf die verlinkte Seite gehen, egal ob Sie auf die Schaltfläche „Suche verfeinern“ oder den in diesem Beitrag eingefügten Link klicken oder die URL in die Adressleiste einfügen, funktioniert dies (normalerweise) nicht; die Seite kehrt zurück, ohne dass Suchkriterien eingegeben wurden. Interessant für mich ist, dass es wieder ein Problem mit dem Server oder der Benutzeroberfläche zu sein scheint (möglicherweise beides).

Wenn Sie in den Entwicklertools Ihres Browsers auf die Registerkarte „Netzwerk“ gehen und zu dieser Seite navigieren, ist der erste Eintrag, der in der Aktivitätsliste erscheint, die Anfrage an „Pages/Advanced.aspx?action=advanced&color=+++“. Wenn Sie auf die Antwort klicken, sehen Sie den vollständigen HTML-Code der Seite, so wie er beim ersten Aufruf angezeigt wurde. An der Stelle, an der die Suchkriterien ausgefüllt werden sollten, finden Sie

<div class="filters" ><span style="display: none;">None yet.</span>

Darunter befindet sich ein Aufruf eines Skripts, das anscheinend diese Liste ausfüllen soll:

<script type="text/javascript">RetrieveCurrentSearchConditions();</script>

Bei RetrieveCurrentSearchConditions in AdvancedSearch.js wird versucht, eine Ajax-Anfrage mit den folgenden Parametern zu stellen (Zeile 406):

parameters: { cacheBust: new Date().getTime(), encodedSerializedPrevious: $(ClientIDs.encodedSerializedParameters).value }

Das Problem ist, dass das Element, auf das sich encodedSerializedParameters bezieht, in dieser Antwort keinen Wert hat, wenn man in dieser Zeile einen Breakpoint setzt (oder einfach die rohe HTML-Antwort des Servers liest). Wenn wir also diese Anfrage mit encodedSerializedParameters: "" stellen, erhalten wir vorhersehbar leere Suchfilter zurück. Warum ist das so? Nun, wenn Sie zu den Suchergebnissen zurückgehen und sich den Quelltext ansehen, werden Sie feststellen, dass encodedSerializedParameters einen Wert hat: YwBvAGwAbwByAD0AKwBbAFUAXQArAFsAQgBdACsAWwBSAF0A (Base 64-Kodierung für „color=+++“).

Es scheint also, dass dieser Code in der Erwartung geschrieben wurde, dass er aufgerufen wird, während er sich noch auf der Seite mit den Suchergebnissen befindet, aber er wird erst dann aufgerufen, wenn der Browser bereits zur Seite mit der erweiterten Suche zurückgesprungen ist.

Es scheint also, dass der Server mit dem value-Feld des encodedSerializedParameters-Elements reagieren sollte, das bereits ausgefüllt ist, aber nicht. Oder die Benutzeroberfläche soll diesen Wert irgendwie sammeln, bevor sie weg navigiert, und ihn durch die Navigation weitergeben, um auf der nächsten Seite verwendet zu werden. Oder die Benutzeroberfläche soll eine Funktion haben, die diese Suchinformationen aus der URL (in der die Abfrageinformationen eingetragen sind) abruft und sie dem Suchkriterienfeld hinzufügt.

Ich weiß, dass all dies irgendwann einmal funktioniert hat, daher habe ich keine Ahnung, wie ein solch fehlerhafter Code veröffentlicht werden konnte und wie er so lange fehlerhaft geblieben ist. Kurz bevor ich diesen Beitrag geschrieben habe, habe ich beschlossen, eine Suche speziell auf r/magicTCG durchzuführen, und ich habe Beiträge gefunden, die sich möglicherweise auf dieselben Probleme beziehen (z.B. Gatherer’s ‚Advanced Search‘ search criteria resets semi-randomly. Help?, Trouble with Gatherer Advanced Search), und ich war überrascht zu sehen, dass sie so alt sind (1 Jahr bzw. 3 Jahre für die obigen Beispiele). Wenn sie sich also auf dieselben Probleme beziehen, sind sie schon seit langem bekannt.

Die Frage ist also: Hat Wizards of the Coast Gatherer einfach aufgegeben? (Oder zumindest die erweiterte Suche?)

Leave a Reply