10. Dr.SabinBuragawww.purl.org/net/busaco
Un program JavaScript are acces la arborele DOM
(Document Object Model)
corespunzător documentului HTML
minimal, navigatorul Web implementează
recomandarea DOM Level 2 HTML (2003)
www.w3.org/TR/DOM-Level-2-HTML
11. Dr.SabinBuragawww.purl.org/net/busaco
De asemenea, programele JavaScript au acces
la diverse obiecte oferite de mediul de execuție
pus la dispoziție de browser
e.g., informații privind contextul rulării
(caracteristici ale navigatorului, latența rețelei),
istoricul navigării, fereastra de redare a conținutului,
transfer (a)sincron de date,…
13. Dr.SabinBuragawww.purl.org/net/busaco
interface HTMLDocument : Document {
attribute DOMString title; // titlul documentului
readonly attribute DOMString referrer; // adresa resursei ce referă pagina
readonly attribute DOMString domain; // domeniul de care aparține
readonly attribute DOMString URL; // URL-ul absolut al documentului
attribute HTMLElement body; // acces la elementul <body>
readonly attribute HTMLCollection images; // lista tuturor imaginilor
readonly attribute HTMLCollection links; // lista tuturor legăturilor
readonly attribute HTMLCollection forms; // lista tuturor formularelor
attribute DOMString cookie; // acces la cookie-uri
// emite o excepție dacă e asignată o valoare
void open (); // deschide un flux de scriere (alterează DOM-ul curent)
void close (); // închide fluxul de scriere și forțează redarea conținutului
void write (in DOMString text); // scrie un șir de caract. (e.g., cod HTML)
void writeln (in DOMString text); // idem, dar inserează și new line
NodeList getElementsByName (in DOMString numeElement);
// furnizează o listă de elemente conform unui nume de tag
};
interfață specificată în limbajul declarativ WebIDL
24. Dr.SabinBuragawww.purl.org/net/busaco
function topLevelNodeAt (nod, top) {
while (nod && nod.parentNode != top)
nod = nod.parentNode;
return nod;
}
function topLevelNodeBefore (nod, top) {
while (!nod.previousSibling && nod.parentNode != top)
nod = nod.parentNode;
return topLevelNodeAt (nod.previousSibling, top);
}
discuție
Ce rol au cele două funcții?
26. Dr.SabinBuragawww.purl.org/net/busaco
// un element HTML generic
interface HTMLElement : Element {
attribute DOMString id; // identificator asociat elementului
attribute DOMString title; // titlu explicativ
attribute DOMString lang; // limba în care e redactat conținutul
attribute DOMString className; // numele clasei CSS folosite pentru redare
};
// specifică un formular Web
interface HTMLFormElement : HTMLElement {
readonly attribute HTMLCollection elements; // elementele HTML incluse în formular
readonly attribute long length; // numărul câmpurilor formularului
attribute DOMString action; // URI-ul resursei ce procesează datele
attribute DOMString enctype; // tipul MIME de codificare a datelor
// (e.g., application/x-www-form-urlencoded)
attribute DOMString method; // metoda HTTP folosită: GET, POST
void submit(); // trimite date URI-ului definit de ‘action’
};
// o imagine (conținut grafic raster)
interface HTMLImageElement : HTMLElement {
attribute DOMString alt; // text alternativ descriind conținutul grafic
attribute DOMString src; // URI-ul resursei grafice
};
27. Dr.SabinBuragawww.purl.org/net/busaco
Interfața HTMLCollection modelează o listă de noduri
un nod poate fi accesat folosind un index numeric
sau pe baza unui identificator (e.g., stabilit via atributul id)
interface HTMLCollection {
readonly attribute unsigned long length; // oferă lungimea listei
Node item (in unsigned long index); // oferă un nod via un index numeric
Node namedItem (in DOMString name); // furnizează un nod pe baza numelui
};
37. Dr.SabinBuragawww.purl.org/net/busaco
// funcție care generează un număr de elemente HTML
// pe care le adaugă elementului identificat prin 'identificator'
function genereazaElemente (numarElem, numeElem, identificator) {
for (var it = 0; it < numarElem; it++) {
// creăm un element specific
var element = document.createElement (numeElem);
// ...și-i atașăm un nod text
var text = document.createTextNode ("Salut, lumea...");
element.appendChild (text);
// adăugăm nodul creat
document.getElementById (identificator).appendChild (element);
}
}
genereazaElemente (3, "div", "continut"); // 3 <div>-uri
genereazaElemente (2, "p", "lumi"); // 2 paragrafe (<p>)
<div id="lumi"></div>
<h1 id="continut"></h1> a se studia exemplele
din arhivă
44. Dr.SabinBuragawww.purl.org/net/busaco
Găsirea de noduri via selectori CSS
querySelector (selectori)
furnizează primul element – folosind traversarea
în adâncime în preordine – care se potrivește grupului
de selectori (deliminați de virgulă)
querySelectorAll (selectori)
oferă lista de tip NodeList a tuturor elementelor găsite
60. Dr.SabinBuragawww.purl.org/net/busaco
Răspunsul la evenimente
proprietăți asociate evenimentelor
privind acțiunile mouse-ului
button – butonul acționat (0=stâng, 1=median, 2=drept)
detail – numărul de apăsări ale butonului
clientX – coordonata orizontală a poziției mouse-ului
clientY – coordonata verticală a poziției mouse-ului
61. Dr.SabinBuragawww.purl.org/net/busaco
interface MouseEvent : UIEvent {
readonly attribute long screenX, screenY; // coordonate relative la ecran
readonly attribute long clientX, clientY; // coordonate relative la zona de redare
readonly attribute boolean ctrlKey, shiftKey, altKey, metaKey; // taste speciale utilizate?
readonly attribute unsigned short button; // indică butonul acționat
readonly attribute EventTarget relatedTarget;
void initMouseEvent (in DOMString typeArg, // inițializează evenimentul de tratare
in boolean canBubbleArg,
in boolean cancelableArg,
in views::AbstractView viewArg,
in long detailArg,
in long screenXArg,
in long screenYArg,
in long clientXArg,
in long clientYArg,
in boolean ctrlKeyArg,
in boolean altKeyArg,
in boolean shiftKeyArg,
in boolean metaKeyArg,
in unsigned short buttonArg,
in EventTarget relatedTargetArg);
};
detalii la www.w3.org/TR/DOM-Level-2-Events/events.html
argumente specifice
84. Dr.SabinBuragawww.purl.org/net/busaco
for (var i = 0; i < 6; i++) { // construim tabelul cu câmpuri de intrare
var row = document.querySelector ("table").insertRow (-1); // adăugăm un rând la tabel
for (var j = 0; j < 6; j++) {
var letter = String.fromCharCode ("A".charCodeAt (0) + j - 1);
row.insertCell (-1).innerHTML = i && j ? "<input id='" + letter + i + "'/>" : i || letter;
}
}
var DATA={}, INPUTS=[].slice.call (document.querySelectorAll ("input"));
INPUTS.forEach ( function(elm) { // pentru fiecare element <input>, procesăm valoarea
elm.onfocus = function (e) { e.target.value = localStorage[e.target.id] || ""; };
elm.onblur = function (e) { localStorage[e.target.id] = e.target.value; computeAll(); };
var getter = function () { // funcție de furnizare a valorii (deja stocată în localStorage)
var value = localStorage[elm.id] || "";
if (value.charAt(0) == "=") { // începe cu =, deci e o formulă care va fi evaluată
with (DATA) return eval (value.substring(1));
} else { return isNaN (parseFloat (value)) ? value : parseFloat (value); }
};
Object.defineProperty (DATA, elm.id, { get: getter });
Object.defineProperty (DATA, elm.id.toLowerCase(), { get: getter });
} );
( window.computeAll = function () {
INPUTS.forEach (function (elm) { try { elm.value = DATA[elm.id]; } catch(e) {} });
} )();
89. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
suită de tehnologii deschise
interschimb și manipulare de date reprezentate prin:
diverse dialecte XML,
JSON (JavaScript Object Notation),
HTML,
alte formate
95. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
obiectul XMLHttpRequest
permite realizarea de cereri HTTP – e.g., GET, POST,… –
dintr-un program rulând la nivel de client (browser)
spre o aplicație / un serviciu Web existent(ă) pe server,
în mod asincron ori sincron
96. Dr.SabinBuragawww.purl.org/net/busaco
interface XMLHttpRequest : XMLHttpRequestEventTarget {
attribute Function? onreadystatechange;
// funcția de tratare a evenimentului de schimbare a stării transferului
readonly attribute unsigned short readyState; // starea transferului
// realizarea unei cereri HTTP
void open (DOMString metoda, DOMString url, optional boolean asinc = true,
optional DOMString? cont, optional DOMString? parola); // deschide conex.
void setRequestHeader (DOMString campAntet, DOMString valoare);
// stabilește antetul HTTP
void send (optional data = null); // trimite date spre serverul Web
void abort (); // abandonează transferul
// receptarea răspunsului de la serverul Web
readonly attribute unsigned short status; // codul de stare HTTP: 200, 303, 400,…
readonly attribute DOMString statusText; // textul asociat codului de stare
DOMString? getResponseHeader (DOMString antet); // preia antetul HTTP
DOMString getAllResponseHeaders (); // preia toate câmpurile răspunsului
readonly attribute any response; // conține răspunsul propriu-zis
readonly attribute DOMString responseText; // conține răspunsul: format text
readonly attribute Document? responseXML; // stochează răspunsul: date XML
};
97. Dr.SabinBuragawww.purl.org/net/busaco
interface XMLHttpRequestEventTarget : EventTarget {
// funcții de tratare a evenimentelor asociate transferului asincron
attribute Function? onloadstart; // transferul a început
attribute Function? onprogress; // se realizează transferul datelor…
attribute Function? onabort; // s-a abandonat transferul de date
attribute Function? onerror; // a apărut o eroare de transmisie
attribute Function? onload; // datele au fost recepționate de client
attribute Function? ontimeout; // a apărut o întârziere de transfer
attribute Function? onloadend; // transferul s-a terminat
};
// constante ce specifică starea transferului (vezi proprietatea readyState)
const unsigned short UNSENT = 0; // încă n-au fost efectuate transferuri
const unsigned short OPENED = 1; // s-a deschis conexiunea cu serverul
const unsigned short HEADERS_RECEIVED = 2; // primire câmpuri-antet HTTP
const unsigned short LOADING = 3; // datele se încarcă
const unsigned short DONE = 4; // gata! (transfer efectuat complet)
110. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
obiectul XMLHttpRequest
excepții specifice care pot fi emise (conform DOM 4 Core)
AbortError InvalidAccessError InvalidStateError
NetworkError SecurityError TimeoutError
…
114. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
noutăți:
utilizând constructorul AnonXMLHttpRequest,
transferurile sunt considerate „anonime”
(i.e., nu se trimit cookie-uri, anteturi de autentificare,…)
120. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
stabilirea unui mod de interacțiune clar
interacțiune HTML clasică
versus
interacțiune „bogată” cu Ajax
versus
interacțiune la nivelul unei aplicații convenționale
121. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
adoptarea Ajax pentru creșterea utilizabilității,
nu doar de dragul tehnologiei
exemple negative:
distragerea utilizatorului, abuz de resurse
(e.g., supradimensionarea arborelui DOM)
122. Dr.SabinBuragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML
oferă premisele invocării asincrone de servicii Web
în stilul REST
transferul de date se realizeaza via POX (Plain Old XML),
JSON (JavaScript Object Notation),
AHAH (Asynchronous HTML and HTTP)
sau text neformatat
123. Dr.SabinBuragawww.purl.org/net/busaco
Șabloane de proiectare AJAX
privind programarea:
invocare de servicii Web (RESTful Service, JSON Message)
dialog între browser & server
(Periodic Refresh, Submission Throttling, Cross-Domain Proxy)
asigurarea performanței (Fat Client, Browser-Side Cache,
Guesstimate, Predictive Fetch, Code Compression, On-Demand JS)
popularea arborelui DOM
124. Dr.SabinBuragawww.purl.org/net/busaco
Șabloane de proiectare AJAX
referitoare la interacțiunea cu utilizatorul:
formulare
(Live Form, Data Grid, Progress Indicator, Suggestion, Slider)
widget-uri de afișare a conținutului
arhitectura informației
funcționalitate (Lazy Registration, Direct Login, Heartbeat,
Autosave, Unique URLs)
128. Dr.SabinBuragawww.purl.org/net/busaco
Comet
șablon de proiectare a aplicațiilor Web
care necesită realizarea de conexiuni persistente,
în stilul peer-to-peer
utilizat de aplicațiile Web intensiv interactive,
eventual colaborative – e.g., Google Docs, Mibbit,…
132. Dr.SabinBuragawww.purl.org/net/busaco
Ajax/Comet oferă suport pentru dezvoltarea de
aplicații Web hibride – mash-ups
combinarea – în contextul nostru, la nivel de client –
a conținutului ce provine din surse (situri)
multiple, oferind o funcționalitate/experiență nouă
134. Dr.SabinBuragawww.purl.org/net/busaco
Surse de date
(data feeds)
Atom, RSS, geoRSS,
microdate HTML5, RDFa,…
Interfețe de programare
(API-uri)
specifice serviciilor publice
și de procesare JSON/XML
Biblioteci/framework-uri
pentru dezvoltare
framework-uri Web generice
sau oferite de organizații
Instrumente interactive
(Web tools)
eventual, disponibile în cloud
e.g., Yahoo! Pipes
Platforme
(Platform As A Service)
Heroku, Google App Engine,
Nodejitsu, Windows Azure,…
140. Dr.SabinBuragawww.purl.org/net/busaco
interactiune web: ajax – studiu de cazvar url = "http://profs.info.uaic.ro/~busaco/teach/courses/web/web-film";
// realizăm o cerere HEAD pentru a obține meta-date despre o resursă
var client = new XMLHttpRequest ();
client.open ("HEAD", url, true);
client.send ();
client.onreadystatechange = function () {
// am recepționat câmpurile-antet?
if (client.readyState == 2) {
// semnalăm tipul MIME și data ultimei actualizări
alert ("Resursa de tip '" +
client.getResponseHeader ("Content-Type") + "' s-a actualizat la " +
client.getResponseHeader ("Last-Modified"));
}
}
preluarea în mod asincron
via HEAD a unor meta-date
142. Dr.SabinBuragawww.purl.org/net/busaco
CORS (Cross-Origin Resource Sharing)
recomandare a Consorțiului Web (ianuarie 2014)
http://www.w3.org/TR/cors/
mecanism ce permite partajarea la nivel de client
a resurselor provenind din domenii Internet diferite
astfel, se pot emite cereri via XMLHttpRequest între domenii
143. Dr.SabinBuragawww.purl.org/net/busaco
Având un mash-up Web la nivel de client
ce utilizează N surse de date provenite din domenii
diferite, la câți arbori DOM are acces
programul JavaScript?
întrebări (pentru acasă)
Transferul datelor
via Comet
este bidirecțional?
De ce?