Issue #1

Gatherer advanced search lijkt kapot, en dat is het al een tijdje (ik schat minstens een half jaar). Ik was niet in staat om iemand te vinden die er over sprak via Google. Dit deed me afvragen of ik iets verkeerd deed, of dat niemand anders het gemerkt had, of dat ik gewoon niet goed genoeg zocht om eerdere discussies te vinden. Ik besloot wat onderzoek te doen.

De twee belangrijkste problemen voor Gatherer zoals ik ze zie.

  1. Doe een geavanceerde zoekopdracht met twee of meer criteria (bijv. een zoekopdracht voor alle blauwe, zwarte en rode kaarten. Klik dan op de x naast één van deze criteria op de zoekresultaten pagina. Het criterium verdwijnt uit de lijst, maar de kaartresultaten worden niet bijgewerkt.
  2. Doe een geavanceerde zoekopdracht met een of meer criteria (bijv. Kleur: Bevat Blauw). Klik vervolgens op “Zoekopdracht verfijnen”. De vorige parameters verschijnen niet in het vak met de geavanceerde zoekcriteria.

Ik meen me te herinneren dat ik in het verleden een derde probleem heb gehad, iets met betrekking tot het vullen van de criteria op de geavanceerd zoeken pagina, maar nu kan ik me niet herinneren wat het was.

Ik heb dit getest in meerdere browsers (Google Chrome, Mozilla Firefox, en Microsoft Edge). Ik heb dit getest op meerdere apparaten (een laptop, twee desktops, en een telefoon). Ik heb dit getest op meerdere besturingssystemen (Windows 10, Ubuntu 16.04, Ubuntu 18.04, Android 8, Android 9).

Zo goed als ik kan vertellen door alleen naar de client-side code te kijken, geloof ik dat dit een probleem is met hoe de serverrespons wordt afgehandeld door de Gatherer UI (en mogelijk een probleem met hoe de server reageert, ook).

In AdvancedSearch.js::AdvSearchConditionCallback, regel 872, kunnen we zien hoe de Gatherer UI verwacht het antwoord van de server te behandelen:

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

Het antwoord dat de server hier stuurt is JSON. Bijvoorbeeld, als ik een zoekopdracht voor alle blauwe, zwarte en rode kaarten, en klik dan op de x om de “DOES contain Red” criterium te verwijderen, de respons die ik krijg is:

{ "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=++"} 

Merk op dat de JSON niet lijkt te hebben geen informatie over welke kaarten moeten worden weergegeven, en ik zie geen code in AdvancedSearch.js die een lijst van kaarten zou verwerken.

Dus, het aanroepen van eval("(" + transport.responseText + ")") op dit werkt prima, het converteren van de JSON string in een JSON object. AdvancedSearch.js gebruikt dan dat JSON object om de weergave van het zoekcriteria vak bij te werken. De huidige URL wordt echter niet bijgewerkt (om bijvoorbeeld van “?action=advanced&color=++” naar “?action=advanced&color=++” te gaan).

Nu, Prototype.js is op zo’n manier geconfigureerd dat het ook zal proberen om de reactie te evalueren. Maar, Prototype.js is niet geschreven om aan te nemen dat het antwoord JSON is. Dus, in Prototype.js::respondToReadyState (regel 1498), probeert Prototype.js deze JSON string te eval evalueren als JavaScript (in evalResponse (regel 1533)), en aangezien de JSON string niet tussen haakjes staat, mislukt de eval:

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)

Het is echter de moeite waard om op te merken dat zelfs als je Prototype.js wijzigt om de string tussen haakjes te zetten, het alleen de string converteert in een JSON object en er vervolgens niets mee doet. Ook als u AdvancedSearch.js zo wijzigt dat Prototype.js het antwoord niet evalueert, gaat het gewoon verder en is het eindresultaat hetzelfde.

Dus, voor zover ik kan zien, zijn er twee mogelijke problemen:

  1. De Gatherer UI (en AdvancedSearch.js in het bijzonder) wordt verondersteld om de huidige URL te veranderen, navigeren naar de nieuwe zoekresultaten.
  2. De Gatherer UI wordt verondersteld om de teruggegeven URL op de achtergrond te bevragen (of misschien wordt de server verondersteld om alle kaarten in het antwoord op te nemen), en dan de kaartlijst dynamisch bij te werken.

Als # 1 het geval is, dan zou alle logica voor het dynamisch bijwerken van de zoekcriteria lijst zinloos zijn; zodra de browser naar de nieuwe URL navigeert, zal het een geheel nieuwe pagina laden, met de criteria lijst al gevuld en de nieuwe kaarten getoond. Dit zou ook de eerste query (en het antwoord van de server) zinloos maken, omdat de UI de informatie die de server terugstuurt al heeft, en gewoon direct naar die URL zou kunnen navigeren.

Als #2 het geval is, is het waarschijnlijk dat de server een probleem heeft met de kaartlijst die hij moet teruggeven. Als dat niet het geval is, lijkt deze eerste query opnieuw zinloos, omdat het antwoord niets bevat dat de UI niet al had. Hoe dan ook, de UI heeft een probleem waar het (blijkbaar) geen code heeft voor het dynamisch bijwerken van de kaartlijst, hoe dan ook.

Deze is nog ingewikkelder, omdat het niet altijd gebeurt. Soms als u klikt op “Verfijnen Zoeken”, het werkt correct. Maar meestal niet. Voor degenen die niet in de software ontwikkel industrie zitten, dit is waarschijnlijk wat bekend staat als een “Race Condition”: twee dingen gebeuren tegelijkertijd, en het eindresultaat hangt af van in welke volgorde ze eindigen. (Het is een beetje zoals de stapel in Magic, waar de volgorde van twee effecten drastisch verschillende resultaten kan hebben).

Dit is wat ik zie als de kern van het probleem.

Laten we ons bovenstaande voorbeeld nog eens gebruiken, van een zoekactie naar alle blauwe, zwarte en rode kaarten. Als u de knop “Zoeken verfijnen” inspecteert, ziet u dit:

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

Dus, dit zou vrij eenvoudig moeten zijn. Navigeer terug naar de geavanceerde zoekpagina met dezelfde zoekcriteria. Het probleem is wat daar nu mee gebeurt. Als je naar de gelinkte pagina gaat, of je nu op de “Verfijn zoekopdracht” knop klikt, of op deze link die in deze post is toegevoegd, of je kopieert de URL in de adresbalk, werkt dit (meestal) niet; de pagina komt terug zonder dat de zoekcriteria zijn ingevuld. Wat ik interessant vind is dat, nogmaals, het een probleem lijkt te zijn met ofwel de server ofwel de UI (mogelijk beide).

Als je naar de Netwerk tab gaat in je browser’s ontwikkelaars tools, en naar die pagina navigeert, is het eerste item dat verschijnt in de activiteiten lijst het verzoek naar “Pages/Advanced.aspx?action=advanced&color=+++”. Als u klikt om de respons te bekijken, ziet u de volledige HTML van de pagina zoals die verscheen toen hij voor het eerst werd teruggestuurd. Waar de zoekcriteria moeten worden ingevuld, vindt u

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

Daaronder staat een oproep aan een script dat bedoeld lijkt om die lijst te vullen:

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

Kijkend naar RetrieveCurrentSearchConditions in AdvancedSearch.js, probeert het een Ajax verzoek te doen, met de volgende parameters (regel 406):

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

Het probleem is dat, als je op deze regel breekt (of gewoon de ruwe HTML respons van de server doorleest), het element waar encodedSerializedParameters naar verwijst geen waarde heeft in deze respons. Dus, we doen dan dit verzoek met encodedSerializedParameters: "", en we krijgen, voorspelbaar, lege zoekfilters terug. Dus waarom gebeurt dit? Nou, als je terug gaat naar de zoekresultaten, en de bron bekijkt, dan zul je zien dat encodedSerializedParameters wel een waarde heeft: YwBvAGwAbwByAD0AKwBbAFUAXQArAFsAQgBdACsAWwBSAF0A (basis 64 codering voor “color=++”).

Het lijkt er dus op dat deze code is geschreven in de verwachting dat hij wordt aangeroepen terwijl hij nog op de pagina met zoekresultaten staat, maar dat hij pas wordt aangeroepen als de browser al terug is genavigeerd naar de pagina met geavanceerde zoekresultaten.

Het lijkt er dus op dat de server zou moeten reageren met het value veld van het encodedSerializedParameters element al gevuld, maar dat is niet zo. Of, de UI moet op een of andere manier die waarde verzamelen voordat hij weg navigeert, en het door de navigatie doorgeven om op de volgende pagina te worden gebruikt. Of, mogelijk, moet de UI een functie hebben om die zoek informatie uit de URL te halen (waar de query informatie is ingevuld), en toe te voegen aan de zoek criteria box.

Ik weet dat dit allemaal ooit heeft gewerkt, dus ik heb geen idee hoe zo’n kapotte code is vrijgegeven, en hoe het zo lang kapot is gebleven. Vlak voordat ik dit postte, besloot ik een specifieke zoekopdracht te geven op r/magicTCG, en ik vond berichten die misschien over dezelfde problemen gaan (bijv. Gatherer’s ‘Advanced Search’ zoekcriteria worden semi-willekeurig gereset. Help?, Trouble with Gatherer Advanced Search), en ik was verbaasd om te zien dat ze zo oud zijn (respectievelijk 1 jaar, 3 jaar voor de bovenstaande voorbeelden). Dus als ze verwijzen naar dezelfde problemen, zijn deze al een lange tijd uit.

Dus, de vraag is, heeft Wizards of the Coast Gatherer gewoon verlaten? (Of in ieder geval het geavanceerd zoeken?)

Leave a Reply