Välkommen till den andra delen av Använda ryggraden Inom WordPress Admin. I den första delen sätter vi upp "back-end" av vårt plugin och nu i den andra delen kommer vi att slutföra med att lägga till vår "client-side" eller "front end" -funktionalitet. För en översikt över vad vi bygger i denna handledning tillsammans med vår mappstruktur och -filer, var god och granska den första delen.
Inom src mapp, skapa en annan som heter mallar och en fil inuti den som heter metabox.templ.php. Det är här vi ska sätta HTML-koden som behövs för vår meta-box. Det är också ett utmärkt tillfälle att skriva ut de JSON-data som behövs för våra svar.
Dina mappar och filer ska nu se ut så här.
Låt oss ta en titt på vad vi skapar. Du kan tänka på varje svar som en Modell av data och för att vi ska använda klientsidemallar för att skapa en se för vart och ett kan den vyn reagera på förändringar inom modellen. Detta gör det möjligt för oss att vara väldigt specifika när bindande händelser till användargränssnittet och leder naturligtvis till ett enklare arbetsflöde - när du har fått huvudet runt det, det är.
Inuti vår nyskapade metabox.templ.php, Det här är den mall som vi ska använda för var och en av våra modeller. Du kan se att vi i grund och botten förpackar lite HTML i en skript tagg. Vi ger skriptet taggen attributet type = "text / mall"
så att webbläsaren inte gör det till sidan. Denna lilla bit av HTML ska användas senare för att generera markeringen som behövs för varje vy. Vi kommer att använda Underscore's inbyggda mallfunktioner så att värden inlindade så här kommer att ersättas med data i våra modeller senare.
Fortfarande inuti src / mallar / metabox.templ.php - här lägger vi bara ner behållarna som kommer att fyllas med ingångarna från mallen ovan. Detta händer efter att Backbone har analyserat de JSON-data som behövs för modellen, så nu är det allt vi behöver göra här.
Ange svaren nedan
Rätt svar:
Den sista sak som behövs inuti src / mallar / metabox.templ.php fil, är JSON-data som representerar varje svar. Här skapar vi ett objekt på Global Namnrymd och tilldelar sedan de värden som vi skickade genom med $ viewdata
array. Jag gillar också att spara referenser till behållarna vi kommer att använda senare så att jag inte har ID i två separata filer.
Okej, om du har kommit så långt har du lyckats konfigurera ditt plugin för att tillåta användningen av Backbone.js och din meta-box matar ut de nödvändiga mark-up- och JSON-data. Nu är det dags att ta med allt och använda Backbone.js för att organisera vår klientsidkod. Det är dags att täcka:
Din slutliga katalogstruktur och filer ska se ut så här.
Först och främst lägger vi allt vi gör i en omedelbar kallad funktion och skickas i jQuery för att användas med $
signera, jag kommer inte visa det här inslaget i några fler utdrag, så se till att du lägger allt under det.
/ * js / admin.js * / (funktion ($) / ** Vår kod här ** / (jQuery));
Därefter måste vi få tillgång till våra data lagrade på den globala namespace och skapa också ett nytt objekt som lagrar våra Backbone-objekt.
/ * js / admin.js * / var Quiz = Visningar: ; var wpq = window.wpQuiz;
Modellen representerar ett enda svar. Inom konstruktören gör vi ett par saker.
falsk
ajaxurl
variabel som är tillgänglig på varje admin sida. Vi lägger också till namnet på vår metod som hanterar ajaxförfrågantoJSON
Metod för att lägga till det aktuella inläggets ID för varje modell. Det här kunde ha gjorts på serversidan, men jag har lagt in det här som ett exempel på hur du kan åsidosätta det som sparas på servern (det här kan komma in mycket praktiskt varför jag har inkluderat det här)/ * js / admin.js * / Quiz.Model = Backbone.Model.extend (standardvärden: 'correct': false, url: ajaxurl + '? action = save_answer', toJSON: funktion () var attrs = _ .clone (this.attributes); attrs.post_id = wpq.post_id; return attrs;, initiera: funktion () om (this.get ('answer_id') === wpq.answers.correct) this.set ("korrekt", sant););
En samling är i grund och botten bara en omslag för ett gäng modeller och det gör arbetet med dessa modeller en bris. För vårt lilla exempel kommer vi inte att ändra samlingen, förutom att ange vilken modell den ska använda.
/ * js / admin.js * / Quiz.Collection = Ryggraden.Kollection.extend (modell: Quiz.Model);
Vår första vy kan betraktas som en omslag för de enskilda inmatningsfälten. Vi behöver inte deklarera en mall eller vilket HTML-element som vi vill ha Backbone att skapa för oss i det här fallet, eftersom vi senare skickar den här ID-filen till en div
som vi skapade i metaboxfilen. Ryggraden kommer då enkelt att använda det här elementet som behållare. Denna vy kommer att ta en samling och för varje modell i den samlingen kommer den att skapa en ny inmatning
element och lägg till det själv.
/ * js / admin.js * / Quiz.Views.Inputs = Backbone.View.extend (initiera: funktion () this.collection.each (this.addInput, this);, addInput: funktion (modell, index ) var input = ny Quiz.Views.Input (modell: modell); detta. $ el.append (input.render (). el););
Denna nästa vy representerar en enda modell. För att visa vilka typer av saker du kan göra när du kodar JavaScript på det här sättet har jag försökt att ge några olika interaktionstekniker och visa hur man reagerar på dem med ryggraden.
Observera att vi specificerar en "taggnamn
"här tillsammans med en mall. I vårt fall kommer detta att ta tag i den mallen vi tittade på tidigare, analysera den med hjälp av data från modellen och sedan pakka in allt i en p
tagg (vilket ger oss en bra marginal runt varje sida).
Observera också hur händelser är bundna till element i en vy. Mycket renare än din genomsnittliga jQuery callback och vad som är ännu bättre är möjligheten att använda en jQuery-väljare som denna detta. $ (input)
inom våra synpunkter att veta att de automatiskt scoped i vyn. Det betyder att jQuery inte tittar på hela DOM när man försöker matcha en väljare.
I den här vyn kan vi:
/ * js / admin.js * / Quiz.Views.Input = Backbone.View.extend (tagName: 'p', // Hämta mallen från DOM-mallen: _. mall ($ (wpq.inputTempl) .html ()), // När en modell är sparad, returnera knappen till inaktiverat tillstånd initiera: funktionen () var _this = this; this.model.on ("sync", funktionen () _this. $ (' ') .text (' Save ') .attr (' disabled ', true););, // Bifoga händelser händelser: ' keyup input ': "oskärpa", "oskärpa input": "oskärpa" klicka på knappen ':' spara ', // Utför Spara spara: funktionen (e) e.preventDefault (); $ (e.target) .text (' wait '); this.model.save (); , // Uppdatera modellattributen med data från inmatningsfältet blur: funktion () var input = this. $ ('Input') .val (); om (input! == this.model.get ('answer' )) this.model.set ('answer', input); detta. $ ('knapp'). attr ('inaktiverat', false);, // Render den enkla ingången - inkludera ett index. funktion () this.model.set ('index', this.model.collection.indexOf (this.model) + 1); this. $ el.html (this.template (this.model.toJSON ())); returnera detta; );
Det här valet är där användaren kan välja rätt svar. När den här vyn i instansieras kommer den att få samma samling av modeller som insatsens omslag gjorde. Detta kommer att vara till nytta senare eftersom vi kan lyssna på förändringar i modellen i inmatningsfälten och automatiskt uppdatera motsvarande värden inom detta väljningselement.
/ * js / admin.js * / Quiz.Views.Select = Backbone.View.extend (initiera: funktion () this.collection.each (this.addOption, this); addOption: funktion (modell) var option = new Quiz.Views.Option (modell: modell); detta. $ el.append (option.render (). el););
Vår sista vy kommer att skapa ett alternativ för varje modell och läggas till i väljningselementet ovan. Den här gången har jag visat hur du dynamiskt kan ange attribut på elementet genom att returnera en hash från en återuppringningsfunktion tilldelad egenskapen attribut. Observera också att i initialisera ()
metod vi har "prenumererat" på att ändra händelser på modellen (specifikt, svar
attribut). Detta innebär i princip bara: när som helst denna modell är svar attributet har ändrats, ringa till göra()
metod (som i detta fall kommer bara att uppdatera texten). Detta begrepp att "prenumerera" eller "lyssna" på händelser som förekommer inom en modell är verkligen vad som gör Backbone.js och de många andra biblioteken som det så kraftfulla, användbara och glädje att arbeta med.
/ * js / admin.js * / Quiz.Views.Option = Backbone.View.extend (tagName: 'option', // returnerar en hash låter oss ange attribut dynamiska attribut: funktion () return 'value' : this.model.get ('answer_id'), 'selected': this.model.get ('correct'), // Se efter ändringar av varje modell (som händer i inmatningsfälten och återställ då är en ändring initialisera: funktion () this.model.on ('change: answer', this.render, this); render: function () this. $ el.text (this.model.get (' svara ")); returnera detta;);
Vi är så nära nu, allt vi behöver göra är att omedelbargöra en ny samling och skicka den till JSON den behöver, så instansera både "wrapper" -vyer för väljelementet och för ingångarna. Observera att vi också passerar el
egendom till våra synpunkter. Dessa är hänvisningar till div och väljelementet som vi lämnade tomma tidigare i metaboxen.
/ * js / admin.js * / var answers = new Quiz.Collection (wpq.answers); var selectElem = ny Quiz.Views.Select (collection: answers, el: wpq.answerSelect); var inputs = nya Quiz.Views.Inputs (samling: svar, el: wpq.answerInput);
Om du har gjort det till slutet, borde du nu ha ett fullt fungerande exempel på hur man införlivar Backbone JS i ett WordPress-plugin. Om du fortsätter och tittar på källfilerna märker du att den faktiska mängd kod som behövs för att integrera ryggraden är relativt liten. Mycket av koden som vi gick här var PHP som behövs för plugin. Att jobba med ryggraden dagligen under de senaste 6 veckorna har verkligen gett mig en ny funnit respekt för front-end-kodorganisationen och jag hoppas att du kan uppskatta de fördelar som säkert kommer att komma ifrån att arbeta på detta sätt.
Inom WordPress-samhället kan jag tänka på några av de mer komplexa och högkvalitativa pluginsna där ute, och dra fördel av att använda Backbone och jag är hedrad att ha kunnat dela med dig en teknik för att göra exakt det.