Backbone gebruiken binnen de WordPress Admin The Front End

Welkom bij het tweede deel van Using Backbone Within the WordPress Admin. In het eerste deel hebben we de 'back-end' van onze plug-in opgezet en nu zullen we in het tweede deel afronden door onze 'client-side' of 'front-end' functionaliteit toe te voegen. Zie het eerste deel voor een overzicht van wat we in deze zelfstudie samen met onze mappenstructuur en bestanden bouwen.


1. Maak het sjabloonbestand

Binnen de src map, maak een andere aangemaakt templates en een bestand binnen dat genoemd metabox.templ.php. Hier plaatsen we de HTML die nodig is voor onze metabox. Het is ook een geweldige kans om de JSON-gegevens uit te voeren die nodig zijn voor onze antwoorden.

Uw mappen en bestanden zouden er nu als volgt uit moeten zien.

Maak de sjabloon voor één antwoord

Laten we nog een keer kijken naar wat we aan het creëren zijn. Je kunt elk antwoord zien als een Model van gegevens en omdat we client-side sjablonen zullen gebruiken om een ​​te genereren uitzicht voor elk daarvan kan die weergave reageren op veranderingen binnen het model. Dit stelt ons in staat om heel specifiek te zijn bij het binden van evenementen aan de gebruikersinterface en leidt op natuurlijke wijze tot een eenvoudiger workflow - als je eenmaal je hoofd eromheen hebt, dat is.

In onze nieuw gecreëerde metabox.templ.php, dit is de sjabloon die we zullen gebruiken voor elk van onze modellen. U kunt zien dat we in feite wat HTML in een script-tag inpakken. We geven het script het kenmerk tag type = "text / template" zodat de browser deze niet naar de pagina leidt. Deze kleine brok HTML moet later worden gebruikt om de markup te genereren die nodig is voor elke weergave. We zullen de ingebouwde template-mogelijkheden van Underscore gebruiken, zodat de waarden op deze manier worden ingepakt worden later door gegevens in onze modellen vervangen.

    

Base HTML

Nog steeds binnen van src / templates / metabox.templ.php - hier leggen we alleen de containers neer die worden gevuld met de invoer van de sjabloon hierboven. Dit gebeurt nadat Backbone de JSON-gegevens die nodig zijn voor het model heeft geparseerd, dus voor nu is dit alles wat we hier moeten doen.

  

Voer de antwoorden hieronder in

Goed antwoord:

Voer de JSON uit

Het laatste ding dat nodig is in de src / templates / metabox.templ.php bestand, zijn de JSON-gegevens die elk antwoord vertegenwoordigen. Hier maken we een object op de Global Namespace en vervolgens wijzen we de waarden toe die we hebben doorgestuurd met de $ Viewdata matrix. Ik wil ook graag verwijzingen opslaan naar de containers die we later zullen gebruiken, zodat ik geen ID's in twee afzonderlijke bestanden heb.

  

2. Het JavaScript

Ok, als je zover bent gekomen, heb je met succes je plug-in ingesteld om het gebruik van Backbone.js mogelijk te maken en je metabox voert de vereiste mark-up en JSON-gegevens uit. Nu is het tijd om alles samen te brengen en Backbone.js te gebruiken om onze client-side code te organiseren. Het is tijd om te bespreken:

  1. Een verzameling modellen maken op basis van de JSON-gegevens
  2. Sjablonen voor de client gebruiken om een ​​weergave voor elk te maken
  3. Kijken naar klikken, toets omhoog en vervagen gebeurtenissen binnen elke weergave
  4. Een model terug opslaan in de database

Maak het bestand admin.js en plaats het in de js Map

Uw definitieve mapstructuur en bestanden moeten er als volgt uitzien.

Allereerst zullen we alles wat we doen in een onmiddellijk opgevraagde functie verpakken en in jQuery doorgeven om gebruikt te worden met de $ teken, ik zal deze wrapper niet in andere fragmenten weergeven, dus zorg ervoor dat je alles eronder erin legt.

 / * js / admin.js * / (function ($) / ** Onze code hier ** / (jQuery));

Vervolgens moeten we toegang krijgen tot onze gegevens die zijn opgeslagen in de globale naamruimte en ook een nieuw object maken waarin onze Backbone-objecten worden opgeslagen.

 / * js / admin.js * / var Quiz = Bekeken: ; var wpq = window.wpQuiz;

Het model

Het model vertegenwoordigt een enkel antwoord. Binnen de constructor doen we een paar dingen.

  1. Een standaardwaarde instellen voor correct als vals
  2. De URL instellen die Backbone nodig heeft om het model terug in de database op te slaan. We hebben toegang tot de juiste URL dankzij WordPress die de ajaxurl variabele die beschikbaar is op elke beheerderspagina. We voegen ook de naam toe van onze methode die het ajax-verzoek afhandelt
  3. Vervolgens overschrijven we de toJSON methode om de ID van het huidige bericht aan elk model toe te voegen. Dit had op de server gedaan kunnen worden, maar ik heb het hier weergegeven als een voorbeeld van hoe je kunt overschrijven wat is opgeslagen op de server (dit kan binnenkomen heel handig, daarom heb ik het hier toegevoegd)
  4. Tot slot controleren we in de initialisatiemethode of het huidige model het juiste antwoord is door de ID te vergelijken met de ID van het juiste antwoord. We doen dit zodat we later weten welk antwoord standaard moet worden geselecteerd
 / * js / admin.js * / Quiz.Model = Backbone.Model.extend (default: 'correct': false, url: ajaxurl + '? action = save_answer', toJSON: function () var attrs = _ .clone (this.attributes); attrs.post_id = wpq.post_id; return attrs;, initialize: function () if (this.get ('answer_id') === wpq.answers.correct) this.set ('correct', waar););

De verzameling

Een collectie is in wezen slechts een verpakking voor een aantal modellen en het maakt het werken met die modellen een fluitje van een cent. Voor ons kleine voorbeeld zullen we de verzameling niet wijzigen, behalve dat we specificeren welk model hij moet gebruiken.

 / * js / admin.js * / Quiz.Collection = Backbone.Collection.extend (model: Quiz.Model);

De invoerwikkelaar

Ons eerste beeld kan worden beschouwd als een dekblad voor de afzonderlijke invoervelden. We hoeven in dit geval geen sjabloon te declareren of welk HTML-element we willen dat Backbone voor ons maakt, omdat we later deze ID doorgeven aan de ID van een div die we hebben gemaakt in het metaboxbestand. Backbone gebruikt dat element dan gewoon als container. Voor deze weergave is een verzameling nodig en voor elk model in die verzameling wordt een nieuwe gemaakt invoer element en voeg het toe aan zichzelf.

 / * js / admin.js * / Quiz.Views.Inputs = Backbone.View.extend (initialize: function () this.collection.each (this.addInput, this);, addInput: function (model, index ) var input = new Quiz.Views.Input (model: model); this. $ el.append (input.render (). el););

Een enkele ingang

Deze volgende weergave vertegenwoordigt een enkel model. In het belang van het laten zien van de dingen die je kunt doen als je JavaScript op deze manier codeert, heb ik geprobeerd een paar verschillende interactietechnieken te bieden en laat ik zien hoe ik kan reageren op mensen met Backbone.

Merk op dat we een 'tagName'hier samen met een sjabloon. In ons geval gaat dit de sjabloon pakken die we eerder hebben bekeken, deze hebben geparseerd met behulp van gegevens uit het model en vervolgens alles in een p tag (die ons een aardig beetje marge geeft rondom elke tag).

Merk ook op hoe gebeurtenissen gebonden zijn aan elementen binnen een weergave. Veel schoner dan je gemiddelde jQuery-callback en wat nog beter is, is de mogelijkheid om een ​​jQuery-selector als deze te gebruiken dit. $ ( 'input') binnen onze standpunten wetende dat ze automatisch binnen het gezichtsveld vallen. Dit betekent dat jQuery niet naar de hele DOM kijkt wanneer hij een selector probeert te matchen.

In deze weergave kunnen we:

  1. Weet wanneer een invoerveld is gewijzigd
  2. Werk het gekoppelde model automatisch bij (dit wordt gebruikt om het selectieveld eronder automatisch bij te werken)
  3. Schakel de opslagknop aan de zijkant van de invoer in die is gewijzigd
  4. Voer het opslaan terug naar de database uit
 / * js / admin.js * / Quiz.Views.Input = Backbone.View.extend (tagName: 'p', // Haal de sjabloon op uit de DOM-sjabloon: _. template ($ (wpq.inputTempl) .html ()), // Wanneer een model is opgeslagen, zet u de knop terug naar de uitgeschakelde toestand initialize: function () var _this = this; this.model.on ('sync', function () _this. $ ('Knop ') .text (' Opslaan ') .attr (' disabled ', true););, // Voeg events toe: ' keyup input ':' blur ',' blur input ':' blur ',' klik knop ':' save ', // Voer de Save save: functie (e) e.preventDefault (); $ (e.target) .text (' wait '); this.model.save (); , // Werk de modelattributen bij met gegevens uit het vervaagde invoerveld: function () var input = this. $ ('Input'). Val (); if (input! == this.model.get ('answer') )) this.model.set ('answer', input); this. $ ('button'). attr ('disabled', false);, // Render de enkele invoer - voeg een index toe. render: function () this.model.set ('index', this.model.collection.indexOf (this.model) + 1); this. $ el.html (this.template (this.model.toJSON ())); geef dit terug; );

Het Selecteer Element

Dit select element is waar de gebruiker het juiste antwoord kan kiezen. Wanneer deze weergave wordt geïnstantieerd, ontvangt deze dezelfde verzameling modellen als de wrapper van de invoer. Dit zal later van pas komen, omdat we in de invoervelden kunnen luisteren naar wijzigingen in het model en de corresponderende waarden binnen dit geselecteerde element automatisch kunnen bijwerken.

 / * js / admin.js * / Quiz.Views.Select = Backbone.View.extend (initialize: function () this.collection.each (this.addOption, this);, addOption: function (model)  var option = new Quiz.Views.Option (model: model); this. $ el.append (option.render (). el););

Een enkele optieweergave

Onze laatste weergave creëert een optie-element voor elk model en wordt toegevoegd aan het geselecteerde element hierboven. Deze keer heb ik laten zien hoe je dynamisch attributen op het element kunt instellen door een hash te retourneren uit een callback-functie die is toegewezen aan de eigenschap attributes. Merk ook op dat in de initialiseren () methode die we hebben 'geabonneerd' om gebeurtenissen in het model te wijzigen (met name de antwoord attribuut). Dit betekent in feite gewoon: elke keer dat dit model is antwoord attribuut is gewijzigd, bel het render () methode (die in dit geval alleen de tekst zal bijwerken). Dit concept van 'subscribing' of 'listening' naar gebeurtenissen die zich binnen een model voordoen, is echt wat Backbone.js en de vele andere bibliotheken zo leuk maken, nuttig en een plezier om mee te werken.

 / * js / admin.js * / Quiz.Views.Option = Backbone.View.extend (tagName: 'option', // een hash retourneren stelt ons in staat attributen dynamisch in te stellen: function () return 'value' : this.model.get ('answer_id'), 'selected': this.model.get ('correct'), // Let op wijzigingen in elk model (dat gebeurt in de invoervelden en wordt opnieuw gerenderd wanneer er is een change-initialize: function () this.model.on ('change: answer', this.render, this);, render: function () this. $ el.text (this.model.get (' antwoord ')); retourneer dit;);

Instantiëren verzameling en weergaven

We zijn nu zo dichtbij, het enige wat we moeten doen is een nieuwe verzameling instantiëren en deze doorgeven aan de JSON die het nodig heeft, dan een instantiëren van beide 'wrapper'-views voor het geselecteerde element en voor de inputs. Merk op dat we ook de el eigendom van onze opvattingen. Dit zijn verwijzingen naar het div- en select-element dat we eerder in de metabox blanco hebben gelaten.

 / * js / admin.js * / var answers = new Quiz.Collection (wpq.answers); var selectElem = nieuwe Quiz.Views.Select (collection: answers, el: wpq.answerSelect); var inputs = new Quiz.Views.Inputs (collection: answers, el: wpq.answerInput);

3. Activeer de plug-in

Als je het tot het einde hebt gehaald, zou je nu een volledig werkend voorbeeld moeten hebben van hoe je Backbone JS kunt integreren in een WordPress-plug-in. Als je doorgaat en de bronbestanden bekijkt, zul je merken dat de werkelijke hoeveelheid code die nodig is om Backbone te integreren relatief klein is. Veel van de code die we hier bezochten was de PHP die nodig was voor de plug-in. Het werken met Backbone op dagelijkse basis gedurende de laatste 6 weken heeft me echt een nieuw gevonden respect voor de organisatie van de front end code gegeven en ik hoop dat je de voordelen zult waarderen die zeker zullen voortvloeien uit het werken op deze manier.

Binnen de WordPress-community kan ik me een aantal van de meer complexe en hoogwaardige plug-ins voorstellen die echt profiteren van het gebruik van Backbone en ik ben vereerd dat ik een techniek heb kunnen delen om precies dat te doen.