prototype 1.7
TRANSCRIPT
Prototype
Inhalte Prototype
AjaxResponders, Response, Request, (Periodical)Updater
DOMJSON, $, $F, Abstract, Element, Form, document
SpracherweiterungenWeitere $‘s, Array, Class, Date, Function, Object, String,Template, Enumerable, RegExp, Prototype/Try
Prototype: Ajax.Responders
FunktionGlobale Events/Callbacks für alle Ajax Requests
RegistrationAjax.Responders.register/unregister
CallbacksonCreate, onComplete, onException
Prototype: Ajax.Responders
Herkömmlicher Ajax Responder
Ajax.Responders.register({onCreate: function(request,XmlHttpRequest,Json) {
alert('new request registered');Ajax.activeRequestCount++;
},onComplete: function(request,XmlHttpRequest,Json) {
alert('request has ended');Ajax.activeRequestCount--;
}});
Prototype: Ajax.Request
FunktionGewöhnlicher Ajax Request
Wichtige Optionenasynchronous = true: (A)synchrone AnfragecontentType: Ändern wenn man z.B. XML senden willencoding = UTF8: Falls es mal Probleme mit Kodierung gibtparameters: Parameter im URL oder JSON Format
Wichtige CallbacksonFailure: Wird bei HTTP Errors geworfen 40x – 50xonSuccess: Kommt zum Zug bei 20x Statuscodes
Prototype: Ajax.Request
JSON Antwortobjekt
var data = {};data.getres = 1001;data.language = SV_LANG_DE;data.isIE = true;
new Ajax.Request('/pfad/zum/script/?id=685', {parameters : data,method : 'post',onSuccess: function(response) {
var json = response.responseText.evalJSON();alert('Antwort: ' + json.message);
}});
Prototype: Ajax.Request
Synchroner Request
var data = {};data.getres = 1001;data.language = SV_LANG_DE;data.isIE = true;
var myRequest = new Ajax.Request('/service/class/getres/', {parameters : data,method : 'post',asynchronous : false
});
alert(myRequest.transport.responseText);
Prototype: Ajax.Response
FunktionAntwortobjekt eines Ajax.Request
Wichtige PropertiesresponseText: Text der Ajax AntwortresponseXML: XMLDOM Objekt, wenn application/xml Header responseJSON: JS Objekt, wenn application/json Headertransport: Zugriff auf das Native XmlHttpRequest Objekt
Prototype: Ajax.Updater
FunktionUpdatet einen Container, erbt von Ajax.Request
Und wozu ist das gut?- Vereinfachung eines oft verwendeten Use-Case- Verwendet das verhalten von Element.update()
Zusätzliche PropertiesevalScripts = false: Führt Code in <script> Tags ausinsertion: Mögliche Werte: top, bottom, before, after-> Mehr dazu bei den Element Methoden
Prototype: Ajax.Updater
Codebeispiel
<script type="text/javascript">function UpdateChat() {
new Ajax.Updater({ success: 'chatWindow' }, '/getmessage/?chat=45764',{ insertion: 'top‚ }
);setTimeout('UpdateChat()',1000);
}UpdateChat();
</script><div id="chatWindow"></div>
Prototype: Ajax.PeriodicalUpdater
FunktionWie Updater, führt sich aber periodisch selbst wieder aus
Wichtige Optionenfrequency = 2: Warten zwischen Abfragendecay = 1: Erhöht die Rate von frequency, wobei der übergebene Wert ein Multiplikator ist. 1 Hat daher keine Wirkung, 2 z.B. verdoppelt den Wert von frequency. Wenn Resultat !=, wird frequency zurückgesetzt.
Nutzen- Sehr wenig Code nötig für automatische Updater- Spart Ressourcen durch den decay Parameter
Prototype: Ajax.PeriodicalUpdater
Codebeispiel
<script type="text/javascript">new Ajax.PeriodicalUpdater(
{ success: 'chatWindow'‚ failure : 'errorMsg' }, '/getmessage/?chat=34756',{ insertion: 'top', frequency: 2 }
);</script><div id="chatWindow"></div><div id="errorMsg"></div>
Kurze Einführung: JSON
Wer ist Jason?Die Javascript Object Notation
Wozu wird es verwendet?- Objektorientiertes Javascript- Interner Datenaustausch (z.B. Funktionsparameter)- Externer Datenaustausch (z.B. Ajax)
SyntaxProperties, Arrays, Objektarrays, Funktionen…… mit relativ wenig Zeichen (Leichtgewichtig)
Kurze Einführung: JSON
Einfache Daten und Arrays
var object = {message : 'this is json',really : true,howmany : 1337,inner : {
value : 'inneres objekt',great : false
},array : [ 1,2,3,4,5,6,7,8 ],strings : [ 'hello', 'world' ]
};
Kurze Einführung: JSON
Objektarrays (Einfaches verschachteln)
var object = {objectarray : [
{ message : 'this is json', really : true },{ message : 'this is xml', really : false },{ message : 'this is asp', really : false }
],additional : 'hello world'
};
Kurze Einführung: JSON
Funktionen (Dazu mehr unter „Klassen“)
var Calculator = {Add : function(param1,param2) {
return(param1 + param2);},Subtract: function(param1,param2) {
return(param1 – param2);},
};
Prototype: $... Die Funktion
FunktionAlias für document.getElementById und mehr
Wie mehr?$(‘eleID‘) gibt ein Element zurück$(‘eleID‘,‘inputID‘,‘textID‘) gibt ein Array zurückDOM der Elemente wird erweitert (Dazu gleich mehr)
NutzenEffizienter / besser lesbarer Code
Prototype: $... Die Funktion
Typischer Code einer Validierungsroutine
// Validierbares Element holenvar ele = document.getElementById('eleID');// Array von Werten für For bastelnvar some = [];some[0] = document.getElementById('eleID');some[1] = document.getElementById('inputID');some[2] = document.getElementById('textID');// Error Message Divs ausblendendocument.getElementById('errorMessage').style.display = 'none';document.getElementById('errorDiv').style.display = 'none';
Prototype: $... Die Funktion
Typischer Code gleicher Code mit Prototype
// Validierbares Element holenvar ele = $('eleID');// Array von Werten für For-Schlaufevar some = $('eleID','inputID','textID');// Mit „hide“ Funktion auf allen Elementen, Divs ausblenden$('errorMessage','errorDiv').invoke('hide');
Anmerkung: Die hide() und show() Methode ist nur eine derzahlreichen DOM Erweiterungen die jedes Element bekommt
Prototype: Geht‘s noch schneller?
Eine Nanosekunde effizienterJa, mit der $F() Methode
Formularwert holenErwartet eine ID als Wert, und gibt den Wert des dahinterliegenden Formularfeldes mit der getValue() Methode zurück.
$(‘example‘).getValue()Gleich wie .value Property ausser bei Multiselect,da kommt immer ein Array zurück
Prototype: Geht‘s noch schneller?
Schnell ein Formular speichern
var Assistant = Class.create();Assistant.prototype = {
Save : function() {new Ajax.Request('/admin/content/?id=324',
method : 'post',parameters : {
'Name' : $F('Name'),'Firstname' : $F('Firstname'),'Email' : $F('Email')
});
}};
Prototype: Klassen
Objektbasiert?Orientiert, wir können Abstrakt.
Wie kann man vorgehen- Klasse leer erstellen und Body erweitern- Klasse direkt vollständig ausprogrammieren
EigenheitenKlassendefinitionen sind zur Laufzeit erweiterbar (Für alle Instanzen)Statische Properties kennt Javascript nichtPublic, Private, Protected? Umsetzbar, aber kein Bestandteil
Prototype: Klassen
Erstellen und erweitern…
var Assistant = Class.create();Assistant.prototype = {
// Konstruktorinitialize : function() {
},
// SpeicherfunktionSave : function() {
alert('data saved');}
};
Prototype: Klassen
…oder direkt ausprogrammieren
var Assistant = Class.create({
// Konstruktorinitialize : function(id) {
// Hier sind meist window.onload/dom:loaded Events},
// SpeicherfunktionSave : function() {
alert('data saved');}
});
Prototype: Klassen
Erben des einer Klasse
var BetterAssistant = Class.create(Assistant,{
// Konstruktorinitialize : function($super,id) {
// Parent Methode aufrufen, geht bei allen überschriebenen
$super(id);},
// Speicherfunktion überschreibenSave : function($super) {
this.Validate(); // Erst validieren$super();
}});
Prototype: Klassen
Methoden überschreiben (Clean way)
BetterAssistant.addMethods({// Speichern geht noch besserSave : function($super) {
// Validieren und speichern$super();// Meldung an User gebenthis.Notify();
},// Meldung an UserNotify : function() {
$('message').update('Daten gespeichert!');$('message').show();
}});
Prototype: Element Erweiterungen
Wie bekomme ich die ErweiterungenMit Element.method() oder $(‘someElement‘).method()
Einige Beispiele- Element.update(): Ein Block Element verändern- Element.setStyle()/getStyle(): CSS, Browserkompatibel- Element.show()/hide()/toggle(): Anstatt direkt CSS zu modifizieren- Element.absolutize()/relativize(): Element Positionstyp ändern- Element.removeClassName()/addClassName(): Sprechend- Und 76 weitere Methoden
Welche wir hier findenGibt es hier: http://api.prototypejs.org/dom/element/
Prototype: Element Erweiterungen
Element.update() - Beispiel
var html = '<p>Gleich passiert was<p>' +'<script type="text/javascript">' +' alert("sehen sie?");' +'</script>';$('message').update(html);
Prototype: Element Erweiterungen
Anwendung der toString() Methode mit Element.Update()
var Fruit = Class.create({initialize : function(name) {
this.Name = name;}toString: function() {
return('Hey ' + this.Name + '! I'm an orange.');}
});var apple = new Fruit('apple');$('fruits').update(apple);$('fruits').innerHTML;
Prototype: Element Erweiterungen
Klassen hinzufügen oder entfernen
<div id="msg" class="float left invisible"> </div><script type="text/javascript">
$('msg').addClassName('visible','error');$('msg').removeClassName('invisible');// -> float left visible error// -> toggleClassName(cssClass)
</script>
Prototype: Element Erweiterungen
XML Arbeit vereinfachen
<ul id="apples"><li>Mutsu</li>
</ul><script type="text/javascript">
$('apples').firstChild.innerHTML;// -> undefined$('apples').cleanWhitespace();$('apples').firstChild.innerHTML;// -> 'Mutsu'
</script>
Prototype: Element Erweiterungen
Elementinhalt Erweitern oder umranden
// Paragraph in ein Element einbauen$('element').insert('<p>HTML to append</p>');// Fügt über den Paragraphen ein Bild ein$('element').insert({
top: Element('img', {src: 'logo.png'})});// Fügt vor und nach dem Element ein HR ein$('element').insert({
before: '<hr>',after: '<hr>'
});
Prototype: Element Erweiterungen
Element bzw. Object.inspect()
$('element').inspect();// -> <div id="element" class="hello world">Object.inspect();// -> 'undefined'Object.inspect(null);// -> 'null'Object.inspect(false);// -> 'false'Object.inspect([1, 2, 3]);// -> '[1, 2, 3]'Object.inspect('hello');// -> "'hello'"
Prototype: Element.Layout
WozuVerschiedene Grössen/Abstände eines Elements lesen
Vorteile- Geht auch, wenn alles in CSS definiert ist- Umgeht die Tendenz, dass Browser inkorrekte Werte liefern- Umgeht den Quirksmodus, welcher meist gar nichts liefert- Umgeht die Schwierigkeit mit unsichtbaren Elementen
VorsichtDa Resourcenintensiv sind die Werte gecached!
Prototype: Element.Layout
Instanz des Layout Objekts holen
// Mit der Element Methode verwendenlayout = new Element.Layout(element);// Als Instanzmethode eines Elementslayout = $('element').getLayout();// Wert lesen, CSS Version ausgebenvar pl = layout.get('padding-left');var css = layout.toCSS();
Prototype: Element.Layout
Weitere Properties
height, widthtop, left, right, bottomborder-left, border-right,border-top, border-bottompadding-left, padding-right, padding-top, padding-bottommargin-top, margin-bottom, margin-left, margin-rightpadding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height
Prototype: Event Objekt
Events: Ein geordnetes ChaosError 10050, too many nerves wasted
Vorteile- Einfache Eventregistration- Einheitliche KEY_ Konstanten- Einheitliches Event-Daten Objekt- Diverse Helper Methoden
Prototype: Event Objekt
KEY_ Konstanten
KEY_BACKSPACE, KEY_TAB,KEY_RETURN, KEY_ESC,KEY_LEFT, KEY_UP,KEY_RIGHT, KEY_DOWN,KEY_DELETE, KEY_HOME,KEY_END, KEY_PAGEUP,KEY_PAGEDOWN, KEY_INSERT
Prototype: Event Objekt
Standard Event registrieren
function SomeFunction(event) {// Event ist immer "event", auch im IE!// Dieses Event Objekt ist ebenfalls erweitert
}
Event.observe(window, 'load', SomeFunction);$(window).observe('load', SomeFunction);$('element').observe('click', SomeOtherFunction);
Prototype: Event Objekt
Events löschen
// Genau einen Event löschen, Handler muss übergeben werdenElement.stopObserving(element,'click',SomeFunction);$('element').stopObserving('click',SomeFunction);// Alle Events eines Typs löschen (Keinen Handler übergeben)Element.stopObserving(element,'blur');$('element').stopObserving('blur');// Oder komplett alle Event entfernenElement.stopObserving(element);$('element').stopObserving();
Prototype: Event Objekt
Intelligente Events (Mit Daten)
function SomeFunction(event,param) {if (event.keyCode == KEY_RETURN) {
alert('daten sind: ' + param);}
}
$(window).observe('keydown',function(event) {SomeFunction(event,$('content').getValue());
});
Prototype: Event Objekt
Do it the OOP way
var AssistantClass = Class.create({initialize : function() {
this.Input = $('myInput');this.WeWillUseThatLater = 'Hello World';this.Input.observe('blur',this.Validate.bind(this));
},Validate : function(event) {
// Das Event wird im Objekt Kontext ausgeführtalert(this.WeWillUseThatLater);
}});
Prototype: Event Extensions
Erweiterungen am Event ObjektAlle registrierten Events liefern ein modifiziertes ‚event‘ zurück
Beispiele- event.element(): Das Element auf dem der Event ausgeführt wurde- event.findElement(): Findet Objekte innerhalb des Event Elements- event.pointerX/Y(): Für Maus Events, immer absoluter Pixelwert!- event.is[Left|Right|Middle]Click(): Wie genau wurde geklickt?
Prototype: CSS Selektoren
Exkursion zu $$Damit holen wir alles was mit CSS zu holen ist
Syntax Beispiele$$(‘div.myclass‘): Alle Divs mit der Klasse myclass $$(‘.myclass‘): Alle Elemente mit der Klasse myclass $$(‘.myclass .error‘): Alle Elemente mit myclass und error $$(‘#mydiv‘): Element mit der ID mydiv $$(‘#mydiv input[type=checkbox]‘): Alle Checkboxen in #mydiv $$(‘:checked‘): Alle ausgewählten Elemente. Weitere, :disabled :enabled$$(‘#mytable tr:nth-child(even)‘): Alle geraden Zeilen von #mytable
…Und alles weitere was bis und mit CSS3 möglich ist!
Prototype: CSS Selektoren
Alle Checkboxen markieren
$$('#mycheckerdiv input[type=checkbox]').each(function(f) {f.checked = true;
});
Schöne Tabelle bauen
$$(‘#mytable tr:nth-child(even)‘).each(function(tr) {tr.className = 'AdminTabRowDark';
});$$(‘#mytable tr:nth-child(odd)‘).each(function(tr) {
tr.className = 'AdminTabRowLight';});
Prototype: Event.Handler
Zurück bei den EventsDiese arbeiten auf Wunsch auch mit Selektoren
Wozu ein weiterer Handler- Der Event.Handler delegiert an Unterelemente- Delegation des Callback erfolgt über CSS Selektoren
Prototype: Event.Handler
Einen Event Handler definieren
function SaveForm(event) {// Formular per Prototype Ajax Post speichernevent.element.request();
}// Speichern aller "saveable" Forms, beim verlassen der Seiteobserver = new Event.Handler(
window, // Auf das Window hören'unload', // Wenn es verlassen wird'form.saveable', // Alle Forms mit "saveable" KlasseSaveForm // SaveForm Methode ausführen
);observer.start();
Prototype: Der Form Namespace
Auch die Forms sind erweitert…Sofern diese mit der $-Funktion geladen werden
Einige Methoden im Überblick- $(‘frm‘).disable(): Deaktiviert alle Formularelemente- $(‘frm‘).enable(): Aktiviert alle Formularelemente- $(‘frm‘).getElements(): Array aller Formularelemente- $(‘frm‘).getInputs(type): Gibt z.B. alle Checkboxen eines Forms zurück- $(‘frm‘).request(): Formular per Ajax Posten/Requesten- $(‘frm‘).serialize(true): Formular Daten als JSON oder Query holen
Prototype: Der Form Namespace
Und sonst?…nur einige Convenience Methoden
Form.Observer- Trackt Änderungen in einem Formular- Kann für generische Validation verwendet werden
Form.Element.Observer- Gleich wie Form.Observer, auf ein einzelnes Element- Explizite automatische Validation eines Feldes
Prototype: Der Form Namespace
Beispiele von Form(.Element).Observer
// Formular alle 500ms prüfennew Form.Observer(myFrm, 0.5, GenericValidation);
// Formularelement alle 300ms prüfennew Form.Element.Observer(myEle, 0.3, ExplicitValidation);
Prototype: Selector
Noch mehr CSS SelektorenMit dem ‚Selector‘ kann nach Elementen gesucht werden
Ist doch das gleiche wie $$?- Genau, plus eine spezielle Funktion- .match() gibt an, ob ein Element dem Selektor entspricht
Und sonst?Das Objekt ist schlecht dokumentiert, kann aber wahrscheinlicheffektiv nicht viel mehr als ein Aufruf der $$-Funktion
Prototype: Selector
Anwendung des Selector
// <div id="firstFormContainer" class="FormContainer" />// <div id="anotherFormContainer" class="FormContainer" />// <div id="aFormContainer" />var Sel = new Selector('div.FormContainer');Sel.match($('someOtherDiv')); // falseSel.match($('firstFormContainer')); // true// Beide obigen Container holenvar cont1 = Sel.findElements();// Oder wenn man es in einem bestimmten div suchen willvar cont2 = Sel.findElements($('containsDivs'));
Prototype: document
Erweiterungen des document ObjektsEs wird das registrieren/abfeuern von Events ermöglicht mit den bekannten Methoden „observe“ und „stopObserving“
Der viewport (was im Browser sichtbar ist)document.viewport.getHeight(): Höhe des sichtbaren Bereichsdocument.viewport.getWidth(): Breite des sichtbaren Bereichsdocument.viewport.getScrollOffsets(): left/top Offset des Scrollbalken
Prototype: $A
Arrays castenHiermit kann man so gut wie alles zu einem Array casten
Warum? Weil man……oft eine NodeList oder eine HTMLCollection bekommt unddiese nicht mit Prototype Features erweitert werden (können)
Was kann ein Prototype ArrayBasiert auf „Enumerable“ und bietet damit 44 neue Methodenzum iterieren, suchen und arbeiten mit Arrays
Prototype: $A
Beispiel inkl. each() Funktion
var ps = $A(document.getElementsByTagName('p'));// Nun können wir mit Each jedes Element durchgehenps.each(function(item) {
alert(item.innerHTML);});// Oder eine bestehende Funktion darauf ausführenps.each(Element.hide);
Prototype: Array Funktionen
Prüfen ob alle Elemente einem Wert entsprechen
// -> true (Ein leeres Array hat keine falschen Werte)[].all();// -> true (Alle Werte in 1 bis 5 sind true)$R(1, 5).all();// -> false (0 gilt als false)[0, 1, 2].all();// -> false (Auf 9 kommt false zurück)[9, 10, 15].all(function(n) { return n >= 10; });// Selbe Funktion mit "any", gibt jedoch schon bei// einem gültigen Wert true zurück
Prototype: Array Funktionen
Funktionsauswertung aller Elemente als Array
// Gibt folgendes Array ['H', 'H', 'G']['Hitch', "Hiker's", 'Guide'].collect(function(s) {
return(s.charAt(0).toUpperCase());});// Gibt alle Quadratzahlen von 1 bis 5 [1, 4, 9, 16, 25]$R(1,5).collect(function(n) {
return(n * n);});
Prototype: Array Funktionen
Geprüfte Werte zurück bekommen
// Wir wenden auf jedes Objekt Object.IsString an// Alle Werte die "true" ergeben kommen als Array zurück[1, 'two', 3, 'four', 5].filter(Object.isString);// Resultiert daher in ['two','four']
// Wir wenden auf jedes Objekt Object.IsString an// Alle Werte die "false" ergeben kommen als Array zurück[1, 'two', 3, 'four', 5].reject(Object.isString);// Resultiert daher in [1,2,3]
// Das geht auch mit eigenen Funktionen[1, 'two', 3, 'four', 5].filter(function(item)) {
// Hier item prüfen und true/false zurückgeben});
Prototype: Array Funktionen
Das selbe noch mit Regex
// Alle Strings mit Doppelbuchstaben finden['hello', 'world', 'this', 'is', 'cool'].grep(/(.)\1/);// Ergibt folgendes Array: ['hello', 'cool']
// Innerhalb 1 bis 30 alle Zahlen die mit 0 oder 5// enden holen und eins davon abziehen$R(1, 30).grep(/[05]$/, function(n) { return(n - 1); });// Ergibt folgendes Array: [4, 9, 14, 19, 24, 29]
Prototype: Array Funktionen
Zahl, String oder Objekt in einem Array finden
// Gibt true, da 10 im Range 1 bis 15 vorkommt$R(1, 15).include(10);// Gibt false, da Gross-/Kleinschreibung beachtet wird['hello', 'world'].include('HELLO');// Gibt true, da hello 1:1 so vorkommt['hello', 'world'].include('hello');// Gibt true, da 3 == '3' in JS true ergibt[1, 2, '3', '4', '5'].include(3);
Prototype: Array Funktionen
Objektmethoden aufrufen
// Einfacher Aufruf, der Arraywert ist immer der 1. Parameter// Resultat ergibt: ['HELLO', 'WORLD']['hello', 'world'].invoke('toUpperCase');
// Parameter folgen dem Methodennamen// Substring calls ergeben: ['hel', 'wor']['hello', 'world'].invoke('substring', 0, 3);
// Stoppt den 'change' event auf allen Input Feldern$$('input').invoke('stopObserving', 'change');
Prototype: Array Funktionen
Objektmethoden aufrufen (An eigenen Objekten)
var AddCalc = Class.create({initialize : function(first,second) {
this.First = first;this.Second = second;
},Compute : function() {
return(this.First + this.Second);}
});[ new AddCalc(5,5), new AddCalc(8,9)].invoke('Compute');// Ergibt folgendes Array [10, 17]
Prototype: Array Funktionen
Feldwerte lesen und als Array zurückbekommen
// Stringlänge aller Objekte herausfinden// Gibt folgendes Array: [5, 5, 4, 2, 4]['hello', 'world', 'this', 'is', 'nice'].pluck('length');
// checked Feld aller Checkboxen lesenvar checks = $$('input[type=checkbox]');var values = checks.pluck('checked')// Alles umkehrenfor (i = 0;i < checks.length;i++) {
checks[i].checked = !values[i];}
Prototype: Array Funktionen
Array Sortieren
// Nach Stringlänge sortieren// Ergibt: ['is', 'nice', 'this', 'world', 'hello']['hello', 'world', 'this', 'is', 'nice'].sortBy(function(s) {
return(s.length);});
// Objekte mit internem Sortierwert sortierenMyObjectArray.sortBy(function(s) {
// Mit „this“ könnte man hier auf das ganze Array zugreifenreturn(s.GetInternalOrder());
});
Prototype: Array Funktionen
Zusammenführen von Arrays
var firstNames = ['Jane', 'Nitin'];var lastNames = ['Doe', 'Patel'];var ages = [23, 41];// Ergibt: [['Jane', 'Doe'], ['Nitin', 'Patel']]firstNames.zip(lastNames);// Ergibt [['Jane', 'Doe', 23], ['Nitin', 'Patel', 41]]firstNames.zip(lastNames, ages);// Oder wir wenden eine Funktion an, um das // resultierende Array zu beeinflussen// Ergibt: ['Jane Doe is 23', 'Nitin Patel is 41']firstNames.zip(lastNames, ages, function(tuple) {
return(tuple[0] + ' ' + tuple[1] + ' is ' + tuple[2]);});// Man kann so z.B. Objekte aus Arrays kreieren
Prototype: $H / Hash
Was ist ein Hash?Äquivalent zu „Dictionary“ in ASP oder .NET
Zusammenfassen von DatenKann als alternative zu Objekten verwendet werden. Ein HashHat zudem einige Hilfreiche Funktionen
Methoden des HashtoQueryString(): Falls Post nicht möglich, Daten als QuerystringtoJSON()/toObject(): Liefern beide ein Objekt für z.B. Ajax Postsset()/get()/unset(): Kommen gleich im Codebeispielupdate(): Erweitert den Hash mit dem übergebenen Objektkeys()/values(): Liefert entsprechende Arrays
Prototype: $H / Hash
Anwendung des Hash
var h = $H({name: 'Michael', age: 21, country: 'England'});// Ist das selbe wie...var h = new Hash({name: 'Michael', age: 21, country: 'England'});// Mit "get" erhält man den entsprechenden Wertvar country = h.get('country');// Mit "set" kann man einen neue Wert setzen oder bearbeitenh.set('name','John');h.set('lastname','Doe');// Iterieren kann man auch hier mit der "each" Methodeh.each(function(pair,index) {
alert('on ' + index + ': ' + pair.key + '=' + pair.value);});
Prototype: $R / ObjectRange
Was ist ein ObjectRange?Ein Objekt, welches einen Range (Array) kreiert
Wozu kann man es verwenden?Man weiss es nicht. z.B. um ein Zahle-n oder Buchstabenarray zu erzeugen, welches man dann irgendwie weiter verwenden kann
Was kann der RangeAls erstes: Alles was eine Enumeration auch kanninclude(): Überschreibt include() der Enumerationend/start: Properties für das beginnende und endende Objekt
Prototype: $R / ObjectRange
Anwendung des Range
// Range von 1 - 10$R(0, 10)// Range von String aa bis ah: aa ab ac ad af ag ah$R('aa', 'ah')// Range von 1 bis 10 ohne letzte Zahl (Also 1 bis 9)$R(0, 10, true).include(10)// Range gibt eine Enumeration, man kann also each verwenden$R(0, 10, true).each(function(value) {
alert(value);});
Prototype: $R / ObjectRange
Anwendung des Range mit eigenem Objekt
var BigCounter = Class.create({initialize : function(value) {
this.Value = value},succ : function() {
return(this.Value + 750);}
});// Range mit BigCountern: 1500, 2250 ... 6000, 6750$R(new BigCounter(1500),new BigCounter(6750));
Prototype: Funktionserweiterungen
Methoden für FunktionenPrototype erweitert die Funktionsreferenzen automatisch
Hier kommt Magie zum EinsatzDas gibt‘s sonst nirgendwo: Deferier- und delaybare Aufrufe, Parametererweiterungen und Methodisierung
Prototype: Funktionserweiterungen
Parameternamen herausfinden
// Funktion. (Das alles geht auch mit Objektmethoden)function add(first, second) {
return(first + second);}// Array der Argumente holen: ['first', 'second']add.argumentNames();
Prototype: Funktionserweiterungen
Kontext binden (Wichtig für OOP implementationen)
var AlertOnClick = Class.create({initialize: function(msg) {
this.msg = msg;// Klappt nicht, da Events „kontextlos“ sind$('submit').observe('click', this.Click);// Klappt, da der Objektkontext übergeben wird $('submit').observe('click', this.Click.bind(this));
},Click: function(event) {
event.stop();$('message').update(this.msg).show();
}});
Prototype: Funktionserweiterungen
Parametererweiterung (Do it the indian way)
function showArgs() {// 'arguments' ist ein Array aller Paremteralert($A(arguments).join(', '));
}// Liste der Parameter ausgeben: '1, 2, 3'showArgs(1,2,3);// Mit Curry eine Funktionskopie erstellen, welche// Die Funktion mit Default 1,2,3 aufruftvar showExtended = showArgs.curry(1,2,3);// Diese mit weitere Parametern aufrufen: '1, 2, 3, a, b'showExtended('a','b');
Prototype: Funktionserweiterungen
Deferieren (Verschieben ans Ende)
// Funktionen die mit "defer" aufgerufen werden, wird der// Interpreter erst Ausführen wenn er nichts mehr zu tun hatfunction showMsg(msg) {
alert(msg);}showMsg("One"); // Normaler AufrufshowMsg.defer("Two"); // Verschobener AufrufshowMsg("Three"); // Normaler Aufruf// Output: One, Three, Two
Prototype: Funktionserweiterungen
Klassisches Beispiel (defer Methode)
// Klassiker, den man immer wieder sieht:var Assistant = Class.create({
function : initialize() {},// Funktion die ein Control per Effekt einblendetfunction : ShowInput(ele) {
$(ele).appear({ duration: 3.0 });// 1. Nicht im Objekt Kontext, 2. UnschönsetTimeout('MyObject.DoSomething()',3000);
},// Funktion die nach dem Effekt aufgerufen werden sollfunction : DoSomething() {}
});
Prototype: Funktionserweiterungen
Klassisches Beispiel (defer Methode)
var Assistant = Class.create({function : initialize() {},// Funktion die ein Control per Effekt einblendetfunction : ShowInput(ele) {
$(ele).appear({ duration: 3.0 });// 1. Im Objektkontext, 2. Optimal, da am
Funktionsende.// Wird ausgeführt wenn der Interpreter idle ist,
und das// ist er zufälligerweise erst, wenn der Effekt
beendet istthis.DoSomething.defer();
},// Funktion die nach dem Effekt aufgerufen werden sollfunction : DoSomething() {}
});
Prototype: Funktionserweiterungen
Delayen (Verschieben auf fixen Zeitpunkt)
// Ist defer nicht sicher genug, geht es immer noch sovar Assistant = Class.create({
function : initialize() {},// Funktion die ein Control per Effekt einblendetfunction : ShowInput(ele) {
$(ele).appear({ duration: 3.0 });// Funktonsaufruf gleich wie Effekt delayenthis.DoSomething.delay(3.0);
},// Funktion die nach dem Effekt aufgerufen werden sollfunction : DoSomething() {}
});
Prototype: Funktionserweiterungen
Delayen mit Parameter
var Assistant = Class.create({function : initialize() {},// Funktion die ein Control per Effekt einblendetfunction : ShowInput(ele) {
$(ele).appear({ duration: 3.0 });// Erst das Timeout, dann die Parameterthis.DoSomething.delay(3.0, 'hello', 'world');
},// Funktion die nach dem Effekt aufgerufen werden sollfunction : DoSomething(param1, param2) {}
});
Prototype: Funktionserweiterungen
Methodisierung (Statische Funktionen an Objekte binden)
// Funktion, die auf ein Objekt, das "name" Prop. setztfunction setName(target, name) {
target.name = name;}// Kann man z.B. so ohne Kontext verwendenobject = {};setName(object, 'Fred');
// Man kann aber auch das Objekt "Methodisieren"obj.setName = setName.methodize();// "target" ist nun "this" und wird direkt angewendetobj.setName('Barney');// Prototype setzt dies für fast alle Funktionen ein
Prototype: Funktionserweiterungen
Bestehende Methoden erweitern
// capitalize Funktion mit einem Parameter erweiternString.prototype.capitalize = String.prototype.capitalize.wrap(
function(OriginalMethod, eachWord) {if (eachWord && this.include(" ")) {
// Wenn Parameter (true), jedes Wort kapitalisieren
return(this.split(" ").invoke("capitalize").join(" "));
} else {// Oder die bisherige Standarmethode
anwendenreturn(OriginalMethod());
}}
);"hello world".capitalize(); // "Hello world""hello world".capitalize(true); // "Hello World"
Prototype: Number Methoden
Erweiterung von „Math“Number vereint Math und mehr
Beispiele- Fügt für jede Zahl abs(), ceil, floor(), und round() hinzu- toColorPart(): Gibt die Hex Version einer Zahl zurück- toPaddedString(n): Gibt den Zahlenwert mit führenden Nullen zurück
Prototype: The Object Object
Wer profitiert davonAlle primitiven Datentypen, alle Objekte, selbst Eigenbauten
Hilfreiche Funktionen- clone(): Erzeugt eine Shallow Copy. Deep Copy umsetzbar- extend(): Erweitert ein bestehendes Objekt- inspect(): Gibt Debug-Informationen des Objekts aus- Anwendbar statisch oder im Objektkontext als Methode
ValidierungValidierung (Nur statisch) kann nicht schaden: isArray(), isElement(), isFunction(), isHash(), isNumber(), isString(), isUndefined().
Prototype: PeriodicalExecuter
Warum nicht setInterval?Weil die Ausführungszeit dort nicht eingerechnet ist
Und sonst?- Die stop() Methode haltet den Executer an- Geeigneter für OOP da Kontextübergabe möglich
Prototype: PeriodicalExecuter
Simpler Aufruf
// Übergabe einer direkten Funktionnew PeriodicalExecuter(function(executer) {
if (!confirm('Hey bananas, what\'cha doin\'?')) {executer.stop();
}}, 5.0);
// Verwendung innerhalb eines Objektsthis.Exec = new PeriodicalExecuter(this.DoIt.bind(this),5.0);// Funktion DoIt als BeispielDoIt : function(pe) {
pe.stop(); // Übergebenen Executer stoppenthis.Exec.stop(); // Oder die Objektreferenz, da Kontext
}
Prototype: Prototype.Browser
Der Prototype NamespaceBietet nicht viel gescheites ausser „Browser“
Ein Set von BooleansWenns mal doch nicht klappt: Prototype.Browser.IE: Check ob IE vorhanden (Zudem: IE6, IE7, IE8).Opera: Check auf jegliche Versionen von Opera.WebKit: Check auf Webkit Browser (Safari, Anroid).MobileSafari: Expliziter Check auf iPhone Browser.Gecko: Browser basierend auf Gecko (Firefox, Netscape)
Prototype: String
Sind wir nicht endlich durch?Nein. Mit dem String Objekt kommt nochmal eine grobe Sache
Gültigkeit der MethodenJeder String besitzt die neuen Methoden, da Prototype direktdas String Objekt erweitert (Wie bei Zahlenwerten)
Wichtige Funktionen.capitalize(): Ersten Buchstaben gross schreiben.endsWith()/startsWith(): Start oder Ende des Strings prüfen.(un)escapeHtml(): Konvertiert reinen Text in HTML Entitäten und zurück
Prototype: String
Noch etwas mehr Funktionen.evalJSON(): JSON String zu einem Objekt konvertieren.isJSON(): Gibt an, ob der String evaluierbares JSON enthält.evalScripts(): Javascript Code innerhalb des Strings ausführen.extractScripts(): Gibt ein Array aller Javascript Codezeilen zurück.sub()/.gsub(): Einfache Form von Regex und/oder Replace.scan(): Erlaubt die Anwendung eines Callback für jeden Teilstring.stripScripts(): Löscht alle <script> Tags und JS Codes aus dem String.stripTags(): Entfernt alle HTML Tags aus dem String.toArray(): Erstellt ein Char Array aus dem String.toQueryParams(): Erstellt JSON Code aus URL Parametern.truncate(): Kürzt den String auf X-Zeichen und fügt Suffix an
Prototype: Template
Sowas wie String.Format in .NETString mit Variablen durch Objektproperties ersetzen
Gedacht für mehrfache VerwendungDas Template ist z.B. für Listenansichten sehr geeignet, lässt aberauch herkömmlichen „Verknüpfungscode“ schöner aussehen
Wichtige Funktionen.evaluate(obj): Ersetzt die Templatevariablen mit entsprechenden Variablen im gegebenen Objekt (JSON oder Prototype Objekt)
Prototype: PeriodicalExecuter
Anwendung des Template
var conv1 = { from: 'meters', to: 'feet', factor: 3.28 };var conv2 = { from: 'kilojoules', to: 'BTUs', factor: 0.9478 };var conv3 = { from: 'megabytes', to: 'gigabytes', factor: 1024 };// Template erstellenvar tpl = new Template(
'Multiply by #{factor} to convert from #{from} to #{to}.');// Alle formatieren... mit on-the-fly-array-each :D[conv1, conv2, conv3].each(function(conv){ tpl.evaluate(conv);});// -> Multiply by 3.28 to convert from meters to feet.// -> Multiply by 0.9478 to convert from kilojoules to BTUs.// -> Multiply by 1024 to convert from megabytes to gigabytes.
Inhalte Scriptaculous
EffekteEffektbeispiele, Queues, Combination, Toggle
ControlsSlider, Sortable(s), Ghostly, Test.Unit
AjaxAutocompleter, In Place Editing
Scriptaculous: Effekte
Zurück zum KerngeschäftScriptaculous bietet Effekte und Controls
Warum bietet Prototype das nicht an?Prototype und Scriptaculous haben eine strikte Trennung ausfunktionalem Framework und Effekten/Controls
EffekttypenEs wird zwischen Kerneffekten und Kombinationseffekten unterschieden
Scriptaculous: Effektbeispiele
Anzeige-EffekteEffect.Highlight: Lässt die Hintergrundfarbe kurz aufblinkenEffect.Morph: Erlaubt Farbwechsel zwischen zwei FarbenEffect.Move: Absolute oder Relative Veränderung der Position
Erschein-EffekteEffect.Appear: Sanftes Einblenden eines ControlsEffect.BlindDown: Herunterfahren eines Controls
Ausblende-EffekteEffect.Fade: Sanftes ausblenden eines ControlsEffect.BlindUp: Herauffahren eines Controls
Scriptaculous: Effekt Queues
Effect.QueueJeder Effekt lässt sich in eine Queue stellen, da er ansonstenparallel mit anderen Effekten ausgeführt würde
EinschränkungMan muss eindeutige „Scopes“ definieren, um Sie während derLaufzeit mit Effect.Queue steuern (z.B. Abbrechen) zu können
BeispielDas folgende Beispiel zeigt die Grundlegende Arbeit mit Queues.Merke: Queues sind nur nötig, wenn Effekte auf dem selben Element nacheinander anstatt gleichzeitig ausgeführt werden sollen
Scriptaculous: Effekt Queues
Erstellen von Queues
// Menu anzeigen, ans Ende des 'sc_menu' Scopenew Effect.SlideDown('menu',
{ queue: { position: 'end', scope: 'sc_menu' } });// Banner anzeigen, ans Ende des 'sc_banner' Scopenew Effect.Appear('bannerbig',
{ queue: { position: 'end', scope: 'sc_banner' } });// Menu pulsieren lassen, nach SlideDown Effektnew Effect.Pulsate('menu',
{ queue: { position: 'end', scope: 'sc_menu' } });
Scriptaculous: Effekt Queues
Steuern der Scopes
// z.B. die Menu Queue holenvar queue = Effect.Queues.get('sc_menu');// 'queue' ist eine Prototype Enumeration, daher...queue.each(function(effect) { effect.cancel(); });// ... um alles abzubrechen oder ...queue.invoke('cancel');// …Wartezeit zwischen Effekten beeinflussenqueue.interval = 100;
Scriptaculous: Combination / Toggle
Combinations toggeln und mergelnSlideUp()/Down(), Appear()/Fade() und BlindDown()/Up() lassen sich mit toggle() einfach kombinieren bzw. ein- und ausblenden
Sinn dahinterSpart einiges an Code, da ein-/ausblenden mit einerZeile Code realisiert werden kann
Questions
Aufwachen!Ihr habt‘s hinter euch.