1 Realizacja Aplikacji InternetowychJavaScript
2 Quiz [] + [] [] + {} [0]+1 [0]-1 A = [0] A == A A == !AA = [null, undfined, [] ] A == ”,,”
3 JavaScript vs ECMAScriptJavaScript is nie jest związany z Javą Wprowadzony w przegladarce Netscape w XII 1995 Najbardziej popularny język programowania na świecie ? MS wyprodukował zbliżony język: JScript Oba języki bazują na standardzie ECMAScript wprowadzonym przez European Computer Manufacturers Association (3 wyd w XII 1999) JavaScript i JScript są nadzbiorami ECMAScript Są hostowane w przeglądarkach, ale nie tylko (Acrobat Forms, Node.js)
4 Typy Undefined (pojedyncza wartość: undefined)Null (pojedyncza wartość: null) Boolean (wartości: true, false) String (niemutowalna sekwencja znaków Unicode, brak typu znakowego) Number (64-bitowa liczba zmiennoprzecinkowa, brak typu całkowitego, specjalne wartości NaN i Infinity) Object "...i to by było na tyle...".
5 Nowe operatory === jest identyczny (wartość i typ)!== nie jest identyczny (wartość lub typ)
6 Zmienne var nie jest typowaneDwa poziomy granularności zakresu: globalne i funkcja (brak zakresu bloku) Tylko zmienne defioniowane jako var w obrebie funkcji mają zakres funkcji – inne są globalne. Nie na sensu używać bloków gdy nie są wymagane przez instrukcje złożone. var nie zaincjalizowane ex-plicite ma wartość undefined. var nie jest typowane In JavaScript blocks do not have scope. Only functions have scope. Do not use blocks except as required by the compound statements.
7 Obiekty Referencjonalne kontenery par nazwa/wartość Metody ?Nazwy: napisy (Jeśli treba wykonywan konwersja) Wartości: dowolny typ danych (właczajac inne obiekty) Nie trzeba implementować dostępu API (hashtable) Właściwości tworzone w locie var myObj={}; var myObj=new Object(); myObj.p1=”blah” ; myObj[”p1”]=”blah”; var myObj={”p1”:new String(”blah”)}; Metody ?
8 Obiekty Obiekty są w istocie tablicami haszowanymi z ładną składniąMożna więc iterować po obiekcie... for (name in object) { if (object.hasOwnProperty(name)) { value = object[name]; } }
9 Obiekt Globalny Unikalny, pre-definiowany obiekt który zawiera wszytskie funkcje i zmienne nie zdefionowane wewnątrz innych funkcji lub obiektów W przeglądarkach implementacja this, window i self pokazują na Obiekt Globalny Wszystkie globalne funkcje i zmienne są zdefiniowane jako funkcje i zmienne Obiektu Globalnego this.NaN=0; //changes value of NaN ‘constant’ ! Jeśli zmienna/funkcja nie jest zdefiniowana w bieżącym zakresie jest poszukiwana w Obiekcie Globalnym
10 Tablice Regularne obiekty (właściwości dostępne za pośrednictem nazw!) properties accessed via names!), ale okreslona klasa nazw (non-negative integers) właściwości traktowana inaczej Nie typowane (mogą zawierać wartości różnych typów) Właściwość length jest ustawiana na największy klucz całkowity w tablicy +1 var myArr=[”val0”]; //myArr.length == 1 myArr[1]=”val1”; //myArr.length == 2 myArr[”v2”]=”val2”; //myArr.length == 2 myArr.2=”val2”; //nielegalne
11 Funkcje Obiekty typu first-class ze skojarzonym kodem i możliwą operacją call Składnia function func(x) {alert(x);} Operator (nazwa f. jest opcjonalna – f.anonimowe) var func=function(x) {alert(x);}; Konstruktor (nie ma słowa function) var func=new Funkcja(”x”,”alert(x);”); Wsparcie dla zmiennej liczby argumentów (właściwość arguments) Ma zakres leksykalny
12 Funkcje (c.d.) var arr=[]; arr[0]=function(x){return x*x;};Mogą być przypisywane do zmiennych (wcześniejszy przyklad) Mogą być elementami tablicy var arr=[]; arr[0]=function(x){return x*x;}; arr[1]=arr[0](2); alert(arr[1]); //displays 4 Mogą mieć swoje właściwości var func=function(x) {alert(x);} func.ownProperty=”test”; Mogą być właściwościami obiektu (metody!) var obj={”show”: function(){return ”-object-”;}} alert(obj.show()); //displays -object-
13 Funkcje (c.d.) opOn(16,square); //displays 256Mogą być przekazywane jako argument function square(x) {return x*x;} function opOn(num,func) { return func(num);} opOn(16,square); //displays 256 Mogą być zwracane jako wartość function createIncrementer() { return function(x){return x+1;} } var inc = createIncrementer(); alert(inc(7)); //displays 8 Muszą zwracać wartość (domyślnie jest to undefined, z wyjątkiem wołań operatora new)
14 Metody myFunction.call(myObject,...)Metoda jest funkcją wołaną z kontekstem określonego obiektu Metody mogą być definiowane przez : Ustawienie funkcji jako właściwości obiektu myObject.method1=function(...){...} myObject.method1(...) Ex-plicite wskazany kontekst myFunction.call(myObject,...) Specjalna zmienna this jest dostępna wewnątrz funkcji i odnośi się do obiektu wskazanego jako kontekt (lub Obiektu Globalnego dla f. niezwiązanych)
15 Operator new i konstruktoryoperator new jest używany wraz z wywolaniem funkcji: Tworzy nowy pusty obiekt Ustawia go jako this dla wywołanej funkcji Ustawia go jako domyślny zwrot z funkcji (może być nadpisany) ... Jeżeli f. Jest użyta do ustawienia właściwości nowego obiektu wraz z operatoem new może być uznana (i jest nazywana) konstruktorem function func() {this.prop1=”val1”;} var x=new func(); alert(x.prop1); //displays val1
16 Realizacja Aplikacji InternetowychWielkie udawanie
17 OOP Emulacja metod Metody mogą być definiowane przez ustawienie właściwości na daną funkcję myObj1.func=function(){alert(this.name);}; Połączenie obiekt-metoda jest b. słabe var myObj1={”name”:”obj1”}; var myObj2={”name”:”obj2”}; myObj1.func(); //displays obj1 myObj1.func.call(myObj2); //displays obj2
18 OOP Emulacja klas Konstruktory definiują sposób tworzenia obiektu (OOP klasy) function myConstructor(value) { this.prop1=value; this.check=function(val) { if(this.prop1==val) alert(”ok!”); } } var myObj1=new myConstructor(”obj1”); myObj1.check(”obj1”); //displays ok! myObj1.check(”obj2”); //do nothing
19 OOP Emulacja klas (c.d.) Obiekty mogą współdzielić implementację swoich metod function checkFunction(val) { if(this.prop1==val) alert(”ok!”); } function myConstructor(value) { this.prop1=value; this.check=checkFunction; } var myObj1=new myConstructor(”obj1”); myObj1.check(”obj1”); //displays ok!
20 OOP Emulacja klas (c.d) Konstruktor (funkcja) nie jest związany z żadnym typem Każda funkcja może być wywołana jako konstruktor var myObj1={”name”:”obj1”}; myObj1.func=function() { alert(this.name); return {}; }; var x = new myObj1.func(); //x is empty object Obiekty nadpisują domyslny zwrot z funkcji. Typy proste już nie.
21 OOP emulacja metod statycznychPonieważ funkcja konstruktor faktycznie reprezentuje klasę obiektów i może być rozszerzna o własne właściwości implementacja metod i właściwości statyczny jest trywialna function BaseClass(name){ this.name = name; } BaseClass.staticMethod = function() { return new OtherClass(); }; ... var other = BaseClass.staticMethod();
22 Mamy obiekt i chcielibyśmy mieć drugi - podobny…Application.GUI.Panel; ... Application.GUI.SecondPanel = Application.GUI.Panel; // this is in fact the same object!!! //What about Application.GUI.SecondPanel.Name = “Second”; //What is the name of the first panel? Application.GUI.Panel.Name = ???
23 Klony nadchodzą Funkcje są obiektami i można je kopiować!Application.GUI.Panel; ... App.GUI.SecondPanel = {}; App.GUI.SecondPanel.Show = App.GUI.Panel.Show; App.GUI.SecondPanel.Validate = App.GUI.Panel.Validate; //and many, many more…. //what about ? App.GUI.SecondPanel.Config = App.GUI.Panel.Config;
24 Helper z ExtJS? //this copies all the stuff (including functions)//from Panel to SecondPanel Ext.apply(Application.GUI.SecondPanel, Application.GUI.Panel) // Exemplary implementation Ext.apply = function(d, e, b) { if (d && e && typeof e == "object") { for (var a in e) { d[a] = e[a] } } return d }; Issues: shallow copy prototypes
25 OOP Emulacja dziedziczenia – podejście funkcyjnefunction Base(name){ this.name = name; } var b = new Base("b1"); alert(b.name); //displays b1 //class Derived : Base function Derived(name,count) { Base.call(this,name); //this.baseClass=Base; this.count = count; //this.baseClass(); var d = new Derived("d1",5); alert(d.count); //displays 5 alert(d.name); //displays d1
26 Prototypy Każda funkcja ma właściwość prototype wskazującą na obiekt (domyślnie pusty) Każdy obiekt (włączając funkcje) ma właściwość constructor. Obiekt wskazywany domyślnie przez prototype danej funkcji ma swoją właściwość constructor ustawioną na pierwotną funkcję Property constructor oraz prototype można nadpisać.
27 Prototypy (c.d.) Obiekty nie-funkcyjne mają ukrytą (niedostępną) właściwość _prototype, która pokazuje na prototyp (obiekt), który obowiązywał (wskazywało na niego prototype w konstruktorze) w momencie tworzenia obiektu. Operator new aktualizuje tworzony obiekt: Ustawia wlaściwość _prototype na prototype konstructora
28 Emulacja dziedziczenia (c.d.)Łańcuch dziedziczenia po utworzeniu jest stabilny Derived.prototype=new Base1(); var d1=new Derived(...); //d1 cannot be altered to inherit //from object other than Base1 ...ale można go zmienić dla nowych obiektów Derived.prototype=new Base2(); var d2=new Derived(...); //d1 and d2 inherit from //different objects
29 Prototypy (c.d.) Jeżeli obiekt nie implementuje żadanej właściwości,sprawdzany jest jego prototyp, stąd: Obiekt efektywnie "dziedziczy" wszystkie własciwości po swoim prototypie Zmiany w prototypie są natychmiast widoczne w obiektach potomnych (równiez już utworzonych) Każda wartość w prototypie może być "nadpisana" w obiekcie Obiekty potomne mogą być prototypami innych obiektów, tworząc łańcuch dziedziczenia (aż do Obiektu Globalnego) Ponieważ własciwości są tworzone w locie, obiekty pochodne w momencie zapisu do dziedziczonej (z _prototype) wartości automatycznie tworzą własną kopię ("nadpisując" dziedziczoną wartość)
30 Prototypy (c.d.)
31 Dziedziczenie na poziomie obiektu?InheritFromObject (objectToDerrive) { var f = function() {}; f.prototype = objectToDerrive; return new f(); } App.GUI.Panel; ... App.GUI.SecondPanel = InheritFromObject(App.GUI.Panel); // albo nawet ze składnią zbliżoną do f. wbudowanych Object.prototype.BegetObject = function () { f.prototype = this; App.GUI.SecondPanel = App.GUI.Panel.BegetObject();
32 Dziedziczenie na poziomie obiektuAle: Object jest globalny więc begetObject może być nadpisane Co będzie jak oldObject się zmieni?
33 Zmiany: App.GUI.Panel; ... App.GUI.SecondPanel = App.GUI.Panel.BegetObject(); //some behaviors and attributes can be overwritten App.GUI.SecondPanel.Show = function() {}; App.GUI.SecondPanel.Title = “new panel”; Co będzie w momencie zmiany w App.GUI.Panel ?? Application.GUI.Panel.Validate = function() {}; //they will cause change in behavior SecondPanel in //case when the Hide function wasn’t overridden
34 Emulacja dziedziczenia klas – podejscie prototypowefunction Base(name){ this.name = name; } //here is an example how to create method that will be //shared across all objects of Base ‘class’ Base.prototype.toString = function(){ return "name:" + this.name; }; var b = new Base("b1"); alert(b.toString()); //displays name:b1 //in fact alert() calls toString() method //and Base.toString() overrides Object.toString() method
35 Emulacja dziedziczenia klas(c.d.)var b = new Base("b1");
36 Emulacja dziedziczenia klas (c.d.)//class Derived : Base function Derived(name,count) { Base.call(this,name); //Derived : base(name) this.count = count; } //Derived prototype have to be linked with Base prototype Derived.prototype = new Base(); //yes, Derived has custom toString() implementation Derived.prototype.toString = function() { return "name:"+this.name+",count:"+this.count; }; var d = new Derived("d1",5); alert(d.toString()); //displays name:b1,count:5
37 Emulacja dziedziczenia klas (c.d.)Derived.prototype = new Base(); var d = new Derived("d1",5);
38 Prototypy Nie można emulować prywatnych składowychBrak duplikacji funkcji – rozmiar obiektu nie zależy od liczby ani rozmiaru funkcji Główny problem to niekontrolowana zmiana zawertości prototypu -
39 Domknięcia Funkcje mogą być definiowane wewnątrz innych funkcjiWewnętrzne funkcje mają dostep do zmiennych i parametrów f. zewnętrznej Jesli referencja do wewnętrznej funkcji (callback) istnieje – utrzymywana jest przy życiu f. zewnętrzna function createChecker(treshold) { return function(numberToCheck) { return (numberToCheck > treshold) ? true : false; } } var checker100 = createChecker(100); alert(checker100(99)); //displays false
40 Emulacja prywatnych właściwościPrywatne właściwości można zaemulować przy użyciu domknięć function Person(name){ //C# readonly this.getName=function() {return name;}; var count; this.getCount=function() {return count;}; this.setCount= function(newCount) { count=newCount;}; this.publicMethod=function(){ alert(this.name); //undefined alert(this.getName()); //ok }
41 Uwaga na prototypy function Base(){ var count;this.GetCount=function() {return count;}; this.SetCount=function(newCount){count=newCount;}; } function Derived() { Base.call(this); //!!! } Derived.prototype = new Base(); var cd1=new Derived(); var cd2=new Derived(); //cd1.GetCount()==cd2.GetCount() cd1.SetCount(100); //cd1.GetCount()!=cd2.GetCount()
42 Emulacja namespaces Przestrzenie nazw mogą być emulowane jakovar DATA={}; DATA.IO={}; DATA.IO.Parsers={}; var SC = DATA.IO.Parsers; //jak C# using DATA.IO.Class1=function(...){...}; DATA.IO.Class1.prototype.toString=function(){...}; var c1 = new SC.Class1(...);
43 Dziwactwa Javascript-uvoid nie jest typem, to prefiksowy operator zwracajacy zawsze wartość undefined Operatory bitowe i przesuniecia są wspierane ale nie ma wbudowanego typu integer. 64-bitowy typ zmiennoprzecinkowy Number jest konwerowany na 32-bitowy typ całkowity przed operacją i po niej konwertowany ponownie do Number Operator typeof zwraca string opisujący dany obiekt. typeof(new Array()) i typeof(null) zwrócą ”object” (zamiast odpowiednio ”array” i ”null”)
44 Czy już wszystko jasne?
45 function getLabel() { var count = 0, concatenation = "" ['dog','cow','rabbit'].forEach(function(animal,i){ count = i+1 concatenation += animal + ' ' }) return { 'count' : count, 'animals' : concatenation }
46 Javascript wymaga średników… więc je sam sobie dodaje Gdy po nowej linii jest błedny token Gdy po nowej linii następuje ++ lub -- Gdy nowa linia następuje po continue, break, return, throw Na koncu pliku – jeśli to potrzebne ale nie dodaje Gdyby to zaowocowało pustą instrukcją Wewnątrz nagłówka instrukcji for
47 function getLabel() { var count = 0, concatenation = "" ['dog','cow','rabbit'].forEach(function(animal,i){ count = i+1 ; concatenation += animal + ' ' ; }) ; return ; { 'count' : count, 'animals' : concatenation } ; }
48 function getLabel() { var count = 0, concatenation = "" ['dog','cow','rabbit'].forEach(function(animal,i){ count = i+1 ; concatenation += animal + ' ' ; }) ; return ; { 'count' : count, 'animals' : concatenation } ; }
49 undefined Zwraca undefinefined pomijane ""['dog','cow','rabbit']return ; { 'count' : count, 'animals' : concatenation } ; Zwraca undefinefined pomijane
50 Dodajemy wszędzie średniki undefined ""['dog','cow','rabbit'] return ; { 'count' : count, 'animals' : concatenation } ; Możliwe rozwiazania: Dodajemy wszędzie średniki Dodajemy srednik przed linią która zaczyna się od ‘[‘ ‘(‘ binarnego operatora +- */ Uzywamy JSLinta/JSHinta Zwraca undefinefined pomijane
51 function getLabel() { var count = 0, concatenation = "" ;['dog','cow','rabbit'].forEach(function(animal,i){ count = i+1 concatenation += animal + ' ' }) return { 'count' : count, 'animals' : concatenation }
52 Spostrzeżenie Aplikacje (również JS) maja tendencję do bycia:Bardziej skomplikowanymi większymi (i bardziej skomplikowanymi) Sa pisane w zespołach (więc są trudniejsze do ogarnięcia)
53 Typowy kod Setki tysiace zmiennych i funkcji ?AppState = “Modal”; ... function ShowWindow() { if (AppState) } Setki tysiace zmiennych i funkcji ? Problem został już odkryty – rozwiązanie nazywa się Obiektowo Zorientowane ... Wszysko Co Byście Chcieli .
54 W praktyce problem może być takiApplication.GUI.Config.State = “Modal”; Application.GUI.Validate() = function () {...} Application.GUI.ShowMainWindow = function () { ... if (this.Config.State) Application.Utils.DataInterface.ReadData(); } Jest hierarchia: ale nie ma kontroli nad tworzeniem (jak utworzyć podobną funkcjonalność w innym miejscu) zależności miedzy obiektami stanowią poważny problem
55 Truizmy ... Jak sobie radzić z komplikacją kodu? Unikać duplikacji:Mniej kodu = mniej problemów Dzielić kod na części Mniejsze części sa łatwiejsze do zrozumienie, użycia i modyfikacji, ale muszą być niezależne! Kod powinien być jasny i łatwy do zrozumienia
56 Praktyczne wskazówki Wydzielone tworzenie/reużycie obiektów: emulacja klas (clousures czy prototypy) lub dziedziczenie obiektów Zależności rozwiązywane na poziomie obiektów nie odniesień do DOMa, ani hierarchii obiektów: Obiekt ma property wskazujace na inny obiekt a nie odwoluje sie do konkretnego miejsca w hierachii klas. Wzorzec obserwator (event) można zaimplementowac rownież w JS Testy jednostkowe, integracyjne, akceptacyjne
57 Gotowe rozwiązania Alternatywy: GWT, CofeeScript, TypeScript, DARTLekki javascipt wspierajacy różne aspekty pracy aplikacji np. JQuery Framework organizujący całą logikę aplikacji, kontrolki itd. np. ExtJS Frameworki: Angular, Knockout, Backbone Single Page Applications
58 Dokumentacja, narzędziahttps://developer.mozilla.org/en/JavaScript/Reference JSLint, JSHint FireBug, Chrome Developer Tools, IE Inspector / WebDeveloper Fiddler
59 Realizacja Aplikacji InternetowychTESTOWANIE
60 Testowanie Testy jednostkowe Testy akceptacyjne
61 Środowisko Środowisko uruchomieniowe Framework Narzędzia dodatkoweFireUnit
62 Środowisko uruchomieniowePrzeglądarka uruchamiana ręcznie Selenium + przeglądarka Na serwerze: jsdb, rhino + env.js, WebKit
63 Framework QUnit (używany np. przez wiele plug-inów JQuery)module('calculator'); test('add numbers', function() { var calc = new Calculator(); equals(4, calc.add(2, 2)); })
64 Framework Jasmine (BDD, hierarchiczna definicja setup-ów)describe('panda',function(){ it('is happy',function(){ expect(panda).toBe('happy'); });
65 Framework Screw.Unit JSSpecdescribe("Calculator", function() { it("should add numbers", function() { var calc = new Calculator(); expect(calc.add(2, 2)).to(equal, 4); }); }); JSSpec describe("Calculator", function() { with(this) { it("should add numbers", function() { var calc = new Calculator(); calc.add(2, 2).should(equal(4)); }); }});
66 Framework jsUnitTest jsUnitTest + jShouldanew Test.Unit.Runner({ testCalculatorAdd: function() { with (this) { var calc = new Calculator(); assertEqual(4, calc.add(2, 2)); }} }); jsUnitTest + jShoulda context('Calculator', { should('add numbers', function() { with (this) { var calc = new Calculator(); assertEqual(4, calc.add(2, 2)); }})
67 Framework I wiele innych m.inUnittest, jsAssertUnit, YUItest, Qooxdoo, JSUnit, JSUnit , Crosscheck, Ecmaunit, Dojo Objective Harness, FireUnit, Qunit, RhinoUnit, JSpec (by Yehuda Katz)
68 Tools Smoke Amok MockMenew Smoke.Stub(Calculator, 'add').and_return(5); Smoke.Mock(Calculator).should_receive('add').at_least('once') .with_arguments(2, 2).and_return(5); Amok var mock = amok.mock(Calculator); mock.should_receive('add').with_args(2, Number) .times(1).and_return(5); MockMe mock(Calculator).andDo(function() { SomethingThatUsesCalculator.calculate("2 + 2"); verify(Calculator.add)(2, 2); });
69 Tools qMock Jack JSMock (abandoned?) var mock = new Mock();mock.expects(1).method('add').withArguments(2, 2).andReturn(5); Jack jack.expect("Calculator.add").exactly("1 time") .withArguments(2, 2).mock(function() { … return sth; }) jack.create("mock", ['add', 'substract']); .whereArgument(0).isOneOf(2, 3, 4); JSMock (abandoned?) var factory = new MockControl(); var mock = factory.createMock(Calculator); mock.expects().add(2, 2).andReturn(4);
70 Istotne uwagi Izolacja od drzewa DOM i globalnych odwołań do obiektówLokalne referencje do używanych obiektów Rozluznienie połączeń miedzy obiektami Mozliwość stosowanania wzorca obserwator (event) Stosowanie broker event (serviceBus) do komunikacji
71 Pokrycie kodu testami JSCoverage
72 Realizacja Aplikacji InternetowychJQuery
73 JQuery Silny model selekcjiWsparcie dla typowych akcji np. ustawienie obsługi zdarzenia, dodanie, usunięcie klasy stylu itd. Gotowe rozwiazania typowych problemów Rozszerzalny model - wtyczki Dużo gotowych wtyczek Testowalny
74 JQuery Problem: wyszukiwanie elementów na stronie np:for ( var (i in document.getElementsByTagName("p") ) { i.onclick = function(event) { alert("Hello!"); } } JQuery: $("p").click(function(event){ alert("Hello!!"); }
75 Jquery – Referencjonowanie // Standard. jQuery $ jQuery(document).ready( function () { alert('DOM is ready!'); }); // Shortcut, but same thing as above. jQuery( function () { alert('No really, the DOM is ready!'); }); // Shortcut with fail-safe usage of $ jQuery(function($) {alert('Seriously its ready!'); }); { "@context": "http://schema.org", "@type": "ImageObject", "contentUrl": "http://slideplayer.pl/417809/1/images/75/Jquery+%E2%80%93+Referencjonowanie.jpg", "name": "Jquery – Referencjonowanie", "description": " // Standard. jQuery $ jQuery(document).ready( function () { alert( DOM is ready! ); }); // Shortcut, but same thing as above. jQuery( function () { alert( No really, the DOM is ready! ); }); // Shortcut with fail-safe usage of $ jQuery(function($) {alert( Seriously its ready! ); });", "width": "800" } 76 JQuery Problem: wyszukiwanie elementów na stronie np:for ( var (i in document.getElementsByTagName("p") ) { i.onclick = function(event) { alert("Hello!"); } } JQuery: $("p").click(function(event){ alert("Hello!!"); }
77 JQuery Selektor zwraca kolekcję obiektów DOM "owiniętych" w obiekty JQuery (dodatkowe metody) Pojedynczy obiekt można owinac stosujac $ np. $(this) Kolekcję można ją zapamiętać i wyłuskać z niej referencje do poszczególnych elementów var jqlinki = $("a"); var pierwszy_link = linki[0]; Kolekcję można też sprowadzic do tablicy obiektów DOM var jqlinki = $("a").get();
78 JQuery - selektory Selektory zwracają kolekcję elementów JQuery opakowujących elementy DOM: $("*") – wszystko $("a") - po nazwie tagu $('#myDivId') - po id $('.myCssClass'), $(‘a.myCssClass')- po klasie CSS $("[id]") – po atrybucie $("[id=wartosc]") – po wartości atrybutu Np. $('div').each( function() { alert($(this).html(); });
79 JQuery – selektory strukturalne$ (“selektor1, selektor2, selektorN”) $("p,a,div,code.bold") $("rodzic > dziecko") $(„p>a") $("przodek potomek") $("p a.bold") $ (“poprzedni+nastepny”) $ (“label.MyLabelClass + input”) $ (“poprzedni ~ cale_rodzenstwo”) $ (“h3 ~ p”)
80 JQuery - atrybuty $("[id]") $("p[id][name]")$("[id=wartosc]") $("input[name='newsletter']"), $("input[type=‘text']") $("[id~=slowo]") $("input[name~='test']") $("[id|=poczatek_do_kreski_lub_rowny]") $("a[hreflang|='en']") $("[id*=podciag]") $("input[name~='xx']") $("[id^=poczatek]") $("input[name^='news']") $("[id$=koniec]") $("input[name^=letter']")
81 JQuery - selektory Selektory można łaczyć i dodawać$("a.myCssClass, '#myDivId>a")
82 JQuery – modyfikatory selekcji:animated, :checked, :disabled :enabled, :empty, :hidden, :visible, :selected :file, :checkbox, :button, :header, :password, :radio, :reset, :submit, :text :even, :odd, :first, :first-child, :last, :last-child, :parent :contains() $("div:contains('John')") :has() $("div:has('p')") :not(sektor) $("input:not(:checked) + span") :eq(), :lt(), :gt() $("td:eq(2)")
83 JQuery – filtry .eq(), .first(), .last(), .slice(od,[do]) $('li').eq(2) $('li').eq(-1) $('li').slice(3,-2) .filter(selector), filter(function) $('li').filter(':even') $('li').filter(function(index) { return index % 3 == 2; }) .has(selektor_potomka), .has(DOM_element_potomny) $('li').has('ul') .not(selektor), not(DOM_elementy), not(function(index)) $('li').not(':even') $("p").not( $("#selected")[0] )
84 JQuery – pobieranie zawartości.get([pozycja]) - pobieranie elementów Dom $("a").get() .html() $('div.demo-container').html(); $( "#myDiv p:first" ) .html( "New first paragraph!" ); .length, size() var n = $("div").length; .val() $('select.foo option:selected').val() .attr() var title = $("em").attr("title"); $("em").attr("title“,”new title”);
85 JQuery – trawersowanie drzewa.find(), .end() – kończy ostatnie find $("p").find("a") .siblings(), .children(), .contents(), .closest(), .next(), .prev(), .parent(), .parents() .prevAll(), .nextAll(), .andSelf() $("div:last").prevAll(".myClass") .nextUntil(), .parentsUntil(), .prevUntil() #("#term-2").nextUntil("dt") .offsetParent() – pozycja na ekranie .add() $('li').add('p')
86 JQuery – ZMIANY .replaceAll(co_zastapic_selekcja) $("Paragraph.").replaceAll("p") .replaceWith(noweElementy), replaceWith(funkcja), $('.second').replaceWith("New heading
"); $('.third').replaceWith($('.first'));
87 JQuery – transformacje.map( callback(this, index) ) var oneBased = $.map([0,1,2,3,4], function(value){return value+1;}); var ids = $(':checkbox').map(function() { return this.id; })
88 JQuery – predykaty .hasClass() $('#mydiv').hasClass('foo').is() $(this).is(".blue,.red")
89 JQuery – modyfikacje .addClass(), removeClass() $('p').addClass('myClass yourClass'); .toggleClass( className ), .toggleClass( className, switch ), .toggleClass( function(index, class), [ switch ] ) $("p").click(function () { $(this).toggleClass("highlight"); }); .removeAttr() $(this).next().removeAttr("disabled") .css(), .attr(), .val() $(‘p’). css( { fontSize: "100px", color: "red“ } )
90 JQuery – zdarzenia .error(), .resize(), .scroll() $('#book').error(function() { alert('Handler called.') }); .load(), .ready(), .unload() .blur(), .change(), .focus(), .select(), .submit() $('form').submit(function() { alert('Handler for .submit() called.'); return false; }); .focusin(), .focusout(), .keydown(), .keypress(), .keyup() .hover(), .mousedown(), .mouseenter(), .mouseleave(), .mousemove(), .mouseout(), .mouseover(), .mouseup(), .click(), .dblclick(), .toggle() $('#target').toggle( function() { alert('First handler for .toggle() called.'); }, function() { alert('Second handler for .toggle() called.'); });
91 JQuery – efekty .hide(), show() $('p').addClass('myClass yourClass');.focus() .slideDown(), .slideToggle(), .slideUp() ("div").slideDown("slow"); .fadeIn(), .fadeOut(), .fadeTo() $("div:hidden:first").fadeIn("slow"); .animate(), .stop(), .delay(), jQuery.fx.off $('#book').animate({ width: ['toggle', 'swing'], height: ['toggle', 'linear'], opacity: 'toggle' }, 5000, function() { // Animation complete. }); );
92 JQuery – Ajax load(), jQuery.get(), jQuery.getJSON(), jQuery.getScript(), jQuery.post() $.get("test.cgi", { name: "John", time: "2pm" }, function(data){ alert("Data Loaded: " + data); }); $('#result').load('ajax/test.html', function() { alert('Load was performed.'); }); jQuery.ajax(), jQuery.ajaxSetup(), $.ajax({ type: 'POST', url: url, data: data, success: success, dataType: dataType }); .ajaxComplete(), .ajaxError(), .ajaxSend(), .ajaxStart(), .ajaxStop(), .ajaxSuccess(), . jQuery.param(), .serialize(), .serializeArray()
93 JQuery – Różne .clone(), .append(), appendTo(), .prepend(), .prependTo(), text(), html() $('h2').appendTo($('.container')); $("p").text("Some new text."); .unwrap(), .wrap(), .wrapAll(), .wrapInner() $("span").wrap("New heading
').replaceAll('.inner');$("").replaceWith(""); .detach(), .empty(), .remove() $('.hello').empty();
94 JQuery – Literatura Materiały: Ksiązki Doc do VS jquery.com“jQuery Succinctly” “JQuery in Action” “Learning jQuery” Doc do VS
95 Realizacja Aplikacji InternetowychExt-Js
96 Ext-JS (Sencha, Aptana)Ext-core – skrócona wersja – bez frameworka UI Ext-all – pełna wersja z kontrolkami Jak selektora dom moze korzystać z GWT, jQuery, DOM, YUI Framework: Komercyjny/opensource Komercyjny: Ext builder
97 Ext - core Uruchamianie skryptów na DOM Szukanie elementow po idExt.onReady(function() { ... }); Szukanie elementow po id var el=Ext.get('myElementId'); el.addClass('error'); Lekkie "nietrwałe" referencje Ext.fly('elId').hide(); Szukanie elementow Ext.query('div:nth-child(2)'). findParent('div');
98 Ext - core Zdarzenia AnimacjeExt.fly('myEl').on('click', function(e, t) { alert("clicked!!!"); }); Animacje var el=Ext.get('myElementId'); el.slideOut('t', { easing: 'easeOut', duration: .5, remove: false, useDisplay: false });
99 Ext - "klasy" DziedziczeniePerson = Ext.extend(Object, { constructor: function(first, last){ this.firstName = first; this.lastName = last; } getName: function(){ return this.firstName + ' ' + this.lastName; } }); var p1 = new Person('John', 'Smith'); var p2 = new Person({firstName:'John', LastName: 'Smith'); { "@context": "http://schema.org", "@type": "ImageObject", "contentUrl": "http://slideplayer.pl/417809/1/images/99/Ext+-+klasy+Dziedziczenie.jpg", "name": "Ext - klasy Dziedziczenie", "description": "Person = Ext.extend(Object, { constructor: function(first, last){ this.firstName = first; this.lastName = last; } getName: function(){ return this.firstName + + this.lastName; } }); var p1 = new Person( John , Smith ); var p2 = new Person({firstName: John , LastName: Smith );", "width": "800" } 100 Ext - narzędzia Odwołania do klasy bazowej Przestrzenie nazwMyClass = Ext.extend(Object, { constructor: function(config){ MyClass.constructor.call(this, config); }, foo: function(){ ... } }); Przestrzenie nazw Ext.namespace( 'MyCompany', 'MyCompany.Application'); Ext.namespace('MyCompany.Application');
101 Ext – wzorzec obserwatorvar MyClass = Ext.extend(Ext.util.Observable, { constructor: function(config){ this.addEvents('datachanged'); // event MyClass.constructor.call(this, config); }, update: function(){ // jakies transformacje // Przy "odpaleniu" zdarzenia mozemy okreslic // parametry ktore maja byc przekazane this.fireEvent('datachanged', this, this.data.length); } }); // Subskrypcja eventu var c = new MyClass(); c.on('datachanged', function(obj, num){ /* obsluga.*/ });
102 Ext - DOM Modyfikacja DOMa createHtml (przestarzale), markupinsertHtml,insertBefore,insertAfter, insertFirst, append, overwrite Ext.DomHelper.append(document.body, { id: 'my-div', cn: [{ tag: 'a', href: 'http://www.yahoo.com/', html: 'My Link', target: '_blank' }] });
103 Ext - DOM Skryptowanie: var myEl = document.createElement('a');myEl.href = 'http://www.yahoo.com/'; myEl.innerHTML = 'My Link'; myEl.setAttribute('target', '_blank'); var myDiv = document.createElement('div'); myDiv.id = 'my-div'; myDiv.appendChild(myEl); document.body.appendChild(myDiv);
104 Ext - AJAX Globalne handlery: Typowe wołanie:Ext.Ajax.on('beforerequest', this.showSpinner, this); Ext.Ajax.on('requestcomplete', this.hideSpinner, this); Ext.Ajax.on('requestexception', this.hideSpinner, this); Typowe wołanie: Ext.Ajax.request({ url: 'ajax_demo/sample.json', success: function(response, opts) { var obj = Ext.decode(response.responseText); console.dir(obj); }, failure: function(response, opts) { console.log('server-side failure with status code ' + response.status); }});
105 Ext - GUI ViewPort, Window Toolbar, Progresbar, TabPanel, Panel,Editor, DataPicker, DataView Button, ButtonGroup
106 Ext - przykład Ext.onReady(function() { var item1 = new Ext.Panel({ title: 'Accordion Item 1', html: '
107 Ext - przykład Ext.onReady(function() { var item1 = new Ext.Panel({ }); var accordion = new Ext.Panel({ region:'west', margins:' ', split:true, width: 210, layout:'accordion', items: [item1, item2, item3, item4, item5] }); var viewport = new Ext.Viewport({ layout:'border', items:[ accordion, { region:'center', margins:' ', cls:'empty',bodyStyle:'background:#f1f1f1', html:'
108 Ext – przykład: reużycie kontrolekExt.onReady(function() { MyPanel = extend(Ext.Panel, { title: 'Accordion Item 1', html: '
109 Ext-GUI Przykłady: Lauout Drag&Drop Form Desktop
110 Ext-GUI Rozluznienie powiazań m. Komponentami Lokalne referencjeObserwator Mediator: publish/subscribe Simplebus Ext.bus
111 Realizacja Aplikacji InternetowychCoffeeScript
112 Języki kompilowane do JavaScriptTraceur (google: kompilator javascript next 2 javascript) Ecma Harmony / Narcisius (jw) Script# (c# 2 javascript) GWT (java 2 javascript) Pyjamas (python 2 javascript) CoffeeScript TypeScript Dart
113 Instalacja Node.js + coffee-script.js CoffeeSharp.zipNUGet: Install-Package CoffeeSharp Coffee.exe CoffeeScriptHttpHandler.dll CoffeeSharp.dll Jurassic.dll
114 Motywacja Zwięzła składnia Redukcja szumu {} itd Dodatkowe możliwościPoprawione problemy (==, var) Produkowany jest dobry kod Javascript Informacje Ksiazki: Screencast:
115 Podstawy Komentarz # Przypisanie – tworzy zmienna Abc =5 var Abc = 5Bloki realizowane za pomoca wcięć if happy and knowsIt clapsHands() chaChaCha() else showIt() if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt();
116 Operatory Operatory CoffeeScript vs JavaScript is isnt not and ortrue, yes, on false, no, off @, this of in, ? === !== ! && || true false this in Brak odpowiednika alert "I knew it!" if elvis? if (typeof elvis !== "undefined" && elvis !== null) alert("I knew it!");
117 Interpolacja zmiennychZmienne w " " podlegają interpolacji a w ' ' nie podlegają author = "Wittgenstein" quote = "A picture is a fact. -- #{ author }" sentence = "#{ 22 / 7 } is a decent approximation of π" var author, quote, sentence; author = "Wittgenstein"; quote = "A picture is a fact. -- " + author; sentence = "" + (22 / 7) + " is a decent approximation of π";
118 Wieloliniowe literały i komentarze blokowehtml = ''' cup of coffeescript ''' ### CoffeeScript Compiler v1.1.2 Released under the MIT License
119 Kaskadowe porównania cholesterol = 127healthy = 200 > cholesterol > 60 var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60);
120 Funkcje Składnia ala Ruby, zwraca wynik ostaniej instrukcjiNawiasy przy wywołaniach można pomijać square(x) -> x*x test(x,y) -> a=5 x+y+a function square(x) { return x*x; } function test(x,y) { var a = 5; return x+y+5; } z = square 5 var z = square(5);
121 Funkcje i this Account = (customer, cart) -> @customer = customer@cart = cart $('.shopping_cart').bind 'click', (event) -> var Account; var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').bind('click', __bind(function(event) { return this.customer.purchase(this.cart); }, this)); };
122 Obiekty Składnia wymaga wcięć math = root: Math.sqrt square: squarecube: (x) -> x * square x math = { root: Math.sqrt, square: square, cube: function(x) { return x * square(x); } };
123 Wszystko jest wyrażeniemgrade = (student) -> if student.excellentWork "A+" else if student.okayStuff if student.triedHard then "B" else "B-" else "C" eldest = if 24 > 21 then "Liz" else "Ike" var eldest, grade; grade = function(student) { if (student.excellentWork) { return "A+"; } else if (student.okayStuff) { if (student.triedHard) { return "B"; } else { return "B-"; } return "C"; }; eldest = 24 > 21 ? "Liz" : "Ike";
124 Pętle for, while, until, Petle zwracają wartośćeat food for food in ['toast', 'cheese', 'wine'] var food, _i, _len, _ref; _ref = ['toast', 'cheese', 'wine']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { food = _ref[_i]; eat(food); }
125 Pętle Zwrot z petli mozna przypisaccubes = (math.cube num for num in list) cubes = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) { num = list[_i]; _results.push(math.cube(num)); } return _results; })();
126 Przypisania wielokrotnetheBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] var theBait, theSwitch, _ref; theBait = 1000; theSwitch = 0; _ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
127 switch switch (day) { case "Tue": go(relax); break;case "Thu": go(iceFishing); case "Fri": case "Sat": if (day === bingoDay) { go(bingo); go(dancing); } case "Sun": go(church); default: go(work); switch day when "Tue" then go relax when "Thu" then go iceFishing when "Fri", "Sat" if day is bingoDay go bingo go dancing when "Sun" then go church else go work
128 try/catch/finally try allHellBreaksLoose() try { allHellBreaksLoose();catsAndDogsLivingTogether() catch error print error finally cleanUp() try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error) { print(error); } finally { cleanUp(); }
129 Sklejanie tablic numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]copy = numbers[0..numbers.length] middle = copy[3..6] var copy, middle, numbers; numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; copy = numbers.slice(0, numbers.length); middle = copy.slice(3, 7);
130 Sklejanie tablic numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]var numbers, _ref; numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; [].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
131 Przypisania mogą dekomponowac strukturyvar city, futurists, name, street, _ref, _ref2; futurists = { sculptor: "Umberto Boccioni", painter: "Vladimir Burliuk", poet: { name: "F.T. Marinetti", address: ["Via Roma 42R", "Bellagio, Italy 22021"] } }; _ref = futurists.poet, name = _ref.name, _ref2 = _ref.address, street = _ref2[0], city = _ref2[1]; futurists = sculptor: "Umberto Boccioni" painter: "Vladimir Burliuk" poet: name: "F.T. Marinetti" address: [ "Via Roma 42R" "Bellagio, Italy 22021" ] {poet: {name, address: [street, city]}} = futurists
132 Przypisania mogą dekomponowac zakresytag = "
133 Argumenty Funkcji gold = silver = rest = "unknown"awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ "Michael Phelps" "Liu Xiang" "Yao Ming" "Allyson Felix" "Shawn Johnson" "Roman Sebrle" "Guo Jingjing" "Tyson Gay" "Asafa Powell" "Usain Bolt" ] awardMedals contenders... var awardMedals, contenders, gold, rest, silver; var __slice = Array.prototype.slice; gold = silver = rest = "unknown"; awardMedals = function() { var first, others, second; first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? __slice.call(arguments, 2) : []; gold = first; silver = second; return rest = others; }; contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"]; awardMedals.apply(null, contenders);
134 Klasy CoffeScript oferuje koncepcję klasKlasy mają składnię zbliżoną do obiektów Wspierane jest dziedziczenie i odwołania do klas bazowych
135 class Animal constructor: -> move: (meters) -> + " moved #{meters}m." class Snake extends Animal move: -> alert "Slithering..." super 5 sam = new Snake "Sammy the Python" sam.move() class Horse extends Animal alert "Galloping..." super 45 tom = new Horse "Tommy the Palomino" tom.move()
136 var Animal, Horse, Snake, sam, tom;var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; Animal = (function() { function Animal(name) { this.name = name; } Animal.prototype.move = function(meters) { return alert(this.name + (" moved " + meters + "m.")); return Animal; })();
137 Snake = (function() { __extends(Snake, Animal); function Snake() { Snake.__super__.constructor.apply(this, arguments); } Snake.prototype.move = function() { alert("Slithering..."); return Snake.__super__.move.call(this, 5); }; return Snake; })(); Horse = (function() { __extends(Horse, Animal); function Horse() { Horse.__super__.constructor.apply(this, arguments); } Horse.prototype.move = function() { alert("Galloping..."); return Horse.__super__.move.call(this, 45); return Horse; sam = new Snake("Sammy the Python"); tom = new Horse("Tommy the Palomino"); sam.move(); tom.move()
138 Przypisania mogą dekomponowac zakresytag = "
139 Inne Zagniezdzanie javascriptu regexpy