AutoSave für AJAX-Formulare Timo Holzherr

Slides:



Advertisements
Ähnliche Präsentationen
interaktiver Web Service Workflows
Advertisements

Object Relational Mapping
Webinar für [Name der Gruppe] [Name des Institutes]
Sortieren I - Bubblesort -
Datenbankanbindung mit ASP Wilhelm-Schickard-Schule Tübingen
JDataSet & Persistenz Layer
MySQL.
Seminar Internetdienste Web 2.0 und Rich Internet Applications (RIA) JavaFX Rainer Scholz.
Stefanie Selzer - Pascal Busch - Michael Kropiwoda
Java: Dynamische Datentypen
Listen Richard Göbel.
Java: Grundlagen der Sprache
Wie überwacht man Objekte im "Alltag" ?. Indem man "Wanzen" an diese anbringt.
Ein Beispiel in Java.
Konstruktoren.
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (05 – Elementare Datenstrukturen) Prof. Th. Ottmann.
XINDICE The Apache XML Project Name: Jacqueline Langhorst
SQL als Abfragesprache
IS: Datenbanken, © Till Hänisch 2000 CREATE TABLE Syntax: CREATE TABLE name ( coldef [, coldef] [, tableconstraints] ) coldef := name type [länge], [[NOT]NULL],
XForms Von Matthias Keck.
Text-Retrieval mit Oracle Vortrag von Andreas Mück & David Diestel.
AWT – Detailbetrachtung Java 3D – Seminar im Wintersemester 2002/2003 Christian Schneider.
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
Projekt Web Engineering
NetUSE Web Application Framework Kai Voigt NetUSE AG 28. Februar 2003.
JavaScript - Einführung
Einführung MySQL mit PHP
Hänchen & Partner GmbH 1 Web-Anwendungen mit dem Jakarta Struts Framework 3.Juli 2003 Martin Burkhardt.
Wizards & Builders GmbH Schulung Visual SourceSafe für Visual FoxPro Norbert Abb W&B.
Uwe Habermann WPF Avalon Formulare aus VFP verwenden Venelina Jordanova
Seite Common Gateway Interface. Konzepte. Übersicht 1Einleitung 2Was ist CGI? 3Wozu wird CGI verwendet? 4Geschichtlicher Überblick 5Grundvoraussetzungen.
CRM Editor auf der Basis von Qt (Beispiel von Ubi erat Lupa)
FH-Hof HTML - Einführung Richard Göbel. FH-Hof Komponenten des World Wide Webs WWW Browser HyperText Transfer Protocol (HTTP) via Internet WWW Server.
FH-Hof 1 XML-Parser Richard Göbel. FH-Hof 2 XML-Parser- DOM Object Tree Parser Objekt der Klasse 'DocumentBuilderFactory' mit 'newInstance()' erzeugen.
Bezirksregierung Detmold Hier könnte ein schmales Bild eingefügt werden Online-Beteiligungsverfahren zum Entwurf von Bewirtschaftungsplan und den Maßnahmenprogrammen.
PRJ 2007/1 Stefan Dissmann Verkettete datenstruktur: Liste Problem: Liste, die eine beliebige Zahl von Elementen verwaltet Operationen: Erzeugen, Anfügen,
Automatische Übersetzungen mit Google
Agenda Vereinfachte Grundeinrichtung und Dateneingabe
Einführung in das Programmieren mit JavaScript Mag. Andreas Starzer weloveIT – EDV Dienstleistungen.
Delphi II - OOP IFB Fortbildung
Online -System des Projekts Tomáš Baxa. Inhalt der Präsentation Einzelne Teile des Websystems Registrierung und Anmeldung (Einloggen) im System Eingabe.
LearningApps: Mehr Interaktivität für E-Learning im Web 2.0
Relationale Datenbanken III
Publicvoid - Onlinenotes SWOS HS 2011/12. Inhalt Vorstellung Website Probleme - Lösungen Quick & easy 2 kalik1, messu2, joosp1, stahm3.
Abteilung für Telekooperation Übung Softwareentwicklung 1 für Wirtschaftsinformatik Dr. Wieland Schwinger
Einführung / Geschichte Einführung / Geschichte Motivation Motivation Beispiel Beispiel Architektur / Komponenten Architektur / Komponenten Konfiguration.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Was macht eigentlich dieses ExsoForm? Ein Beispiel für eine Dokumentendefinition in Screenshots.
Developer Day Office APPs entwicklen Simon Amrein Trivadis AG Die ersten Schritte in eine neue Office-Welt.
Entwicklung verteilter Anwendungen II, SS 13 Prof. Dr. Herrad Schmidt SS 13 Kapitel 2 Folie 2 ASP.NET HTTP-Handler (1)
Dynamische Datentypen
Aufgaben Version 1: Es soll eine Wetterstation mit folgenden zwei Anzeigen implementiert werden: Aktuelle Wetterbedingungen mit Temperatur und.
PHP Basic.
Screen Scraping Für Frühaufsteher.
Caliburn.Micro.
Objectives Verstehen was unterDelegate verstanden wird
Webseiten mit PHP, SQL, XML und Webservices Anhand praktischer Beispiele.
Mag. Andreas Starzer weloveIT – EDV Dienstleistungen
Erstelle deine eigene Timeline
Tutorium zur LV Forschungspraktikum II (Higher Education) Ein Computerprogramm tut, was Du schreibst, nicht was Du willst.
CompuTreff: „Blog“ und „Skype“ Wichtig! Schauen Sie sich die Kassensturz- Sendung vom 11. November 2008 an. Thema Informations-Sammler „Google“
Formulare Vanessa Kogelbauer.
Internet-Grundtechnologien. Client / Server Client („Kunde“): fordert Information / Datei an im Internet: fordert Internetseite an, z.B.
JQuery: New Wave Javascript Seite 1 jQuery: New Wave Javascript Jörn Zaefferer TIMETOACT Software & Consulting GmbHT: Im Mediapark 2F:
Institut für Kartographie und Geoinformation Prof. Dr. L. Plümer, Dipl.-Ing. D. Dörschlag, Dr. G. Gröger Einführung in die Programmierung mit Java 13.
Datenbank für Skriptenverkauf
PHPmyadmin Maya Kindler 6c.
Diskrete Mathe Diskrete Mathematik I Listen Vorlesung 4.
Geomapping. Themen Heute GeoJSON Paths Projections Features Daten beschaffen Projekte weiter bringen.
 Präsentation transkript:

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

Web Application Developer bei der Nero AG / Karlsbad 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

Agenda Was ist AutoSave? Praktische Anwendungen Formulareingaben überwachen Zeitintervalle steuern, Eingaben zählen AJAX-Request absenden Formular-Validierung

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 – 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 bei My Nero

Regelmäßiges Speichern im Hintergrund AutoSave bei My Nero Blog-Editor Regelmäßiges Speichern im Hintergrund

Recovery-Feature auf dem Login-Screen AutoSave bei My Nero Recovery-Feature auf dem Login-Screen

Autosave bei Google Mail

AutoSave bei Google Mail Während der Eingabe der E-Mail: Regelmäßiges Speichern der Eingaben

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

Entwicklung eines AutoSave-Frameworks Trennung der Aufgaben Formulareingaben überwachen Zeitintervalle steuern Formulardaten absenden Verschiedene Klassen FormObservable.js AutoSave.js Note.js Vorteil der Trennung Komponenten können einzeln verwendet werden Bsp.: Live-Validierung von Formularen durch FormObservable

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

Klasse FormObservable Speichert die Liste der Observer Initialisiert die Klasse an einer Form-Node Sendet ein Event an alle Observer Fügt einen Observer hinzu

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

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

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

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

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 this JS-Event-Handling: Ansonsten Verlust des Kontextes

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

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]

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

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

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

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

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

Klasse FormObservable: _loadDefaultValues FormObservable = function( formNode ) { … // Initialisierung der Event-Handler this._loadDefaultValues(); } Nach der bereits erwähnten Initialisierung: Laden der Default Values

Klasse FormObservable: _loadDefaultValues FormObservable = function( formNode ) { … // Initialisierung der Event-Handler this._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 ); } };

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

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

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

Klasse AutoSave Hält eine Instanz der Klasse FormObservable vor Instanziert die Klasse an einer Form-Node, Timeout konfigurierbar Fügt einen Observer hinzu, delegiert FormObservable Setzt alle Timeouts zurück

Klasse AutoSave var as = new AutoSave( document.forms[0], 5 ); as.addObserver( { ontimeout: function(){ /* AJAX Request senden */ }, onupdate: function() { /* aktivieren */ } } );

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

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

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

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)

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

Klasse AutoSave: _updateInterval AutoSave.prototype._updateInterval = function( ) { this._resetInterval(); this._interval = window.setTimeout( this._timeExceeded.bind( this ), this._options.saveTime ); }; Timeout starten Aufgerufene Methode: AutoSave._timeExceeded() Setzt this._interval zurück Löst mit notifyObservers das Event „timeout“ aus

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'; } } ); Beispiel AutoSave[2]

Durchgehendes Tippen Problem Ansatz 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

Klasse AutoSave: HitsCounter

Klasse AutoSave mit HitsCounter Neuer Parameter hitsLimit Spezifiziert die maximale Anzahl ungespeicherter Änderungen Observer-Events: update: Element hat sich geändert timeout: Timeout wurde erreicht hitslimit: Maximale Anz. an Änderungen erreicht

Konkrete Anwendung von AutoSave.js Verwendet AutoSave Observer-Events Klasse Note Konkrete Anwendung von AutoSave.js Verwendet AutoSave Observer-Events update: aktivieren timeout: Daten senden, deaktivieren hitslimit: Daten senden, deaktivieren

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“

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)

Speicherung der Daten (2)

Beim Empfangen von Formularen 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

Demonstration Ergebnis Framework für AutoSaving Kann universell eingesetzt werden AJAX-Requests und Persistence müssen selbst implementiert werden

[2] Folien und Beispiele dieses Vortrags 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