Autor Zpráva
ForestCZE
Profil
Zdravím, mám následující kód:

function Searching()
    {
        $("#insuranceSearching").keyup(function(){
            let val = $(this).val();
            let url = window.location.href;
            window.location.replace(url + "&search=" + val);
        });
    }

Když začnu psát do inputu, změní se mi odkaz a hodnota v GET. Problém je v tom, že to refreshne stránku. Jak to udělat bez refreshnutí? Děkuji předem za pomoc.
Kajman
Profil
Můžete to dávat do hash části místo do query stringu. Tedy za znak # - to se ma server neposílá.
Keeehi
Profil
Ale jo, jde to.
Živá ukázka

Kvůli history API - replaceState to má omezení hlavně na IE10+. To je nutné pro manipulaci s tou url, bez toho to nejde.
Pak pro vytvoření nové url (přidání, nebo nahrazení searche v query stringu) jsem použil URL API. To má ještě horší podporu ale pro jednoduchost ukázky to bylo výhodné. Není to však nutné a pokud si ten string zvládneš sestavit jinak dá se to klidně vynechat. Smazání searche v obecné url není vůbec nic triviálního. Po nějaké době testování jsem přišel na toto, což funguje celkem dobře, ale může to mít své mouchy.
window.location.href.replace(/(?<=[&?])search=[^&]*&*/g,"")
pak musíš rozlišit, jestli se má na konec připojit ?, nebo &, nebo vůbec nic a pak search=<hodnota>

No a nebo když použiješ tu Kajmanovu metodu s hashem, bude ti to fungovat i ve starších prohlížečích. Je tam trochu problém s tím, že hash se na server neodesílá, takže výsledky hledání se nemohou vrátit ihned, když někdo na takovou stránku přijde z odkazu, ale bude se muset nejdříve načíst prázdná* stránka a pak odeslat ajaxový požadavek s hledáním. Takže to bude déle trvat.
*prázdná znamená search=""

Samozřejmě optimální řešení by bylo udělat kombinaci obou, kde moderní replaceState by byla preferovaná varianta s fallbackem na hash variantu. Ovšem to už je docela komplexní systém.

Jinak do té ukázky jsem přidal ještě jednu featuru. Ten search se nedělá okamžitě, ale až s 300ms zpožděním. Je zbytečné posílat požadavek s každým úhozem uživatele. Stačí to přece až když dopíše.
ForestCZE
Profil
Kajman:
Děkuji

Keeehi
Tušil jsem, že to bude složitější. Moc děkuji za živou ukázku a za pěkné vysvětlení. Nějak to zkusím a popřípadě ještě napíšu.
ForestCZE
Profil
Pokoušel jsem se to přepsat na JS

function searching()
{
    var searchTimeout;
    
    var searchExamination = function(){
        var xhttp;
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function(){
            if(xhttp.readyState === 4 && xhttp.status === 200)
                document.getElementById("snippet--examinations").innerHTML = "Whatever";
            xhttp.open("POST", window.location.href, true);
            xhttp.send();
        };
    };
    
    var examination = document.getElementById("examinationSearching");
    if(examination !== null)
    {
        examination.addEventListener("keyup", function(){
            clearTimeout(searchTimeout);
            var value = this.value;
            var url = new URL(window.location.href);
            url.searchParams.set("search", value);
            window.history.replaceState({}, "", url.toString());
            searchTimeout = setTimeout(searchExamination, 300);
        });
    }
}

Fce searchExamination se provede, soudě podle console, ale ten ajax se neprovede. Co dělám špatně?
Kajman
Profil
Asi máte open a send v místě, které se vykoná až po vyřízení požadavku. Ten se tedy nikdy nepošle. Ty metody dejte až za definici návratové funkce.
ForestCZE
Profil
Kajman:
Já hlupák. Vůbec jsem si toho nevšiml. Moc děkuji :)
lionel messi
Profil
ForestCZE:

Ako píše Kajman:

 var searchExamination = function(){
        var xhttp;
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function(){
            if(xhttp.readyState === 4 && xhttp.status === 200)
                document.getElementById("snippet--examinations").innerHTML = "Whatever";
                };
            xhttp.open("POST", window.location.href, true);
            xhttp.send();
    };
ForestCZE
Profil
Ještě jedna věc - s JS defacto začínám. V jQuery mám:

success: function(data){
  $("#snippet--examinations").html(data.snippets['snippet--examinations']);
}

Jak tedy získám data?

Zkoušel jsem:

document.getElementById("snippet--examinations").innerHTML = xhttp.responseText.snippets['snippet--examinations'];

Ale nefunguje. Jak by to mělo být?
ForestCZE
Profil
Tak jsem zjistil, že přes jQuery se ta data vrací jako JSON a JS to vrací jako string. Lze to nějak nekomplikovaně převést na JSON?
lionel messi
Profil
ForestCZE:
Lze to nějak nekomplikovaně převést na JSON?

Myslím, že hľadáš metódu JSON.parse()
ForestCZE
Profil
lionel messi:
Problém je, že ta data nejsou v JSON formátu. Tudíž ani nechápu, jaktože je jQuery jako JSON vrací.

JSON.parse jsem samozřejmě zkoušel, ale dostanu:

Uncaught SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at XMLHttpRequest.xhttp.onreadystatechange
Kajman
Profil
ForestCZE:
Problém je, že ta data nejsou v JSON formátu.

Pokud není možné použít JSON formát, napište si vlastní parser podle Vašeho formátu dat.
Serg
Profil
ForestCZE:
Tudíž ani nechápu, jaktože je jQuery jako JSON vrací.

Záleží kterou metdou se ten AJAX volá.
Základní metodou je $.ajax, tam je parametr dataType, který když se nezadá, tak zkusí formát dat uhodnout, a asi si jQuery myslí že data vypadají jako json. Ostatní metody jako $.get(), $.post(), $.getJSON() jsou jen kratší zápisy pro $.ajax() s jiným výchozím nastavením, ale jen $.getJSON přenastavuje dataType na "json", u ostatních by to mělo zůstat výchozí, tedy že to jQuery zkusí uhodnout.

Problém je, že ta data nejsou v JSON formátu.
Možná by stálo za to ten dataType nastavit např na "html", nebo "text" pokud server nevrací výsledek v JSON formátu.

Dokumentace tady: api.jquery.com/jquery.ajax
Trochu níž je popsaný dataType a jaký hodnoty jdou nastavit a co dělají
Keeehi
Profil
Na to hádání datového typu ajaxem v jquery pozor. Když si to totiž myslí, že odpověď je javascript, nebo html s javascriptem, tak ten javascript bezostyšně spustí. V kombinaci s uživatelským vstupem v hledání to může teoreticky způsobovat XSS zranitelnost. Proto je vždy dobré dataType explicitně uvádět.
ForestCZE
Profil
Kajman:
Pokud není možné použít JSON formát, napište si vlastní parser podle Vašeho formátu dat.

Nakonec jsem zjistil, že stačí přidat:

xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");

Momentálně to vrací:

{"state":{"emsid":"17ba0791499db908433b80f37c5fbc89b870084b"},"snippets":{"snippet--examinations":"        <table class=\"tab tab_h\">\n            <tr>\n                <th>Jméno</th>\n                <th>Narozen(a)</th>\n                <th>Druh</th>\n                <th>Výsledky</th>\n                <th>Zapsáno</th>\n                <th>Provedl(a)</th>\n                <th>Vyřešil(a)</th>\n            </tr>\n            \n        </table>\n"}}

Potřebuji z toho dostat "snippet--examinations"

Předpokládám, že to budu muset parsovat, takže něco jako:

var json = JSON.parse(xhttp.response);
// A nevím, jak to získat. Jestli to chápu správně, tak je to celé vnořené do state

EDIT: Tak snad takto:

var json = JSON.parse(xhttp.response);
console.log(json["snippets"]["snippet--examinations"]);

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0