'; ?> Ajax (Asynchronous JavaScript and XML) - WWW-sovellukset TJTA270

Ajax (Asynchronous JavaScript and XML)

Käsittelemme edellisen viikkotehtävän ja jatkamme Ajaxin parissa ja tutustumme myös PHP:n DOM-funktioihin ja muiden tekemien WWW-sivujen käyttämiseen tiedonlähteinä.

Luentotaltiointi

Ongelmia videon katselussa?

Viikkotehtävä 8

XMLHTTPRequest-objekti

XMLHTTPRequest-objektin ominaisuudet kuvataan esim. W3C:n The XMLHttpRequest Object - draft-dokumentissa.

Tärkeimmät metodit:

XMLHTTPRequest-objekti
abort() Keskeytä menossa oleva pyyntö
setRequestHeader("nimi", "arvo") Asettaa pyynnön otsikkotietoja
getResponseHeader("nimi") Palauttaa yhden halutun http-otsakkeen arvon
getAllResponseHeaders() Palauttaa kaikki pyynnölle palautetut http-otsakkeet
open("method", "URL"[, async[, "tunnus"[, "salasana"]]]) Asettaa metodin (POST|GET|HEAD etc.), osoitteen ja mahdollisen käyttäjätunnuksen, salasanan ja tehdäänkö pyyntö asynkronisesti vai ei
send(data) Lähettää pyynnön ja mahdollisen datan

send-metodille annettava data on oltava querystring-muodossa:

nimi=arvo&toinen=arvo&kolomas=jotain

Käytettäessä POST-metodia täytyy mediatyyppi määrätä seuraavalla tavalla:

http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
XMLHTTPRequest-objektin ominaisuudet
onreadystatechange Tapahtumankäsittelijä
readyState Objektin tila
  • 0 = alustamaton
  • 1 = lataa
  • 2 = ladattu
  • 3 = interaktiivinen
  • 4 = valmis
responseText Palautettu data merkkijonona
responseXML Palautettu data DOM-yhteensopivina dokumenttina
status HTTP-statuskoodi
statusText HTTP-statuskoodin mukana tullut mahdollinen teksti esim. virheilmoitus

Mochikit-kirjaston avulla XMLHTTPRequest-objektin käsittely on helppoa eikä selainkohtaisia eroja tarvitse juurikaan huomioida:



 // taulukoihin halutut GET-parametrit
 var keys = ["email", "etunimi", "sukunimi"];
 var values = ["tjlahton@mit.jyu.fi", "Tommi", "Lahtonen"];
 var query = queryString(keys, values);

 // tehdään yksinkertainen GET-kysely
 var d = doSimpleXMLHttpRequest("http://appro.mit.jyu.fi/example.php?" + query );
 // määrätään mikä funktio käsittelee kutsun palautteen ja mikä mahdollisen virheen
 d.addCallbacks(kasittelija, virhe);

 // sama POST-metodilla
 var obj = getXMLHttpRequest();
 // määrätään oikea mediatyyppi
 obj.open("POST", "http://appro.mit.jyu.fi/example.php", true);
 obj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
 var d = sendXMLHttpRequest(obj, query);
 d.addCallbacks(kasittelija, virhe);

 function kasittelija(obj) {
  // merkkijono
	 alert(obj.responseText);
  // xml-data. importNode ei toimi IE:ssä vaan täytyy tehdä kopiointi silmukassa...
  var data = document.importNode(obj.responseXML.documentElement, true);
  // ... jatkokäsitellään kuten mitä tahansa DOM-solmua
 }

function virhe(obj) {
  alert("virhe:" + obj.status + " " + obj.statusText);
}

 

PHP DOM

DOM-rajapinta toimii PHP:ssa hyvin samaan tapaan kuin Javascriptissakin:


header("content-type: text/xml");

// luodaan uusi dokumentti haluttuun nimiavaruuteen ja määrätään dokumenttielementti
$doc = new DOMDocument;
$doc = $doc->implementation->createDocument("http://www.w3.org/1999/xhtml", "table");

try {
  $dbh = new PDO('sqlite:/home3/368/tjlahton/public_html/php/ajax/malli');
}
catch ( PDOException $e ) {
  die ( $e->getMessage() );
}

$taulut = array("harrastus", "users", "harrastuslaji");

if ( isset($_REQUEST["taulukko"]) ) {
  $i = $_REQUEST["taulukko"];
  if ( $i >= 0 && $i < count($taulut) )
	  $taulu = $taulut[$i];
}
else {
 $taulu = $taulut[0];
}

$sql = $dbh->prepare("select * from $taulu");

$ok = $sql->execute();

if ( !$ok ) { print_r( $sql->errorInfo() ); }

// populoidaan dokumentti tietokannan perusteella

$table = $doc->documentElement;

while ($row = $sql->fetch(PDO_FETCH_ASSOC)) {

 $tr = $doc->createElement("tr");
 foreach ( $row as $value ) {
   $td = $doc->createElement("td");
   $tr->appendChild($td);
   // suora textContentin määrääminen ei kelpaa vaan täytyy
	 // oikeasti luoda textNode.
   $td->appendChild( $doc->createTextNode( $value ) );
 }
 
 $table->appendChild($tr);
}

 print $doc->saveXML();

harrastus.php DOM-versiona

Ulkopuolisten WWW-sivujen parsinta

PHP:n DOM-kirjaston avulla voi parsia myös ulkopuolisten XML-dokumentteja ja WWW-sivuja ja käyttää niitä tietokannan tapaan tiedonlähteenä.


$url = "http://www.jyvaskyla.fi/ajankohtaista/uutiset.rss";

$jkl = new DomDocument();
$jkl->load($url);

$doc = new DomDocument();
$doc->load("pohja.xml");
$body = $doc->getElementById("body");
$h1 = $doc->createElement("h1");
$h1->appendChild( $doc->createTextNode( utf8_encode("Jyväskylän uutiset") ) );
$body->appendChild($h1);
$ul = $doc->createElement("ul");
$body->appendChild($ul);

$item = $jkl->getElementsByTagName("item");

foreach ( $item as $i ) {
  $title = $i->getElementsByTagName("title");
  $link = $i->getElementsByTagName("link");
  $a = $doc->createElement("a");
  $a->setAttribute("href", $link->item(0)->textContent );
  $a->appendChild( $doc->createTextNode( $title->item(0)->textContent ) );
  $li = $doc->createElement("li");
  $li->appendChild($a);
  $ul->appendChild($li);

}

print $doc->saveXML();

RSS-feedin tekeminen ATK-keskuksen ajankohtaista tiedoista

Kaaviot PHP:lla (libchart)

Kaavioita voi PHP:ssa piirtää helposti monellakin valmiilla kirjastolla. Yksi näistä on


require_once ("libchart-1.1/libchart/libchart.php");

try {
  $dbh = new
PDO('sqlite:/home3/368/tjlahton/public_html/php/ajax/malli');
}
catch ( PDOException $e ) {
  die ( $e->getMessage() );
}

$sql = $dbh->prepare('select harrastuslaji.harrastuslaji, COUNT(*) as lkm
		FROM harrastus, harrastuslaji
		WHERE harrastus.Harrastuslaji = harrastuslaji.HarrastuslajiID
		GROUP BY harrastus.harrastuslaji');

if ( !$sql ) { print_r ( $dbh->errorInfo() ); }

$ok = $sql->execute();

if ( !$ok ) { print_r( $sql->errorInfo() ); }

$chart = new VerticalChart(500, 250);

while ($row = $sql->fetch(PDO_FETCH_ASSOC)) {

$chart->addPoint(new Point($row['Harrastuslaji'], $row['lkm']));

}

$chart->setTitle("Harrastuksien lukumäärä kussakin harrastuslajissa");
$chart->render("harrastukset.png");