Avatar billede xfox Nybegynder
29. februar 2008 - 20:07 Der er 32 kommentarer

Grundlæggende Ajax regler

Hej alle

Jeg har for nylig taget Ajax til mig, og baner mig vej med små skridt. Det hele virkede så nemt til at starte med, indtil jeg løb ind i problemer med danske specieltegn. Så ledte jeg med lys og lygte, for at se om andre havde de samme problemer, og der faldt jeg over Olebole der kommenterede et indlæg om emnet.

Det gik op for mig at man kun må trække rå data ud, og f.eks. ikke må have html kode med. Hvad gør man så hvis det er flere værdier der skal hives ud på én gang? Hvordan håndtere man dette?

Når man så har fået sine data ud og vil have dem placeret i f.eks en tabelcelle, hvad gør man så, når nu ikke man må bruge innerHTML. Så vidt jeg kunne forstå på Ole var innerHTML en dårlig løsning, og man skulle hellere bruge DOM. Men er innerHTML ikke en del af DOM? Samtlige guides jeg har fundet på nettet omkring emnet bruger nemlig innerHTML, ikke at det skulle gøre det mere rigtigt :o)
Avatar billede w13 Novice
29. februar 2008 - 20:14 #1
Nej, innerHTML er bestemt ikke DOM. Snarere det modsatte.
Og dét at samtlige guides bruger innerHTML styrker kun Oles påstand om, at stort set samtlige guides er noget l*rt. =)

Du bør nok læse Oleboles artikler her:
http://wwww.dengodekode.dk/artikler/DOM/no_innerhtml.php
http://wwww.dengodekode.dk/artikler/ajax/xmlhttprequest_wrapper.php

Skal du bruge ASP/PHP til at generere data med?
Avatar billede xfox Nybegynder
29. februar 2008 - 20:21 #2
Jeg var inde på w3schools hvor jeg fandt innerHTML under DOM, så jeg var lidt i tvivl: http://www.w3schools.com/htmldom/dom_obj_tabledata.asp

Det er PHP jeg bruger, og jeg vil da med det samme kigge på Ole's artikler.
Avatar billede thesurfer Nybegynder
29. februar 2008 - 20:26 #3
xfox> Brugerne roenving og olebole plejer at sige, at følgende 2 sider er skod (de bruger nok ikke ordet "skod", men hey..), da de indeholder fejl:

html.dk
w3schools.com

Jeg ved ikke om du har lagt mærke til det, men der står også "No" under "W3C" (helt ud til højre i tabellen) ud for "innerHTML".. så noget har de fanget.. :-)
Avatar billede thesurfer Nybegynder
29. februar 2008 - 20:29 #4
PS:
W3C = World Wide Web Consortium = http://www.w3.org/

De laver internationale standarder, som man kan vælge at følge eller lade vær..

Hvis alle browserne, og alle webudviklerne, fulgte W3C standarderne, ville alle siderne virke i alle browserene, på alle platform..

Det er en teori, da dette aldrig er sket.. og sker nok ikke forløbigt..
Avatar billede xfox Nybegynder
29. februar 2008 - 20:40 #5
Aha, har nu fået slået fast at innerHTML ikke er DOM. Så mangler jeg bare at finde ud af hvordan jeg håndtere flere værdier i output'et. Hvis jeg nu henter 3 værdier fra en database, via Ajax, hvordan kan jeg så bruge dem hver for sig? Jeg har jo kun en responseText hvor de havner i....eller?
Avatar billede thesurfer Nybegynder
29. februar 2008 - 21:01 #6
Du sender dataene tilbage som noder via XML..

Ellers kan du f.eks. også bare sende en streng tilbage, der indeholder samtlige værdier, separeret af et specielt tegn..

Eksempel på det med en streng:

var s = "hej:med:dig"; // strengen som du får tilbage via ajax

var a = s.split(":"); // split strengen op ved tegnet ":", som opretter en array (a)

for(var i = 0, len = a.length; i < len; i++)
{
alert("På plads " + i + " har vi: " + a[i]);
}

Så siger browseren:

På plads 0 har vi: hej
På plads 1 har vi: med
På plads 2 har vi: dig
Avatar billede w13 Novice
29. februar 2008 - 21:06 #7
Mange vælger også JSON frem for XML, da man så kan outputte f.eks.:

{"navn1":"værdi1","navn2":"værdi2"}

Så kan du (når du har lavet noget json-fixfaxeri) hente værdierne med json.navn1 og json.navn2

Du kan også overføre hele arrays:

{"navn1":"værdi1" , "navn2":["værdi2_1","værdi2_2","værdi2_3"]}

Eller objekter:

{"navn1":"værdi1" , "navn2":{"navn2_1":"værdi2_1","navn2_2":"værdi2_2"}}
Avatar billede w13 Novice
29. februar 2008 - 21:14 #8
Fixfaxeriet er nærmere betegnet:

var json=eval("("+req.responseText+")");

alert(json.navn1);
alert(json.navn2);

:)
Avatar billede thesurfer Nybegynder
29. februar 2008 - 21:18 #9
Jeg har engang læst/hørt/set/andet at det at bruge "eval" er no-no, fordi det skulle være krævende.. måske noget reference-halløj også.. men det kan de kloge hovedet nok svare på.. :-)
Avatar billede w13 Novice
29. februar 2008 - 21:34 #10
Ja, har hørt nogen sige, der er ulemper, nogle overforbruger det derimod. Personligt bruger jeg det kun sammen med JSOn, som vist ovenfor.
Og jeg mener i øvrigt, det kun kan gøres med Eval().
Avatar billede kalp Novice
29. februar 2008 - 23:00 #11
returner det som XML, så kan du få så mange værdier du vil med tilbage.
Avatar billede w13 Novice
29. februar 2008 - 23:13 #12
Det kan man da også med JSON? :) Og der skal ikke hentes ligeså meget kode ned med JSON. Det er kun rå data.
Avatar billede olebole Juniormester
01. marts 2008 - 03:15 #13
<ole>

kalp >> Du bør sætte dig ind i, hvad JSON er. JSON og XML kæmper ingenlunde om samme plads eller forsøger at udelukke hinanden, men kan forskellige ting og har hver deres fordele. Dog er JSON ofte at foretrække til brug i Ajax - og her kan du sende ligeså komplekse data tilbage til klienten, som du kan med XML  ;o)

thesurfer >> Det er helt korrekt, at man bør begrænse brugen af eval til et absolut minimum. Eval er i virkeligheden en fantastisk funktion, der kan en utrolig bunke, men netop fordi den skal kunne så meget, bliver den ret langsom.
Mange kodere bruger den til ting, hvor den ligeså godt kan undværes - og så bør den _absolut_ undværes - men den kan ikke undværes, når et XMLHttpRequest objekt returnerer en JSON-streng, der skal 'tilbage-serialiseres' til et JavaScript objekt.

xfox >> kik evt. i denne tråd, hvor jeg har forklaret lidt om brugen af JSON - og dermed også om at få mere komlekse data overført og indsat i siden:
    http://www.eksperten.dk/spm/817625

/mvh
</bole>
Avatar billede olebole Juniormester
01. marts 2008 - 03:19 #14
Til at hjælpe på forståelsen af JSON kan det måske være en idé at læse denne artikel om sammenhængen mellem arrays (ikke mindst de associative arrays) og objekter i java script:
    http://www.eksperten.dk/artikler/227

Endvidere kan du læse om emnet her:
    http://www.json.org/
Avatar billede olebole Juniormester
01. marts 2008 - 04:04 #15
De store problemer med Ajax opstår, når man sætter event handlers på elementer. Problemerne opstår primært i IE, der har en 'ret særegen' garbage collection.
Der opstår meget let en situation, hvor det indre af en funktion refererer til et DOMElement - som igen refererer til en funktion (eller reference til en sådan), indenfor den første funktions scope.
Derved 'låses' funktions-scopet sammen med DOMElementet i en såkaldt cirkulær reference. Denne reference kan ikke umiddelbart brydes, når elementet nedlægges, men vil fortsætte med at beslaglægge plads i hukommelsen. Ikke engang når der navigeres til en anden side, bliver der frigivet hukommelse. Først når browserinstansen lukkes, frigives hukommelsen endelig.

Den slags memory leaks kan ved større applikationer meget let ende med at rive browseren på gulvet - og i bedste fald få applikationen til at blive ekstremt langsom!

Egentlig er problemet ikke knyttet til Ajax som sådan. Det bliver blot meget lettere synligt, når der ikke navigeres og der oprettes og nedlægges i hundredevis (og ofte tusindvis) af elementer ... så summer de enkelte, forholdsvis små leaks hurtigt op!

Forestil dig et forretnings- eller lagerstyrings system - eller noget andet, hvor man vedligeholder en database med mange felter.
Her vil man ofte bruge en tabel, hvor rækker hele tiden oprettes og nedlægges - og måske endda gennem en hel dag. Det bliver lynhurtigt _rigtig_ mange rækker med mange celler i hver - og med tilhørende mouseover effekter og sikkert også noget onclick.
That spells 'DEATH'! ... eller et iskoldt overblik  ;o)

En anden ting er at udføre tingene i en hensigtsmæssig rækkefølge, når man koder DOM. Hvis du opretter et element med createElement og tilføjer en event handler, inden elementet er indsat i dokumentets DOM-træ, vil der også opstå en memory leak.
I så tilfælde vil der nemlig blive oprettet et 'midlertidigt', lokalt script scope. Når elementet indsættes i dokumentet, oprettes det endelige script scope for det pågældende element, og det midlertidige burde nedlægges i hukommelsen. Det sidste sker bare ikke i IE med en memory leak til følge  :o|

Derfor bør man altid først tilføje event handlers, efter et element er appended til et eller anden i dokumentets DOM-træ. Det kan medføre lidt ekstra kode, men det må man tage med.
Af performance hensyn sætter man helst ikke elementer direkte ind i dokumentet, hvis der er tale om mange elementer - f.eks. at skifte 50 rækker i en tabel med nye data. I stedet opretter man et tbody-element i hukommelsen, som man appender alle de nye rækker til. Når alle rækker er indsat, bruges replaceChild til at bytte det eksisterende tbody-element ud med det nye ... og man skal derefter huske at fjerne/null'e alle event handlers på elementer i det fjernede tbody-element og null'e disse.
Først derefter går man alle rækker igennem i en ny løkke og tildeler event handlers.

Hermed fik vi lige kradset en anelse i Ajax' overflade. Det er absolut ikke en teknik, der er lige til kaste sig ud i. Først, når du er i stand til at skrive rigtig komplekse HTML, JavaScript, CSS, DOM applikationer - og har opnået meget stor erfaring med de forskellige browseres mere eller mindre udokumenterede særheder - kan du så småt begynde at kaste dig ud i at udforske Ajax  :)
Avatar billede olebole Juniormester
01. marts 2008 - 04:22 #16
Du kan såmænd sagtens bruge innerHTML til indsættelse af data i dokumentet. Loftet falder ikke ned over dig, og du får ikke blodfyldte bylder omkring ringmusklen af det. Er man meget påpasselig, kommer man endda heller ikke til at overskrive event handlers eller referencer. Derfor er der mange, der argumenterer for brugen af innerHTML og finder det religiøst hysteri at argumentere mod.

Selvom man kan være nok så påpasselig med den kode, man sidder og koder ind i, kan man ikke forudse, hvordan koden evt. skal udvides på et senere tidspunkt. Overfor disse udvidelser ken man ikke være påpasselig - og brugen af innerHTML kan derfor meget vel begrænse mulighederne for evt. senere udvidelser.

Desuden er det ikke muligt for mig at arbejde med den form for 'fleksibilitet' overfor standarderne. Der er fortrinlige muligheder for manipulation af elementer med DOM og dermed igen grund til at bruge invalid kode.
Hvis det er okay at bruge invalid kode som innerHTML, hvor meget er det så nødvendigt at overholde andre dele af standarderne - og hvorfor? Hvormange procent invalid kode kan jeg tillade mig at bruge?

Hvorfor dog besvære sig med den slags komplicerede overvejelser, når der findes fremragende, valide alternativer til invalid kode?  ;o)
Avatar billede olebole Juniormester
01. marts 2008 - 04:24 #17
Der skulle sæ'fø'li' stå 'ingen grund':
"Der er fortrinlige muligheder for manipulation af elementer med DOM og dermed ingen grund til at bruge invalid kode."  =)
Avatar billede kalp Novice
01. marts 2008 - 09:16 #18
Det er kun logisk for mig, at vælge XML da det til dagligt er det jeg arbejder med.
Arbejder stortset kun med SOA og alt kommunikation mellem systemerne er via. XML.

Jeg siger ikke, at JSON er skidt:) og jeg kommer sikkert også til at prøve det af på et tidspunkt når den rigtige opgave lander på mit bord:)
Avatar billede w13 Novice
01. marts 2008 - 13:12 #19
Ole>> Måske lidt off-topic, og så måske alligevel ikke. Synes det passer godt til din beskrivelse af DOM i hvert fald.

documentFragment-objektet beskrives som en "letvægts"-udgave af document-objektet og og virker da derfor langt mere hensigtsmæssig at bruge til midlertidig opbevaring af elementer/noder, inden de placeres synligt i dokumentet.
Hvornår vil det så være bedst at bruge document.documentFragment fremfor blot document? Jeg synes ikke, jeg kan finde så mange gode eksempler af det på nettet - for det meste er det bare variationer af den samme W3C-forklaring.

Jeg så bl.a., at du brugte documentFragment i en af dine artikler og det skærpede jo lidt min interesse, da jeg aldrig selv rigtig har benyttet det.
Avatar billede olebole Juniormester
01. marts 2008 - 16:18 #20
w13 >> ikke spor off-topic - tværtimod  :)

Et dokumentFragment er en lidt pudsigt, 'pseudoagtig' node. Du kan bruge den til at indsætte andre noder i. Når de ønskede elementer er tilføjet, kan fragmentet indsættes et sted i DOM-træet - hvorefter fragmentet så at sige 'forsvinder'.

DokumentFragmentet er ikke til at finde i DOM-træet, og undersøger man fragmentets indhold efter dets indsættelse i træet, viser det sig at være tomt! Dets 'børn' er blot blevet overført til dokumentets DOM-træ, mens fragmentet selv bliver liggende i hukommelsen.

Prøv denne lille kode (Bemærk, at et documentFrament's nodeType er 11 - mens et alm. DOMElement har nodeTypen 1):

<script type="text/JavaScript">
function foo() {
    var oDocFrag = document.createDocumentFragment();
    var oDiv = document.createElement("div");
    oDocFrag.appendChild(oDiv);
    oDiv.appendChild( document.createTextNode("Blabla A") );
    document.getElementById("gnu").appendChild(oDocFrag);
    alert("NodeType af divets parentNode: " + oDiv.parentNode.nodeType);
   
    alert("Antal childNodes i fragmentet efter indsættelse: " + oDocFrag.childNodes.length);
    var oDivB = document.createElement("div");
    oDocFrag.appendChild(oDivB);
    oDivB.appendChild( document.createTextNode("Blabla B") );
    document.getElementById("gnu").appendChild(oDocFrag);
}
</script>

<p><button onclick="foo()">TEST</button></p>

<div id="gnu"></div>

Man kan indsætte tabelrækker i et tbody-element og efterfølgende udskifte en tabels tbody med den ny tbody ... og tømme/rense den gamle tbody (og dermed frigøre hukommelse).

I stedet kan man indsætte tabelrækker i et documentFragment. Så vil man først tømme/rense en tabels bestående tbody og efterfølgende appende fragmentet til tbody-elementet.

Umiddelbart tror jeg ikke, der er den store forskel på de to metoder - men den antagelse bygger alene på 'tro og religion'. Jeg har endnu ikke testet og sammenlignet performance, m.m, men det vil jeg nok gøre meget snart  ;o)
Avatar billede xfox Nybegynder
06. marts 2008 - 00:13 #21
Meget interessanter informationer. Det gav lidt at både tænke og læse over. Uden at være den store haj til hverken DOM, AJAX eller JSON prøvede jeg at lave koden om så den passede til min HTML med Div'er. I stedet for at holde øje med hvilket nummer TD man var kommet til ved indsættelse af data, lavede jeg et almindelig plain reference til ID'et på mine div'er:

var d=document;
function gE(id){return d.getElementById(id)};
function gA(o,t){return o.getElementsByTagName(t)};

function myCallBack(oHttp) {
    eval("var oResp = " + oHttp.responseText);
   
    var aRows = oResp.rows;
    for (var i=0,j=aRows.length; i<j; i++) {
        gE("info-overskrift").childNodes[0].nodeValue = aRows[i].aktivitet;
        gE("content").childNodes[0].nodeValue = aRows[i].beskrivelse;
        gE("link").childNodes[0].nodeValue = aRows[i].link;
       
    }
}

Det virker også fint, og data bliver indsat. Desværre er den ikke helt glad for æøå. Syntes ikke det hjælper, om jeg bruger utf-8 eller iso-8859-1 i charset, uden at kende forskellen. Er jeg helt på vildspor?
Avatar billede olebole Juniormester
06. marts 2008 - 01:45 #22
I dokumentet, du udskriver JSON med, skriver du aller øverst en HTTP-header:
    header("Content-Type: application/json; charset=utf-8");

- ligesom du skal bruge en utf-8 meta i dit HTML-dokument.

Desuden skal du sørge for at gemme alle dokumenter som utf-8. Du kan evt. åbne dem i Notepad og sørge for, de bliver gemt korrekt (encoding håndteres nederst i Save As dialogen i Notepad).

Henter du data fra en database, skal du f.eks. i phpMyAdmin sørge for den korrekte kollation på dine tabeller (utf-8).

Til sidst kan du tjekke hvilket tegnsæt, dine HTML-dokumenter serves med - også selvom de hedder '*.php'. Skriv URL'en her:
    http://validator.w3.org/#validate_by_uri+with_options

Husk at sætte flueben i 'Verbose Output'. Så vil du kunne aflæse det tegnsæt, serveren sender dokumenterne med. Er det iso-8859-1, må du omdøbe filen til '*.php', hvis det nu hedder '*.html'. Derefter skriver du endnu en HTTP-header ... denne gang i toppen af HTML-dokumentet:

<?php
header("Content-Type: text/html; charset=utf-8");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
... osv ... osv ...
Avatar billede olebole Juniormester
06. marts 2008 - 01:49 #23
Husk også at sætte en request header, når du kalder med XMLHttpRequest objektet:

var oHttp = new XMLHttpRequest();
oHttp.open("post", sURL, true);
// Sæt en request header her:
oHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
oHttp.onreadystatechange = fnCallBack;
oHttp.send(sQuery);
Avatar billede roenving Novice
06. marts 2008 - 16:45 #24
-- og såvidt jeg husker bør din eval på json-objektet se således ud:

var oResp = eval("(" + oHttp.responseText + ")");
Avatar billede olebole Juniormester
06. marts 2008 - 17:00 #25
roenving >> Det er helt korrekt. Det er af hensyn til brug af sære feltnavne, som evt. kan kollidere med JavaScripts vokabularium. Det burde ikke genere her, men det er da en vigtig detalje at tage med  ;o)
Avatar billede xfox Nybegynder
06. marts 2008 - 18:31 #26
Det er som om at det ikke hjælper. Jeg har sat alle headers, og ændret min database kollation fra latin til utf8_unicode_ci. Desuden melder validatoren også tilbage at det er utf-8, dog siger den at det tekst jeg har på siden, hvoriblandt der er æøå, ikke kan valideres da det ikke er korrekt utf8 format..?
Avatar billede xfox Nybegynder
06. marts 2008 - 18:35 #27
Det kan da lige nævnes at dataene fra ajax/json bliver skrevet ud til den når et æøå. Altså ved sætningen "Nu søger" kommer kun "Nu s".
Avatar billede olebole Juniormester
16. marts 2008 - 23:12 #28
Jeg kan ikke komme tættere på, hvad du laver af fejl uden at se et link - men det er helt sikkert, du laver fejl et eller andet sted. Er du f.eks. helt sikker på, dine dokumenter er gemt som Unicode (utf-8)?
Avatar billede olebole Juniormester
17. marts 2008 - 01:01 #29
Prøv at lave et dokument, som det her:

<?php
header("Content-Type: text/html; charset=utf-8");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>TITLE</title>
</head>
<body>

<?php
[OPEN_MYSQL_DATABASE];
$sql = [MYSQL_QUERY];
$res = mysql_query( $sql ) or die ( mysql_error() );
$a = array();
while ($row=mysql_fetch_assoc($res)) {
    $a[] = "<div>" . $row["FELT_NAVN"] . "</div>";
}
print implode("\r\n", $a);
?>

</body>
</html>

- og gem det som utf-8. Hvad sker der så med specialtegn som æ, ø og å? Det skal være de samme felter, du prøver at kalde med Ajax
Avatar billede w13 Novice
22. april 2008 - 11:40 #30
Kommet videre?
Avatar billede xfox Nybegynder
03. december 2010 - 18:28 #31
Jeg fandt aldrig en løsning, men vil gerne have tråden lukket. Er der nogen der vil komme med et svar?
Avatar billede w13 Novice
03. december 2010 - 18:32 #32
Ikke til mig, tak. :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester