Cu ceva la fel de important ca un formular de contact, doriți să funcționeze corect pentru toți vizitatorii - chiar și JavaScript provocat. Cum gestionați acest lucru dacă doriți să utilizați un formular modal (pop-up)? Răspunsul este o îmbunătățire progresivă; începe cu linia de bază, funcționalitate utilizabilă; apoi creșteți experiența utilizatorilor pentru cei care au browsere pentru al susține.
Înainte de a începe orice călătorie, ajută (de cele mai multe ori) să aibă o destinație. Scopul acestui proiect este de a lua un link standard la o pagină care conține un formular de contact și de a permite ca această formă să apară pe pagina curentă într-un dialog modal.
Există mai multe motive pentru această abordare:
Pentru a scrie acest lucru de la zero, JavaScript ar fi o mulțime de cod. Din fericire pentru noi, există instrumente existente pe care le putem folosi pentru a ușura sarcina. Acest tutorial se bazează pe:
Pentru a face acest cod cât mai reutilizabil, vom scrie un plug-in. Dacă nu sunteți familiarizați cu crearea unui plug-in, puteți obține o introducere din articolul lui Jeffrey Way aici pe Nettuts +. Funcționalitatea modală va proveni din dicționarul $ jQuery-UI.
Vom urmări modelul normal pentru un plug-in jQuery: sunând plug-in-ul pe un selector și setarea opțiunilor prin intermediul matricei. Ce opțiuni sunt necesare? Vor exista opțiuni atât pentru fereastra modală, cât și pentru plug-in-ul propriu-zis. Vom aștepta ca plug-in-ul să fie apelat pe o ancora și să-l punem în cod.
$ ('a.form_link') popUpForm (container: ", modal: true, resizeable: false, width: 440, title: , onError: funcție (container) );
container: Acesta este modul în care utilizatorul plug-in va specifica ID-ul formularului pe pagina de la distanță. Linia însăși specifică pagina, dar opțiunea containerului ne va permite să preluăm partea relevantă. Acesta va fi numai dorită atunci când apelați pluginul.
Modal, Redimensionabil, Lățime, Titlu: Toate aceste opțiuni vor fi transmise în jurnalul $ jQuery UI. Valorile de mai sus sunt implicite, iar plug-in-ul va funcționa foarte bine fără ca oricare dintre acestea să fie setată când se numește $ .popUpForm.
înainteOpen, onSuccess, onError: Acestea sunt toate apelurile de apel și se așteaptă la o funcție. Funcția va fi trecută de obiectul pentru link-ul care a fost apăsat ca "acest" și containerul la care este vizată acea legătură. Comenzile de returnare a apelurilor sunt concepute astfel încât să permită funcționalitatea personalizată pentru utilizatorii unui plug-in. Implicit pentru aceste apeluri de apel va fi o funcție goală.
Codul minim necesar pentru utilizarea plug-in-ului ar arăta astfel:
$ ('a.form_link'). popUpForm (container: '#form_id');
Asta pare simplu, nu-i așa? Când apeși un plug-in ca acesta, codul plug-in-ului se numește cu o colecție jQuery a tuturor elementelor DOM care se potrivesc selectorului, care vor fi disponibile în variabila specială "this".
Cele mai multe plug-in-uri jQuery urmează un model foarte asemănător. Ei repetă grupul de selectori și fac tot ce fac ei. Am un "plug-in" de bază pe care de obicei lucrez și se va potrivi aici frumos. Acesta ar fi începutul fișierului dvs. plug-in, popUpForm.jquery.js.
(funcția ($) $ .fn.popUpForm = funcție (opțiuni) // Valori implicite și opțiuni var defaults = container: ", modal: true, resizeable: false, width: 440; : functie (container) , onSuccess: functie (container) , onError: functie (container) var opts = $ .extend ( // Lucrarea REAL se intampla aici. // In cadrul acestei functii 'this' se refera la un singur element // DOM din colectia jQuery (nu jQuery obj));) (jQuery);
Codul este înfășurat într-o funcție de auto-execuție și se adaugă la jQuery utilizând spațiul de nume $ .fn. Identificatorul care urmează $ .fn este numele metodei pe care o veți utiliza pentru a o invoca.
De asemenea, urmăm bune practici de codificare prin trecerea în mod explicit a variabilei jQuery. Acest lucru ne va împiedica să ne confruntăm cu probleme dacă plug-in-ul este utilizat pe o pagină cu alte cadre JavaScript, dintre care unele utilizează $ ca variabilă.
Apoi, se creează o serie de valori implicite, iar aceste valori implicite vor fi utilizate dacă nu sunt definite când se solicită pluginul. Linia care urmează imediat după matricea prestabilită îmbină opțiunile parcurse cu valorile implicite și le stochează pe toate în opta matrice.
În cele din urmă, este creată o buclă pentru iterarea peste colecția jQuery identificată de selector când se numește plug-in ... În timp ce șansele sunt, în majoritatea situațiilor, vor fi un singur element (ancora), acesta va gestiona mai multe link-uri cu un singur apel - presupunând că toate se încarcă în același format.
Un important lucru de înțeles este că valoarea variabilei speciale "this" se schimbă atunci când intrăm în buclele self.each; este o metodă specială jQuery concepută pentru a face mai ușoare colecțiile DOM. Funcția de apel invers utilizează contextul elementului DOM curent, astfel încât variabila "this" se referă la acel element din cadrul bucla.
Puteți vedea într-un exemplu foarte simplu modul în care 'this' se referă la o colecție jQuery de obiecte jQuery în domeniul funcției plug-in, dar în interiorul fiecărei buclă, 'this' se referă la un singur element non-jQuery DOM.
Codul pentru următoarele secțiuni este conținut în interiorul blocului propriu al scheletului nostru. Ce facem acum? Pentru fiecare element jQuery trecut, vor fi făcuți mai mulți pași:
Înainte de a face oricare dintre aceste lucruri, vom adăuga o singură linie de cod în cadrul callback-ului, chiar în partea de sus
var $ this = $ (acest lucru);
Aceasta este mai mult decât comoditate; variabila "aceasta" va ieși din sfera de aplicare în orice închideri din fiecare buclă și vom avea nevoie de acces la obiectul curent mai târziu. Din moment ce aproape întotdeauna o dorim ca un obiect jQuery, îl stocăm ca unul.
$ .popUpForm va funcționa numai pe etichetele ancorei, iar eticheta de ancorare trebuie să aibă o valoare href, astfel încât să știm de unde să preluăm formularul. Dacă oricare dintre aceste condiții nu este îndeplinită, vom lăsa elementul singur. A doua linie a "curajului" nostru va fi:
dacă ! $ this.is ('a') || $ this.attr ('href') == ") retur;
Unii oameni urăsc mai multe puncte de întoarcere într-o funcție, dar întotdeauna mi-am dat seama că unul de la început poate face o funcție mai ușor de citit, spre deosebire de folosirea unei condiții if (pentru a înfășura restul funcției). În mod performant, sunt identice.
Metoda $ .load are o funcționalitate plăcută care permite un apel pentru a specifica și ID-ul pentru a atașa doar o parte a unui document preluat. Scriptul nu va atașa HTML returnat direct DOM, deoarece $ .load suprascrie, nu se adaugă.
var SRC = $ acest.attr ('href') + + + opts.container; var formDOM = $ ("") .load (SRC, funcția ()
Variabila opts.container are ID-ul elementului de form pe pagina de la distanță. Al doilea rând încarcă această pagină de la distanță și atașează formularul și conținutul său la o div, a cărei totalitate este stocată în formDOM variabilă. Observați că $ .load include un apel invers (funcția) - vom folosi formaDOM în cadrul acelui callback.
În cadrul callback-ului $ .load, codul va atașa formularul, va suprascrie evenimentul de clic al ancorei și va suprascrie evenimentul de trimitere al formularului.
Formularul HTML este stocat în variabila formDOM în acest moment și atașarea acestuia la pagina existentă este ușoară.
$ ( '# PopUpHide') append (formDOM).;
ID-ul #popUpHide se referă la o div ascunsă care va fi atașată paginii de plug-in. Pentru a furniza div, se va adăuga următoarea linie în partea de sus a plug-in-ului. Dacă există deja, nu o recreăm.
$ ("# popUpHide") lungime || $ (“') .AppendTo (' organism ') css (.' Ecran“ 'none');
Acum că formularul este ascuns în siguranță pe pagina noastră, este timpul să folosiți un apel pentru metoda $. Dialog pentru a crea formularul. Cele mai multe paramuri de configurare sunt luate de la plug-in-ul nostru. Opțiunea "autoopen" este codată greu, deoarece dorim ca dialogul să se deschidă când se face clic pe link și nu când se creează dialogul.
// Crearea și memorarea dialogului $ (opts.container) .dialog (autoOpen: false, lățime: opts.width, modal: opts.modal, resizable: opts.resizeable, title: opts.title);
Dacă am fi oprit aici, plug-in-ul nu ar face prea mult. Linkul ne va duce încă la pagina următoare. Comportamentul dorit este ca linkul să deschidă dialogul.
$ this.bind ('click', functie (e) e.preventDefault (); opts.beforeOpen.call ($ this [0], opts.container); $ (opts.container) .dialog ;);
Prima linie a acestui handler pentru clicuri este foarte importantă. Aceasta oprește legătura de la încărcarea noii pagini când este apăsată.
A doua linie este apelul nostru "înainteOpen". Variabila opts.beforeOpen conține o referință a funcției - care este evidentă. Metoda .call este folosită pentru a invoca funcția într-un mod în care putem oferi context - variabila "aceasta" pentru acea funcție. Primul argument trecut devine "acest" funcției chemate.
Atunci când o funcție are acces la variabila "aceasta" există câteva contracte pe care JavaScript le are cu programatorul pe care ar trebui să-l păstrăm.
Pentru a menține acel contract, vom trece $ this [0] în loc de $ this. $ this [0] reprezintă un singur obiect DOM non-jQuery.
Pentru a vă ajuta să înțelegeți acest lucru puțin mai bine, imaginați-vă următoarea funcție de apel invers:
opts.beforeOpen = funcția (container) // Oferă valoarea linkului pe care tocmai ați făcut clic pe alertă ('Pagina de la distanță este' + this.href '); // Oferă containerul de identificare atribuit acestei alerte de legătură ('Și containerul este' + container);
Clicul de legătură nu este singurul comportament implicit de suprascris. De asemenea, dorim ca formularul să se trimită prin intermediul AJAX, astfel încât evenimentul onsumbit normal trebuie împiedicat și codificat noul comportament.
$ (opts.container) .bind ('trimite', funcția (e) e.preventDefault (); ajaxSubmit (););
Din nou, folosim preventDefault () pentru a opri evenimentul și, în acest caz, adăugați o nouă funcție pentru a gestiona transmiterea formularului. Codul ajaxSubmit () poate merge direct în callback-ul, dar a fost mutat într-o nouă funcție de citire.
Această funcție ar fi adăugată imediat după încheierea ciclului de autoeachare (nu vă faceți griji, veți vedea întregul cod plug-in într-o singură fotografie într-un pic). Aceasta ia forma, o trimite la un script de la distanță și declanșează apelurile corespunzătoare.
Primul pas este să obțineți forma ca obiect jQuery și să determinați metoda formularului, fie GET sau POST.
funcția ajaxSubmit () var form = $ (opts.container); metoda var = form.attr ("metoda") || 'OBȚINE';
Dacă vă aduceți aminte, am stocat ID-ul formularului în opts.container. Următoarea linie verifică formularul pentru o metodă și atribuie "GET" dacă nu există nicio metodă. Acest lucru este compatibil cu codul HTML care utilizează GET în mod implicit pe formulare dacă nu este specificată nici o metodă.
Utilizați metoda $ .ajax pentru a trimite formularul:
$ .ajax (tip: metoda, url: form.attr ('action'), date: form.serialize (), succes: function () $ (opts.container) .dialog ('close'); onSuccess.call ($ this [0], opts.container);, eroare: function () $ (opts.container) .dialog ('close'); opts.onError.call .container););
Opțiunea adresei URL este determinată din atributul de acțiune al etichetei de formular. Datele sunt produse utilizând metoda serialize pe obiectul jQuery care conține formularul.
Opțiunile de succes și de eroare sunt $ .axax callbacks, pe care suntem, la rândul lor, folosind pentru a apela callback-urile noastre, în același mod în care a fost invocat callback-ul înainte.
De asemenea, închidem dialogul atât pentru operatorii de succes, cât și pentru operatorii de eroare.
Ca o revizuire, să examinăm codul pe care l-am scris până acum ca un întreg, inclusiv unele comentarii de cod utile:
(funcția ($) var alog = fereastră.console? console.log: alert; $ .fn.popUpForm = funcția (opțiuni) // REQUIRE un container dacă (! options.container) alert (' ); returnare; / / Dă-ne unde să atașăm formula $ ("# popUpHide") lungime || $ ('') .AppendTo (' organism ') css (.' Ecran“ 'none'); // Valori implicite și opțiuni var defaults = container: ", modal: true, resizeable: false, width: 440, title: peerror: function (container) var opts = $ .extend (, implicit, optiuni); care functioneaza pe acest each (function () / * Vrem sa pastram valoarea 'this' disponibil pentru $ .load * callback * / var $ this = $ (this); este un link și * are o valoare href * / if (! $ this.is ('a') || $ this.attr ('href') == ") return; / * Pentru $. ), param este URL-ul urmat de * selectorul de ID pentru secțiunea paginii pentru a apuca * / var SRC = $ this.attr ('href') + "+ opts.container; / * în apelul înapoi în cazul în care formularul * nu se încarcă sau utilizatorul face clic pe link înainte de * modal este gata * / var formDOM = $ ("") .load (SRC, function () // Adăugați la pagina $ ('# popUpHide') append (formDOM); , lățime: opts.width, modal: opts.modal, resizable: opts.resizeable, title: opts.title); / * oprește trimiterea obișnuită a formularului, a trebuit să vină după crearea dialogului, altfel formularul nu există * încă să punem un handler de evenimente la * / $ (opts.container) .bind ("trimite", funcția (e) e.preventDefault (); ajaxSubmit ($ this [0]);); obligatoriu pentru link-ul transmis către plug-in $ this.bind ("click", funcția (e) e.preventDefault (); opts.beforeOpen.call ($ this [0], opts.container); .container) .dialog ('deschis');););); funcția ajaxSubmit (anchorObj) console.log (anchorObj); var forma = $ (opts.container); var method = form.attr '') $ (opts.container)) $ (opts.container)), .dialog ("închide"); opts.onSuccess.call (anchorObj, opts.container ); , eroare: funcție () opts.onError.call (anchorObj, opts.container); ); ) (jQuery);
Acest cod ar trebui salvat într-un fișier numit popUpForm.jquery.js
Primul pas în utilizarea plug-in-ului ar fi includerea tuturor dependențelor necesare pe pagina HTML. Personal prefer să folosesc Google CDN. Fișierele care se află pe un domeniu separat pot ajuta viteza de încărcare a paginii, iar serverele sunt rapide. De asemenea, crește șansele ca un vizitator să aibă deja aceste fișiere memorate în cache.
În documentul HEAD al documentului HTML, adăugați următoarele:
Fișierul principal.css este pentru stilurile noastre specifice site-ului, tot ce este altceva de la CDN-ul Google. Observați că puteți folosi chiar și temele jQuery-UI din CDN în acest mod.
Rețineți că nu vrem decât să invocăm plug-in-ul pe legături care merg către o pagină de formular. În demo-ul online, formularele sunt conținute în form.html și doar două link-uri merg către acea pagină.
Apelurile sunt înfășurate într-un bloc document.ready astfel încât să putem fi siguri că elementele de ancorare există înainte de a încerca să acționeze asupra lor. Cel de-al doilea apel, $ ('. Survey a') este un exemplu al cantității minime necesare pentru utilizarea noului plug-in. Primul exemplu stabilește un apel invers atât pentru onSuccess, cât și pe onError.
Dacă ați ajuns atât de departe și ați creat exemple de formulare și o pagină pentru a le apela, ați observa că formularul din modal este probabil, bine, urât. Modul în sine nu este rău, pentru că folosim o temă jQuery-UI. Dar forma din interiorul modalului este în cea mai mare parte nestingherită, așa că ar trebui să facem niște eforturi pentru ao face destul.
Există câteva lucruri pe care trebuie să le țineți cont atunci când creați stiluri pentru a fi utilizate într-un mod jQuery-UI:
Folosind aceste mici biți de informații putem începe să aplicăm stiluri la forma în modal. Mai întâi oferim culorilor modale culoarea de fundal cu care suntem mulțumiți și, de asemenea, modificăm fontul pentru bara de titlu.
.ui-dialog background: rgb (237,237,237); font: 11px verdana, arial, sans-serif; .ui-dialog .ui-dialog-titlubar font: small-caps bold 25px Georgia, Times, serif;
Apoi, dorim să separăm fiecare element din formular cu linii. Deoarece structura formei suprapune h3s cu divs conținând elemente de formă, adăugăm următoarele reguli:
.ui-dialogul h3, .ui-dialog div granița-sus: 1px rgb solid (247,247,247); margine de fund: 1px rgb solid (212,212,212); umplutura: 8px 0 12px 10px;
Și vrem doar linii între secțiuni, nu chiar în partea de sus sau foarte jos.
.ui-dialog .puForm div: ultimul-copil margin-bottom: nici unul; .ui-dialog .puForm h3: prim-copil border-top: nici unul;
Să nu uităm să stilim h3s-urile și elementele de formă. Butoanele radio trebuie să fie afișate în linie, astfel încât acestea să fie toate într-un rând.
.ui-dialog h3 font: 18px Georgia, Times, serif; marja: 0; . dialogul de selectare a textului,. textarea dialogului, dialogul de introducere a dialogului lățime: 76%; afișare: bloc; . dialog de intrare # rating, .ui-dialog #rating etichetă display: inline; lățime: auto;
Rețineți că aceste stiluri sunt specifice acestui proiect, va trebui să personalizați propriile formulare în funcție de structura pe care o utilizați. Pentru a direcționa în mod specific elementele de formă, puteți orienta direct descendenții dialogului .ui sau să stilizați fiecare formular individual, să includeți stiluri descendente din ID-ul de formă pe care l-ați inclus.
Forma stilată:
Deci, ce am făcut cu adevărat? Am luat o legătură normală care duce la un formular de contact (sau formulare) și a cauzat încărcarea acestui formular într-un dialog modal și trimiterea prin intermediul ajax. Pentru utilizatorii fără javascript, nu se întâmplă nimic și legăturile se comportă normal, așa că nu am împiedicat pe nimeni să completeze formularele.
Dacă dați clic pe link-ul anchetei din demo, asigurați-vă că ați trimis ceva. Voi posta rezultatele în comentariile pentru distracție după o săptămână sau cam asa ceva!