NxTIC/js/lib/form-builder.js

228 lines
7.3 KiB
JavaScript

/* CONSTRUCTEUR -> INITIALISE UNE L'INSTANCE
*
* @parent_element<Element> Element qui contiendra le formulaire
* @form_object<Object> Objet définissant le formulaire
*
*/
var FormBuilder = function(parent_element, form_object){
/* (1) On définit le parent */
this.parent_element = parent_element;
/* (2) On définit le formulaire (sous forme de description formelle) */
this.form_object = form_object;
/* (3) On formatte l'objet (référence des 'children' vers le 'parent') */
FormBuilder.formatFormObject(this.form_object);
};
/* DEFINITION DES ATTRIBUTS
*
*/
FormBuilder.prototype = {
form_object: this.form_object, // objet permettant la construction du formulaire
defs_object: {}, // objet des définitions des éléments
parent_element: this.parent_element, // element qui contiendra le formulaire
allowed_attr: [ // Liste des attributs fixes autorisés
'node', /* nom du modèle à utiliser (dans @defs_object) */
'node_type', /* nom réel de l'élément */
'node_attr', /* tableau des attrbuts réels de l'élément */
'node_children', /* tableau des enfants (innerHTML) du noeud courant */
'next_nodes', /* tableau des enfants à ajouter à la suite de l'élément */
'prev_nodes', /* tableau des enfants à ajouter à avant l'élément */
'attributes', /* tableau des attributs à passer au niveau inférieur */
'children', /* tableau des enfants à passer au niveau inférieur */
'text', /* texte à insérer (innerHTML), REMPLACE 'children' */
'repeat' /* nombre/tableau déterminant qu'il faut répéter @n fois ou en fonction de la taille du tableau */
],
built_form: null, // Element correspondant au formulaire construit
regex: {
primitive_ouput_value: /\{([a-z-]+)\}/g,
primitive_input_key: /^\$([a-z-]+)$/,
array_output_set: /^\{\{([a-z-]+)\}\}$/,
array_output_value: /\{([a-z-]+)\.([a-z-]+)\}/g,
array_input_key: /^\$\$([a-z-]+)$/
}
};
/* FORMATTE L'OBJET DE DESCRIPTION DU FORMULAIRE
*
*/
FormBuilder.formatFormObject = function(object){
/* (1) Si a un enfant */
if( object.hasOwnProperty('children') )
/* (2) Pour chaque enfant */
for( var child in object.children ){
/* (1) On ajoute le parent + on lance récursivement */
object.children[child].parent = object;
FormBuilder.formatFormObject(object.children[child]);
}
return object;
};
/* AJOUTE UNE DEFINITION
*
* @def_object<Object> Objet de définition
*
*/
FormBuilder.prototype.add_definition = function(def_object){
for( var key in def_object )
this.defs_object[key] = def_object[key];
};
/* REMPLACE RECURSIVEMENT LES VALEURS DE @OBJECT AVEC LE @SCOPE -> RECURSIF
*
* @object<Object> Objet dans lequel remplacer les valeurs
* @scope<Object> Ensemble des variables permettant le remplacement
*
* @return replaced<Object> Objet avec les remplacements effectués
*
*/
FormBuilder.replaceStatements = function(object, scope){
/* [0] Initialisation
=========================================================*/
var key, r, tmpr, m;
var next_scope = scope;
/* [1] On remplace les valeurs
=========================================================*/
for( key in object ){
/* [1.1] Si c'est une string, on regarde s'il faut remplacer
=========================================================*/
if( key != 'parent' && typeof object[key] == 'string' ){
/* (2.1) On cherche tous les TABLEAUX à remplacer
---------------------------------------------------------*/
/* (1.1) On récupère les remplacements de TABLEAUX */
m = null, r = FormBuilder.prototype.regex.array_output_set;
var m_arr = [];
/* (1.2) Si ça match */
m = r.exec(object[key]);
if( m !== null )
m_arr.push( m[1] );
/* (1.3) Pour chaque match */
for( m in m_arr ){
// {1} Si la var n'est pas dans le scope //
if( !scope.hasOwnProperty(m_arr[m]) )
scope[m_arr[m]] = []; // on met un tableau vide
// {2} on attribue le tableau //
object[key] = scope[m_arr[m]];
}
/* (1.4) Si on a trouvé qqch, on passe à la clé suivante */
if( m_arr.length > 0 )
continue;
/* (2.2) On cherche toutes les variables PRIMITIVES à remplacer
---------------------------------------------------------*/
/* (1.1) On récupère les remplacements PRIMITIFS */
m = null, r = FormBuilder.prototype.regex.primitive_ouput_value;
var m_pri = [];
/* (1.2) Tant que ça match */
while( ( m=r.exec(object[key]) ) !== null )
m_pri.push( m[1] );
/* (1.3) Pour chaque match */
for( m in m_pri ){
// {1} Si la var n'est pas dans le scope //
if( !scope.hasOwnProperty(m_pri[m]) )
scope[m_pri[m]] = ''; // on met une chaine vide
// {2} on remplace toutes les occurences par la valeur //
tmpr = new RegExp( "\{"+m_pri[m]+"\}", 'g' );
object[key] = object[key].replace(tmpr, scope[m_pri[m]]);
}
/* (1.4) Si on a trouvé qqch, on passe à la clé suivante */
if( m_pri.length > 0 )
continue;
/* (2.3) On cherche toutes les valeurs de TABLEAUX à remplacer
---------------------------------------------------------*/
/* (1.1) On récupère les remplacements de valeurs de TABLEAUX */
m = null, r = FormBuilder.prototype.regex.array_output_value;
var m_aval = [];
/* (1.2) Tant que ça match */
while( ( m=r.exec(object[key]) ) !== null )
m_aval.push( m[1] );
/* (1.3) Pour chaque match */
for( m in m_aval ){ //TODO: implémenter l'ajout des items d'un tableau au scope lors d'un "repeat"
// {1} Si la var n'est pas dans le scope //
if( !scope.hasOwnProperty(m_arr[m]) )
scope[m_arr[m]] = ''; // on met une chaine vide
// {2} on remplace toutes les occurences par la valeur //
tmpr = new RegExp( "/\{"+m_arr[m]+"\}/", 'g' );
object[key].replace(tmpr, scope[m_arr[m]]);
}
}
}
/* [2] On ajoute les variables '$var' et '$$arr' au scope suivant
=========================================================*/
for( key in object ){
/* (1) Ajout des variables de type '$nomVar'
---------------------------------------------------------*/
if( FormBuilder.prototype.regex.primitive_input_key.test(key) )
next_scope[ key.substring(1) ] = object[key];
/* (2) Ajout des tableaux de type '$$nomArr'
---------------------------------------------------------*/
else if( FormBuilder.prototype.regex.array_input_key.test(key) )
next_scope[ key.substring(2) ] = object[key];
}
console.log('scope', scope);
/* [3] On lance récursivement
=========================================================*/
for( key in object ){
/* S'il ne s'agit pas de l'attribut PARENT */
if( key != 'parent' ){
/* Si c'est un objet ou tableau, on lance récursivement */
if( object[key] instanceof Object || object[key] instanceof Array )
object[key] = FormBuilder.replaceStatements(object[key], next_scope);
}
}
return object;
};