Erweitern Sie ein Formular schrittweise zu einem modalen Formular

Mit etwas so Wichtigem wie einem Kontaktformular möchten Sie, dass es für alle Besucher ordnungsgemäß funktioniert - auch für JavaScript. Wie gehen Sie damit um, wenn Sie ein modales (Popup) Formular verwenden möchten? Die Antwort ist eine progressive Verbesserung. Beginnen Sie mit der Basislinie und der verwendbaren Funktionalität. Steigern Sie dann die Benutzererfahrung für diejenigen, die über Browser verfügen, um dies zu unterstützen.


Schritt 1: Legen Sie die Projektziele fest

Bevor Sie eine Reise beginnen, hilft es (meistens), ein Ziel zu haben. Das Ziel dieses Projekts ist es, einen Standard-Link zu einer Seite mit einem Kontaktformular zu verwenden, damit dieses Formular auf der aktuellen Seite in einem modalen Dialogfeld angezeigt werden kann.

Es gibt mehrere Gründe für diesen Ansatz:

  • Wenn der Benutzer JavaScript deaktiviert hat, werden diese wie üblich an die Kontaktformularseite gesendet.
  • Es muss nur eine Version des Formulars gepflegt werden.
  • Der zusätzliche Inhalt (das Formular) kann asynchron geladen werden.

Schritt 2: Listen Sie die Tools auf

Dies in rohem JavaScript von Grund auf zu schreiben, wäre viel Code. Glücklicherweise gibt es bereits vorhandene Tools, mit denen wir die Aufgabe erleichtern können. Dieses Tutorial basiert auf:

  • jQuery
  • jQuery UI
  • jQuery-UI-Stylesheets (CSS)

Um diesen Code möglichst wiederverwendbar zu machen, schreiben wir ein Plug-In. Wenn Sie mit dem Authoring eines Plug-Ins nicht vertraut sind, erhalten Sie eine Einführung in den Artikel von Jeffrey Way über Nettuts +. Die modale Funktionalität wird aus dem $ .dialog der jQuery-UI stammen.


Schritt 3: Entwerfen Sie die Plug-In-Schnittstelle

Wir folgen dem normalen Muster für ein jQuery-Plug-In: Aufrufen des Plug-Ins auf einem Selector und Einstellen der Optionen über ein Array. Welche Optionen werden benötigt? Es gibt Optionen sowohl für das modale Fenster als auch für das Plug-In. Wir erwarten, dass das Plug-in auf einem Anker aufgerufen wird, und erzwingen Sie dies im Code.

 $ ('a.form_link'). popUpForm (container: ", modal: true, skalierbar: false, width: 440, Titel: 'Website Form', beforeOpen: Funktion (Container) , onSuccess: Funktion (Container) , onError: Funktion (Container) );

Optionen prüfen

Container: Auf diese Weise gibt der Plug-In-Benutzer die ID des Formulars auf der Remote-Seite an. Der Link selbst gibt die Seite an, aber die Containeroption ermöglicht das Abrufen des relevanten Teils. Das wird das sein nur Erforderliche Option beim Aufruf des Plug-Ins.

Modal, Größe veränderbar, Breite, Titel: Diese Optionen werden alle an den $ .dialog der jQuery-Benutzeroberfläche übergeben. Die oben genannten Werte sind Standardwerte und das Plug-In wird problemlos ausgeführt, ohne dass beim Aufruf von $ .popUpForm irgendwelche Werte festgelegt werden.

beforeOpen, onSuccess, onError: Dies sind alles Rückrufe und erwarten eine Funktion. Der Funktion wird das Objekt für den Link, auf den geklickt wurde, und der Container, auf den der Link gerichtet ist, übergeben. Rückrufe ermöglichen den Benutzern eines Plug-Ins eine benutzerdefinierte Funktionalität. Die Standardeinstellung für diese Rückrufe ist eine leere Funktion.

Der für die Verwendung des Plug-Ins erforderliche Mindestcode würde dann wie folgt aussehen:

 $ ('a.form_link'). popUpForm (container: '#form_id');

Das scheint einfach zu sein, nicht wahr? Wenn Sie ein Plug-In wie dieses aufrufen, wird der Code des Plug-Ins mit einer jQuery-Auflistung aller DOM-Elemente aufgerufen, die mit dem Selektor übereinstimmen. Dieser wird in der speziellen Variablen 'this' verfügbar sein.


Schritt 4: Das Skelett des Plug-Ins

Die meisten jQuery-Plug-Ins folgen einem sehr ähnlichen Muster. Sie durchlaufen die Auswahlgruppe und machen, was immer sie tun. Ich habe ein einfaches Plug-In "Outline", von dem ich normalerweise arbeite, und es wird hier gut passen. Dies wäre der Start Ihrer Plug-in-Datei, popUpForm.jquery.js.

 (Funktion ($) $ .fn.popUpForm = Funktion (Optionen) // Defaults und Optionen var defaults = container: ", modal: true, skalierbar: false, width: 440, Titel: 'Website Form', beforeOpen : function (container) , onSuccess: function (container) , onError: function (container) ; var opts = $ .extend (, Standardeinstellungen, Optionen); self.each (function ()  // Die ECHTE ARBEIT findet hier statt // Im Rahmen dieser Funktion bezieht sich 'this' auf ein einzelnes // DOM-Element innerhalb der jQuery-Auflistung (kein jQuery obj));) (jQuery);

Der Code ist in eine selbstausführende Funktion eingeschlossen und fügt sich mit dem $ .fn-Namespace zu jQuery hinzu. Der Bezeichner nach $ .fn ist der Methodenname, den Sie zum Aufrufen verwenden.

Wir befolgen gute Kodierungspraktiken, indem wir die jQuery-Variable explizit übergeben. Dies verhindert, dass Probleme auftreten, wenn das Plug-In auf einer Seite mit anderen JavaScript-Frameworks verwendet wird, von denen einige $ als Variable verwenden.

Als Nächstes wird ein Array von Standardwerten erstellt, und diese Standardwerte werden verwendet, wenn sie beim Aufruf des Plug-Ins nicht definiert werden. Die Zeile, die unmittelbar auf das Standardarray folgt, führt die übergebenen Optionen mit den Standardwerten zusammen und speichert sie alle im optionalen Array.

Schließlich wird eine Schleife zum Durchlaufen der jQuery-Auflistung erstellt, die vom Selector identifiziert wird, wenn das Plug-In aufgerufen wird. In den meisten Situationen besteht die Wahrscheinlichkeit, dass es sich um ein einzelnes Element (einen Anker) handelt, es werden jedoch immer mehrere Links mit einem einzigen Element behandelt call - vorausgesetzt, sie laden alle das gleiche Formular.

Ein wichtig Was zu verstehen ist, ist, dass sich der Wert der speziellen Variablen 'this' ändert, wenn wir die self.each-Schleife betreten. Es ist eine spezielle jQuery-Methode, die das Durchlaufen von DOM-Sammlungen vereinfacht. Die Callback-Funktion verwendet den Kontext des aktuellen DOM-Elements. Daher bezieht sich die Variable 'this' auf dieses Element in der Schleife.

In einem sehr einfachen Beispiel können Sie sehen, wie sich "this" auf eine jQuery-Auflistung von jQuery-Objekten im Funktionsbereich der Plug-In-Funktion bezieht. Innerhalb dieser Schleife bezieht sich "this" auf ein einzelnes Nicht-jQuery-DOM-Element.


Schritt 5: Starten der Eingeweide

Der Code für die nächsten Abschnitte ist alles im self.each-Block unseres Skeletts enthalten. Was tun wir jetzt? Für jedes übergebene jQuery-Element sind mehrere Schritte erforderlich:

  • Stellen Sie sicher, dass es sich um einen Link handelt und dass er irgendwo hingeht
  • Rufen Sie den angegebenen Teil der Remote-Seite ab
  • Hängen Sie das Remote-Formular an die Seite an und erstellen Sie einen verborgenen Dialog
  • Stehlen Sie den Link, um unser Popup zu erstellen
  • Handle Formulareinreichungen im AJAX-Stil

Bevor wir dies tun, fügen wir jedoch eine Zeile Code in den Callback ein, ganz oben

 var $ this = $ (this);

Das ist mehr als nur Bequemlichkeit. Die Variable 'this' wird bei allen Schließungen innerhalb der einzelnen Schleifen außerhalb des Gültigkeitsbereichs, und wir müssen später auf das aktuelle Objekt zugreifen. Da wir es fast immer als jQuery-Objekt haben wollen, speichern wir es als eins.


Schritt 6: Stellen Sie sicher, dass das Element gültig ist

$ .popUpForm kann nur mit Ankertags ausgeführt werden, und das Ankertag muss den Wert href haben, damit wir wissen, woher das Formular abgerufen werden soll. Wenn eine dieser Bedingungen nicht erfüllt ist, lassen wir das Element in Ruhe. Die zweite Zeile unseres "Mut" wird sein:

 if (! $ this.is ('a') || $ this.attr ('href') == ") return;

Einige Leute hassen mehrere Rückgabepunkte in einer Funktion, aber ich habe immer festgestellt, dass einer am Anfang eine Funktion lesbarer machen kann, im Gegensatz zu einer if (Bedingung), um den Rest der Funktion zu umschließen. Leistungstechnisch sind sie identisch.


Schritt 7: Abrufen der From von der Remote-Seite

Die $ .load-Methode verfügt über eine nette Funktionalität, mit der ein Aufruf und eine ID angegeben werden können, um nur einen Teil eines abgerufenen Dokuments anzuhängen. Das Skript hängt den zurückgegebenen HTML-Code nicht direkt an das DOM an, da $ .load nur überschreibt und nicht angehängt wird.

 var SRC = $ this.attr ('href') + "+ opts.container; var formDOM = $ ("
") .load (SRC, function ()

Die Variable opts.container hat die ID des Formularelements auf der Remote-Seite. Die zweite Zeile lädt diese Remote-Seite und fügt das Formular und seinen Inhalt einem div hinzu, dessen Gesamtheit in der Variablen formDOM gespeichert ist. Beachten Sie, dass $ .load einen Rückruf (die Funktion) enthält. In diesem Rückruf verwenden wir formDOM.


Schritt 8: Hängen Sie den HTML-Code an und erstellen Sie den Dialog

Im $ .load-Rückruf wird der Code das Formular anfügen, das Klickereignis des Ankers überschreiben und das Übermittlungsereignis des Formulars überschreiben.

Der HTML-Code des Formulars wird an dieser Stelle in der Variablen formDOM gespeichert. Das Anhängen an die vorhandene Seite ist einfach.

 $ ('# popUpHide'). append (formDOM);

Die ID #popUpHide bezieht sich auf ein verstecktes div, das vom Plug-In an die Seite angehängt wird. Um dieses div bereitzustellen, wird die folgende Zeile hinzugefügt am oberen Rand des Plug-Ins. Wenn es bereits existiert, erstellen wir es nicht neu.

 $ ("# popUpHide"). Länge || $ ('
') .appendTo (' body '). css (' display ',' none ');

Jetzt, da das Formular auf unserer Seite sicher versteckt ist, ist es an der Zeit, einen Aufruf der $ .dialog-Methode zum Erstellen des Formulars zu verwenden. Die meisten Setup-Parameter werden von unserem Plug-In übernommen. Die Option "autoopen" ist hart codiert, da das Dialogfeld beim Klicken auf den Link und nicht beim Erstellen des Dialogfelds geöffnet werden soll.

 // Erzeuge und speichere den Dialog $ (opts.container) .dialog (autoOpen: false, width: opts.width, modal: opts.modal, resizable: opts.resizeable, title: opts.title);

Schritt 9: Überschreiben der Standardereignisbehandlung

Wenn wir hier aufhören würden, würde das Plug-In nicht viel ausrichten. Der Link würde uns immer noch zur nächsten Seite führen. Das gewünschte Verhalten besteht darin, dass der Link den Dialog öffnet.

 $ this.bind ('click', Funktion (e) e.preventDefault (); opts.beforeOpen.call ($ this [0], opts.container); $ (opts.container) .dialog ('open') ;);

Die erste Zeile dieses Click-Handlers ist sehr wichtig. Der Link wird nicht mehr geladen, wenn die neue Seite angeklickt wird.

Die zweite Zeile ist unser 'beforeOpen' Callback. Die Variable opts.beforeOpen enthält eine Funktionsreferenz - das ist offensichtlich. Die .call-Methode wird verwendet, um die Funktion in einer Weise aufzurufen, in der wir Kontext bereitstellen können - die Variable "this" für diese Funktion. Das erste übergebene Argument wird "this" für die aufgerufene Funktion.

Wenn eine Funktion Zugriff auf die Variable 'this' hat, gibt es einige Verträge, die JavaScript mit dem Programmierer hat und die wir beibehalten sollten.

  • Die Variable 'this' sollte das Objekt sein, auf das die Funktion wirkt
  • Die Variable 'this' ist ein einzelnes DOM-Objekt

Um diesen Vertrag aufrechtzuerhalten, übergeben wir $ this anstelle von $ this. $ this [0] steht für ein einzelnes Nicht-jQuery-DOM-Objekt.

Stellen Sie sich die folgende Rückruffunktion vor, um das Verständnis zu erleichtern:

 opts.beforeOpen = function (container) // Gibt den Wert des Links aus, auf den Sie gerade geklickt haben ('Die entfernte Seite ist' + this.href); // Gibt den ID-Container an, der diesem Link zugewiesen ist ("Und der Container ist" + Container); 

Der Link-Klick ist nicht das einzige Standardverhalten, das überschrieben wird. Wir möchten auch, dass das Formular über AJAX übermittelt wird. Daher muss das normale Onsumbit-Ereignis verhindert und neues Verhalten codiert werden.

 $ (opts.container) .bind ('submit', Funktion (e) e.preventDefault (); ajaxSubmit (););

Auch hier verwenden wir removeDefault (), um das Ereignis zu stoppen, und fügen in diesem Fall eine neue Funktion hinzu, um die Formularübergabe abzuwickeln. Der ajaxSubmit () - Code könnte direkt in den Callback gehen, wurde aber zur besseren Lesbarkeit in eine neue Funktion verschoben.


Schritt 10: Formulareinreichungen im AJAX-Stil behandeln

Diese Funktion wird unmittelbar nach dem Ende der self.each-Schleife hinzugefügt (keine Sorge, Sie werden den gesamten Plug-in-Code in einem Schritt in einem Schuss sehen). Es nimmt das Formular an, übermittelt es an ein Remote-Skript und löst die entsprechenden Rückrufe aus.

Der erste Schritt besteht darin, das Formular als jQuery-Objekt abzurufen und die Methode des Formulars (entweder GET oder POST) zu bestimmen.

 function ajaxSubmit () var form = $ (opts.container); var method = form.attr ('method') || 'ERHALTEN';

Wenn Sie sich erinnern, haben wir die ID des Formulars in opts.container gespeichert. Die nächste Zeile überprüft das Formular auf eine Methode und weist 'GET' zu, wenn keine Methode vorhanden ist. Dies ist konsistent mit HTML, das GET standardmäßig für Formulare verwendet, wenn keine Methode angegeben ist.

Verwenden Sie die $ .ajax-Methode, um das Formular zu senden:

 $ .ajax (Typ: Methode, URL: Form.attr ('Aktion'), Daten: Form.serialize (), Erfolg: Funktion () $ (opts.container) .dialog ('close'); opts. onSuccess.call ($ this [0], opts.container);, Fehler: function () $ (opts.container) .dialog ('close'); opts.onError.call ($ this [0], Optionen) .container););

Die URL-Option wird aus dem Aktionsattribut des Formular-Tags bestimmt. Die Daten werden mithilfe der serialize-Methode für das jQuery-Objekt erzeugt, das das Formular enthält.

Die Erfolgs- und Fehleroptionen sind $ .ajax-Callbacks, mit denen wir unsere Callbacks auf dieselbe Weise aufrufen, wie der beforeOpen-Callback aufgerufen wurde.

Wir schließen auch den Dialog für die Erfolgs- und Fehlerbehandlungsroutinen.


Schritt 11: Das gesamte Plug-In

Lassen Sie uns als Übersicht den Code betrachten, den wir bisher geschrieben haben, einschließlich einiger hilfreicher Code-Kommentare:

 (function ($) var alog = window.console? console.log: alert; $ .fn.popUpForm = function (options) // ERFORDERN EINEN Container if (! options.container) alert ('Containeroption erforderlich') ); return; // Geben Sie uns irgendwo Formulare $ ("# popUpHide") an. length || $ ('
') .appendTo (' body '). css (' display ',' none '); // Defaults und Optionen var defaults = container: ", modal: true, skalierbar: false, width: 440, Titel: 'Website Form', beforeOpen: function (container) , onSuccess: function (container) , onError: function (container) ; var opts = $ .extend (, Standardwerte, Optionen); // Das "this" innerhalb der jeweiligen Schleife bezieht sich auf das einzige DOM-Element // der jQuery-Sammlung, die wir derzeit verwenden Verarbeiten auf this.each (function () / * Wir möchten den Wert 'this' für $ .load * callback * / var verfügbar lassen. $ this = $ (this); / * wir möchten ein Element nur bearbeiten, wenn Es ist ein Link und * hat einen href-Wert * / if (! $ this.is ('a') || $ this.attr ('href') == ") return; / * Für ein $ .load ( ) Funktion, der Parameter ist die URL, gefolgt von * der ID-Auswahl für den Abschnitt der Seite * / var SRC = $ this.attr ('href') + "+ opts.container; / *, mit dem die Ereignisbindung erfolgt im Rückruf, falls das * Formular nicht geladen werden kann oder der Benutzer auf den Link klickt, bevor * das Modal fertig ist * / var formDOM = $ ("
") .load (SRC, function () // An die Seite anhängen $ ('# popUpHide'). anfügen (formDOM); // Erstellen und speichern Sie den Dialog $ (opts.container) .dialog (autoOpen: false) , width: opts.width, modal: opts.modal, anpassbar: opts.resizeable, Titel: opts.title); / * stoppt die normale Formularübergabe; musste nach dem * Erstellen des Dialogs erscheinen, andernfalls ist das Formular nicht vorhanden * noch, um einen Event-Handler auf * / $ (opts.container) .bind ("submit", Funktion (e) e.preventDefault (); ajaxSubmit ($ this [0]);); // zu setzen Bindung für den Link, der an das Plug-in übergeben wird $ this.bind ("click", Funktion (e) e.preventDefault (); opts.beforeOpen.call ($ this [0], opts.container); $ (opts .container) .dialog ('open');););); Funktion ajaxSubmit (anchorObj) console.log (anchorObj); var form = $ (opts.container); var method = form.attr ( 'method') || 'GET'; $ .ajax (type: method, url: form.attr ('action'), data: form.serialize (), success: function () $ (opts.container)) .dialog ('close'); opts.onSuccess.call (anchorObj, opts.container.) ); , Fehler: function () opts.onError.call (anchorObj, opts.container); ); ) (jQuery);

Dieser Code sollte in einer Datei namens popUpForm.jquery.js gespeichert werden


Schritt 12: Einrichten des Plug-Ins

Der erste Schritt bei der Verwendung von Plug-Ins besteht darin, alle erforderlichen Abhängigkeiten auf Ihrer HTML-Seite anzugeben. Ich persönlich bevorzuge die Google-CDN. Dateien, die sich in einer separaten Domäne befinden, können das Laden der Seite beschleunigen und die Server sind schnell. Außerdem erhöht sich die Wahrscheinlichkeit, dass ein Besucher diese Dateien bereits zwischengespeichert hat.

Fügen Sie im HEAD des HTML-Dokuments Folgendes hinzu:

    

Die Datei main.css ist für unsere Site-spezifischen Stile bestimmt, alles andere stammt aus dem CDN von Google. Beachten Sie, dass Sie auf diese Weise auch jQuery-UI-Designs aus dem CDN verwenden können.


Schritt 13: Aufrufen des Plug-Ins

Denken Sie daran, dass wir das Plug-In nur für Links aufrufen möchten, die zu einer Formularseite führen. In der Online-Demo sind die Formulare in form.html enthalten und es werden nur zwei Links auf diese Seite geleitet.

 

Die Aufrufe sind in einen document.ready-Block eingeschlossen, sodass wir sicher sein können, dass die Ankerelemente vorhanden sind, bevor Sie versuchen, auf sie zu reagieren. Der zweite Aufruf $ ('. Umfrage a') ist ein Beispiel für den Mindestbetrag, der für die Verwendung unseres neuen Plug-Ins erforderlich ist. Im ersten Beispiel wird ein Callback für onSuccess und onError festgelegt.


Schritt 14: Modalisieren

Wenn Sie bis hierher gekommen sind und Beispielformulare und eine Seite erstellt haben, von der aus sie aufgerufen werden können, werden Sie feststellen, dass das Formular im Modal wahrscheinlich hässlich ist. Das Modal selbst ist nicht schlecht, weil wir ein jQuery-UI-Design verwenden. Aber die Form innerhalb des Modals ist meistens nicht gestylt, also sollten wir uns bemühen, es zu ordnen.

Bei der Erstellung von Stilen für die Verwendung in einem jQuery-UI-Modal sind einige Dinge zu beachten:

  • Das Modal selbst ist nur ein untergeordnetes Element des BODY-Elements der Seite
  • Die Inhalte des Modals sind alle Kinder eines Div der Klasse 'Ui-Dialog'.

Mit diesen kleinen Informationen können wir beginnen, Stile auf das Formular im Modal anzuwenden. Zuerst geben wir dem Modal eine Hintergrundfarbe, mit der wir zufrieden sind, und ändert auch die Schriftart für die Titelleiste.

 .ui-dialog hintergrund: rgb (237,237,237); font: 11px verdana, arial, serifenlos;  .ui-dialog .ui-dialog-titlebar font: small-caps fett 24px Georgia, Times, serif; 

Als Nächstes möchten wir jedes Element im Formular durch Zeilen trennen. Da die Formularstruktur h3s mit divs enthält, die Formularelemente enthalten, fügen wir die folgenden Regeln hinzu:

 .ui-dialog h3, .ui-dialog div border-top: 1px solid rgb (247,247,247); Rand unten: 1px festes rgb (212,212,212); Polsterung: 8px 0 12px 10px; 

Und wir wollen nur Linien zwischen den Abschnitten, nicht ganz oben oder ganz unten.

 .ui-dialog .puForm div: last-child border-bottom: none;  .ui-dialog .puForm h3: first-child border-top: none; 

Vergessen Sie nicht, die h3s und die Formularelemente zu formatieren. Die Optionsfelder müssen inline angezeigt werden, damit sie alle in einer Reihe stehen.

 .ui-dialog h3 font: 18px Georgia, Times, serif; Marge: 0;  .ui-Dialogauswahl, .ui-Dialogtextbereich, .ui-Dialogeingabe width: 76%; Bildschirmsperre;  .ui-dialog #rating input, .ui-dialog #rating label display: inline; Breite: Auto; 

Denken Sie daran, dass diese Stile für dieses Projekt spezifisch sind. Je nach verwendeter Struktur müssen Sie Ihre eigenen Formulare formatieren. Um gezielt auf die Formularelemente zu zielen, können Sie entweder Nachkommen des .ui-Dialogs anvisieren oder jedes Formular einzeln formatieren, indem Sie Formatvorlagen einschließen, die von der von Ihnen eingeschlossenen Formular-ID abweichen.

Die gestaltete Form:


Schritt 15: Fazit

Was haben wir wirklich getan? Wir haben einen normalen Link genommen, der zu einem Kontaktformular (oder zu Formularen) führt. Dieses Formular wurde in einem modalen Dialogfeld geladen und über Ajax gesendet. Für Benutzer ohne Javascript passiert nichts und die Links verhalten sich normal, sodass wir niemanden daran gehindert haben, Ihre Formulare auszufüllen.

Wenn Sie in der Demo auf den Umfrage-Link klicken, senden Sie unbedingt etwas ab. Ich werde die Ergebnisse in den Kommentaren nach einer Woche oder so zum Spaß posten!