JavaScript-Ini, un fichier de configuration pour JavaScript

Un script pour charger et sauver un fichier de configuration JSON, qui génère une interface utilisateur automatiquement pour configurer une application.

L'intérêt de ce script est que le développeur a seulement besoin de définir la liste d'options pour la configuration d'une application dans un tableau JSON. Le script se charge de générer l'interface utilisateur correspondante en HTML et de mettre à jour le fichier de configuration pour sauvegarder les choix de l'utilisateur.

  1. Les options sont définies dans un fichier JSON. Elle contiennent des valeurs initiales que l'utilisateur pourra changer.
  2. Le fichier JSON est chargé dans une page web et le présent script génère un formulaire selon son contenu.
  3. L'utilisateur peut changer les options à partir de ce formulaire interactif.
  4. Les changements sont enregistrés dans le même fichier JSON.

Le script utilise Ajax pour sauver le fichier de configuration, lequel peut se trouver sur un poste local ou sur un serveur pour une application en ligne.

En fait vous avez le choix entre

  1. Envoyer les données à une autre page ou un script par le bouton Submit.
    Dans ce cas pour pouvez supprimer l'inclusion du framework Ajax
  2. Utiliser Ajax pour stocker les données directement dans un fichier.
    Dans ce cas vous pouvez supprimer les lignes de génération de la balise form.

Par défaut la démo utilise Ajax.

Le fichier de configuration et son chargement

Pour le charger c'est très simple, il suffit d'inclure le fichier .ini en tant que script JavaScript:

<script type="text/javascript" src="myapp.ini"></script>

Ce fichier contient un tableau nommé config qui se trouve dès lors inclu dans la page d'interface et utilisable par le code JavaScript de la page.

Exemple de fichier de configuration:

var config={
  "Language": {
    "name": "lang",
       "initial": "es",
       "select": [ "en", "fr", "es"]
  },
  "Url": {
    "name": "url",
    "input": "http://www.scriptol.com/",
  },
  "Saving options": {
    "list": [
       {
         "name": "save",
         "label": "Autosave",
         "checkbox": true
       },
       {
         "name": "prompt",
         "label": "Prompt",
         "checkbox": false
       }
     ]
  }
}

Ce fichier contient trois exemples de sections: "Language", "Url", "Saving options". Le nom des sections est totalement libre.
Elle peuvent contenir un objet de formulaire ou plusieurs, c'est le cas de la troisième section. On peut ajouter autant de sections et d'objets de formulaire que nécessaire dans le tableau config.

Un certain nombre de mots réservés sont utilisés par le générateur:

L'ordre est important à l'intérieur d'une section. On doit avoir les valeurs de name et de initial avant de générer l'objet de formulaire.

Génération du formulaire

On génère des balise fieldset et form puis on parcourt la liste des sections:

form +="<fieldset><legend>Configuration</legend>\n";
form +="<form method='POST' action='myapp.php'>\n";
for(group in config)
{
  form += "<p class='group'>" + group + "</p>";
  parseGroup(config[group]);
}
form += "<p><input type='button' onclick='saveIni(\"myapp.ini\")'
         value='Update Configuration'></p>";
form += "</form>";
form += "</fieldset>";

On a généré un objet de type button pour sauver la configuration en Ajax. Si l'on veut envoyée les données de formulaire à un script par POST, on remplacera le type button par submit.

Pour chaque section on appelle la fonction de génération d'objet de formulaire parseGroup:

function parseGroup(innarr)
{
  var initial = '';
  var name = '';
  for(option in innarr)
  {
    switch(option)
    {
      case 'list':
            var garr = innarr[option];
            for(var i = 0; i < garr.length; i++)
            {
              parseGroup(garr[i]);
              form +="<br>";
            }
            break;
      case 'label':
           addLabel(innarr[option]);
           break;
      case 'name':
          name = innarr[option];
          break;
      case 'initial':
           initial = innarr[option];
           break;
      case 'select':
           addSelect(name, initial, innarr[option]);
           break;
      case 'input':
           addInput(name, innarr[option]);
           break;
      case 'checkbox':
           addCheck(name, innarr['checkbox']);
           break;
      default:
           break;
   }
  }
}

Ensuite, pour chaque type de balise, une fonction est appelée. Voir le script complet dans l'archive de démonstration.

Ce script permet de générer l'interface suivante:

JavaScript ini

L'utilisateur, après voir choisi les options de l'application, clique sur update pour sauvergarder la configuration.

Sauvegarde de la configuration

Le même algorithme est utilisé pour mettre à jour le tableau config avant de le sauvegarder dans un fichier INI.

De nouveau on parse chaque section:

function update(config)
{
  for(group in config)
  {
    updateEntry(config[group]);
  }
}

Et pour chacune on accède à chaque objet de formulaire en fonction de son identifieur. C'est ce que l'on a assigné à l'attribut name dans le fichier JSON.

function updateEntry(innarr)
{
  var initial = '';
  var name = '';
  var element = null;
  for(option in innarr)
  {
    switch(option)
    {
      case 'list':
            var garr = innarr[option];
            for(var i = 0; i < garr.length; i++)
            {
              updateEntry(garr[i]);
            }
            break;
      case 'name':
            name = innarr[option];
            element = document.getElementById(name);
            break;
      case 'initial':
            initial = innarr[option];
            break;
      case 'select':
            var value = element.options[element.selectedIndex].value;
            innarr['initial'] = value;
            break;
      case 'input':
            innarr['input'] = element.value;
            break;
      case 'checkbox':
            innarr['checkbox'] = element.checked;
            break;
      default:
            break;
    }
  }
}

On assigne donc les valeurs données par l'utilisateur, aux attributs du tableau, et cela dépend du type d'objet de formulaire. Reste alors à sauvegarder le tableau config dans le fichier myapp.ini. La fonction saveInit est associée au bouton update.

function done(content) { alert(content); }
function saveIni(filename)
{
  update(config);
  var data = 'url=' + filename + '&data=var config=' + JSON.stringify(config, null, 4);
  AAWrite('saveconfig.php', data, done);
}

On appelle la fonction AAWrite du framework Ajax léger Anaa pour exécuter le script saveconfig.php auquel on envoie le contenu JSON. Le script saveconfig.php stocke ce contenu dans le fichier ini. Voici ce script:

<?php
  $data = $_POST['data'];
  $url  = $_POST['url'];
  $f = fopen($url, 'w');
  fputs($f, $data);
  fclose($f);
  echo "Saved.";
?>

Si l'on utilise JavaScript-Ini pour une application locale avec Node.js, il faudra plutôt utiliser WebSocket et inclure socket.io dans la page d'interface à la place du framework Anaa.

Télécharger la démo Ajax complète

Liste des fichiers: