Archives de
Étiquette : javascript

Un plugin Gutenberg pour ajouter une carte Google statique

Un plugin Gutenberg pour ajouter une carte Google statique

Gutenberg est le nouvel éditeur de WordPress, il est dans le même type que celui de Medium. Tout est bloc, texte, image, galerie, titre, liste. J’ai voulu voir comment rajouter un nouveau bloc. Il est basé sur React, c’est donc du JavaScript.

La première partie du plugin est un fichier PHP afin de charger notre fichier JavaScript:

function dayo_gutenberg_map_enqueue_block_editor_assets() {
	wp_enqueue_script(
		'dayo_gutenberg_map',
		plugins_url( 'block.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element' )
	);
}

add_action( 'enqueue_block_editor_assets', 'dayo_gutenberg_map_enqueue_block_editor_assets' );

La partie JavaScript fessant dans les 100 lignes, je vais la décomposer pour bien l’expliquer.

Dans la première partie nous déclarons des variables afin d’alléger la suite du code. La première ligne fait référence a une fonction de React. Comme vous pouvez le voir, nous utilisons wp.element et wp.blocks que nous avions déclaré en dépendance dans le script PHP.

var el = wp.element.createElement,
  registerBlockType = wp.blocks.registerBlockType,
  InspectorControls = wp.blocks.InspectorControls,
  TextControl = wp.blocks.InspectorControls.TextControl,
  SelectControl = wp.blocks.InspectorControls.SelectControl,
  RangeControl = wp.blocks.InspectorControls.RangeControl,
  google_api_key = 'YOUR_GOOGLE_API_KEY_HERE';

const linkOptions = [
  {value: 'roadmap', label: 'roadmap'},
  {value: 'satellite', label: 'satellite'},
  {value: 'hybrid', label: 'hybrid'},
  {value: 'terrain', label: 'terrain'},
];

L’étape suivante est de déclarer notre nouveau bloc. Nous utilisons la fonction registerBlockType que nous avons déclaré au dessus.

Le premier argument est le nom de notre bloc, il faut qu’il soit sous la forme « vendeur/nom-du-bloc ».

Le deuxième argument est un objet. Dans un premier temps nous lui donnons un titre, une icône (peut être une icône Dashicons), une catégorie (common, formatting, layout, widgets, embed) et des attributs (ce sont des informations persisté en base qui servent à l’affichage).

registerBlockType('dayo/gutenberg-map', {
  title: 'Google Map Static',

  icon: 'location',

  category: 'layout',

  attributes: {
    location: {type: 'string', default: 'Brooklyn+Bridge,New+York,NY'},
    mapType: {type: 'string', default: 'roadmap'},
    zoom: {type: 'int', default: 13}
  },

Ce qui donnera:

Toujours dans le deuxième paramètre nous définissons une fonctions save , sa valeur de retour est le code HTML qui sera visible coté utilisateur.

Dans notre cas nous récupérons les trois valeurs que nous avons déclaré dans les attributs, puis nous créons une image avec ces valeurs. Une classe CSS est automatiquement créé pour notre bloque, nous l’ajoutons avec className: props.className .

save: function (props) {
    var location = props.attributes.location,
      mapType = props.attributes.mapType,
      zoom = props.attributes.zoom;

    return el('img', {
      className: props.className,
      src: 'https://maps.googleapis.com/maps/api/staticmap?center=' + location + '&zoom=' + zoom + '&size=600x300&maptype=' + mapType + '&key='+google_api_key
    });
  },

Le gros morceau arrive, la partie de l’éditeur. Elle consiste en une fonction edit , sa valeur de retour est un tableau qui contient ce qui seras affiché, mais aussi d’autre informations tels que la barre d’outils et des informations l’inspecteur (la partie à droite de Gutenberg).

Dans un premier temps nous récupérons les valeurs des attributs ou nous les initialisons et nous récupérons le focus. Ensuite viennent trois fonctions pour mettre à jour nos attribut, il faut bien utiliser la fonction props.setAttributes()  pour que les changements soit visible a l’écran.

edit: function (props) {
    var location = props.attributes.location || 'Brooklyn+Bridge,New+York,NY',
      mapType = props.attributes.mapType || 'roadmap',
      zoom = props.attributes.zoom || 13,
      focus = props.focus;

    function onBlurType(mapType) {
      props.setAttributes({mapType: mapType});
    }

    function onChangeZoom(zoom) {
      props.setAttributes({zoom: zoom});
    }

    function onChangeLocation(loc) {
      props.setAttributes({location: loc});
    }

Viens ensuite la valeur de retour.

Le premier élément est ce qui doit être affiché dans l’éditeur, vous remarquerez que c’est la même chose que le retour de la fonction save , nous voulons afficher la carte.

Le deuxième élément commence par !!focus  afin de n’afficher la suite que si nous avons sélectionné notre bloc. Nous définissons ici la partie inspection avec un titre et trois éléments de contrôle, rien de bien compliqué ici.

return [
      el('img', {
        className: props.className,
        src: 'https://maps.googleapis.com/maps/api/staticmap?center=' + location + '&zoom=' + zoom + '&size=600x300&maptype=' + mapType + '&key='+google_api_key
      }),
      !!focus && el(
        InspectorControls,
        {key: 'inspector'},
        el('h3', null, 'Map Settings'),
        el(
          SelectControl,
          {
            label: 'Map Type',
            select: mapType,
            onBlur: onBlurType,
            options: linkOptions
          }
        ),
        el(
          TextControl,
          {
            label: 'Location Name',
            value: location,
            onChange: onChangeLocation
          }
        ),
        el(
          RangeControl,
          {
            label: 'Zoom Level',
            value: zoom,
            onChange: onChangeZoom,
            min: '1',
            max: '20'
          }
        )
      )
      ,
    ];

Voici a quoi ressemble l’interface d’édition:

Une documentation est accessible sur ce site ainsi que sur le Github du projet.

Ajouter une option dans WordPress puis la récupérer avec l’API REST

Ajouter une option dans WordPress puis la récupérer avec l’API REST

Dans cette article nous verrons comment ajouter une option dans les réglages de WordPress, puis comment la récupérer avec une route REST personnalisé.

La première étape est donc d’ajouter une nouvelle option dans l’onglet Général:

add_action( 'admin_init',
	function () {
		add_settings_field(
			'dayo_map_key',
			'Google Map Static API Key',
			function () {
				echo '<input name="dayo_map_key" id="dayo_map_key" type="text" value="' . get_option( 'dayo_map_key' ) . '" class="code" />';
			},
			'general'
		);

		register_setting( 'general', 'dayo_map_key' );
	} );

Ce qui donnera :

L’étape suivante est d’ajouter une route personnalisé a l’API REST de WordPress:

add_action( 'rest_api_init',
	function () {
		register_rest_route( 'dayo/v1',
			'/map/key',
			array(
				'methods'  => 'GET',
				'callback' => function () {
					get_option( 'dayo_map_key' );
				},
			) );
	} );

La route sera donc « dayo/v1/map/key » et renverra la valeur de l’option « dayo_map_key ».

La dernière partie de code PHP est celle qui fournira au JavaScript les informations pour la requête :

add_action( 'enqueue_block_editor_assets',
	function () {
		wp_localize_script( 'dayo_gutenberg_map',
			'DAYO',
			array(
				'api' => array(
					'url'   => esc_url_raw( rest_url( 'dayo/v1/map/key' ) ),
					'nonce' => wp_create_nonce( 'wp_rest' ),
				),
			) );
	} );

Dans le code JavaScript, nous utilisons la variable DAYO que nous avons fournit en PHP afin d’effectuer une requête

jQuery(function ($) {

  $.ajax({
    method: 'GET',
    url: DAYO.api.url,
    beforeSend: function (xhr) {
      xhr.setRequestHeader('X-WP-Nonce', DAYO.api.nonce);
    }
  }).then(function (r) {
    console.log(r)
  })

});

Et voila comment ajouter une option dans les réglages de WordPress et la récupérer avec l’API REST.

Vue.js partie 2

Vue.js partie 2

Allons un peu plus loin en ajoutant un formulaire et une collection de livre.

Commençons par Vue.js. Pour ajouter un livre à une collection, il nous faut donc une collection de livre, un tableau feras l’affaire:

data: {
        livre: {nom: '', commentaire: '', lu: ''},
        livres: []
    }

Afin de commencer avec de livre, nous utilisons la fonction suivante qui est appelé lors de l’instanciation de Vue.js:

ready: function() {
    var livres = [
        { nom: 'Fondation', commentaire: 'Un bon livre de SF', lu: '12-03-2016'}
    ];
    this.$set('livres', livres);
}

Il nous reste une dernière chose a faire en Javascript, l’ajout d’un nouveau livre lors de l’envoie du formulaire. pour cela nous définissons une fonction qui vérifie que le livre que l’on veux ajouter à bien un nom, puis nous l’ajoutons a notre tableau et enfin réinitialisons le formulaire:

methods: {
    ajouterLivre: function() {
        if(this.livre.nom) {
            this.livres.push(this.livre);
            this.livre = {nom: '', commentaire: '', lu: ''};
        }
    }
}

Passons maintenant que html. De côté là, la première chose et d’ajouter un bouton qui va faire appelle a notre fonction Javascript:

<button v-on:click="ajouterLivre">Ajouter</button>

La syntaxe v-on:click= »ajouterLivre »  permet de dire à Vue.js d’invoquer la fonction ajouterLivre lors de l’événement click.

Dernière étape, afficher notre collection de livres. Pour cela nous allons itéré sur notre tableau et afficher chacun de livres en utilisant v-for  :

<div v-for="livre in livres">
    <h2>{{ livre.nom }}</h2>
    <p>{{ livre.commentaire }}</p>
    <p>{{ livre.lu }}</p>
</div>

Et voila, avec un peu de css vous pouvez voir ça ici.

 

Vue.js – partie 1

Vue.js – partie 1

Pour commencer à découvrir Vue.js, voyons avec un exemple simple comment fonctionne le Twoway Binding.

Le code suivant permet de bien comprendre le Two-way Binding en action:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue.js Lumen</title>
</head>
<body>

<div id="livres">
    <h1>Ajouter un livre</h1>
    <input v-model="livre.nom"><br />
    <textarea v-model="livre.commentaire"></textarea><br />
    <input v-model="livre.lu"><br /><br />

    <h2>{{ livre.nom }}</h2>
    <p>{{ livre.commentaire }}</p>
    <p>{{ livre.lu }}</p>
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/1.0.17/vue.js"></script>
<script>
    new Vue({
        // Sélecteur pour notre application Vue.js
        el: '#livres',

        // Nos données serons stocké ici
        data: {
            livre: {nom: '', commentaire: '', lu: ''}
        }
    });
</script>
</body>
</html>

Commençons par le javascript, nous instancions Vue.js avec deux options:

  • el: ‘#livres’, fournit a Vue.js sa zone de travail dans le DOM
  • data: { livre: {nom:  », commentaire:  », lu:  »} } décrit les données qui serons accessible par Vue.js dans sa zone de travail

Pour la partie html du code, deux élément aussi:

  • v-model cet attribue permet à Vue.js de faire le lien avec le modèle décris plus haut
  • la syntaxe {{livre.nom}} permet d’afficher la valeur stocké par Vue.js pour cette variable.

Pour voir ce code en action: c’est par ici.

Mes débuts avec Ember.js 1 [FR]

Mes débuts avec Ember.js 1 [FR]

Voulant m’essayer au framework JavaScript pour des Single Page Application j’ai cherché sur internet ce qu’il se fessait et mon choix c’est arrêté sur Ember.js.

Pour commencer il faut créer la base l’application:

  • Télécharger les dépendances, jQuery, Handlebars, Ember.js et Ember Data.
  • Créer un fichier html
  • Ajouter les feuilles de styles

Le code de base est disponible dans un de mes dépôts github sous le tag 0.1.

Dans un premier temps, nous allons créer notre application :

App = Ember.Application.create();

Puis notre modèle de donnée :

App.Race = DS.Model.extend({
    name: DS.attr('string'),
    avatar: DS.attr('string'),
    description: DS.attr('string')
});

Puis nous définissons le data store utilisé :

App.Store = DS.Store.extend({
    revision: 13,
    adapter: 'DS.FixtureAdapter'
});

Dans notre cas nous utilisons la version 13 de l’api et l’adaptateur DS.FixtureAdapter.

Nous déclarons enfin nos fixtures :

App.Race.FIXTURES = [
    {id: 1, name: 'Amazon', description: "Long ago, driven by a desire for adventure, the Valkyries of the Norse settlement in Lustria sailed away from their menfolk and founded a colony deep within the estuary of the river Amaxon. Now these ferocious warriors have taken to the Blood Bowl pitch – and Nuffle save those who dare to challenge them!"},
    {id: 2, name: 'Ogre', description: 'Ogre teams have existed since the forming of the NAF and have even won the XV Blood Bowl. However, as any right-minded person will tell you, having more than one Ogre in the same place at the same time is a disaster waiting to happen!'},
    {id: 3, name: 'Elves', description: 'When the NAF collapsed, many Elven teams were left penniless. Those that survived the financial fallout are not as rich as their High Elf cousins nor as well equipped, but they still sure know how to play!'},
    {id: 4, name: 'Human', description: "Although Human teams do not have the individual strength or outstanding abilities available to other races, they do not suffer from any outstanding weaknesses either. This makes Human teams extremely flexible, equally at home running the ball, passing it, or ignoring it and pounding the opposition into the turf instead."}
]

Enfin, nous déclarons la route :

App.ApplicationRoute = Ember.Route.extend({
    model: function() {
        return App.Race.find();
    }
});

Passons au fichier html. Il faut parcourir la liste des élément et afficher le nom pour chacun d’eux. Pour ce la nous déclarons un script x-handlebars a l’intérieur duquel nous itérons avec l’instruction {{#each item in model}} :

<script type="text/x-handlebars">
    <ul class="nav well">
        {{#each item in model}}
        <li>{{item.name}}</a></li>
        {{/each}}
    </ul>
</script>

Le résultat doit être le suivant :

races

Dans la console web on peut voir les versions des librairies utilisées pas Ember.js. Si il y avait une erreur, elle serait également visible à cet endroit.

Le code de cette version est accessible sur le tag 0.2.