Immagine #1
La ricerca avanzata di Gatherer sembra rotta, e lo è da un po’ (direi almeno sei mesi). Non sono stato in grado di trovare nessuno che ne parli attraverso Google. Questo mi ha fatto chiedere se stavo facendo qualcosa di sbagliato, o se nessun altro l’ha notato, o se semplicemente non stavo cercando abbastanza bene da trovare discussioni precedenti. Ho deciso di fare qualche indagine.
I due problemi principali per Gatherer come li vedo io.
- Fai una ricerca avanzata con due o più criteri (ad esempio una ricerca per tutte le carte blu, nere e rosse. Poi, clicca sul
x
accanto a uno di questi criteri nella pagina dei risultati della ricerca. Il criterio scompare dalla lista, ma i risultati delle carte non si aggiornano. - Fai una ricerca avanzata con uno o più criteri (es. Colore: contiene Blu). Poi, clicca su “Raffina la ricerca”. I parametri precedenti non appaiono nella casella dei criteri di ricerca avanzata.
Mi sembra di ricordare di aver riscontrato un terzo problema in passato, qualcosa riguardante il popolamento dei criteri nella pagina di ricerca avanzata, ma ora non riesco a ricordare quale fosse.
Ho testato questo in più browser (Google Chrome, Mozilla Firefox e Microsoft Edge). L’ho testato su più dispositivi (un laptop, due desktop e un telefono). L’ho testato su più sistemi operativi (Windows 10, Ubuntu 16.04, Ubuntu 18.04, Android 8, Android 9).
Per quanto posso dire guardando solo il codice lato client, credo che questo sia un problema con il modo in cui la risposta del server viene gestita dall’interfaccia utente di Gatherer (e forse un problema con il modo in cui il server risponde, pure).
In AdvancedSearch.js::AdvSearchConditionCallback
, linea 872, possiamo vedere come l’UI di Gatherer si aspetta di gestire la risposta del server:
var results = eval("(" + transport.responseText + ")");
La risposta che il server sta inviando qui è JSON. Per esempio, se faccio una ricerca per tutte le carte blu, nere e rosse, e poi clicco su x
per rimuovere il criterio “CONTIENE il rosso”, la risposta che ottengo è:
{ "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=++"}
Nota che il JSON non sembra avere alcuna informazione su quali carte dovrebbero essere visualizzate, e non vedo alcun codice in AdvancedSearch.js
che possa gestire una lista di carte.
Quindi, chiamare eval("(" + transport.responseText + ")")
su questo funziona bene, convertendo la stringa JSON in un oggetto JSON. AdvancedSearch.js
poi usa quell’oggetto JSON per aggiornare la visualizzazione della casella dei criteri di ricerca. Tuttavia, non aggiorna l’URL corrente, (per passare da “?action=advanced&color=+++” a “?action=advanced&color=++”, per esempio).
Ora, Prototype.js è configurato in modo tale che tenterà anche di valutare la risposta. Ma, Prototype.js non è scritto per assumere che la risposta sia JSON. Così, in Prototype.js::respondToReadyState
(linea 1498), Prototype.js tenta di eval
questa stringa JSON come JavaScript (in evalResponse
(linea 1533)), e poiché la stringa JSON non è racchiusa tra parentesi, la valutazione fallisce:
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)
Vale la pena notare, tuttavia, che anche se si modifica Prototype.js
per racchiudere la stringa tra parentesi, converte semplicemente la stringa in un oggetto JSON e poi non ne fa nulla. Inoltre, se si modifica AdvancedSearch.js
per configurare Prototype.js per non valutare la risposta, va semplicemente avanti e il risultato finale è lo stesso.
Quindi, per quanto posso dire, ci sono due possibili problemi:
- L’UI di Gatherer (e
AdvancedSearch.js
in particolare) dovrebbe cambiare l’URL corrente, navigando verso i nuovi risultati di ricerca. - Il Gatherer UI dovrebbe interrogare l’URL restituito in background (o forse il server dovrebbe includere tutte le carte nella risposta), quindi aggiornare dinamicamente la lista delle carte.
Se #1 è il caso, allora tutta la logica per aggiornare dinamicamente l’elenco dei criteri di ricerca sarebbe inutile; non appena il browser naviga verso il nuovo URL, caricherà una pagina completamente nuova, con l’elenco dei criteri già popolato e le nuove schede visualizzate. Questo renderebbe anche inutile la prima query (e la risposta del server), poiché l’UI ha già le informazioni che il server restituisce, e potrebbe semplicemente navigare direttamente verso quell’URL.
Se #2 è il caso, credo che sia probabile che il server abbia un problema in cui si suppone che restituisca la lista di carte risultante in primo luogo. Se no, di nuovo, questa prima query sembra inutile, poiché la risposta non include nulla che l’UI non avesse già. In ogni caso, l’UI ha un problema in cui non ha (apparentemente) alcun codice per aggiornare dinamicamente la lista delle carte, comunque.
Questo è ancora più contorto, perché non succede sempre. A volte, quando si clicca su “Raffina la ricerca”, funziona correttamente. Tuttavia, il più delle volte no. Per coloro che non sono nel settore dello sviluppo del software, questo è probabilmente ciò che è noto come una “Condizione di gara”: due cose stanno accadendo simultaneamente, e il risultato finale dipende dall’ordine in cui finiscono. (È un po’ come la pila in Magic, dove l’ordine di due effetti può avere risultati drasticamente diversi).
Ecco quello che vedo come il nocciolo della questione.
Utilizziamo ancora il nostro esempio precedente, di una ricerca di tutte le carte blu, nere e rosse. Se ispezionate il pulsante “Raffina la ricerca”, vedrete questo:
<a href="/Pages/Advanced.aspx?action=advanced&color=+++" class="refineSearchLink">Refine Search</a>
Quindi, questo dovrebbe essere abbastanza semplice. Torna alla pagina di ricerca avanzata con gli stessi criteri di ricerca. Il problema è cosa succede effettivamente con questo. Se si va alla pagina collegata, sia che si clicchi sul pulsante “Raffina la ricerca”, o su questo link aggiunto in questo post, o che si copi-incolli l’URL nella barra degli indirizzi, questo (di solito) non funziona; la pagina torna indietro senza criteri di ricerca popolati. Ciò che è interessante per me è che, ancora una volta, sembra essere un problema sia con il server che con l’UI (forse entrambi).
Se vai alla scheda Network negli strumenti per sviluppatori del tuo browser e navighi verso quella pagina, la prima voce che appare nell’elenco delle attività è la richiesta a “Pages/Advanced.aspx?action=advanced&color=+++”. Se si fa clic per visualizzare la risposta, si vede l’HTML completo della pagina come è apparsa al primo ritorno. Dove i criteri di ricerca dovrebbero essere popolati, si trova
<div class="filters" ><span style="display: none;">None yet.</span>
Sotto c’è una chiamata a uno script che sembra essere destinato a popolare quella lista:
<script type="text/javascript">RetrieveCurrentSearchConditions();</script>
Guardando RetrieveCurrentSearchConditions
in AdvancedSearch.js
, sta tentando di fare una richiesta Ajax, con i seguenti parametri (linea 406):
parameters: { cacheBust: new Date().getTime(), encodedSerializedPrevious: $(ClientIDs.encodedSerializedParameters).value }
Il problema è che, se si fa un breakpoint su questa linea (o semplicemente si legge la risposta HTML grezza dal server), l’elemento a cui encodedSerializedParameters
si riferisce non ha un valore in questa risposta. Quindi, facciamo questa richiesta con encodedSerializedParameters: ""
, e noi, prevedibilmente, otteniamo indietro dei filtri di ricerca vuoti. Perché succede questo? Bene, se tornate ai risultati della ricerca e visualizzate il sorgente, troverete che encodedSerializedParameters
ha un valore: YwBvAGwAbwByAD0AKwBbAFUAXQArAFsAQgBdACsAWwBSAF0A
(codifica base 64 per “color=+++”).
Quindi, sembra che questo codice sia scritto aspettandosi di essere chiamato mentre si è ancora nella pagina dei risultati di ricerca, ma poi non viene effettivamente chiamato finché il browser non è già tornato alla pagina di ricerca avanzata.
Quindi, sembrerebbe che il server dovrebbe rispondere con il campo value
dell’elemento encodedSerializedParameters
già popolato, ma non lo è. Oppure, l’UI dovrebbe in qualche modo raccogliere quel valore prima di navigare via, e passarlo attraverso la navigazione per essere usato nella pagina successiva. Oppure, forse, l’interfaccia utente dovrebbe avere una funzione per estrarre le informazioni di ricerca dall’URL (dove le informazioni della query sono popolate) e aggiungerle alla casella dei criteri di ricerca.
So che tutto questo ha funzionato ad un certo punto, quindi non ho idea di come questo codice rotto sia stato rilasciato, e come sia rimasto rotto per così tanto tempo. Proprio prima di postare questo, ho deciso di fare una ricerca specifica su r/magicTCG, e ho trovato post che potrebbero riferirsi a questi stessi problemi (ad esempio, i criteri di ricerca di Gatherer “Ricerca avanzata” si resettano in modo semi-casuale. Aiuto?, Problemi con la ricerca avanzata di Gatherer), e sono rimasto sorpreso nel vedere che sono così vecchi (1 anno, 3 anni rispettivamente per gli esempi di cui sopra). Quindi, se si riferiscono agli stessi problemi, questi sono stati fuori per molto tempo.
Quindi, la domanda è: Wizards of the Coast ha semplicemente abbandonato Gatherer? (O almeno la sua ricerca avanzata?)
.
Leave a Reply