NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Vyhledávání na webu mezi elementy

V předchozím kvízu, Online test znalostí HTML a CSS, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Verquido
Tvůrce
Avatar
Verquido:6.4.2016 21:00

Zdravím, potřeboval bych vědět jestli jde nějak udělat vyhledávání na webu. Třeba vyhledávání v ID nebo NAME atp.. Aby se k tomu, ale nemusela používat databáze. bez PHP to sice asi nepůjde, ale bez databáze alespon..

Měl bych na stránce třeba seznam věci takže by byly třeba id="hrabe(zidle, stul)...".. A vyhledaval bych..

Ještě lepší by bylo aby se to samo obnovovalo abych nemusel mačkat VYHLEDAT, ale aby mi to automaticky hledalo.. myslím že u databází se na to používá AJAX.

Díky moc :)

 
Odpovědět
6.4.2016 21:00
Avatar
Odpovídá na Verquido
Neaktivní uživatel:6.4.2016 22:59

Jsou to jen elementy na webu? Jen elementy co jsou v soucasne dobe nactene v DOMu? (zjednodusene receno to, co muzes videt v okne prohlizece?) Pokud ano, vykasli se na phpcko ... tady se vsecka prace bude delat na klientu, pokud mas milion divu na strance, kazdy ma nejaky atribut a ty podle tech atributu chces vyhledavat, pak je JS presne pro tebe.

Jenoduse udelas

<input id="search" type="text">

, v javascriptovem kodu mu nastavis naslouchani na udalost onkeyup

(document.getElementById("search").addEventListener("keyup", function(){});

Uvnitr funkce budes nacitat do stringu obsah inputu v danej moment, pak to chce funkci, ktera vybere vsechny elementy, ktery by mohly bejt ve hre, na to muzes pouzit velice silnej selector document.query­SelectorAll (https://developer.mozilla.org/…ySelectorAll) vyhleda ti po spravnem specifikovani elementy s danou id, s danou classou, s kombinaci, daneho tagname, daneho atributu, proste je to jako svicarskej nuz, co budes s danyma elementama delat je na tobe, muzes skryt vsechny, krome tehle, muzes tyhle posunout nahoru, muzes je obarvit na duhovo, to je jedno ... dobry je, ze i kdyz si uzivatel umaze kousek stringu, tak backspace taky aktivuje keyup ...

pozor si dej na tohle, pokud to budes delat takhle, tak se ti muze stat, ze ti v jeden moment pri rychlejsim pripisovani pozadavku a pomalem vyhledavani nastane situace, kdy bys pri neustalem aktualizovani DOMu par sekund jen blikal zobrazit/scho­vat/zobrazit/scho­vat, protoze javascript bezi synchronne nemel by starsi vypocet dobehnout pozdeji, nez mladsi, ale dobehnou velmi kratce za sebou tak jak pisu velmi rychle slovo a to znamena, ze pri slove dlouhem deset pismen desetkrat zbytecne manipulujes s DOMem, nebo zbytecne desetkrat menis display velkemu mnozstvi prvku, to neni zadarmo.

Takze jak se tomu vyvarovat, no javascript nenabizi mnoho hezkych reseni, jednim z nich je mit globalni promennou, na kterou uvidi vsechny tyhle funkce, ktere se budou provadet na stisk tlacitka v inputu a ted pozor, nemuzes zastavit provadeni funkce v atomickem prikazu, ber to tak, ze proste nejde rict interuptni se zrovna v okamziku kdy javascript louska treba ten tvuj DOM a hleda spravne elementy, ALE co jde a je to docela elegantni -> predtim, nez doopravdy zacnes hybat s DOMem (zvyraznovat vyhledany vysledky, posouvat je, skryvat ostatni, atd...) se ujistis, ze tohle volani, je to posledni, to chce hned na zacatku funkce do lokalni promenne ulozit timeStamp, pak bude globalni timeStamp, do kteryho na zacatku volani (hned na to zvednuti prstu) zapises taky, nez tedy (zase se posuneme na konec tve funkce) provedes neco s tema elementama, ujistis se, ze ten lokalni timeStamp souhlasi s tim globalnim, pokud souhlasi, vis ze tohle volani/provadeni je to aktualni/posledni chtene .. pokud nesouhlasi, znamena to, ze byla zavolana instance teto funkce znovu, logicky s jinyma datama, no a ty proste udelas return a nic nezobrazujes, skoda, ze jsi hledal mezi elementama zbytecne, ale to je zivot...

Nekomu by mohl vadit fakt, ze timeStamp (ten hlavni) je zde pristupovan a nebyl funkci pridelen, bohuzel se s tim asi budes muset smirit, nenapada me ted zpusob co by nezneuzival vareable object funkce ...

Doufam, ze jsem to popsal alespon slovne dost detailne, otazka znela dost na popis implementace, kdybys stal o vic kodu a prikladu, pravdepodobne te pozadam o doplneni nejakeho ukazkoveho kodu (co uz mas treba) a jsem ti ochotny k tomu neco dopsat, poradit. :)

Taky bys mohl pockat az user zmackne enter, ale nekdo je zvyklej klikat na lupu, nekdo enteruje a jak jsem pochopil, ty to chces auto.

Editováno 6.4.2016 23:00
Nahoru Odpovědět
6.4.2016 22:59
Neaktivní uživatelský účet
Avatar
Verquido
Tvůrce
Avatar
Verquido:6.4.2016 23:25

Tak, tohle sem nečekal.. To byla opravdu vyčerpávající odpověď :) Vážím si toho.. A ano asi budu potřebovat trochu více kódu kvůli trochu praktiky. nejsem v JavaScriptu nijak extra zběhlý a tak se to učím spíš za pochodu.

Myšlenku tohohle všeho chápu, jen bych to potřeboval trochu přiblížit v té praxi no. A ano nemělo by se tam klikat na žádné tlačítko ani lupu ani ukončovat enterem, ale tou změnou znaku.

Já sem ještě s kódem moc nezačal, protože sem chtěl vědět jak bude vypadat tohle abych se k tomu nějak přispůsobil, kdyby to bylo nějak složité. Ale asi bych to vzal tak že budu mít na stránce několik divů, který budou mít asi class="box <jmeno>" takže box bude pro stylování všech divů na té stránce a <jméno> tam bude jméno podle kterého bude vyhledávání.

<p><input class="vstup" /></p>

<div class="box Pepa">IMG</div>
<div class="box Jroslav"IMG</div>
<div class="box Vladimír">IMG</div>
<div class="box Ludmila">IMG</div>
<div class="box Karolína">IMG</div>
<div class="box Karel">IMG</div>
<div class="box Jiří">IMG</div>

Zkrácený kód. Nahoře je vstupní polu do kterého se bude psát co se bude vyhledávat a bude se vyhledávat mezi divy pod tím.. Je to jen teoretické, takže názvy atp bych neřešil tak moc je to jen pro ukázku. Stylování tu taky neřeším. Po vyhledání bych asi nechal jenom vyhledané a ostatní bych schoval :)

Dále nevím jak to bude fungovat a hledat. Ale bylo by dobré, kdyby to nehledalo jenom celé názvy, ale kdybych do vyhledávacího pole napsal například "m" tak aby mi vyskočil Vladimír a Ludmila atp. Prostě aby to hledalo i to co mají společné.

 
Nahoru Odpovědět
6.4.2016 23:25
Avatar
Odpovídá na Verquido
Neaktivní uživatel:7.4.2016 10:33

Já jsem tam samozřejmě těmi úpravami a přepisováním udělal chybu v té části o zastavování již nepotřebného vyhledávání, ale když počkáš 30 minut až budu ve škole už pro tebe mám připravené správné řešení i s odpovědí na poslední otázky.

Nahoru Odpovědět
7.4.2016 10:33
Neaktivní uživatelský účet
Avatar
Verquido
Tvůrce
Avatar
Verquido:7.4.2016 10:37

jj počkám já sem taky ve škole :)

 
Nahoru Odpovědět
7.4.2016 10:37
Avatar
Odpovídá na Verquido
Neaktivní uživatel:7.4.2016 12:28

Takze, prvni co bych udelal, rozdelil oznacovani elementu na tri mnoziny, pomoci ID, pomoci CLASS, pomoci data-* ... zasadni je rychlost a citelnost kodu.

Tvemu input elementu bych dal id="search" a tridu bych mu nedaval,
tvym divum bych nechal class="box" ale to je jedina trida co by mely mit,
jejich jmeno, tag, stitek, cosi, to je informace, ktera nepatri do class, je to ve skutecnosti informace, kterou by mel nest atribut data- ... treba data-tag="Pepa", proc? Ve skutecnosti se podle ID hleda jedinecnej kontent na strance, je to rychly, v kodu prehledny a nejde to nemit rad, classou oznacenych elementu je hodne, obvykle se pomoci tridy styluje, obvykle se podle tridy v JS vybira seznam (mnozina) elementu vyhovujicich nejakemu kriteriu, ovsem co ta pridavna informace o tom poli, pokud je box elementem jednoho zaznamu, tak kazdy zaznam musi byt podle neceho vyhledan, no a tahle pridana informace patri do atributu data*, atributy se v javascriptu ctou velmi snadno, neni duvod to nepouzit, tvoje html pak bude vypadat mnohem cistejsi. No proste jdi do toho.

A pak resime problem s zobrazenim pouze vyhovujicich, ve skutecnosti jde o pravy opak zejo, ty se snazis najit ty ktery nevyhovoujou a schovat je, bohuzel myslim, ze querySelectorAll neumi regularni vyrazy, ale to ve vysledku nevadi, poresime si to sami, querySelectorAll ti poslouzi na ziskani seznamu vsech box divu, pak pojedes forem jeden po druhem a budes zjistovat jestli ten konknretni element ma v atributu data-tag ukryty substring pomoci metody indexOf (http://www.w3schools.com/…_indexof.asp) pokud tahle metoda vrati zaporne cislo hledany vyraz se tam nenechazi, pak element skryjeme, pokud se tam nachazi pak element nechame byt.

A ted opraveni me predchozi chyby, pokud chces stornovat ulohu po pripsani dalsiho pismena, musis pouzit figl a setTimeout(), jednoduse to udelas tak, ze na udalost stisku klavesy uvnitr inputu zachytis cas, zapises si ho globalne a pak zavolas s pul vterinovym zpozdenim dalsi funkci, predas ji obsah inputu, predas ji cas ve ktery byla vyvolana, predas ji odkaz na globalni timeStamp (jen kvuli elegantnimu kodu) a zasadni je, ze se provede z pulvterinovym zpozdenim, za tu dobu totiz prumerny clovek napise dalsi pismeno pokud chce, dojde k prepsani globalniho casoveho razitka (timeStamp) no a az se provede jiz stara a nechtena vyhledavaci procedura, prvni co po spusteni/probuzeni vykona je porovnani globalniho timestampu a sveho lokalne obdrzeneho v parametrech, pokud nesouhlasi return a nic dal se neresi, takhle se probublas az k te jedine vyhledavaci procedure, ktera nebude nicim nahrazena a ta se provede.

Prilozim ti ukazkovy torzo kodu:

window.onload = function () {
    var searchStamp = {time: new Date()};

    document.getElementById("search").addEventListener("keyup", function (event) {
        if ((!event.ctrlKey) && (event.keyCode > 45 && event.keyCode < 91) || event.keyCode === 8) {
            console.log("reakce");
            // jen pokud se pripsalo pismeno, nebo bylo nejake smazano, nekdo taky mohl jen stisknout spiku
            // taky to reaguje na delete a backspace
            // a ignoruje vstup, pokud byla stisknuta ctrl klavesa napriklad pro oznac vse
            var localTimeStamp = new Date();
            localTimeStamp = localTimeStamp + localTimeStamp.getMilliseconds(); // jde nam vazne o velmi presne casove rozlisovani
            searchStamp.time = localTimeStamp; // otiskneme do globalniho casu

            setTimeout(function (localTime, globalTime, slovo) {
                if (localTime != globalTime.time) {
                    return;
                }
                var listElem = document.getElementsByClassName("box"); // ziskam seznam vsech elementu
                for (var i = 0; i < listElem.length; i++) {
                    if (listElem[i].getAttribute("data-tag").indexOf(slovo) < 0) {
                        // v atributu data-tag nebyl nalezen string, ktery je v soucasnosti v inputu
                        listElem[i].style.display = "none";
                    } else {
                        listElem[i].style.display = "block";
                        // jen pro pripad, ze by byl skryt predchozim vyhledavanim
                    }
                }
            }, 500, localTimeStamp, searchStamp, document.getElementById("search").value); // predavani dalsich parametru nefunguje v IE 9 a nizsich
        }
    })
};

Doufam, ze ted uz bez chyb, v podstate je to zakladni reseni tveho problemu pamatujici i na zakladni klavesove zkratky pro oznaceni celeho textu, pripadne moznosti, ze user se rozhodne pouzit ctrl find a podobne, kdyz bude uvnitr tveho formu.

Kdyztak si napis o dalsi pdorobnosti.

Nahoru Odpovědět
7.4.2016 12:28
Neaktivní uživatelský účet
Avatar
Verquido
Tvůrce
Avatar
Verquido:8.4.2016 18:28

Tak sem to rozchodil :) Funguje to perfektně, ale jen pořád moc nechápu ty časy tam a obecně moc s timeoutem atp v javascriptu takže to bych ještě potřeboval vysvětlit, ale funguje to ;) Dík.

 
Nahoru Odpovědět
8.4.2016 18:28
Avatar
Verquido
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Verquido:8.4.2016 18:32

A také když ty diy mizí tak je to moc rychlý, chtělo by to tam nějaký přechod ale nevím kam to vrazit :)

 
Nahoru Odpovědět
8.4.2016 18:32
Avatar
Odpovídá na Verquido
Neaktivní uživatel:8.4.2016 23:43

Ohledne casovace, v zasade jde o tohle, kdyz ta akce bude nasledovat na udalost stisknuti klavesy (presneji zvednuti tisknute klavesy - protoze je to onkeyup), tak se to neprodlene po ni provede, vis co to znamena?
Ze pokud tam bude dlouhej task a ja do inputu napisu pet pismen, tak pro kazdy jedno dalsi pismeno se ten dlouhej task provede znova to prece nechces!
Nestojis o to neustale prohledave, elementy a hejbat s DOMem, nebo stylama na kazdou nerelevantni zmenu, to je spatne, ale nejde to zastavit, javascript je synchronni (az na vyjimky a triky), takze jakmile se ten proces rozbehne, tak ho nikdo nezastavi, nepredbehne, nevkroci mu do cesty, aby mohl prehodit vyhybku...proste NE ... od toho je tu ten malej trik.
V zasade rikam: Na udalost stisknuti klavesy reaguj neprodlene tak, ze zaznamenas cas stisku a ulozis ho do globalniho objektu, ktery je na to zkonstruovany a pote naplanujes ulohu se zpozdenim pul vteriny.
K cemu mi to je dobry? Za tu pul vterinu stihne prumernej clovek napsat dalsi pismeno, pokud chce, opet se neprodlene provede zaznam casu (aha....provede se, protoze mu v provadeni nic nebrani, kdybych ale rozbehl vyhledavani hned, muselo by dalsi pismeno cekat nez se funkce, prirazena udalosti keyup zacne provadet), tedy opakuji, provede se zaznam casu a v globalnim timeStampu se cas zmeni, kdyz uz user nic nepripise, za maly okamzik se probudi casovac od prvniho pismenka, prvni co udela je, ze se koukne v jaky cas bylo vlozeno pismenko, jez bylo jeho spousti, (funkce dostala ten cas jako argument) porovna ten cas s globalnim poslednim stiskem tlacitka (taky argument) a pokud se lisi (v tomhle pripade ano) rekne si: "skoda, user uz mezitim napsal dalsi pismeno, takze tenhle muj pozadavek je uz zbytecnej", hodi return a konec, za maly okamzik se spusti druhy casovac...zkon­troluje casy, jsou shodne, provede hledani, provede zobrazeni a skryti elementu no a parada mas cos chtel...

ohledne nejakyho fadeout/fadein efektu, najdi si co ti vyhovuje, jQuery ma fadeIn fadeOut funkce, budes je vkladat jednoduse tam, kde menis vlastnost display elementu, nezapomen, ze display bud zakomentujes uplne, nebo v zavislosti na tom jak funguje ta konkretni implementace fade funkci, udelas nejdriv fade a pak se ujistis zmenou displaye, ze je element kompletne srkryt, nebo zobrazen. Samotnej javascript nenabizi jendoduchou radkovou variantu postupneho zmizeni, ci postupneho prolnuti.

No doufam, ze mas co potrebujes, samozrejme uloha nabizi prostor pro nejaky mikrooptimalizace, napriklad, co je lepsi rict jiz skrytemu elementu at se skryje (opetovne mu nastavit display na none i kdyz tak uz byl) nebo se ifem ujistit ze je vlastnost display rovna none a pouze paklize neni, ji prepsat. To necham na tobe, posune te to blize k spravnemu stylu psani webappek.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
8.4.2016 23:43
Neaktivní uživatelský účet
Avatar
Verquido
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Verquido:9.4.2016 12:59

Děkuju ;) Moc mi to pomohlo. Dal sem ti řešení.

 
Nahoru Odpovědět
9.4.2016 12:59
Avatar
Odpovídá na Verquido
Neaktivní uživatel:9.4.2016 13:10

Obojí mě těší :-)

Nahoru Odpovědět
9.4.2016 13:10
Neaktivní uživatelský účet
Avatar
Verquido
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Verquido:17.4.2016 12:48

Ahoj, ještě dodatečně mě teď napadlo že to řeší i velká a malá písmena.. Jak by šlo udělat aby to nebralo v ohledu jaký to jsou? :D

 
Nahoru Odpovědět
17.4.2016 12:48
Avatar
Odpovídá na Verquido
Neaktivní uživatel:17.4.2016 17:56

pouzijes na atribut .toUpperCase() a do indexOf() to pridas taky - abys uppercasoval i ten vyhledavanej vyraz ... nebo muzes pozuti opak, ale je to jedno, jde o to ze si vsechny stringy prevedes na velky pismena a vsechny vyhledavany vyrazy take ... no a pak je to jasny .. je?

Nahoru Odpovědět
17.4.2016 17:56
Neaktivní uživatelský účet
Avatar
Verquido
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Verquido:17.4.2016 19:37

Super, díky :) Já to dával jenom k tomu indexOf() .. proto mi to nešlo :)

 
Nahoru Odpovědět
17.4.2016 19:37
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 14 zpráv z 14.