Sunteți pe pagina 1din 168

Dezvoltarea aplicațiilor Web

la nivel de client

Dr. Sabin Buragawww.purl.org/net/busaco


http://javascript.info/

programare Web
JavaScript în cadrul navigatorului Web
Dr. Sabin Buragawww.purl.org/net/busaco
“Solving the problem is more important
than being right.”

Milton Glaser
Dr. Sabin Buragawww.purl.org/net/busaco
Cum rulează programele JavaScript
în navigatorul Web?
Dr. Sabin Buragawww.purl.org/net/busaco
Majoritatea programelor JavaScript
rulează – sunt interpretate –
în navigatorul Web via un script engine
Dr. Sabin Buragawww.purl.org/net/busaco
Majoritatea programelor JavaScript
rulează – sunt interpretate –
în navigatorul Web via un script engine

Chakra (Edge – Microsoft)


JavaScriptCore (Safari – Apple)
JerryScript (destinat IoT – JS Foundation)
SpiderMonkeyIonMonkey (Firefox – Mozilla)
Rhino (implementare Java – Mozilla)
Nashorn (OpenJDK – Oracle)
V8 (Chrome, Opera, Node.js – Google)
Dr. Sabin Buragawww.purl.org/net/busaco
fazele principale ale procesării și rulării codului JavaScript
(Hyungwook Lee, 2014)
Dr. Sabin Buragawww.purl.org/net/busaco
exemplu real: Chakra – fazele principale
ale procesării și execuției codului JavaScript
https://github.com/Microsoft/ChakraCore
Cod JavaScript intern vs.
preluat dintr-un fișier extern

Dr. Sabin Buragawww.purl.org/net/busaco


<body>

<script type="text/javascript">
alert ("Salut, lume!");
</script>
</body>

<script type="text/javascript" src="http://salutari.info/salut.js">


</script>
Cod JavaScript intern vs.
preluat dintr-un fișier extern

Dr. Sabin Buragawww.purl.org/net/busaco


<body>

<script type="text/javascript">
alert ("Salut, lume!");
</script>
</body>

<script type="text/javascript" src="http://salutari.info/salut.js">


</script>

remarcă: pentru browser-ele moderne poate fi specificat


application/javascript în loc de text/javascript
Dr. Sabin Buragawww.purl.org/net/busaco
arhitectura de bază a interpretorului (script engine) JS
inclus într-un navigator Web (A. Zlatkov, 2017)
blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf
blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e
Dr. Sabin Buragawww.purl.org/net/busaco
execuția codului JavaScript se realizează într-un singur fir de
execuție (proces), dar alte acțiuni efectuate de browser-ul Web nu
www.red-gate.com/simple-talk/dotnet/asp-net/javascript-single-threaded/
Dr. Sabin Buragawww.purl.org/net/busaco
Un program JavaScript are acces la arborele DOM
(Document Object Model)
corespunzător documentului HTML

specificații ale Consorțiului Web


varianta în vigoare: DOM 4 (2015)
www.w3.org/TR/dom/

de revăzut materia „Tehnologii Web”


profs.info.uaic.ro/~busaco/teach/courses/web/
Dr. Sabin Buragawww.purl.org/net/busaco
Un program JavaScript are acces la arborele DOM
(Document Object Model)
corespunzător documentului HTML

DOM Living Standard – dom.spec.whatwg.org

specific HTML5, în continuă dezvoltare


(cea mai recentă actualizare: 21 noiembrie 2017)
Dr. Sabin Buragawww.purl.org/net/busaco
Programul JS recurge la obiecte implementând
interfețele DOM pentru accesarea și modificarea
reprezentării interne a unui document HTML
(i.e. arborele DOM)
<!DOCTYPE html>
HTML
<html> HtmlElement
<body>

Dr. Sabin Buragawww.purl.org/net/busaco


<p>Tehnologii Web</p>
<div>
<img src="web.png"/> HTML
BodyElement
</div>
</body>
</html>
HTML HTML
ParagraphElement DivElement

HTML
Text
ImageElement
dom: browser

Dr. Sabin Buragawww.purl.org/net/busaco


inspectarea arborelui DOM asociat unui document HTML
via instrumentele oferite de navigatorul Web
Dr. Sabin Buragawww.purl.org/net/busaco
Minimal, navigatorul Web implementează
recomandarea DOM Level 2 HTML (2003)

www.w3.org/TR/DOM-Level-2-HTML
dom: core

Dr. Sabin Buragawww.purl.org/net/busaco


în cazul HTML, numele elementelor
sunt disponibile cu litere mari (capitals)

un document HTML și arborele DOM corespunzător


reprezentat via Live DOM Viewer
http://software.hixie.ch/utilities/js/live-dom-viewer/
dom: core

Dr. Sabin Buragawww.purl.org/net/busaco


De ce apare
și acest nod?

un document HTML și arborele DOM corespunzător


reprezentat via Live DOM Viewer
http://software.hixie.ch/utilities/js/live-dom-viewer/
Dr. Sabin Buragawww.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,…
Dr. Sabin Buragawww.purl.org/net/busaco
Arborele DOM asociat documentului HTML
poate fi accesat/alterat via obiectul document

instanță a clasei implementând interfața HTMLDocument


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

Dr. Sabin Buragawww.purl.org/net/busaco


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
Dr. Sabin Buragawww.purl.org/net/busaco
Deoarece interfața HTMLDocument
extinde Document,
putem recurge la funcționalitățile
stipulate de specificația DOM generală
Dr. Sabin Buragawww.purl.org/net/busaco
Proprietatea documentElement
desemnează nodul-rădăcină
Dr. Sabin Buragawww.purl.org/net/busaco
getElementById (identificator)

furnizează un element – nod de tip Element –


conform identificatorului său unic, desemnat de valoarea
atributului id specificat în cadrul documentului
Dr. Sabin Buragawww.purl.org/net/busaco
parentNode

oferă acces la numele nodului-părinte al nodului curent


Dr. Sabin Buragawww.purl.org/net/busaco
nextSibling

acces la următorul nod de pe același nivel al arborelui


Dr. Sabin Buragawww.purl.org/net/busaco
previousSibling

acces la nodul precedent de pe același nivel al arborelui


Dr. Sabin Buragawww.purl.org/net/busaco
childNodes

proprietate furnizând într-un tablou


numele nodurilor-copil ale nodului curent
Dr. Sabin Buragawww.purl.org/net/busaco
firstChild

desemnează primul nod-copil al nodului curent


Dr. Sabin Buragawww.purl.org/net/busaco
lastChild

specifică ultimul nod-copil al nodului curent


Dr. Sabin Buragawww.purl.org/net/busaco
attributes

reprezintă tabloul asociativ


conținând atributele asociate unui nod de tip Element
discuție
function topLevelNodeAt (nod, top) {

Dr. Sabin Buragawww.purl.org/net/busaco


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);
}

Ce rol au cele două funcții?


Dr. Sabin Buragawww.purl.org/net/busaco
Interfața HTMLElement o extinde
pe cea generală oferită de DOM Level 2

fiecare element HTML specific derivă din ea

HTML HTML
Node Element
Element DivElement

o interfață specifică fiecărui element HTML


// un element HTML generic
interface HTMLElement : Element {
attribute DOMString id; // identificator asociat elementului
attribute DOMString title; // titlu explicativ

Dr. Sabin Buragawww.purl.org/net/busaco


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
};
Dr. Sabin Buragawww.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
};
Dr. Sabin Buragawww.purl.org/net/busaco
Cum putem afla/modifica diverse informații
privind nodurile arborelui DOM?
Dr. Sabin Buragawww.purl.org/net/busaco
Informații referitoare la nodurile arborelui DOM

nodeType

proprietate care furnizează tipul unui nod

ELEMENT_NODE (1) = element


TEXT_NODE (3) = conținut text
COMMENT_NODE (8) = comentariu

Dr. Sabin Buragawww.purl.org/net/busaco
Informații referitoare la nodurile arborelui DOM

nodeValue

proprietate oferind valoarea unui nod


Dr. Sabin Buragawww.purl.org/net/busaco
Informații referitoare la nodurile arborelui DOM

innerHTML

proprietate – mutabilă – ce furnizează codul HTML


din cadrul unui nod de tip Element

utilizare
nerecomandabilă
Dr. Sabin Buragawww.purl.org/net/busaco
Informații referitoare la nodurile arborelui DOM

textContent

proprietate ce furnizează/stabilește conținutul textual


al nodului și posibililor descendenți
Dr. Sabin Buragawww.purl.org/net/busaco
Informații referitoare la nodurile arborelui DOM

getAttribute (numeAtribut)

metodă care oferă acces la valoarea unui atribut


Dr. Sabin Buragawww.purl.org/net/busaco
Modificarea structurii arborelui DOM

createElement (element)

creează un nod de tip Element


Dr. Sabin Buragawww.purl.org/net/busaco
Modificarea structurii arborelui DOM

createTextNode (nod)

creează un nod cu conținut textual


Dr. Sabin Buragawww.purl.org/net/busaco
Modificarea structurii arborelui DOM

appendChild (nod)

adaugă un nod-copil nodului curent


// 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++) {

Dr. Sabin Buragawww.purl.org/net/busaco


// 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ă
Dr. Sabin Buragawww.purl.org/net/busaco
arborele DOM corespunzător
codului HTML
generat prin program

inspectarea valorilor
proprietăților DOM
Dr. Sabin Buragawww.purl.org/net/busaco
Modificarea structurii arborelui DOM

removeChild (nod)

elimină un nod-copil
Dr. Sabin Buragawww.purl.org/net/busaco
Modificarea structurii arborelui DOM

cloneChild ()

„clonează” un nod al arborelui


Dr. Sabin Buragawww.purl.org/net/busaco
Modificarea structurii arborelui DOM

setAttribute (atribut, valoare)

stabilește valoarea unui atribut


JS Fiddle

Dr. Sabin Buragawww.purl.org/net/busaco


recurgerea la
createElement()
appendChild()
getElementById()

generare dinamică via JavaScript


a unui formular Web
http://jsfiddle.net/busaco/0wvn3fha/
Dr. Sabin Buragawww.purl.org/net/busaco
Suport pentru procesarea proprietăților CSS

pe baza unui model obiectual specific


CSSOM (CSS Object Model)

specificație în lucru (draft) – 9 noiembrie 2017

drafts.csswg.org/cssom/
Dr. Sabin Buragawww.purl.org/net/busaco
Suport pentru procesarea proprietăților CSS

actualmente, modificarea proprietăților de stil


se poate realiza via proprietatea HTMLElement.style

// asocierea mai multor stiluri CSS


elem.style.cssText = "color: blue; border: 1px solid #000";
// similar cu:
elem.setAttribute ("style", "color: blue; border: 1px solid #000;");

developer.mozilla.org/Web/API/CSSStyleDeclaration
Dr. Sabin Buragawww.purl.org/net/busaco
Găsirea de noduri via selectori CSS

Selectors API – Level 1


recomandare W3C (2013)

acces la diverse date via selectorii CSS cu metodele


query() queryAll() querySelector() querySelectorAll()

www.w3.org/TR/selectors-api/
Dr. Sabin Buragawww.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 (delimitați de virgulă)

querySelectorAll (selectori)
oferă lista de tip NodeList a tuturor elementelor găsite
Dr. Sabin Buragawww.purl.org/net/busaco
Găsirea de noduri via selectori CSS

// toate elementele <li> selectate via CSS (date de tip NodeList)


var elemente = document.querySelectorAll ("ul.menu > li");
for (var i = 0; i < elemente.length; i++) {
prelucrează (elemente.item (i)); // procesăm fiecare nod
}
Dr. Sabin Buragawww.purl.org/net/busaco
selectori
CSS3

exemplificare – folosim consola browser-ului Web:


document.querySelectorAll ("section[id^=\"week\"]:nth-child(odd) > h2");
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

definirea de activități (callback-uri) executate


la apariția unui eveniment

eveniment = acțiune produsă în cadrul mediului de


execuție în urma căreia programul va putea reacționa
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

codul JavaScript invocat la apariția unui eveniment


va putea fi încapsulat într-o funcție de tratare a acestuia
(event handler)
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

tradițional, se atașează cod JavaScript ce va fi executat


la apariția unui eveniment de bază
(e.g., onclick, onmouseover, onchange, onload, onkeypress,…)
asupra unui element
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

<button onclick="alert ('Au!');">Apasă-mă!</button>


Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

<button onclick="alert ('Au!');">Apasă-mă!</button>

pentru a inhiba execuția acțiunii implicite,


codul JavaScript va trebui să întoarcă false
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

<button onclick="alert ('Au!');">Apasă-mă!</button>



document.getElementById ("identificator").onclick
= trateazaClick; // mai ‘evoluat’ via DOM 1
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

tratarea standardizată a evenimentelor:


specificația DOM Level 2 Events

www.w3.org/TR/DOM-Level-2-Events/
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

specificarea de activități executate


la apariția unui eveniment

obiect.addEventListener ("eveniment", funcție, mod);


Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

descrierea arborescentă a fluxului de evenimente

capture versus bubble

de parcurs http://javascript.info/bubbling-and-capturing
Dr. Sabin Buragawww.purl.org/net/busaco
fluxul de evenimente (T. Leithead et al., 2012)

a se studia și W. Page, An Introduction to DOM Events (2013)


www.smashingmagazine.com/2013/11/an-introduction-to-dom-events/
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

descrierea arborescentă a fluxului de evenimente

mod = true
se încearcă tratarea evenimentului pornind
de la rădăcină până la obiectul-țintă – capture phase
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

descrierea arborescentă a fluxului de evenimente

mod = false
se încearcă tratarea evenimentului atunci când
evenimentul e propagat de la obiectul unde a survenit
până la entitățile superioare lui – bubbling phase
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

se va utiliza un set standard de evenimente


Tipuri de evenimente – interacțiune cu utilizatorul

mouse: click dblclick mouseenter mousedown mouseup

Dr. Sabin Buragawww.purl.org/net/busaco


mouseover mousemove contextmenu select wheel
keyboard: keypress keydown keyup
clipboard: copy cut paste
view: resize scroll fullscreenchange fullscreenerror
drag & drop: dragstart drag dragenter dragover dragleave
dragend drop
form: focus blur select submit reset
document (page lifecycle): load DOMContentLoaded
beforeunload unload abort cancel
Tipuri de evenimente – vizând resursele

Dr. Sabin Buragawww.purl.org/net/busaco


network: online offline
session history: pagehide pageshow popstate
printing: beforeprint afterprint
media: canplay play playing pause suspend waiting seeking
seeked stalled complete ended emptied durationchange
ratechange volumechange timeupdate …
progress: loadstart progress error timeout abort load loaded
storage: change storage
Web socket: open message error close
Tipuri de evenimente – altele

Dr. Sabin Buragawww.purl.org/net/busaco


CSS transitions: transitionstart transitionrun
transitionend transitioncancel
CSS animations: animationstart animationend
animationiteration
value change: broadcast hashchange input readystatechange…

pentru amănunte, a se explora și


developer.mozilla.org/Web/Events
Dr. Sabin Buragawww.purl.org/net/busaco
Tipuri de evenimente – specifice HTML5

asociate API-urilor disponibile:

Ambient Light, App Cache, Battery, Contacts,


Device Orientation, Device Storage, Download, File,
IndexedDB, Media Capture & Streams, Payment, Pointer,
Proximity, Push, SVG, Touch, Time & Clock, TV, Web Audio,
WebGL, WebRTC, Web Notifications, Web Speech, WebVR,
Wifi Information, Wifi P2P etc.
vezi cursurile
viitoare
interface Touch { // specifică zona tactilă
readonly attribute long identifier;
exemplificare:
readonly attribute EventTarget target; specificarea
readonly attribute long screenX;
readonly attribute long screenY; evenimentelor tactile

Dr. Sabin Buragawww.purl.org/net/busaco


readonly attribute long clientX;
readonly attribute long clientY;
readonly attribute long pageX;
readonly attribute long pageY;
};
interface TouchList { // definește lista punctelor de contact pentru un eveniment tactil
readonly attribute unsigned long length;
getter Touch? item (unsigned long index);
};
interface TouchEvent : UIEvent {
readonly attribute TouchList touches;
pot fi tratate
readonly attribute TouchList targetTouches; evenimentele
readonly attribute TouchList changedTouches; touchstart
readonly attribute boolean altKey;
readonly attribute boolean metaKey;
touchend
readonly attribute boolean ctrlKey; touchmove
readonly attribute boolean shiftKey; touchcancel
};
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

type

specifică tipul evenimentului ca șir de caractere


e.g., "click", "load", "scroll", "submit"
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

target

desemnează nodul
asupra căruia evenimentul a fost declanșat inițial
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

currentTarget

indică nodul care tratează evenimentul


Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

bubbles

indică dacă evenimentul se propagă


spre elemente ascendente (valoarea true)
ori către descendenți (valoarea false)
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

bubbles

e.g., evenimentele abort, error, select, submit, resize, scroll,


click, mousedown, mouseover, mousemove, mouseout,
touchstart, touchend pot avea bubbles = true
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

bubbles

în cazul evenimentelor focus, blur, load, unload,


proprietatea bubbles are valoarea false
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

cancelable

precizează dacă evenimentul poate fi întrerupt


Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

cancelable

de exemplu, pentru evenimentele load, unload, abort, error,


select, focus, blur, resize, scroll, touchcancel
proprietatea cancelable este setată ca fiind false
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

proprietăți utile ale obiectului Event

cancelable

pentru evenimente precum click, mousedown, mouseup,


mouseover, mousemove, mouseout, touchstart, touchend,
touchmove proprietatea cancelable poate fi true
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

eliminarea tratării unui eveniment

removeEventListener ()
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

ignorarea comportamentului implicit

preventDefault ()
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

comportamentul implicit pentru evenimentul tactil


touchend poate varia în funcție de context/platformă:
mousemove, mousedown, mouseup, click
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

trimiterea evenimentului să poată fi procesat


conform modelului oferit de implementare

dispatchEvent ()
Dr. Sabin Buragawww.purl.org/net/busaco
Tratarea evenimentelor

oprirea propagării unui eveniment


în cadrul arborelui DOM

stopPropagation ()
<!DOCTYPE html>

github.com/bpesquet/thejsway/blob/master/manuscript/chapter16.md
<html>
<head><meta charset="utf-8" /><title>Evenimente JS</title></head>
<body>

Dr. Sabin Buragawww.purl.org/net/busaco


<form>

adaptare după Baptiste Pesquet (2017)


<textarea id="editor"></textarea>
</form>
</body>
<script type="application/javascript">
const infoEv = e => { console.log (
`Eveniment: ${e.type}\n
Caracter: ${String.fromCharCode (e.charCode)}\n
Element țintă al evenim.: ${e.target}\n
Ținta curentă: ${e.currentTarget}`);
};
document.addEventListener ("keypress", infoEv);
</script>
</html>
exemplificare: afișarea datelor vizând un eveniment
inspecție de evenimente
apărute în pagina Web
(tratate printr-un program JS

Dr. Sabin Buragawww.purl.org/net/busaco


sau de o extensie instalată)
// Adaptare după https://eloquentjavascript.net/14_event.html
const trateazaEveniment = ev => {
// plasăm un 'punct' la coordonatele cursorului mouse-ului
let pct = document.createElement ('div');

Dr. Sabin Buragawww.purl.org/net/busaco


pct.className = (ev.type === 'dblclick') ? 'punct roz' : 'punct';
pct.style.left = (ev.pageX - 5) + 'px';
pct.style.top = (ev.pageY - 5) + 'px';
document.body.appendChild (pct);
console.log (`${ev.type}: Am plasat un punct la coord. (${ev.pageX},
${ev.pageY}).`);
};
// "ascultăm" evenimentele click și dblclick
document.addEventListener ('click', trateazaEveniment);
document.addEventListener ('dblclick', trateazaEveniment);

vezi exemplul
complet în arhivă

exemplu: tratarea evenimentelor click și dblclick


Dr. Sabin Buragawww.purl.org/net/busaco
studiu de caz (Ondřej Žára, 2013)

Dr. Sabin Buragawww.purl.org/net/busaco


calcul tabelar în
30 de linii JavaScript
jsfiddle.net/ondras/hYfN3/
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;

Dr. Sabin Buragawww.purl.org/net/busaco


}
}

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) {} });
} )();
Dr. Sabin Buragawww.purl.org/net/busaco
Remarcă:

unele navigatoare acceptă tratarea unor evenimente


nestandardizate (încă) de Consorțiul Web
Dr. Sabin Buragawww.purl.org/net/busaco
Remarcă:

pot fi specificate și evenimente definite de programator

CustomEvent

dom.spec.whatwg.org/#interface-customevent
developer.mozilla.org/Web/API/CustomEvent
(în loc de) pauză

Dr. Sabin Buragawww.purl.org/net/busaco


http://abstrusegoose.com/432
Dr. Sabin Buragawww.purl.org/net/busaco
Browser-ul Web oferă obiectul Window

reprezintă o zonă de redare a conținutului


pe baza reprezentării interne (arborele DOM)
a unui document HTML

developer.mozilla.org/Web/API/Window
Dr. Sabin Buragawww.purl.org/net/busaco
Browser-ul Web oferă obiectul Window

fiecare tab al interfeței navigatorului


conține propriul obiect Window

acest obiect nu este partajat de tab-uri multiple


Browser-ul Web oferă obiectul Window

Dr. Sabin Buragawww.purl.org/net/busaco


proprietăți importante:
document – referință la documentul (arborele DOM)
pe care obiectul Window îl include
history – acces la istoricul navigării (via obiectul History)
https://html.spec.whatwg.org/multipage/history.html
location – adresa Web (URL) curentă
navigator – oferă date despre browser (un obiect Navigator)
https://developer.mozilla.org/Web/API/Navigator
Browser-ul Web oferă obiectul Window

Dr. Sabin Buragawww.purl.org/net/busaco


proprietăți importante – continuare:
screen – oferă detalii despre ecran (obiectul Screen)
https://developer.mozilla.org/Web/API/Screen
localStorage – date persistente stocate local
(obiectul LocalStorage specificat de HTML5)
https://developer.mozilla.org/Web/API/Window/localStorage
sessionStorage – referință la date vizând sesiunea curentă
(stocate într-un obiect SessionStorage oferit de HTML5)
html.spec.whatwg.org/multipage/webstorage.html
Browser-ul Web oferă obiectul Window

Dr. Sabin Buragawww.purl.org/net/busaco


metode utile:
alert() confirm() prompt() postMessage()
focus() blur() find() print()
open() close() stop()
moveBy() moveTo() resizeBy() resizeTo()
scrool() scrollBy() scrollTo()

amănunte: https://drafts.csswg.org/cssom-view/
Browser-ul Web oferă obiectul Window

Dr. Sabin Buragawww.purl.org/net/busaco


evenimente – specificate prin nume prefixat de on
și clasificate ca fiind WindowEventHandlers
(reuniunea evenimentelor definite de interfețele
Window, HTMLBodyElement și HTMLFrameSetElement)

developer.mozilla.org/Web/API/WindowEventHandlers
Dr. Sabin Buragawww.purl.org/net/busaco
suportul cumulat vizând evenimentele
oferit de navigatoarele Web actuale
https://caniuse.com/#search=event
Dr. Sabin Buragawww.purl.org/net/busaco
În ce manieră are loc transferul asincron
între aplicațiile de pe server
și documentul Web?
Dr. Sabin Buragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML

permite transfer asincron de date


între client (browser) și serverul Web

a se revizita cursul
„Tehnologii Web”
Dr. Sabin Buragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML

suită de tehnologii deschise

limbaje standardizate de structurare – e.g., (X)HTML –


și de prezentare a datelor: CSS
Dr. Sabin Buragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML

suită de tehnologii deschise

redare + interacțiune la nivel de client Web


via standardul DOM
Dr. Sabin Buragawww.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
Dr. Sabin Buragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML

suită de tehnologii deschise

transfer (a)sincron de date


facilitat de obiectul XMLHttpRequest
Dr. Sabin Buragawww.purl.org/net/busaco
AJAX – Asynchronous JavaScript And XML

suită de tehnologii deschise

procesare folosind limbajul ECMAScript (JavaScript)


Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

disponibil la nivel de navigator Web via JavaScript


Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

specificația actuală oferită de navigatoarele curente


(Living Standard, 13 octombrie 2017)

xhr.spec.whatwg.org
Dr. Sabin Buragawww.purl.org/net/busaco
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
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

open ( )

inițiază – deschide – o conexiune HTTP cu serverul,


emițând o cerere: GET, POST,…
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

send ( )

transmite (asincron) date – e.g., JSON, XML etc. –,


spre aplicația/serviciul ce rulează pe server
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

send ( )

transmite (asincron) date – e.g., JSON, XML etc. –,


spre aplicația/serviciul ce rulează pe server

orice listener (asociat evenimentelor onloadstart,


onprogress, onload, onloadend, ontimeout, onabort, onerror)
trebuie stabilit înainte de a trimite date
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

abort ( )

abandonează transferul de date curent


Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

setRequestHeader ( )

specifică anumite câmpuri de antet HTTP

exemple: Cookie, Keep-Alive, User-Agent,…


Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

getResponseHeader ( )

furnizează un anumit câmp prezent


în antetul mesajului de răspuns HTTP trimis de server
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

getAllResponseHeaders ( )

oferă toate câmpurile HTTP trimise de server,


exceptând Set-Cookie
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

readyState

furnizează codul de stare a transferului:


0 – UNSENT
1 – OPENED
2 – HEADERS_RECEIVED
3 – LOADING
4 – DONE
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

status

oferă codul de stare HTTP întors de serverul Web:


200 (Ok)
404 (Not Found)
500 (Internal Server Error)

Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

statusText

conține mesajul corespunzător codului de stare HTTP


Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

responseText
responseXML

conțin răspunsul (datele) obținut(e) de la server


Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

onreadystatechange

specifică funcția ce va fi invocată la modificările de stare


ale transferului de date dintre server și client

handler de tratare a
evenimentelor de transfer
Dr. Sabin Buragawww.purl.org/net/busaco
Obiectul XMLHttpRequest

excepții care pot fi emise:


AbortError
InvalidAccessError
InvalidStateError
NetworkError
SecurityError
TimeoutError

Dr. Sabin Buragawww.purl.org/net/busaco
Noutăți:
stabilirea unui timeout privind realizarea unei cereri
(la nivel de milisecunde)

o valoare nenulă cauzează realizarea


unei preîncărcări (fetching) a resursei

de studiat Fetch (HTML5 Living Standard, 26 nov. 2017)


fetch.spec.whatwg.org
Dr. Sabin Buragawww.purl.org/net/busaco
Noutăți:
datele vehiculate pot fi de mai multe tipuri
(ArrayBuffer, Blob, Document, DOMString, FormData)

detalii la xhr.spec.whatwg.org/#interface-formdata
Dr. Sabin Buragawww.purl.org/net/busaco
Noutăți:
procesul de transmitere a datelor spre server (upload)
poate avea asociat un handler specific
via proprietatea upload
Dr. Sabin Buragawww.purl.org/net/busaco
Noutăți:
progresul încărcării poate fi urmărit pe baza
funcționalităților specificate de interfața ProgressEvent

xhr.spec.whatwg.org/#interface-progressevent
Dr. Sabin Buragawww.purl.org/net/busaco
http://caniuse.com/
suportul oferit de browser
studiu de caz: RandomAjax

Dr. Sabin Buragawww.purl.org/net/busaco


preia asincron
o secvență de numere
aleatoare generate de
random.org – trimisă ca
text obișnuit
jsfiddle.net/busaco/2254kdqn/
const URL = 'https://www.random.org/sequences/?min=1&max=33&col=1&format=plain';
const TIME = 2000;

var xhr = new XMLHttpRequest ();


var numbers = document.getElementById ('numbers');

Dr. Sabin Buragawww.purl.org/net/busaco


// eveniment de tratare a expirării timpului de așteptare
xhr.ontimeout = function () { numbers.textContent = 'Time-out... :('; };
// eveniment de tratare a preluării datelor solicitate unui serviciu
xhr.onload = function () {
if (xhr.readyState === 4) { // am primit datele
if (xhr.status === 200) { // răspuns Ok din partea serverului
// înlocuim spațiile albe cu virgulă și plasăm conținutul
// în cadrul elementului HTML identificat prin 'numbers'
numbers.textContent = xhr.responseText.trim ().replace (/\W+/g, ', ');
} else {
numbers.textContent = 'An error occurred: ' + xhr.statusText;
}
}
};

xhr.open ("GET", URL, true); // deschidem conexiunea


xhr.timeout = TIME; // stabilim timpul maxim de așteptare a răspunsului
xhr.send (null); // nu expediem date
studiu de caz: RandomAjax (Fetch)

Dr. Sabin Buragawww.purl.org/net/busaco


soluție folosind Fetch API
pentru aceeași problemă
jsfiddle.net/busaco/a2q9regd/
function status(response) {
// recurgem la promises pentru a realiza procesări în funcție de codul de stare HTTP
if (response.status >= 200 && response.status < 300) {

Dr. Sabin Buragawww.purl.org/net/busaco


return Promise.resolve (response) // cererea poate fi rezolvată
} else {
return Promise.reject (new Error (response.statusText)) // cererea a fost rejectată
}
revezi cursul anterior
}

fetch (URL)
.then (status) // verificăm dacă datele au fost recepționate cu succes
.then ((response) => response.text ()) // transformăm obiectul răspunsului în șir de caract.
.then (function (response) { // procesăm secvența de numere
// înlocuim spațiile albe cu virgulă și plasăm conținutul
// în cadrul elementului HTML identificat prin 'numbers'
var numbers = document.getElementById ('numbers');
numbers.textContent = response.trim ().replace (/\W+/g, ', ');
})
.catch (function (error) { // a survenit o eroare :(
numbers.textContent = 'An error occurred: ' + error;
});
studiu de caz: PostJSON

Dr. Sabin Buragawww.purl.org/net/busaco


Scenariu:
preluăm caractere de la client – introduse în <textarea> –
și le trimitem asincron prin POST unei aplicații Web
rulând pe server care le expediază înapoi

mesaje vehiculate în format JSON


{ "tasta": "caracter", "data": "secunde" }

tratăm evenimentul keypress pentru a capta tastele


acționate de utilizator
const trateazaEveniment = ev => { // tratăm evenimentul de apăsare a unei taste
// mesajul propriu-zis trimis serverului prin POST atunci când survine evenimentul
let msg = `{ "tasta": "${String.fromCharCode (ev.charCode)}", "data": "${Date.now()}" }`;
let request = new Request ('/ajax/post.php', { // încapsulăm o cerere POST
method: 'POST',

Dr. Sabin Buragawww.purl.org/net/busaco


body: JSON.stringify (msg), // convertim datele JSON în șir de caractere
headers: {} // n-avem câmpuri-antet
});
fetch (request) // promitem să executăm codul...
.then (response => { // verificăm dacă am primit date JSON de la server
var contentType = response.headers.get ('Content-Type');
if (contentType && contentType.includes('application/json')) {
return response.json (); };
throw new TypeError ('Datele primite nu-s JSON :('); })
.then (json => { // procesăm efectiv datele
// creăm un nod text care indică tasta apăsată
let elem = document.createTextNode (json.tasta);
document.getElementById ('tasteApasate').appendChild (elem);
// raportăm datele primite și la consola browser-ului
console.log (`Date JSON primite: tasta=${json.tasta}, data=${Date(json.data)}`);
})
};
document.addEventListener ('keypress', trateazaEveniment);
<?php
// post.php -- program PHP care preia date JSON
// transmise via POST de client și le trimite înapoi (echo)

function eJSONValid ($sir) { // verifică dacă datele JSON sunt corecte

Dr. Sabin Buragawww.purl.org/net/busaco


json_decode ($sir);
return json_last_error () == JSON_ERROR_NONE;
}

// preluăm de la intrarea standard datele transmise de client (raw data)


// (aici, cele dintr-o cerere POST)
$date = trim (file_get_contents ("php://input"));

if (eJSONValid ($date)) { // trimitem datele JSON înapoi dacă sunt în regulă


header ("Content-type: application/json");
echo json_decode ($date);
} else {
die ('Date incorecte');
}
?>

aplicația (serviciul) invocat(ă) pe server


Dr. Sabin Buragawww.purl.org/net/busaco
Dr. Sabin Buragawww.purl.org/net/busaco
Ce alte aspecte trebuie considerate
atunci când se recurge la Ajax?
Dr. Sabin Buragawww.purl.org/net/busaco
Oferirea de alternative la Ajax, atunci când suportul
pentru acesta nu este implementat/activat

graceful degradation

progressive enhancement

www.w3.org/wiki/Graceful_degradation_versus_progressive_enhancement
Dr. Sabin Buragawww.purl.org/net/busaco
Minimizarea traficului dintre browser și server
Dr. Sabin Buragawww.purl.org/net/busaco
Transferul de date poate fi monitorizat (+interceptat)
via instrumente dedicate

la nivel de desktop:
instrumentul WireShark
Dr. Sabin Buragawww.purl.org/net/busaco
inspecție a datelor vehiculate
cu instrumentele pentru
dezvoltatorii Web
oferite de browser
Dr. Sabin Buragawww.purl.org/net/busaco
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
Dr. Sabin Buragawww.purl.org/net/busaco
Adoptarea Ajax pentru creșterea utilizabilității,
nu doar de dragul tehnologiei

exemple negative:
distragerea utilizatorului
abuz de resurse (e.g., supradimensionarea arborelui DOM)
Dr. Sabin Buragawww.purl.org/net/busaco
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
Dr. Sabin Buragawww.purl.org/net/busaco
Șabloane de proiectare AJAX

privind programarea:
invocare de servicii Web (RESTful Service, JSON Message)
dialog între navigatorul Web și 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
Dr. Sabin Buragawww.purl.org/net/busaco
Șabloane de proiectare AJAX

referitoare la interacțiunea cu utilizatorul:


formulare Web
(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)
Dr. Sabin Buragawww.purl.org/net/busaco
Șabloane de proiectare AJAX

inginerie Web:
jurnalizare (e.g., Logging)
depanare
inspecție de cod/date (DOM Inspection, Traffic Sniffing)

vezi și cursul viitor


Dr. Sabin Buragawww.purl.org/net/busaco
Comet
termen propus de Alex Russel, 2006

permite ca datele să fie „împinse” (push) de către server


spre aplicația client, utilizând conexiuni HTTP
persistente (long-lived) în vederea reducerii latenței
Dr. Sabin Buragawww.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., Mibbit,…
Dr. Sabin Buragawww.purl.org/net/busaco
Comet

complementar Ajax

long polling
HTTP server push
Reverse Ajax

de studiat M. Carbou, “Reverse Ajax, Part 1.


Introduction to Comet”, IBM developerWorks, 2011
www.ibm.com/developerworks/web/library/wa-reverseajax1/
Dr. Sabin Buragawww.purl.org/net/busaco
Comet

instrumente software – exemplificări:


Atmosphere, DWR, Ice Faces, Jetty, Orbited

în contextul JavaScript, un exemplu notabil este


APE (Ajax Push Engine)
www.ape-project.org
Dr. Sabin Buragawww.purl.org/net/busaco
Comet

soluții alternative, moderne:


adoptarea diverselor tehnologii HTML5

server-sent events
WebSocket
Dr. Sabin Buragawww.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ă
Dr. Sabin Buragawww.purl.org/net/busaco
Aplicații mash-up

se bazează pe fluxuri RSS/Atom,


servicii Web, API-uri publice,…

„curentul” SaaS (Software As A Service)


mash-ups

Dr. Sabin Buragawww.purl.org/net/busaco


lista mash-up-urilor: www.programmableweb.com/mashups/directory
Dr. Sabin Buragawww.purl.org/net/busaco
Nu există o problemă de securitate
privind accesul la resurse via JavaScript?
Dr. Sabin Buragawww.purl.org/net/busaco
Same-Origin Security Policy

“restricts how a document or script loaded from one origin


can interact with a resource from another origin”

astfel, un program JavaScript trebuie să acceseze


doar datele aparținând aceleași origini
– i.e., provenite din același domeniu Internet
Dr. Sabin Buragawww.purl.org/net/busaco
HTTP server
client JSON, XML,… Web

HTTP HTTP
JPG JPG
Same-Origin Policy

API API
public public

se permit doar transferuri vizând reprezentări de resurse


referitoare la imagini, fișiere CSS
și alte programe JavaScript aparținând aceleași origini
Dr. Sabin Buragawww.purl.org/net/busaco
Same-Origin Security Policy

previne cazurile în care un document/program încărcat


dintr-o origine să poată accesa/modifica proprietăți
ale unui document aparținând altei origini

developer.mozilla.org/Web/Security/Same-origin_policy
var url = "http://profs.info.uaic.ro/~busaco/teach/courses/web/web-film";
interactiune web: ajax – studiu de caz

Dr. Sabin Buragawww.purl.org/net/busaco


// 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 cu HEAD a unor
meta-date, în mod asincron
Dr. Sabin Buragawww.purl.org/net/busaco
URL al altui domeniuse încalcă Same Origin Policy
Dr. Sabin Buragawww.purl.org/net/busaco
CORS (Cross-Origin Resource Sharing)

recomandare a Consorțiului Web (2014)


www.w3.org/TR/cors/

permite partajarea la nivel de client a resurselor


provenind din domenii Internet diferite

astfel, se pot emite cereri între domenii (cross-origin)


Dr. Sabin Buragawww.purl.org/net/busaco
episodul viitor: ingineria aplicațiilor JavaScript

S-ar putea să vă placă și