AutoSave für AJAX-Formulare Timo Holzherr AJAX in ACTION 2007, 06.11.2007, Frankfurt.

Post on 05-Apr-2015

108 views 1 download

Transcript of AutoSave für AJAX-Formulare Timo Holzherr AJAX in ACTION 2007, 06.11.2007, Frankfurt.

AutoSave für AJAX-Formulare

Timo Holzherr

AJAX in ACTION 2007, 06.11.2007, Frankfurt

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Timo Holzherr

Web Application Developer bei der Nero AG / Karlsbad

Web-Community My Nero (PHP5, AJAX)

Online Services für verschiedene Nero-Applikationen

Lehrauftrag bei der Berufsakademie Stuttgart

Vorlesung Software-Engineering 2

Betreuung von Studienarbeiten, Thema Compiler-Entwicklung

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Agenda

Was ist AutoSave?

Praktische Anwendungen

Formulareingaben überwachen

Zeitintervalle steuern, Eingaben zählen

AJAX-Request absenden

Formular-Validierung

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Was ist AutoSave?

Auf AJAX basierendes Feature

Für HTML-Formulare

Automatisches Speichern der Benutzer-Eingaben

Eingaben überwachen

Änderungen regelmäßig zum Server übertragen

Recovery-Feature

Browser-Absturz

Versehentliches Schließen des Browserfensters

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AutoSave – Praktische Anwendungen

Vor AJAX nur in Desktop-Applikationen

Microsoft Office

Heute bei vielen Online-Services

My Nero (http://my.nero.com/)

Google Mail (http://mail.google.com/)

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AUTOSAVE BEI MY NERO

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AutoSave bei My Nero

Blog-Editor

Regelmäßiges

Speichern im

Hintergrund

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AutoSave bei My Nero

Recovery-Feature auf dem Login-Screen

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AUTOSAVE BEI GOOGLE MAIL

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AutoSave bei Google Mail

Während der Eingabe der E-

Mail:

Regelmäßiges Speichern der

Eingaben

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

AutoSave bei Google Mail

Der Benutzer findet die automatisch gespeicherte E-Mail im Ordner Entwürfe

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Entwicklung eines AutoSave-Frameworks

Trennung der Aufgaben

i. Formulareingaben überwachen

ii. Zeitintervalle steuern

iii. Formulardaten absenden

Verschiedene Klassen

i. FormObservable.js

ii. AutoSave.js

iii. Note.js

Vorteil der Trennung

Komponenten können einzeln verwendet werden

Bsp.: Live-Validierung von Formularen durch FormObservable

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Formulareingaben überwachen

Eingaben des Benutzers müssen überwacht werden

Registrieren für Events aller Form-Elemente

onkeyup (Nach einem Tastendruck)

onmouseup (Nach einem Mausklick)

onblur (Verlassen eines Formularfeldes)

onchange (Ändern einer Check- oder Dropdown-Box)

Beim Auftreten dieser Events

Prüfen, ob sich die Formularwerte geändert haben

Mithilfe des Observer-Patterns Änderungen signalisieren

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable

Speichert die Liste

der Observer

Initialisiert die Klasse an einer

Form-Node

Sendet ein Event an alle

ObserverFügt einen

Observer hinzu

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable

var observable = new FormObservable( document.forms[0] ); observable.addObserver( { onupdate: function() { alert(“Form element has been updated.“); } } );

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Initialisierung

FormObservable = function( formNode ) { var events = [ 'keyup', 'mouseup', 'blur', 'change' ];

var call = this._onFieldChange.bind( this );

for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item( i ); for( var j=0; j < events.length; j++ ) { elem.addEventListener( events[j], call, true ); } } }

Der Konstruktor erwartet ein HTML-

Form-Objekt als Parameter

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Initialisierung

FormObservable = function( formNode ) { var events = [ 'keyup', 'mouseup', 'blur', 'change' ];

var call = this._onFieldChange.bind( this );

for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item( i ); for( var j=0; j < events.length; j++ ) { elem.addEventListener( events[j], call, true ); } } }

Events, die überwacht

werden sollen

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Initialisierung

FormObservable = function( formNode ) { var events = [ 'keyup', 'mouseup', 'blur', 'change' ];

var call = this._onFieldChange.bind( this );

for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item( i ); for( var j=0; j < events.length; j++ ) { elem.addEventListener( events[j], call, true ); } } }

Methode, die später die

Events verarbeitet

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Initialisierung

FormObservable = function( formNode ) { var events = [ 'keyup', 'mouseup', 'blur', 'change' ];

var call = this._onFieldChange.bind( this );

for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item( i ); for( var j=0; j < events.length; j++ ) { elem.addEventListener( events[j], call, true ); } } }

bind: Methode aus der Bibliothek Prototype [1] Setzt den Kontext der Methode auf die Instanz thisJS-Event-Handling: Ansonsten Verlust des Kontextes

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Initialisierung

FormObservable = function( formNode ) { var events = [ 'keyup', 'mouseup', 'blur', 'change' ];

var call = this._onFieldChange.bind( this );

for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item( i ); for( var j=0; j < events.length; j++ ) { elem.addEventListener( events[j], call, true ); } } }

Jedem Formular-

Element wird call als Event-

Listener hinzugefügt

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Initialisierung

FormObservable = function( formNode ) { var events = [ 'keyup', 'mouseup', 'blur', 'change' ];

var call = this._onFieldChange.bind( this );

for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item( i ); for( var j=0; j < events.length; j++ ) { elem.addEventListener( events[j], call, true ); } } }

Hier: Event-Implementierung nur für Mozilla Firefox

Empfohlen: Bibliothek für Browser-Abstraktion

Bsp.: Prototype [1]

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: _onFieldChange

FormObservable.prototype._onFieldChange = function( ) { … for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item(i);

var oldVal = this._getStoredValue( elem ); var newVal = elem.value;

if( newVal != oldVal ) { this.notifyObservers( 'update' ); this._setStoredValue( elem, newVal ); } } }

Wird vom JS-Event-Handling aufgerufen, wenn eines der überwachten Ereignisse eintritt

• keyup

• mouseup

• blur

• change

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: _onFieldChange

FormObservable.prototype._onFieldChange = function( ) { … for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item(i);

var oldVal = this._getStoredValue( elem ); var newVal = elem.value;

if( newVal != oldVal ) { this.notifyObservers( 'update' ); this._setStoredValue( elem, newVal ); } } }

Dabei wird jedes Formularelement auf eine

Änderung geprüft

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: _onFieldChange

FormObservable.prototype._onFieldChange = function( ) { … for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item(i);

var oldVal = this._getStoredValue( elem ); var newVal = elem.value;

if( newVal != oldVal ) { this.notifyObservers( 'update' ); this._setStoredValue( elem, newVal ); } } }

FormObservable:

Merkt sich lokal für jedes Element den letzten Wert

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: _onFieldChange

FormObservable.prototype._onFieldChange = function( ) { … for( var i=0; i < formNode.elements.length; i++ ) { var elem = formNode.elements.item(i);

var oldVal = this._getStoredValue( elem ); var newVal = elem.value;

if( newVal != oldVal ) { this.notifyObservers( 'update' ); this._setStoredValue( elem, newVal ); } } }

Observers über eine Änderung informieren

Wertänderung lokal merken

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: Default Values

Problem

Formularelemente mit Default-Values

Beim ersten Klick würde das System vermuten, dass sich

Elemente mit Default-Values geändert haben

Abhilfe

Default-Values zu Beginn als Startwert merken

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: _loadDefaultValues

FormObservable = function( formNode ) { … // Initialisierung der Event-Handler this._loadDefaultValues(); }

Nach der bereits erwähnten Initialisierung:

Laden der Default Values

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse FormObservable: _loadDefaultValues

FormObservable.prototype._loadDefaultValues = function( ) { for( var i=0; i < this.form.elements.length; i++ ) { var elem = this.form.elements.item(i); this._setStoredValue( elem, elem.value ); } };

FormObservable = function( formNode ) { … // Initialisierung der Event-Handler this._loadDefaultValues(); }

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

BEISPIEL OBSERVABLE [2]

var observable = new FormObservable( document.forms[0] ); observable.addObserver( { onupdate: function() { alert(“Form element has been updated.“); } } );

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Observer-Notifications empfangen

Empfangen der Observer-Notifications

AJAX-Request muss an FormObservable gekoppelt werden

Ansatz:

var observable = new FormObservable( document.forms[0] ); observable.addObserver( { onupdate: function() { // AJAX Request senden } } );

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Observer-Notifications empfangen

Problem

Bei jedem Tastaturanschlag Übertragung der Änderung

Viele HTTP-Requests

Überlastung des Web-Servers

Lösung

Zeitverzögertes Senden der Daten

Einstellbares Timeout

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave

Hält eine Instanz der Klasse FormObservable

vorInstanziert die Klasse an einer Form-Node,

Timeout konfigurierbar

Fügt einen Observer hinzu, delegiert FormObservable

Setzt alle Timeouts zurück

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave

var as = new AutoSave( document.forms[0], 5 );

as.addObserver( { ontimeout: function(){ /* AJAX Request senden */ }, onupdate: function() { /* aktivieren */ } } );

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: Initialisierung

AutoSave = function( form, saveTime ) { this._options = { form: form, saveTime: saveTime * 1000, // convert into milliseconds }; this._interval = null;

this._observable = new FormObservable( form ); this._observable.addObserver( { onupdate: this._updateInterval.bind( this ), ontimeout: this.reset.bind( this ) } );};

Die übergebenen Parameter werden gespeichert

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: Initialisierung

AutoSave = function( form, saveTime ) { this._options = { form: form, saveTime: saveTime * 1000, // convert into milliseconds }; this._interval = null;

this._observable = new FormObservable( form ); this._observable.addObserver( { onupdate: this._updateInterval.bind( this ), ontimeout: this.reset.bind( this ) } );};

Klassenvariable _interval wird initialisiert.

Referenziert Timeout, um es wieder zu stoppen var to = window.setTimeout( callback, zeit );

window.clearTimeout( to );

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: Initialisierung

AutoSave = function( form, saveTime ) { this._options = { form: form, saveTime: saveTime * 1000, // convert into milliseconds }; this._interval = null;

this._observable = new FormObservable( form ); this._observable.addObserver( { onupdate: this._updateInterval.bind( this ), ontimeout: this.reset.bind( this ) } );};

FormObservable instanzieren

und Observer hinzufügen

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: _updateInterval

AutoSave.prototype._updateInterval = function( ) { this._resetInterval(); this._interval = window.setTimeout( this._timeExceeded.bind( this ), this._options.saveTime ); };

Wird bei einem Update-Event

des FormObservable aufgerufen

(Änderungen am Formular)

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: _updateInterval

AutoSave.prototype._updateInterval = function( ) { this._resetInterval(); this._interval = window.setTimeout( this._timeExceeded.bind( this ), this._options.saveTime ); }; AutoSave.prototype._resetInterval = function()

{ if( this._interval ) { window.clearTimeout( this._interval ); this._interval = null; } }

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: _updateInterval

AutoSave.prototype._updateInterval = function( ) { this._resetInterval(); this._interval = window.setTimeout( this._timeExceeded.bind( this ), this._options.saveTime ); };

Aufgerufene Methode: AutoSave._timeExceeded()• Setzt this._interval zurück• Löst mit notifyObservers das Event „timeout“ aus

Timeout starten

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

BEISPIEL AUTOSAVE[2]

var as = new AutoSave( document.forms[0] ); as.addObserver( { onupdate: function() { document.forms[0].draft.disabled = null; }, ontimeout: function() { alert(“Saving form data.“); document.forms[0].draft.disabled = 'disabled'; } } );

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Durchgehendes Tippen

Problem

Regelmäßiges Eingeben in ein Textfeld

Das Formular wird nie automatisch abgeschickt

Ansatz

Eingaben zählen (Maus, Tastatur)

Ab gewisser Anzahl an Änderungen das Speichern erzwingen

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave: HitsCounter

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse AutoSave mit HitsCounter

Neuer Parameter hitsLimitSpezifiziert die maximaleAnzahl ungespeicherterÄnderungen

Observer-Events: • update: Element hat sich geändert• timeout: Timeout wurde erreicht• hitslimit: Maximale Anz. an Änderungen erreicht

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Klasse Note

Konkrete Anwendung von AutoSave.js

Verwendet AutoSave

Observer-Events

update: aktivieren

timeout: Daten senden, deaktivieren

hitslimit: Daten senden, deaktivieren

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Speicherung der Daten (1)

Implementierung des AJAX-Requests

Abhängig vom eingesetzten AJAX-Framework

Datenbank-Schema zum Ablegen der AutoSave-Daten

Abhängig von der Anwendung

Extra-Tabelle „autosaves“

Inmitten der Nutzdaten: flag: „draft“

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Speicherung der Daten (2)

Fall: Speicherung der Daten inmitten der Nutzdaten

1. AutoSave-Request würde einen neuen Eintrag anlegen

INSERT INTO …

Folge-Requests müssen diesen Datensatz aktualisieren

UPDATE … WHERE ID = …

Deshalb

AutoSave-Request muss den

PK zurückgeben

Notizen

id INT(10) PRIMARY KEY

title VARCHAR(50)

body TEXT

lang VARCHAR(5)

draft TINYINT(1)

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Speicherung der Daten (2)

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Formularvalidierung

Beim Empfangen von Formularen

Formularvalidierung

Sind alle Felder ausgefüllt

Überschreiten die Felder nicht die Maximallänge

Bei AutoSave-Requests

Keine oder nur einfache Validierung!

Sonst: Keine AutoSave der Eingaben obwohl evtl nur ein Feld fehlt

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

DEMONSTRATION ERGEBNIS

• Framework für AutoSaving

• Kann universell eingesetzt werden

• AJAX-Requests und Persistence müssen selbst implementiert werden

AutoSave für AJAX-Formulare

AJAX IN ACTION 2007 - Timo Holzherr

Verweise

[1] Prototype

http://www.prototypejs.org/

JS-Bibliothek für einfache DOM-Manipulation und AJAX-Requests

[2] Folien und Beispiele dieses Vortrags

http://timo.holzherr.de/aia2007