Mitenkähän saisin
Kyseessä on GM-userscripti, jota ajan Operassa. Funktiot ovat Prototypen Class
olion sisällä. Palvelin sylkee ISO-8859-1 -sivuja. En voi muuttaa palvelimen asetuksia. Testimielessä.
Kokeiltu merkistöongelmaan
encoding
-asetusta Ajax.Request
-oliolle sekä xhr.setRequestHeaderiä
. Ei vaikutusta.decodeURIComponent(encode(s))
-kikkaa (jossain mainostettiin toimivaksi UTF-8 dekoodaajaksi). Ei vaikutusta, koska jo alkaessani tutkimaan merkkijonoa, erikoismerkit ovat muotoa U+FFFD, ts. Unicode REPLACEMENT CHARACTER
, ts. siirron merkistön asettaminen ei ole onnistunut?Kokeiltu dokumentinmuodostusongelmaan
new Element(response.responseText)
. Yllättäen epäonnistuu :).
document.implementation.createDocument
.
var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null); doc.innerHTML = response.responseText; var newContentDiv = doc.evaluate('id="sisalto"', doc, null, XPathResult.ANY_TYPE, null), contents = newContentDiv.iterateNext();
Evaluate
kyllä palauttaa XPathResultin
, mutta iterateNext
ja doc.getElementById
palauttavat molemmat nullia
.
response.responseXML
-attribuuttia. Tyhjä olio.Prototypellä
new Ajax.Request(e.element().readAttribute('href'), { method: 'get', encoding: 'iso-8859-1', onSuccess: function(response) { var html = response.responseText, contentStart = html.lastIndexOf('id="alkuid"'); contentDiv.update(html.substring( contentStart + 13, html.lastIndexOf('id="loppuid"') - 13 )); }, onFailure: function(response) { contentDiv.update('<strong>Sisällön lataaminen epäonnistui.</strong>'); } });
Natiivisti
var xhr = new XMLHttpRequest(); xhr.onreadystatechange = updateContentDiv; function updateContentDiv() { if (xhr.readyState === 4) { if (xhr.status === 200) { var html = xhr.responseText, contentStart = html.lastIndexOf('id="alkuid"'); contentDiv.update(html.substring( contentStart + 13, html.lastIndexOf('id="loppuid"') - 13 )); } else { contentDiv.update('<strong>Sisällön lataaminen epäonnistui</strong>'); } } } xhr.open('GET', e.element().readAttribute('href')); xhr.setRequestHeader('Content-Type', 'text/html; charset=iso-8859-1'); xhr.send();
Kuriositeetti: Opera päätti ruveta pätkäisemään GM-userscriptin lopusta pois merkkejä kun lisäsin luokkaan tuon ajax-metodin, piti padata loppuun kommentteja :o. Tarkemmin kun testailin, niin näytti tekevän tuota, kun koodissa on riittävän monta sisäkkäistä blokkia tmv., eikä vaikuttanut vaikka koodi oli kommenttien sisällä, wtf.
GM ei näyttäisi pääsevän näköjään ollenkaan käsiksi sivun alkuperäisiin olioihin, eikä Prototypen lataaminen requirellakaan onnistu (eri versiot heittävät eri ongelmia, mistä kiitos kuuluu luultavasti GM:n astetta tiukemmalle suorituskontekstille), joten enpähän testaile sitten sitäkään, onko vika selaimessa. Pitää kokeilla Chromella, kunhan jaksaa taas tapella.
Merkistöongelmaan
En ota kantaa GM-puoleen, mutta JS:n tekstit ovat Unicodea, Prototype ei vaikuta tähän, XHR:n encoding vaikuttaa vain lähtevään dataan, ja sivun tai JS-tiedoston merkistökään ei käytännössä paina kuin tiedostossa olevien tekstien verran.
XHR-vastauksen pitäisi muuttua tekstiksi ihan HTTP-otsikossa olevan merkistön mukaan. Teinkin tästä pienen testin, ja kaikki näyttää toimivan ihan sääntöjen mukaan paitsi jos palvelin ei ilmoita merkistöä! Eli jos palvelimelta tulee pelkkä "Content-Type: text/html", merkistö näyttäisi maagisesti menevän UTF-8:ksi, jolloin responseText sisältää U+FFFD-merkkejä. Tässä vaiheessa encode-decode-kikka on luonnollisesti jo myöhässä.
Ehdotan siis seuraavaksi kokeiluksi, että lähetät palvelimelta selvän merkistötiedon.
header("Content-Type: text/html; charset=ISO-8859-1");
Dokumentinmuodostusongelmaan
Varmasti tunnet itse datasi paremmin, mutta onkohan tuo -13 kuitenkaan oikein tekstin loppuindeksissä?
Helppo purkkaratkaisu itse ongelmaan voisi olla, että luot vain sivun loppuun näkymättömän divin ja dumppaat HTML:n sinne. Sittenhän käytössä ovat täsmälleen samat hakuvälineet kuin sivulla muutenkin.
jQueryssa taitaisi onnistua myös tuo ensimmäinen ideasi, $(koodi). En sitten tiedä, toimiiko tuosta välttämättä hakeminen.
Yritin tässä siis hakea Putkan alasivuja kehittäessäni lisätoimintoja Putkaan, "alkuid" on oikeasti "sisalto" ja "loppuid" "alapalkki". Jos tän nyt joskus saa toimimaan niin tutkin luonnollisesti lisääkö tämä kaistankulutusta, ts. ohittaako välimuistituksen (ei pitäisi?). En siis pääse vaikuttamaan palvelimen lähettämään dataan :). Ihan hyvä idea tuo diviin puuppaus, tattis.
Ahaa, no toimiiko nyt? :)
Toimii, kiitos :). Kokeilin myös tuota diviin upottamista, mutta DOM-puun luominen kokonaiselle dokumentille on sen verran raskasta, että tuosta aiheutui huomattava nopeusero. Myöskin luodun divin poistamisessa oli ongelmia (sille ei löytynyt parenttia
. Ehkäpä, koska selain ei ollut ehtinyt muodostamaan DOM-puuta?), joten käytän suosiolla tuota substr
-purkkaa. Kiitos myös merkistöselvityksistä, tuntuu taas piirun verran viisammalta. Jonkun hakutuloksen mukaan ECMAScriptin suositeltu koodaus olisi UTF-16, huhhuh.
Kyllähän sillä divillä pitäisi parentNode olla? Ainakin minulla toimii ihan hyvin tämä rimpsu:
var div = document.createElement("div"); document.body.appendChild(div); div.innerHTML = "<a id='testi' href='#abc'>abc</a>"; alert(document.getElementById("testi").href); div.parentNode.removeChild(div);
tsuriga kirjoitti:
Jonkun hakutuloksen mukaan ECMAScriptin suositeltu koodaus olisi UTF-16, huhhuh.
Mitä tarkoitat tuolla suositellulla koodauksella? Uskoisin, että skriptin muuttujat ainakin sisäisesti onkin koodattu UTF16:lla enkä pitäisi sitä mitenkään ihmeellisenä.
Virhe tulikin siitä, kun ylikirjoitin uuden divin epähuomiossa updatella
, ei liene yllätys ettei divillä ole silloin enää parenttia. Diviin puuppamisessa esiintyy kumminkin hitausongelmaa siirryttäessä tietyltä sivulta toiselle, esim. tästä keskustelusta Ohjeet-sivulle. Substring
-purkalla tätä ongelmaa ei ole.
Debuggaus on tällä hieman mystistä, Dragonflyn virhevälilehdelle ei tulostu virheitä ollenkaan, vaan pitäs muistaa ottaa break on error pois skriptivälilehdeltä ja skrollata koodia, tai sitten kattella suoraan Operan virhekonsolia.
Njoo, sisäiseen koodaukseenhan tuolla viitattiin, luin huolimattomasti.
Putkan palvain kehottaa näköjään lataamaan aina uusiksi. AJAX lisää kyllä Prototypellä kaksi ylimääräistä headeria itse sivurequestiin, mutta... Dragonfly näyttää AJAXia käytettäessä vain tuon itse sivun hakemisen. Onko siis niin, että Opera ei yritä hakea sivun resursseja, vaikka lisään koko sivun DOM-puuhun? Koska tällöin kaistansäästöä tulisi selvästi, kun ei tarvitse olla pyytelemässä joka sivupyynnöllä resursseja, jotka eivät vaihdu kuitenkaan (palvelin lähettää 304:sta). Ja jos DOM-puuhun pujottaminen tuottaa resurssihakuja niin pitääkö tässä taas palata substring
-purkkaan?
Pitäisin mahdollisena, että selain aloittaa resurssien lataamisen vasta, kun JS on suoritettu. Tuossa kuitenkin poimit saman tien mukaan pelkän sisällön, jolloin resursseja ei ehkä ehditä käsitellä.
Mahdollisissa substring-kikkailuissa body voisi olla varmempi kiintopiste.
Kunhan Putka ei vaihda id:itä tai elementtien järjestystä niin hyvin toimii :). Yritän emuloida semanttista toimintaa, jossa vaihdetaan vain muuttuva sisältö. Totta tosiaan, tällä ei päivity sivupalkki, mutta sen päänmenoksi olen suunnittellut jo muutakin.
Älä tee liian innokkaasti, ettei muutoksista seuraa pettymyksiä. ;P
Aihe on jo aika vanha, joten et voi enää vastata siihen.