/* CONSTRUCTEUR -> INITIALISE UNE L'INSTANCE * * @parent_element Element qui contiendra le formulaire * @form_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 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 Objet dans lequel remplacer les valeurs * @scope Ensemble des variables permettant le remplacement * * @return replaced 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; };