Diskuze: ajax
V předchozím kvízu, Online test znalostí JavaScript, jsme si ověřili nabyté zkušenosti z kurzu.


Jindřich Máca:26.7.2018 22:25
Ahoj, špatně děláš v první řadě to, že v tom souboru zzzzzzk.html neposíláš validní HTML, ale to asi nebude jediná chybka, které se dopouštíš. Mám dneska dobrou náladu, tak to trochu rozvedu.
1. První problém působí na pohled jako kosmetická vada na kráse, ale v důsledku může způsobovat až časově závislou chybu. Jedná se o pořadí těch příkazů. Přeci nemůžeš definovat funkci pro zpracování až potom, co už je požadavek odeslaný... Takže by to mělo vypadat spíš takhle:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr);
}
};
xhr.open("GET", "zzzzzzk.html");
xhr.responseType = "document";
xhr.send();
P.S.: Nechci Tě mást, ale šlo by to udělat i jednodušeji pomocí
onload
eventu (viz. ukázky v odkazu níže).
2. Druhý a ten zásadní problém je, jak jsem uvedl hned na začátku, že v tom souboru zzzzzzk.html máš nevalidní HTML. V tom první příkladu, co jsi uvedl se to neprojeví, protože tam to přebíráš jako prostý text a nepokoušíš se to nijak dále zpracovat. Trochu mě pak ale zaráží ten styl, jakým jsi to podal. Napíšeš to sem jako
zobrazí i varování
a pod tím chyba jako brno
Chyba parsování XML
Jelikož jsi sem to HTML neuvedl, těžko soudit v čem přesně je problém, ale na druhou stranu v té chybě je to přesně napsané včetně čísla řádku...
Zkusil jsem: hledat, ale nemůžu najít odpověď
A zkusil jsi vůbec přečíst tu přesně definovanou chybu, kterou jsi sem
zkopíroval a která je dokonce v češtině?!
3. Další věc, na které ještě záleží jsou pak HTTP hlavičky s typem obsahu a kódováním, které se při parsování také mohou brát v potaz. Ale to spíš jen pro jistotu, protože bych řekl, že to nebude Tvůj problém...
Každopádně bych vřele doporučil nastudovat si https://developer.mozilla.org/…LHttpRequest, kde je vše
popsáno, včetně omezení a příkladů.
Jinak až se Ti to podaří, tak ten získaný objekt je typu
Document
, defakto stejný jako ten uložený v globální
proměnné document
. Můžeš s ním tedy i stejně pracovat
pomocí jeho rozhraní viz. https://developer.mozilla.org/…API/Document. A pokud tyto
dva chceš nějak propojovat, tak bys měl také využít příslušných metod
z tohoto rozhraní, což obecně nemusí být úplně triviální.
radian1:27.7.2018 9:26
máš pravdu že sem to měl přehodit.
Ale ten dokument html je validní, akorát tomu ajaxu se nelíbí že meta
značky a br elementy nejsou uzavřeny lomítkem.
Jinej způsob než to psát s lomítkama neni?
ale pořád nevím jak můžu vybrat element
v tom mojim mám ve script toto:
var xhr = new XMLHttpRequest();
XMLHttpRequest.responseType = 'document';
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = xhr.response;
console.log(data);
console.log(data.title); // undefined
var element = Document.getElementById('main'); // type error
console.log(element);
console.log(Document.links); // undefined
}
};
xhr.open("GET", "zzzzzzk.html");
xhr.send();
takhle sem zkrátil ten zzzzzk.html a přidal sem tomu lomítka.
<!DOCTYPE html>
<html lang='cs'>
<head>
<title>ZZk</title>
<meta charset='utf-8' />
<meta name='author' content='' />
<meta name='robots' content='all' />
</head>
<body>
<div id="wrapper">
<header id="header" style="" class="js-Menu"></header>
<main id="main" role="main">
<p>Text článku</p>
</main>
<footer id="footer"></footer>
</div>
</body>
</html>
Musis se naucit googlovat.
Je to xml (dom). Neni to html. Nefunguje na to stejny js jako na html.
Muzes s tim pracovat pres childNodes, getElementByTagName. Ale nejde pouzit
ostatni pohodlnejsi funkce.
google = js parse xml
<address>
<street>Roble Ave</street>
<mtfcc>S1400</mtfcc>
<streetNumber>649</streetNumber>
<lat>37.45127</lat>
<lng>-122.18032</lng>
<distance>0.04</distance>
<postalcode>94025</postalcode>
<placename>Menlo Park</placename>
<adminCode2>081</adminCode2>
<adminName2>San Mateo</adminName2>
<adminCode1>CA</adminCode1>
<adminName1>California</adminName1>
<countryCode>US</countryCode>
</address>
if (window.DOMParser)
{
parser = new DOMParser();
xmlDoc = parser.parseFromString(txt, "text/xml");
}
else // Internet Explorer
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(txt);
}
// ---
//Gets house address number
xmlDoc.getElementsByTagName("streetNumber")[0].childNodes[0].nodeValue;
//Gets Street name
xmlDoc.getElementsByTagName("street")[0].childNodes[0].nodeValue;
//Gets Postal Code
xmlDoc.getElementsByTagName("postalcode")[0].childNodes[0].nodeValue;
https://andrew.stwrt.ca/…xml-parsing/
google = js xml to array
<?xml version="1.0" encoding="iso-8859-1"?>
<profiles>
<profile id="1">
<pic>images/profiles/person1/x.jpg</pic>
<name>Joe Bloggs</name>
<nickname>J-Bloggs</nickname>
<age>21</age>
<email>[email protected]</email>
<role>Web Site Manager</role>
<likes>
<like1>Food</like1>
<like2>Drink</like2>
<like3>Computing</like3>
<like4>Music</like4>
</likes>
<dislikes>
<dislike1>Rude People</dislike1>
<dislike2>Rude People</dislike2>
</dislikes>
<favwebsite>http://www.facebook.com</favwebsite>
</profile>
</profiles>
var profiles = xml.getElementsByTagName("profile");
var arr = [];
for (var key in profiles){
arr.push([]);
var nodes = profiles[key].childNodes;
for (var ele in nodes){
if(nodes[ele]){
arr[key].push(nodes[ele]);
}
}
}
console.log(arr);
https://api.jquery.com/…ry.parseXML/
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery.parseXML demo</title>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<p id="someElement"></p>
<p id="anotherElement"></p>
<script>
var xml = "<rss version='2.0'><channel><title>RSS Title</title></channel></rss>",
xmlDoc = $.parseXML( xml ),
$xml = $( xmlDoc ),
$title = $xml.find( "title" );
// Append "RSS Title" to #someElement
$( "#someElement" ).append( $title.text() );
// Change the title to "XML Title"
$title.text( "XML Title" );
// Append "XML Title" to #anotherElement
$( "#anotherElement" ).append( $title.text() );
</script>
</body>
</html>
https://www.codingforums.com/…ascript.html
XMLDocument.prototype.toArray = function()
{
if (typeof Element.prototype.toArray == 'undefined')
{
Element.prototype.toArray = function()
{
if (this.childElementCount)
{
this.array = new Array();
for (i in this.children)
{
if (this.children[i].nodeType == 1)
{
this.array[this.children[i].nodeName] = this.children[i].toArray();
}
}
return this.array;
}
else
{
return this.textContent;
}
}
}
this.array = new Array();
this.array[this.documentElement.nodeName] = this.documentElement.toArray();
return(this.array);
}
radian1:27.7.2018 17:52
protože nemám rád rozsáhlí knížky jako je jquery a 96% věcí mám uděláno ve vanille js
radian1:28.7.2018 10:58
JS je sám o sobě rychlejší (podle vanilla-js.com) a navíc yablko vydává js kurz a já sem si řekl že to udělám čistě v js, jinak původně sem používal jQuery. JS nabízí úplně to stejný až na pár věcí.
1. První problém působí na pohled jako kosmetická vada na kráse, ale v důsledku může způsobovat až časově závislou chybu. Jedná se o pořadí těch příkazů. Přeci nemůžeš definovat funkci pro zpracování až potom, co už je požadavek odeslaný...
A neni to náhodou jedno? Prohlížeč přece musí nejdříve proběhnout celej soubor js a načíst funkce do paměti. Do té doby než neproleze celý soubor tak přece nemůže nic spouštět nebo se pletu? Hoisting se tomu říká. Možná se pletu, ale seš si jistej že by to mohlo způsobit problémy?
1. Na tom poradí nezáleží, iba musíš ten
typ nastaviť pred zavolaním send().
2. Avšak používanie XHR na nahranie HTML je problémové. Pôvodne podporoval iba XML, HTML sa pridávalo neskôr. A aj ťa to zaskočilo, pretože nepárové značky do XML nepatria.
3. Preto ak už čistý JS, tak Fetch API. Ak sa obávaš o kompatibilitu, tak plus polyfill, alebo to nechať na Babel.
4. Ale knižnice nie sú zlo. Ak šetríš bajty, nahraj si axios, malú knižnicu len na AJAX, alebo superagent, tá má prehľadnejší syntax, sám ju tiež používam. Lebo ak fetch() ešte nepoznáš, tak ako XHR s HTML, tak ťa Fetch zaskočí s CORS. A s axios nie.
radian1:11.8.2018 9:54
Tím typem myslíš open(get)? Tak to sem udělal tedy správně.
A co je ten onload? To je i po načtení všech obrázků?
Zhrniem Ti to:
Od začiatku si žiadnu chybu v XHR nerobil. Keď si nenastavil responseType, všetko fungovalo, lebo defaultne je responseType text. Takže bolo doslova fuk čo ti prišlo v odpovedi. Akonáhle si však nastavil responseType na document, očakával sa v odpovedi platný XML dokument. A tam si urobil chybu, v HTML, nie v XHR, lebo bežné HTML nie je platné XML. V tomto zmysle, že v XML musia byť všetky značky párové, uzavreté. A tak ti to zhavarovalo hneď v head, kde sú meta či link značky nepárové. Ak totiž plánuješ HTML strojovo spracúvať, mal by si použiť XHTML zápis, takže každú nepárovú značku, čiže aj ten link, br, img a pod. uzavrieť tým koncovým lomítkom. Iný spôsob nie je, keďže si sa na to vyslovene pýtal... Nasledne ti chýbal find z jQuery, ale to problém nie je. Vrátenú odpoveď môžeš traverzovať napríklad pomocou querySelector. Avšak je ti to celé rovno nanič, lebo to aj tak nemusí fungovať. Myslím, že v Safari napríklad ti to nepôjde. Takže sa zbytočne snažíš a keďže už chceš dve veci, ajax aj traverzovanie, preto som ti navrhol jQuery, lebo sú tam tieto veci ošetrené a je to crossbrowser. Ok, odmietol si. Preto som ti potom navrhol Fetch API, lebo to Ti bude fungovať v každom novom prehliadači, je to náhrada za XHR. Jasne, nejde v starých prehliadačoch, IE je tým pádom out, ale na to sú polyfills. Alebo Babel. S fetch však skôr či neskôr narazíš na CORS. Zasa sa s tým môžeš začať trtkať ručne a hľadať ako správne nastaviť request, alebo ... použi konečne knižnicu. Správne a crossbrowser všetko ponastavovať nie je hračka, to chce väčšiu hĺbku znalostí akú máš teraz. Navyše je to však nezmysel, lebo napísať to všetko sám, univerzálnym a crossbrowser ošetreným spôsobom v konečnom dôsledku znamená, že si napíšeš knižnicu. Akurát, že vlastnú. Takže načo celé toto? Nanič. Axios, superagent a pod. Tak znie tvoje riešenie...
Neodhováram ťa však úplne. Ak na to máš čas, skúšaj. Čím viac do hĺbky budeš chápať, tým lepšie. Mal by si však vedieť, že hlavne sa používa Fetch a až ako záložné riešenie XHR. Na traverzovanie, hľadanie v odpovedi sa používa to, čo v normálnom html, napríklad querySelectorAll('.mojaClass') a áno, tým onload mysleli to, že aj window má onload event, aj img má onload event, aj xhr má onload event...
A ako posledné by si mal vedieť, že správny spôsob je nepýtať sa
niekde na základy. Správny spôsob je otvoriť si na MDN dokumentáciu k
príslušnej API, prejsť ju kompletne aj s príkladmi, a až keď ju
naštuduješ ale aj tak ti niečo nepôjde, lebo si to napríklad zle pochopil,
až potom sa pýtaš. Hlavne nie spôsobom akým to robíš teraz: zahliadol som
niekde nejaké XHR a skúšam ho použiť bez toho, aby som si ho naštudoval. A
nejde mi to. Kde je chyba? No kde kurva asi...
Jindřich Máca:11.8.2018 13:10
Uznávám, že většinou je to jedno stejně jako v tomto případě, ale pokud třeba sleduješ stav, bude se chování při jiném pořadí lišit. Příklad:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {console.log('XHR State: ' + xhr.readyState)};
xhr.open("GET", "test.txt");
xhr.send();
vypíše:
XHR State: 1
XHR State: 2
XHR State: 3
XHR State: 4
Když to:
var xhr = new XMLHttpRequest();
xhr.open("GET", "test.txt");
xhr.send();
xhr.onreadystatechange = function () {console.log('XHR State: ' + xhr.readyState)};
vypíše pouze:
XHR State: 2
XHR State: 3
XHR State: 4
Je to pouhý detail, ale chování je prostě jiné.
P.S.: Co který stav znamená najdeš v dokumentaci - https://developer.mozilla.org/…t/readyState
+20 Zkušeností
+2,50 Kč

:11.8.2018 13:22
Ale mňa stav v princípe nezaujíma. A jeho tiež nie. Čo on chce a nevie, že to tak ide, je napísať to takto:
var xhr = new XMLHttpRequest()
xhr.open('GET', 'page.html')
xhr.responseType = 'document'
xhr.onload = function () {
console.dir(xhr.response.querySelectorAll('.someClass')
}
xhr.send()
Jeste mne napadlo, ze by mohl pouzit response = text. Pres innerHTML to vlozit do nejakeho divu s display=none a pak by s tim slo pracovat jako s html. Ale pak je mozne tam take pridat parazitni js. Tusim, ze innerHTML ma na to nejaka omezeni.
Jinak, na tom poradi pomerne zalezi. Jak pise Jindřich Máca. Send by mel byt posledni v poradi. Hlavne je mozne narazit na cross-browser komplikace.
Vladislav Ladicky - To je zrovna podobne, take muzes narazit na cross-browser
komplikace. Defaultne to neni vzdy xml a vzdy utf8. Mozna ted u novejsich
browseru. Lepsi je kodovani vzdy definovat. A idealne prave do xml nebo text a
utf-8. Nektere browsery nemeli vubec moznost kodovani zmenit. To se vymstilo
jednomu znamemu, ktery chtel posilat w1250
radian1:13.8.2018 17:04
to je fakt, ale já
původně přes Ajax stahoval celou stranku takže by tam byly dvě hlavičky do
té doby než bych to pak celý smazal. Ale mohl bych ověřit zda jde o Ajax
požadavek... Já už jsem to udělal v json. A teď když nad tím
přemýšlím tak ten tvůj způsob by byl daleko jednodušší
než se psát s generováním
jsou. Že sem na to nepřišel sám
's generováním jsou' ???
Na to jsou funkce, v php i ve firefox js.
google = php json -> json_encode($arr)
google = js json -> JSON.parse(str); (str = request.response)
radian1:14.8.2018 17:50
Ano, ale když vybírám třebas komentáře tak tu strukturu JSON musím napsat já. Je pravda že sem to ve výsledku udělal složitější než by to šlo.
Nerozumim, co znamena vybirat komentare.
Z sql vyberes data. Ta preformatujes fetchem do pole a pole zakodujes pres
json_encode na string. String odeslels uzivateli pres echo do requestu. Request
ot prebere jako text. Dekoduje pres parse na pole.
Tusim, jedina zaludnost je, ze nekde je treba rici, ze z toho chces pole a ne
objekty. Tusim, ze to je v php pri decode, ale to tam nepotrebujes.
To bys musel ukazat kod a rici, co to ma vlastne delat a co to nedela, od
ktereho radku je to spatne a tak.
https://developer.mozilla.org/…s/JSON/parse
Tady to dekoduji primo do pole, se kterym se da pracovat.
http://php.net/…n-decode.php
Tady je ta zaludnost...
assoc = When TRUE, returned objects
Example #1 json_decode() examples
<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
var_dump(json_decode($json));
var_dump(json_decode($json, true));
?>
Zobrazeno 22 zpráv z 22.