développer en javascript une extension de a a z
TRANSCRIPT
DÉVELOPPER ENJAVASCRIPT :
UNE EXTENSION DE A À ZWORDCAMP PARIS 2015
QUI SUIS-JE ?Développeur PHP et JavaScriptDéveloppeur avec WordPress depuis 5 ansDéveloppeur à @bea_api
ÉVOLUTION DUJAVASCRIPT
ÉVOLUTION DEWORDPRESS
LES OUTILS
COMMENT LES UTILISER ?Automatisation
NodeJS
NPM
Gulp ou Grunt
Plugins, JSHint, Sourcemap, Concat, Minify...
LES SOLUTIONS DANSWORDPRESS
Backbone
Underscore
Modèles, vues, collections, routes, async, sync etc.
Deux plugins
LE PETIT PLUGINACF
Enfin juste l'admin
simplifiée
STRUCTURE DE L'APPStructure de base en PHP
Ajouter la page admin
Gestion de l'enregistrement
<! Create a header in the default WordPress 'wrap' container ><div class="wrap"> <!?php // Get the current screen $screen = get_current_screen();
settings_errors( 'wcacf' ); ?> <h2><!?php echo get_admin_page_title() ?></h2> <form method="POST" id="wcacfedit" action="<?php echo admin_url( 'adminpost.php' ); ?>" <div class="wc_acf_fields widefat postbox"> <div class="no_fields_message">Aucun champs. Cliquez sur le bouton <div class="fields"></div> <div class="wc_acf_add_wrapper"> <!?php submit_button( 'Ajouter +', 'primary', 'add_field', false, array( 'id' => </div> </div> <!?php wp_nonce_field( 'wcacfedit' ); ?> <!?php submit_button(); ?> <input type="hidden" name="wc_acf_save_fields" value="1"> <input type="hidden" name="redirect_to" value="<?php echo add_query_arg( array( 'page' => self::$page_slug ), admin_url( $screen>parent_file ) ); ?>" <input type="hidden" name="action" value="wc_acf_save"> </form></div><! /.wrap >
STRUCTURE DE L'APPStructure pour le reste
METTRE EN PLACE L'ENVIRONNEMENTpackage.json
"name": "wcacf", "version": "1.0.0", "description": "WC ACF", "author": "Nicolas Juen", "devDependencies": "gulp": "^3.8.1", "gulpconcatsourcemap": "~1.3.1", "gulpcssmin": "^0.1.6", "gulpjshint": "~1.9.0", "gulploadplugins": "^0.5.2", "gulprename": "^1.2.0", "gulpuglify": "~0.2.1", "gulpwatch": "~0.6.8", "matchdep": "*"
npm install --save-dev gulp-rename
NPM INSTALLattendre...
attendre...
Fini !
Enfin tout va dépendre de votre connexion internet ;)
GULPGestionnaire de tâches
Deux tâches
L'importance de watch
GULPgulp.task('dev', function () return gulp.src([ 'assets/js/src/main.js', 'assets/js/src/tools.js', 'assets/js/src/vendor/*.js', 'assets/js/src/tools/*.js', 'assets/js/src/views/*.js', 'assets/js/src/models/*.js', 'assets/js/src/routers/*.js', 'assets/js/src/controllers/*.js', 'assets/js/src/init.js' ]) .pipe(plugins.jshint()) .pipe(concat('app.js', sourceRoot : '../../' )) .pipe(gulp.dest('assets/js/')););
WATCH !"On me dit de carreler, je carrèle, on me
dit de pas carreler j’carrèle pas."// On default task, just compile on demandgulp.task('default', function() gulp.watch('/assets/js/*.js', [ 'dev' ]););
LE MODÈLE/** * Field model */'use strict';fr.wc_acf.models.Field = Backbone.Model.extend( defaults: type : 'text', title : '', name : '', settings : '', description : '' );
Get
Set
...
LES VUESGestion de ses petites affaires
template
el
$el
this
3 VUESPrincipale
Champs
Paramètres
VUE PRINCIPALEEvents
Affichage (render)events : 'click #wc_acf_add_field' : 'add' ,
VUE PRINCIPALEappend_item : function( data ) 'use strict';
var self = this, model = new fr.wc_acf.models.Field( data ), item_view = new fr.wc_acf.views.Field( model : model ); self.counter++; var rendered = item_view.render( ).$el;
self.$el.find( '.wc_acf_fields .fields' ).append( rendered );
rendered.find( 'input:first').focus();
// Update the fields this.on_empty_fields(); ,
VUE CHAMPSEvents
Affichage (render)events : 'click .wc_acf_delete' : 'delete', 'change .wc_acf_type' : 'change_type', 'keyup .wc_acf_title' : 'update_title', 'keyup .wc_acf_name' : 'update_name', 'blur .wc_acf_title' : 'clear_name', 'keyup .wc_acf_description' : 'update_description', 'keyup .wc_acf_settings' : 'update_settings' ,
LE RENDU D'UNE VUErender : function() this.settings = new fr.wc_acf.views.Settings( model : this.model );
this.$el.html( this.template( id : this.model.get('id'), type : this.model.get( 'type' ), title : this.model.get( 'title' ), name : this.model.get( 'name' ), settings : this.model.get( 'settings' ), description : this.model.get( 'description' ), html_field: this.settings.render().$el.html() ) );
this.stickit();
return this; ,
VUE CHAMPSdata-binding : Stick.it
Lier le modèle et la vuebindings: '.wc_acf_title_label .title': observe: 'title', onGet: function(title) return title || 'Nouveau champ'; , '.wc_acf_name': attributes: [ name: 'value', observe: 'name' ] ,
VUE SETTINGSGère un template optionnel
C'est la vue du champs qui va gérer ce champssupplémentaire
RENDRE LES DONNÉESENREGISTRÉES
fr.wc_acf.main_view = new fr.wc_acf.views.Main();
// Fill the viewif( !_.isUndefined( wc_acf_vars.fields_data ) ) _.each( wc_acf_vars.fields_data , function(field) fr.wc_acf.main_view.append_item(field); );
FAIRE COMMUNIQUERTOUT LE MONDE
jQuery.trigger
Mediator
Publish
Subscribe
SubscribeOnce
PARTOUT DANS LE CODEsubscriptions: 'field:remove': 'field_remove' ,
Backbone.Mediator.publish( 'field:remove' );
LES TEMPLATES TAGUNDERSCORE
Afficher les variables, executer du Javascript<%= variable %>
Memoize les templateswp-includes/js/wp-util.js L17
wp.template = _.memoize(function ( id ) var compiled, /* * Underscore's default ERBstyle templates are incompatible with PHP * when asp_tags is enabled, so WordPress uses Mustacheinspired templating syntax. * * @see trac ticket #22344. */ options = evaluate: /<#([\s\S]+?)#>/g, interpolate: /\\\([\s\S]+?)\\\/g, escape: /\\([^\]+?)\\(?!\)/g, variable: 'data' ;
return function ( data ) compiled = compiled || _.template( $( '#tmpl' + id ).html(), null, options ); return compiled( data );;
LE CODEhttps://github.com/Rahe/wc-acf
ou
http://goo.gl/kKjfuZ
CONCLUSION
- - - WordCamp Paris 2015Nicolas JUEN @Raherian @be_api
ET VOUS ?Merci