CodeIgniter + React JS

Introduction

ReactJS est une bibliothèque prometteuse pour changer la façon dont les applications web sont conçues. J’ai retenu une chose importante, ce qui fait la différence par rapport à un appel AJAX simple et classique, c’est que React compare le DOM de la page avant l’appel et après l’appel pour appliquer les changements uniquement sur les modifications.

Il est donc inutile de faire recharger une page complète en cas d’ajout d’item dans une liste, ou même de l’ajouter « à la main » (avec un « append » en jQuery). React s’occupe de faire ces changements.

Soudain, on a envie de passer par cette bibliothèque pour tous les petites modifications à faire sur un écran (notification, compteur) et en exploitant cette technologie à son paroxysme, toute l’application y passe.

 

Quels impacts pour une application MVC ?

Si on prend React avec le framework « Flux », le MVC est mort. Dommage ! Faut-il recoder mes applications avec un autre paradigme ? Pas sûr.

Par contre, une application CodeIgniter qui désire utiliser React doit fondamentalement revoir la signification du V, pour la « Vue ».

En théorie, la vue, c’est ce que que les utilisateurs « voient », donc le HTML qui résulte du serveur hébergeant l’application.

Avec React, la Vue au sens HTML n’est plus à gérer par l’application. React s’en chargera.

Version classique du MVC de CodeIgniter (ou d’autres frameworks)

 

Casser la vue !

Oui, il faut casser la vue. L’application CodeIgniter ne fera que des interactions en manipulant des données JSON, et n’ayant que pour interface technique des WebServices REST.

Une autre application pourra se charger de la vue, des interactions utilisateur et des actions vers le serveur (liste des items, ajout, modification, suppression d’un item). Elle appellera l’application CodeIgniter pour le stockage en base de données, les règles métier, etc.

La partie « vue » de l’application est supportée par une autre application dédiée à l’interaction utilisateur. L’avantage est que si vous avez une application mobile à réaliser, elle pourra interagir avec cette application CodeIgniter en utilisant les mêmes WebServices.

Avec React, la vue peut supportée par une autre application.

Conclusion

La question qu’on peut se poser est la suivante : est-ce utile de s’appuyer sur un Framework MVC pour mon application s’il n’y a plus de Vue ?

S’il y a du boulot côté Modèle ou Controller (ou service) = des objets complexes, des règles métiers, la réponse est oui.

Si c’est une représentation HTML des objets simples en base de données, avec peu de règles métier, la réponse est non.

GanttCalendar + VectorManager

Utilisation de VectorManager

VectorManager est une bibliothèque JS destinée à gérer les vecteurs au sens mathématique (développée par l’auteur de cet article). Avec le GanttCalendar, il est possible de faire calculer à cette bibliothèque JS une information sur l’occupation des ressources d’un calendrier. Le GanttCalendar a donc été mis à jour avec VectorManager pour ajouter cette information pertinente : « au moins une ressource est occupée » et « toutes les ressources sont occupées ».

Pour ces 2 informations, 2 barres sont ajoutées dans le groupe de ressources :

  • bleu : « au moins une ressource est occupée »
  • rouge : « toutes les ressources sont occupées »

 

Bonus : Cette représentation supporte le zoom sur les calendriers sans ajouter de code spécifique. C’est l’avantage de rester sur la notion mathématique le plus loin possible dans le code, jusqu’au moment de l’affichage.

 

Exemples

Calendrier hebdomadaire :

Zoom sur le calendrier mensuel :

 

Démo

Les liens suivants permettent de voir le résultat en live :

Ces pages ont été testées avec FireFox. Il est fort probable qu’Internet Explorer n’affiche pas correctement les calendriers.

 

Sources

https://github.com/jchome/ganttCalendar

SoundBox avec ionic

Introduction

Après avoir réalisé une boite à sons avec Kivy, j’ai tenté de faire la même chose avec ionic. Les réflexes sont les mêmes, la méthode de travail est un peu différente.

 

Ajout du plugin Media

Pour faire jouer un son sur le mobile, il est nécessaire d’installer le plugin Cordova « Media ». Malheureusement, il ne fonctionne pas sous le navigateur du développeur. Il faudra faire le test sur le device mobile. Seule différence notable avec Kivy, qui permet de jouer un son presque de la même façon depuis le PC ou depuis le mobile.

 

Structuration du code

Même s’il n’y a pas grand chose, je tiens à avoir le code le plus structuré et le plus propre possible. L’application se découpe en 2 pages : la liste des catégories (page #1) et la liste des sons de la catégorie choisie (page #2).

Je me suis fortement inspiré du code de cette application : https://github.com/angular-app/angular-app/tree/master/client/src/app

Voici le contenu du répertoire www :

  • app : Répertoire de l’application
    • intro : Répertoire des fichiers de la vue « intro », page #1 de l’application
      • intro.js : Controller de la page « intro »
      • intro.tpl.html : Vue de la page « intro »
    • sounds : Répertoire de la page #2
      • sounds.js : Controller de la page des sons
      • sounds.tpl.html : Vue de la page des sons
    • app.js : Définition des services et du routage des pages
  • css : Répertoire vide pour les CSS spécifiques à l’application
  • js : Répertoire vide pour bibliothèques JS spécifiques à l’application
  • lib : Répertoire des plugins ajoutés pour l’application (géré par cordova)
  • mp3 : les sons

 

Détail du code

Il y a 6 fichiers importants pour que l’application fonctionne correctement.

index.html

<body ng-app="starter">
    <ion-nav-view></ion-nav-view>

    <script src="lib/media/Media.js"></script>
    <script src="lib/media/MediaError.js"></script>

    <script src="app/app.js"></script>

    <script src="app/intro/intro.js"></script>
    <script src="app/sounds/sounds.js"></script>
</body>

 

app.js

angular.module('soundBox.services', [])
.factory('CategoryService', function() {
    // Might use a resource here that returns a JSON array
    var categories = {
            "Animaux": ["Aigle", "Cigales"],
            "Divers": ["Claque", "Dentiste", "Klaxon", "PopDing", "Pouic", "Sieste bebe"],
            "Humain": ["Applaudissements", "Ramirez - alors ausweis papier svp - au trot", "Ramirez - hop hop hop hop", "Ramirez - jai dit ausweis"],
            "Objets": ["Canette Coca", "Casse assiette", "Cloche hotel", "Guitare", "Matrix_phone", "Telephone_Ancien", "Toy telephone", "Corne de brume", "Jouet de chien", "Sirene Alarme", "Telephone_x2"],
            "TV": ["Thames TV", "The Benny Hill Show"]
        };
    return {
        all: function() {
            return Object.keys(categories);
        },
        get: function(aCategory) {
            return categories[aCategory];
        }
    };
})
;

var app = angular.module('starter', ['ionic', 'ui.router', 'soundBox.services'])

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider.state('intro', {
    url: '/',
    templateUrl: 'app/intro/intro.tpl.html',
    controller: 'IntroCtrl'
  });

  $stateProvider.state('sounds', {
    url: '/sounds/:category',
    templateUrl: 'app/sounds/sounds.tpl.html',
    controller: 'SoundsCtrl'
  });

  $urlRouterProvider.otherwise('/');

});

Ce fichier aurait pu être découpé en 2 : le service et le routage.

 

intro.tpl.html

<ion-view title="Sound Box">
    <ion-nav-bar type="bar-positive"
        animation="nav-title-slide-ios7"
        back-button-type="button-icon button-clear"
        back-button-icon="ion-ios7-arrow-back">
        <ion-nav-back-button>
            <i></i> Back
        </ion-nav-back-button>
    </ion-nav-bar>

    <ion-content>
        <ion-list>
            <ion-item ng-repeat="item in items" href="#/sounds/{{item}}">
                {{item}}
                <i></i>
            </ion-item>
        </ion-list>
    </ion-content>
</ion-view>

 

intro.js

app.controller('IntroCtrl', function($scope, $location, $state, CategoryService) {
    $scope.items = CategoryService.all();
})
;

 

sounds.tpl.html

<ion-view title="Sound Box">
    <ion-nav-bar type="bar-positive"
        animation="nav-title-slide-ios7"
        back-button-type="button-icon button-clear"
        back-button-icon="ion-ios7-arrow-back">
        <ion-nav-back-button>
            <i></i> Back
        </ion-nav-back-button>
    </ion-nav-bar>

    <ion-content>
        <ion-list>
            <ion-item ng-repeat="item in items" ng-click="selectSound('{{item}}')">
                {{item}}
            </ion-item>
        </ion-list>
    </ion-content>
</ion-view>

 

sounds.js

app.controller('SoundsCtrl', function($scope, $state, $location, $stateParams, $ionicPlatform, CategoryService) {

    var sounds = CategoryService.get($stateParams.category);
    $scope.items = sounds;

    $scope.selectSound = function(sound) {
        var src = "/mp3/"+sound+".mp3";
        if(ionic.Platform.isAndroid()){
            src = "/android_asset/www" + src;
        }
        if($scope.media){
            $scope.media.stop();
        }
        $scope.media = new Media(src, function(){console.log("successfuly played "+ sound);}, function(e){console.log(e);});
        $scope.media.play();
        // ne pas faire d'autres interprétations du click
        return false;
    };

    $ionicPlatform.onHardwareBackButton(function(){
        if($scope.media){
            $scope.media.stop();
            $scope.media = null;
        }
    });
});

 

Conclusion / comparaison avec Kivy

Le code doit être rigoureusement écrit. Par exemple le tag « <ion-view> » doit être le seul dans la vue, sinon l’affichage est un peu cassé.

Selon le formalisme utilisé, les fichiers sont multiples mais courts et bien classés, ce qui est très agréable à maintenir.

Le design n’a pas été fait de manière aussi complète que l’application réalisée avec Kivy, mais j’imagine que les CSS et images seront faciles à manipuler, comme pour un site web.

Vivement d’autres applications pour mieux comparer les frameworks dans une application plus complète.

 

Téléchargement de l’APK

SoundBox-ionic-debug.apk

Comparatif ionic / Kivy

Introduction

Après quelques applications réalisées avec Kivy, je me rends compte des possibilités et des limites de ce Framework pour réaliser des applications mobiles cross-platform. Je me suis orienté vers une technologie en vogue : Cordova, plus précisément ionic.

Remarque : cet article est le « match aller ». Un autre article « match retour » apporte des précisions.

 

Ionic : Description rapide

Ionic est un Framework pour les développeurs de Javascript. L’objectif est de faire un petit serveur web avec des pages HTML et du code JS. Cordova fourni le serveur web qui sera lancé sur mobile et encapsule le code. Les appels JS à destination du device sont interceptés pour être interprétés selon l’OS (Android, iOS, etc).

L’avantage est que beaucoup de développeurs connaissent le trio HTML + JS + CSS.

D’autres Frameworks sont disponibles avec ces technologies, comme jQuery Mobile et à coupler avec une surcouche, comme Backbone.js pour plus de rigueur. Après une tentative infructueuse, j’ai renoncé à me salir d’avantage les mains.

 

Comparatif de l’installation

Avec Kivy, l’installation est rapide sous Linux car Python est déjà installé. Le téléchargement des fichiers SDK d’Android sont assez rapide car Kivy cible ce qu’il faut télécharger. Ma note : 18/20

Avec ionic, l’émulateur est nécessaire et là, il faut prévoir de faire autre chose pendant les téléchargements. Ma note : 15/20

Mon vainqueur : Kivy

 

Editeur de code (ou IDE)

Il est facile de trouver un IDE : Eclipse avec les plugins pour coder en Python ou en HTML/JS/CSS. Ils peuvent cohabiter dans le même workspace sans souci.

Mon vainqueur : ex-equo

Ma note pour les deux : 18/20

 

Documentation et exemples

Kivy a élevé le niveau avec son API très complète disponible sur le site http://kivy.org ainsi que des projets complets open-source sur GitHub.

Malgré tout, ionic n’est pas en reste, avec un grande communauté de développeurs, le site qui présente son API est assez complète. Il faut parfois jongler entre l’API de Cordova et l’API de ionic pour trouver ses petits.

Mon vainqueur : ex-equo

Ma note pour les deux : 18/20

 

Le premier « Hello world »

Le site de Kivy présente les 6 lignes de code nécessaires à ce test basique. Le principe est facile à comprendre. Facile. Ma note : 18/20

Ionic propose de faire une installation d’une application basique en une ligne de commande. Facile à faire (tout est téléchargé et pré-configuré), moins facile à comprendre comment ca fonctionne dans le détail. Ma note : 15/20

Mon vainqueur : Kivy, d’une courte tête

 

Développement d’une application sur un PC

Kivy lance Python directement depuis Eclipse (après une configuration minimale). Les amateurs de Java ne seront pas déçus. Les logs sont récupérés dans la console d’Ecplise, le mode debug fonctionne à merveille (point d’arrêt, avancée pas à pas, consultation des valeurs des variables, etc). L’application Kivy s’ouvre dans une fenêtre à part pour qu’on puisse interagir. Ma note : 18/20

Pour ionic, il faut lancer une commande qui démarre un serveur web (sur un port libre) et qui ouvre le navigateur par défaut. Chrome est préconisé avec le plugin ADT (pour android). Toute interaction se fait alors dans Chrome. L’IDE devient inutile, il ne sert que d’éditeur de texte. Dommage. Je n’ai pas trouvé le moyen de mettre un point d’arrêt, de consulter les valeurs des variables en temps réel. Au moins, la console de Chrome fonctionne. Ma note : 12/20

Mon vainqueur : Kivy

 

Déploiement sur mobile (Android)

Un outil « magique » est associé à Kivy pour faire l’APK : buildozer. Il faut produire un fichier de configuration pour les autorisations d’accès, le nom du package, le splash screen, l’icone, la version, etc. (un fichier de base est généré avec beaucoup de doc, façon « httpd.conf », très facile à comprendre). A mon avis, un atout très fort. Ma note : 18/20

Ionic n’est pas en reste. Il a lui aussi sa ligne de commande avec le fichier XML de configuration. Moins simple qu’avec buildozer quand même. Ma note : 18/20

Le temps de packaging et l’installation sur le smartphone est aussi rapide.

Mon vainqueur : ex-equo (sans compter la configuration)

 

Développements sans appels au device

La puissance de Python permet de faire beaucoup de choses simplement, avec très peu de code. C’est encore une force de Kivy.

Exemples : lecture de fichier XML ou JSON, appels HTTP-GET ou HTTP-POST, manipulation de chaînes de caractères, tableaux, dictionnaires, appels aux serveurs de cartographie (Google maps, Open Street map, BlueMarble), etc…

Le découpage en couches est facile avec l’utilisation de modules et packages Python pour définir les classes. Ma note : 18/20

Pour ionic, le Javascript permet aussi de faire beaucoup sans faire appel à d’autres choses, peut-être avec un peu plus de complexité. Les bibliothèques JS sont très nombreuses pour aller plus vire. Ionic profite des années de développements JS pour le web.

Pour garantir un code maintenable, ionic s’appuie sur Angular, pas trop complexe à utiliser dans un premier temps. Ma note : 18/20

Mon vainqueur : ex-equo

 

Appels aux fonctionnalités du device

Dans cette catégorie, je comprends une base de données (SQLite), le GPS, le vibreur, la caméra, etc.

Selon le cas, Kivy penne à sortir son épingle du jeu. Il faut utiliser des modules complémentaires pour accéder aux spécificités du smartphone. Par exemple, « plyer » permet de faire beaucoup de choses simplement, mais il est encore en cours de développements pour proposer une panoplie complète. La page de support des fonctionnalités selon l’OS montre pas mal de trous. Ma note : 12/20

Testé et fonctionne très bien : Base de données SQLite, jouer un son MP3, prendre une photo, obtenir la position GPS, bouton Back d’Android

Testé et ne fonctionne pas (encore) : Réalité augmentée

Pour ionic, Cordova semble prendre en charge un grand nombre de fonctionnalités. Cette brique est indispensable, même si je ne pense pas qu’elle puisse faire comme une application native. Ma note : 18/20

Testé et fonctionne bien : jouer un son MP3

Mon vainqueur : ionic (il sera certainement plus performant que Kivy dans ce domaine)

 

Design et interface

Avis aux WebDesigners, Kivy est une torture. Pour ceux qui ont fait du CSS, c’est horrible. Le langage KV est obligatoire et rédhibitoire (tellement que je me suis intéressé à d’autres Frameworks). Il faut prévoir ÉNORMÉMENT de temps pour comprendre comment fonctionne le principe d’affichage. L’option est de faire des widgets (composant graphique) simples à composer entre eux pour composer l’écran. Ma note : 4/20

Avec ionic, on reste sur du CSS (presque) classique. En plus, avec les thèmes déjà tout prêts, les WebDesigners retrouvent leurs marques. Ma note : 18/20

Mon vainqueur : ionic, largement en tête

 

Conclusion

Après avoir réalisé une application similaire avec Kivy et ionic (soundbox), je suis encore resté sur ma faim avec ionic. Je pense qu’il faudra que j’utilise SQLite, la position GPS, et d’autres fonctionnalités pour affiner mes notes.

Si on compte les points, voici mon résultat :

  • Installation : Kivy 18/20 ; ionic : 15/20
  • IDE : 18/20 pour les deux
  • Documentation : 18/20 pour les deux
  • Hello World : Kivy : 18/20 ; ionic : 15/20
  • Développement sur PC : Kivy 18/20 ; ionic : 12/20
  • Déploiement sur mobile : 18/20 pour les deux
  • Développements sans appels aux device : 18/20 pour les deux
  • Appels aux fonctionnalités du device : Kivy 12/20 ; ionic : 18/20
  • Design et interface : Kivy 4/20 ; ionic : 18/20

Total : Kivy 142 pts ; ionic : 150 pts

 

Pill Chart : graphe en forme de pillule

Introduction

Suite à la création du sélecteur de couleur sous forme d’une petite barre, j’ai voulu faire un graphique simple sur une dimension. J’ai repris les mêmes bases que le plugin précédent pour celui-ci.

Description

La syntaxe en JS est assez simple, un « PillChart » est défini par :

  • le DIV qui sera utilisé pour afficher le plugin
  • les données à afficher, avec les clés suivantes :
    • « label » : libellé au survol de la souris
    • « value » : valeur à faire apparaître dans la case du graphe
    • « width » : largeur en pixel ou en pourcentage
    • « cssAttr » : texte à coller dans l’attribut CSS « style »
new PillChart({
            containerId: 'pill_1',
            data: [ {
                label: "moins de 10 ans",
                value: 20,
                width: '20px',
                cssAttr: "background-color: #69C8FF;"
              }, ...
           ],
            updateCallback: function(obj){alert("clicked on : "+obj.label );}
        }).draw();

 

Démo

La page de démo est disponible sur cette page : http://jc.specs.free.fr/pillChart/demo.html

 

Démo avec une légende (générée par le plugin) :

 

Plugin MultiSelect dans le générateur de code

Introduction

Dans le générateur de code (voir l’article qui le décrit), les fichiers classiques de l’entité sont générés, mais il en manque une partie. Lorsqu’on défini une liaison n-n d’une entité vers une autre, on utilise un « objet de liaison ». Cet objet se décrit par :

  • un identifiant qui est clé unique de l’objet de liaison
  • l’identifiant de l’objet A
  • l’identifiant de l’objet B

Grâce à cet objet, un objet A est relié à n objets B et inversement, un objet B est relié à n objets A.

Exemple : entité « Album de bande dessinée » et entité « Auteur » :

  • un album de BD peut avoir plusieurs auteurs
  • un auteur peut avoir fait plusieurs albums de BD

 

L’objectif est de générer automatiquement du code pour avoir un multiselect dans la création et d’édition d’une entité A ou B.

 

Application avec les BD et les auteurs

L’objet « LienAuteurAlbum » est décrit comme ceci :

  • identifiant du lien
  • identifiant de l’album
  • identifiant de l’auteur

Remarque : l’identifiant du lien permet de supprimer facilement et sereinement un enregistrement avec une seule information, en plus des fonctionnalités offertes avec les autres champs.

Après moult réflexion, j’ai ajouté des features sur chaque entité de liaison :

Ces modifications sont faites dans la génération du helper et du modèle. Deux nouvelles vues ont étés faire pour l’appel du plugin multiselect, sous forme d’un fragment (une vue qui s’appelle depuis une vue principale). Une vue pour la création et une vue pour la modification.

Par contre, il faut modifier manuellement les controller et les vues des entités (exemple : Album) pour utiliser cet objet de liaison.

Appel du code généré pour la vue en édition ou en création d’album

Lorsque je crée un album, je veux avoir le multiselect des auteurs. Il faut alors ajouter dans la vue de création d’un album le code suivant :

<?php 

$data["multiselectOf"] = 'Auteur';
$this->load->view('lienauteuralbum/createMultiselectLienAuteurAlbumFragment_view.php', $data);

?>

Le fichier « lienauteuralbum/createMultiselectLienAuteurAlbumFragment_view.php » est généré et ne doit pas être modifié. Dans le paramètre « multiselectOf », il faut spéficier que je veux un multiselect de … « Auteur », afin d’avoir une liste d’auteurs à choisir.

Idem dans la vue d’édition d’un Album.

 

Modification du controller d’édition d’album

Dans le controller d’édition, lorsqu’on sauve les données saisies, il faut [1] supprimer les anciennes relations dans « LienAuteurAlbum » dans lesuqelles il y a l’album édité et [2] créer des nouveaux objets « LienAuteurAlbum » avec cet album et les auteurs cochés.

Première partie :

$lienAuteurAlbum_autidaut = $this->input->post('LienAuteurAlbum_autidaut');
LienAuteurAlbum_model::deleteAllLienAuteurAlbumsBy_xaaidalb($this->db, $model->albidalb);

ligne 1 : récupération des liens avec des identifiants d’auteurs que l’utilisateur a coché dans le multiselect

ligne 2 : suppression des anciens liens à partir de l’identifiant de l’album

 

Deuxième partie :

foreach($lienAuteurAlbum_autidaut as $autidaut){
            $auteurModel = new LienAuteurAlbum_model();
            $auteurModel->xaaidalb = $model->albidalb;
            $auteurModel->xaaidaut = $autidaut;
            $auteurModel->save($this->db);
}

Pour chaque auteur coché, on créer un nouveau lien avec :

  • album : celui que je suis en train d’éditer
  • auteur : un auteur coché

Remarque : Dans le controller de création d’un album, la première partie destinée à supprimer les anciens liens avec les auteurs n’est pas à faire.

 

 Sans oublier le javascript

Le plugin JS est à charger après les différents appels de jQuery et du JS du plugin multiselect. J’ai choisi de le mettre manuellement dans le JS de la vue de l’objet édité ou créé.

$(function(){
    $("#LienAuteurAlbum_autidaut").multiselect();
});

 

Résultat

Dans cet exemple, le champ « Genre » est un select simple (déjà disponible dans le générateur). Le champ « Liste des auteurs » fait appel au plugin multiselect.

 

Conclusion

Finalement, la génération de code a ses limites, mais beaucoup de choses sont pré-mâchées. Pour aider les futurs développeurs à intégrer le plugin, j’ai inséré le code à copier-coller dans la vue et dans le JS.

Rien n’est généré pour le controller, il faudra lire cet article si vous ne savez pas comment faire (mais je trouve que ce n’est pas trop difficile).

 

Bootstrap typeahead & ajax

Introduction

Bootstrap dispose d’un champ d’auto-complete nommé « typeahead« , qui autorise de saisir un item parmi une liste figée ou récupérée par Ajax. Seul bémol : l’exemple fourni montre comment faire avec une liste de libellés seuls. Comment lui passer une liste composée de données avec un identifiant ET un libellé ? L’objectif étant de mettre l’identifiant dans un champ caché et le libellé dans le champ de texte. Lorsque le formulaire est envoyé, le champ caché contient la valeur à sauvegarder (le libellé n’étant pas utile).

Les promesses de Bootstrap Typeahead, sur le choix de la ville (avant l’adaptation) :

 

Sources

Voici les liens qui décrivent les opérations :

 

Résultat

La recherche par nom de ville :

 

La recherche par code postal :

 

Explications

En effet, l’avantage de « typeahead » est qu’il peut être surchargé, avec une nouvelle définition des méthodes. Pour notre cas, ce sera la méthode « updater » (lorsque la sélection de l’item est fait par le clic, la méthode décrit le comportement).

Pour la suite, il faut alimenter la liste avec des objets customisés (avec des méthodes particulières).

 

Détail de la solution

$('#cabidvil_text').typeahead({
    source: function (query, process) {
        return $.get(base_url()+'index.php/json/listvilles/findBy_villbnsc_vilcdcps/'+query,
        { /*query: no more parameters*/ }, function (dataIN_str) {
            data = new Array();
            var dataIN = JSON.parse(dataIN_str);
            for (i in dataIN) {
                var group;
                group = {
                    id: dataIN[i].vilidvil,
                    name: dataIN[i].vilcdcps + ' ' + dataIN[i].villbnsc,
                    toString: function () {
                        return JSON.stringify(this);
                    },
                    toLowerCase: function () {
                        return this.name.toLowerCase();
                    },
                    indexOf: function (string) {
                        return String.prototype.indexOf.apply(this.name, arguments);
                    },
                    replace: function (string) {
                        var value = '';
                        value +=  this.name;
                        if(typeof(this.level) != 'undefined') {
                            value += ' <span>';
                            value += this.level;
                            value += '</span>';
                        }
                        return String.prototype.replace.apply('<div>' + value + '</div>', arguments);
                    }
                };

                data.push( group );
            }
            return process(data);
        });
    },
    updater: function (item) {
        var item = JSON.parse(item);
        $('#cabidvil').val(item.id);
        return item.name;
    }

});

 

Les lignes importantes

1 – L’appel de l’URL par ajax qui peut prendre à la fois le code postal et la ville :

return $.get(base_url()+'index.php/json/listvilles/findBy_villbnsc_vilcdcps/'+query,

Coté controller, si la recherche par code postal ne retourne rien, faire la recherche par nom de ville.

 

2 – Définir les 2 variables de l’objet « group » :

id: dataIN[i].vilidvil,
name: dataIN[i].vilcdcps + ' ' + dataIN[i].villbnsc,

La variable « name » sera affichée dans la liste déroulante et dans le champ de texte une fois l’item sélectionné (vilidvil = identifant ; vilcdcps = code postal ; villbnsc = libellé en majuscule).

 

3 – Mise à jour du champ caché :

$('#cabidvil').val(item.id);

Le champ caché prend pour valeur l’identifiant de la ville sélectionnée par son code postal et son nom.

 

Bibliothèque JS pour gérer les vecteurs à une dimension

Suite à une réflexion autour des vecteurs et leur manipulation dans une espace vectoriel à une dimension, j’ai créé une bibliothèque qui permet de manipuler ces objets relativement simples.

Ce simple objet mathématique qu’est une sorte de trait sur une ligne, avec sa position et sa longueur m’a fait quand même pas mal de nœuds à la tête. Le plus difficile est la gestion des ensembles d’objets : union, intersection dans quelques cas.

Je vous laisse découvrir l’API complète en français (qui fait office de démo car la page s’appuie dessus) et une copie d’écran ci-dessous, si votre navigateur ne peut pas faire tourner mon code (qui est peut-être buggé…).

 

Je pense que les personnes intéressées sauront récupérer le JS depuis la page de démo.

 

 

Plugin jQuery pour choix de couleur

Si vous avez un sélecteur de couleur sous la forme d’un champ SELECT avec une palette de quelques couleurs, je vous propose de tester mon plugin jQuery qui le remplacera par une liste de blocs de couleurs sélectionnables. Je l’ai nommé « Short Color Selector » parce qu’il ne prend pas plus d’une ligne (d’où le « short » — Si vous avez un meilleur nom, je suis preneur !).

Voici un exemple :

Démo (avec syntaxe utilisée) : http://jc.specs.free.fr/shortColorSelector/demo.html

Dans le premier exemple, le champ SELECT est conservé. Dans le second, il est caché.

Pour plus de détail, voici les options possibles :

  • id du SELECT à utiliser pour reprendre les couleurs de la palette
  • largeur de chaque cellule de la palette (en pixels)
  • caractère de sélection de la couleur (par exemple, une étoile, check, etc…). Ce n’est pas une image car avec font-awesome, on peut trouver un picto qui ira très bien…
  • cacher ou pas le SELECT correspondant
  • appel d’une fonction JS pour déclencher un évènement lors de la sélection d’une couleur (le SELECT est mis à jour avec le choix de la couleur par défaut)

Actuellement, il n’est pas possible de choisir plusieurs couleurs en même temps, dans la même palette (je n’ai pas trouver l’intérêt que ça peut avoir — autant mettre 2 palettes pour les 2 couleurs à sélectionner…).

Merci de me donner votre avis et me dire ce qui manque.

inspiration :

Color Rotate

GanttCalendar Hebdomadaire

Suite à la publication du plugin GanttCalendar en mode « affichage mensuel », j’ai créé une version hebdomadaire, avec les mêmes fonctionnalités.

Le zoom est aussi disponible en 4 niveaux.

Voir la démo

Les fonctionnalités de changement de semaine (précédente / suivante) ne sont pas encore au point…