Receptes de cuina amb Recipe XML

De Wikijoan
Dreceres ràpides: navegació, cerca

Contingut

Introducció

RecipeBook XML és un llenguatge de marques que s'utilitza per fer receptes i llibre de cuina. És simple i fàcil d'utilitzar i aprendre, i com tots els llenguatges XML té enormes possibilitats. Un cop s'ha escrit una recepta amb RecipeBook XML, es pot formatar amb diferents formats (HTML, PDF, Rich Text,...), com ja vas veure l'any passat a l'assignatura de XML.

Referències

La definició del llenguatge recipeXML estava a http://www.happy-monkey.net/recipebook/, però malauradament aquest enllaç està trencat. No passa res, doncs els fitxers XML d'exemple de què disposem s'expliquen per ells mateixos. Pots descarregar-te dos fitxers d'exemple:

Desenvolupament

Primera prova

El fitxer index1.html carrega en una select box 2 fitxers XML (fitxers d'exemple que pots descarregar de l'enllaç). Mitjançant la tècnica asíncrona d'AJAX mostra els ingredients per pantalla, en la capa corresponent. Aquest codi és bàsicament similar al que s'ha vist a classe en l'exemple de tutoria. fitxer index1.html:

<html>
<head>
<title>Receptes AJAX</title>
<script>
function loadXMLDoc(url)
{

var xmlhttp;
var txt,x,xx,i;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    txt="<h2>Ingredients</h2>";
    txt = txt + "<ul>";
		x=xmlhttp.responseXML.documentElement.getElementsByTagName("fooditem");
		for (i=0;i<x.length;i++) {
			txt = txt + '<li>' + x[i].firstChild.nodeValue + '</li>';
		}
    txt = txt + "</ul>";
    document.getElementById('info').innerHTML=txt;
    }
  }
xmlhttp.open("GET",url,true);
xmlhttp.send();

}
</script>
</head>
<body>
<h1>Receptes</h1>
<div id="formulari">
<form name="frm_receptes" id="formu" action="#">
	<select name="recipes" onchange="loadXMLDoc(this.value)">
	<option value="recipes/bean-and-ham.xml">bean and ham</option>
	<option value="recipes/corn-chowder.xml">corn chowder</option>
	</select><br />
</form>
</div>
<div id="info">
</div>
</body>
</html>

Obtenim:

    dry navy beans
    medium onion
    garlic
    celery
    carrots
    plum (roma) tomatoes
    cooked ham scraps
    water
    ham bone
    Salt
    pepper

Fixa't bé que estem parsejant el fitxer XML en el cantó del client (Javascript). L'objecte xmlhttp.responseXML conté tot els fitxer complet, i amb Javascript filtrem la informació que ens interessa, en aquest cas els ingredients. Això seria ineficient si el fitxer XML fos molt gros (posem per cas 500K) i només ens interessa una petita part de la informació.

L'alternativa eś que sigui PHP, en el cantó del servidor, qui parsegi el fitxer XML i només envïi al client la informació que interessa, en aquest cas els ingredients. Aquesta manera de fer està discutida en el següent enllaç:

Segona prova

En la primera prova hem recuperat els valors dels fooditem. Però interessa més recuperar la informació dels ingredients, que està format per: fooditem, quantity, unit. Ara la navegació pel document XML és més complicada. Navegarem pels diferents ingredients utilitzant:

getElementsByTagName("ingredient")

i, dins de cada ingredient buscarem els seus childNodes. Utilitzarem la propietat nodeName per buscar les etiquetes quantity, unit i fooditem. I finalment accedirem al valor de text mitjançant childNodes[0].nodeValue. És bastant embolic però funciona bé. Utilitzem variables per formatar la sortida.

fitxer index2.html

<html>
<head>
<title>Receptes AJAX</title>
<script>
function loadXMLDoc(url)
{

var xmlhttp;
var txt,x,xx,i;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    txt="<h2>Ingredients</h2>";
    txt = txt + "<ul>";
	 txt_ingredient = "";
	 txt_quantity = "";
	 txt_unit = "";
	 txt_fooditem = "";
		ingredients=xmlhttp.responseXML.documentElement.getElementsByTagName("ingredient");
		for (i=0;i<ingredients.length;i++) {
			//alert(ingredients[i].innerHTML);			
			for (k=0;k<ingredients[i].childNodes.length;k++) {			
				//alert(ingredients[i].childNodes[k].nodeName);
				if (ingredients[i].childNodes[k].nodeName == "quantity") txt_quantity = ingredients[i].childNodes[k].childNodes[0].nodeValue;
				if (ingredients[i].childNodes[k].nodeName == "unit") txt_unit = ingredients[i].childNodes[k].childNodes[0].nodeValue;
				if (ingredients[i].childNodes[k].nodeName == "fooditem") txt_fooditem = ingredients[i].childNodes[k].childNodes[0].nodeValue;
			}
			txt_ingredient = "<li>" + txt_fooditem + " (" + txt_quantity + " " + txt_unit + ")</li>"
			txt = txt + txt_ingredient;
		}
    txt = txt + "</ul>";
    document.getElementById('info').innerHTML=txt;
    }
  }
xmlhttp.open("GET",url,true);
xmlhttp.send();

}
</script>
</head>
<body>
<h1>Receptes</h1>
<div id="formulari">
<form name="frm_receptes" id="formu" action="#">
	<select name="recipes" onchange="loadXMLDoc(this.value)">
	<option value="">Escull una recepta</option>
	<option value="recipes/bean-and-ham.xml">bean and ham</option>
	<option value="recipes/corn-chowder.xml">corn chowder</option>
	</select><br />
</form>
</div>
<div id="info">
</div>
</body>
</html>

Obtenim:

    butter (2 Tbsp.)
    medium onion (1 Tbsp.)
    garlic (2 cloves)
    celery (2 ribs)
    red pepper (1 ribs)
    corn (4 ears)
    flour (2 Tbsp.)
    chicken broth (2 C.)
    whole milk (2 C.)
    medium red potatoes (3 C.)
    Salt and pepper (3 C.)

Feina per l'alumne

A partir d'aquí hem de fer una aplicació més interessant. S'ha de mostrar la resta d'informació que hi ha en el fitxer XML: la capçalera de la recepta (títol, autor), ingredients, mode de preparació, com es serveix... i la foto.

Incloure una foto és una opció que ha sorgit de la discussió que s'ha fet a classe. L'atribut foto ha d'anar dins la informació relativa a la recepta (a dalt de tot, allà on hi ha el títol i l'autor). La idea dels fitxers XML és que són autocontinguts. Per exemple, pots enviar per mail un fitxer xml a un col.lega. El problema és que si hi ha referència a unes fotos, necessitem que aquestes fotos tinguin una url absoluta (en cas contrari, quan envïis una recepta per mail, a més del fitxer també hauràs d'incloure la foto).

Per incorporar en el llenguatge Recipe XML la informació d'un link amb url relativa, es proposa afegir a sota del title informació sobre la url de la imatge. Tenim dues possibilitats:

<img>img/dish0.jpg</img>
<img src="img/dish0.jpg" />

Com que ens hem de posar d'acord, tothom ho ha de fer igual, ho farem de la primera manera.

Recordatori:

<recipe>
  <title>Bean And Ham Soup</title>
  <img>img/bean-and-ham.jpg</img>
...

La nostra aplicació completa inclou aspectes de disseny i aspectes de usabilitat i funcionalitat, tal com s'ha discutit a classe. Es fa la proposta següent (però l'alumne podrà fer altres proves i millores).

NOTA. Hem fet la prova d'accedir a fitxers XML remots, com ara

i no hem pogut fer-ho. De fet, plantejat així no es pot fer, però hi ha una solució alternativa que mirarem d'implementar.

Com diu en l'anterior enllaç:

You can't send an AJAX request to another server, see http://en.wikipedia.org/wiki/Same_origin_policy A workaround is to use JSONP: http://en.wikipedia.org/wiki/JSONP

SOLUCIÓ JSONP: JSONP:_JSON_with_Padding#RecipeXML_i_JSONP

Repositori de les receptes dels alumnes

La url d'on pots agafar totes les receptes i les imatges és:

Cada alumne ha d'enviar obligatòriament dues receptes (i les dues fotos), a jquintana@jaumebalmes.net. Això és NOTA de classe. Termini màxim: 23/02/2018.

A data 21/02/2018, el repositori de receptes és:

     
<select id="recipes" name="recipes" onchange="loadXMLDoc(this.value)">
     <option value=""></option>
     <option value="Fricase.xml">Fricase</option>
     <option value="Galletas_mantequilla.xml">Galletas de mantequillam de maní</option>
     <option value="Tallarines.xml ">Tallarines</option>
     <option value="arroz_frito_chino.xml">Arroz frito chino</option>
     <option value="baumkuchen_cake.xml">Baumkuchen Cake</option>
     <option value="bean-and-ham.xml">Bean and Ham</option>
     <option value="brownies.xml">Brownies</option>
     <option value="bucatini_amatriciana.xml">Bucatini Amatriciana</option>
     <option value="bunuelos.xml">Bunyols</option>
     <option value="ceviche-de-pescado.xml">Ceviche de Pescado</option>
     <option value="corn-chowder.xml">Corn Chowder</option>
     <option value="crema-catalana.xml">Crema Catalana I</option>
     <option value="cremaCatalana.xml">Crema Catalana II</option>
     <option value="crema_espinaca.xml">Crema de espinacas</option>
     <option value="crepes-alemanas.xml">Crêpes alemanas</option>
     <option value="croquetas-de-patatas-almendradas.xml">Croquetas de patatas almendradas</option>
     <option value="espaguetis_carbonara.xml">Espghettis a la carbonara</option>
     <option value="fricando.xml">Fricandó</option>
     <option value="migas.xml">Migas de pan</option>
     <option value="mini_pay.xml">Mini Pay</option>
     <option value="mousakas.xml">Mousakas</option>
     <option value="parmesan_chicken.xml">Parmesan Chicken</option>
     <option value="pechuga-de-pavo-con-relleno-marinero.xml">Pechuga de pavo marinero</option>
     <option value="piqueMacho.xml">Pique Macho</option>
     <option value="pulpo-a-la-gallega.xml">Pulpo a la Gallega</option>
     <option value="quiche.xml">Quiche</option>
     <option value="saice.xml">Saice</option>
     <option value="silpancho.xml">Silpancho</option>
     <option value="sopa-de-queso.xml">Sopa de Queso</option>
     <option value="sopa_de_mani.xml">Sopa de Maní</option>
     <option value="sopa_tomate.xml">Sopa de Tomate</option>
     <option value="tandoorichicken.xml">Tandoori Chicken</option>
     <option value="tikkamasala.xml">Tikka Masala</option>
     <option value="tiramisu.xml">Tiramisú</option>
</select>

Disseny

Hem de definir una estructura, una plantilla, on mostrar tota la informació desitjada. Evidentment, ho farem amb capes div. Una proposta és:

--------------  -----------------
| select box |  |   Títol       |
--------------  -----------------
-------------   ----------------
|            |  |    Gènere     |
|            |  |---------------|
|ingredients |  | foto          |
|            |  |               |
-------------   -----------------
---------------------------------
|                               |
|    preparació                 |
|                               |
---------------------------------
---------------------------------
|    servir                     |
---------------------------------

però l'alumne la pot canviar segons el seu criteri.

Funcionalitat

Tan important com el disseny és la manera com se'ns mostra la informació (cerquem que sigui una pàgina dinàmica i divertida). Aquí, la proposta que s'ha discutit és que, amb un delay de 5 segons, es vagin carregant les diferents zones de la pàgina: primer el títol, els ingredients, la foto, la preparació, el mode de servir. per tant, seran diferents crides asíncrones al servidor per demanar la informació amb què hem de carregar cadascuna de les pàgines.

Una altra opció és que per mostrar la informació s'una capa s'ha de fer click sobre la capa. Així doncs, només es mostra la informació que volem llegir.

Són propostes, tu pots fer la teva proposta.

Fés la teva recepta

Finalment has d'incorporar a la teva aplicació un parell de receptes de collita pròpia. Si no ets afeccionat a la cuina pots agafar idees d'algun blog de cuina, per exemple una recepta de les Cuineres de Sils:

Hauràs de buscar una foto real de les teves receptes (tamany 200x200px), i ficar-la a la carpeta recipes/img

Solució final

Se t'entrega una solució ben maquetada i funcionant. Contingut de les carpetes:

Entrega

Els alumnes entregaran al Schoology tots els fitxers generats (fitxers html). S'empaquetaran tots aquests fitxers i es pujaran al Schoology dins del termini d'entrega de la pràctica.

Recorda la normativa per entregar les pràctiques al Schoology: ASIX-M10-UF2#Normativa_d.27entrega_de_les_pr.C3.A0ctiques_al_Schoology


creat per Joan Quintana Compte, febrer 2019

Eines de l'usuari
Espais de noms
Variants
Accions
Navegació
Institut Jaume Balmes
Màquines recreatives
CNC
Informàtica musical
joanillo.org Planet
Eines