From 5f0a670d5f0f027024a5efe99919b8c72a2a42c4 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 17 Sep 2016 12:40:29 +0200 Subject: [PATCH] =?UTF-8?q?Gestion=20du=20remplacement=20des=20regex=20+?= =?UTF-8?q?=20conditions=20pour=20noms=20de=20d=C3=A9finitions.=20Reste=20?= =?UTF-8?q?=C3=A0=20faire=20la=20gestion=20du=20scope=20pour=20qu'aucune?= =?UTF-8?q?=20donn=C3=A9e=20n'en=20=C3=A9crase=20d'autre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/form-builder/behaviour.js | 4 +- js/lib/form-builder-min.js | 13 +- js/lib/form-builder.js | 329 ++++++++++++++++++++++++++------ js/lib/form-builder/main-min.js | 6 +- js/lib/form-builder/main.js | 16 +- 5 files changed, 296 insertions(+), 72 deletions(-) diff --git a/doc/form-builder/behaviour.js b/doc/form-builder/behaviour.js index 7e6a210..5e4715c 100644 --- a/doc/form-builder/behaviour.js +++ b/doc/form-builder/behaviour.js @@ -72,7 +72,7 @@ var default_definition = { 'input': { node_type: 'input', node_attr: '{__attributes__}' }, - 'h/^([1-6])$/': { node_type: 'h{$1}', node_attr: '{__attributes__}', node_children: '{__children__}' }, + '/^h([1-6])$/': { node_type: 'h{$1}', node_attr: '{__attributes__}', node_children: '{__children__}' }, 'br': { node_type: 'br', }, 'option': { node_type: 'option', node_attr: '{__attributes__}', node_children: '{__children__}' }, 'select': { node_type: 'select', node_attr: '{__attributes__}', node_children: '{__children__}' }, @@ -80,7 +80,7 @@ var default_definition = { }; var custom_definition = { - 'input:/^([a-z]+)$/': { + '/^input:([a-z]+)$/': { node: 'input', attributes: { 'type': '{$1}', diff --git a/js/lib/form-builder-min.js b/js/lib/form-builder-min.js index 319d69b..3cd4bcb 100644 --- a/js/lib/form-builder-min.js +++ b/js/lib/form-builder-min.js @@ -1,6 +1,7 @@ -var FormBuilder=function(a,c){this.parent_element=a;this.form_object=c;FormBuilder.formatFormObject(this.form_object)}; -FormBuilder.prototype={form_object:this.form_object,defs_object:{},parent_element:this.parent_element,allowed_attr:"node node_type node_attr node_children next_nodes prev_nodes attributes children text repeat".split(" "),built_form:null,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-]+)$/}}; -FormBuilder.formatFormObject=function(a){if(a.hasOwnProperty("children"))for(var c in a.children)a.children[c].parent=a,FormBuilder.formatFormObject(a.children[c]);return a};FormBuilder.prototype.add_definition=function(a){for(var c in a)this.defs_object[c]=a[c]}; -FormBuilder.replaceStatements=function(a,c){var b,e,d;for(b in a)if("parent"!=b&&"string"==typeof a[b]){e=FormBuilder.prototype.regex.array_output_set;var f=[];d=e.exec(a[b]);null!==d&&f.push(d[1]);for(d in f)c.hasOwnProperty(f[d])||(c[f[d]]=[]),a[b]=c[f[d]];if(!(0f;f++)matches["$"+f]=RegExp["$"+f];return{def:d[b],scope:matches}}return null}; +FormBuilder.replaceStatements=function(a,d){a=a instanceof Object?a:{};d=d instanceof Object?d:{};var b,f,e,g=d;if(a.hasOwnProperty("scope")&&a.scope instanceof Object)for(b in a.scope)g[b]=a.scope[b];for(b in a)if(0>FormBuilder.ignore_rec.indexOf(b)&&"string"==typeof a[b]){f=FormBuilder.regex.array_output_set;var c=[];(e=f.exec(a[b]))&&c.push(e[1]);for(e in c)d.hasOwnProperty(c[e])||(d[c[e]]=[]),a[b]=d[c[e]],console.log("arr",c[e],d[c[e]]);if(!(0=f.lastIndex);)lasti=f.lastIndex,c.push(e[1]);for(e in c)d.hasOwnProperty(c[e])||(d[c[e]]=""),f=new RegExp("{\\$"+c[e][1]+"}","g"),console.log("reg",c[e],d),a[b]=a[b].replace(f,d[c[e]]);if(!(0FormBuilder.ignore_rec.indexOf(b)&&(a[b]instanceof Object||a[b]instanceof Array)&&(a[b]=FormBuilder.replaceStatements(a[b],g));return a}; diff --git a/js/lib/form-builder.js b/js/lib/form-builder.js index 12ad48e..6d60c62 100644 --- a/js/lib/form-builder.js +++ b/js/lib/form-builder.js @@ -10,12 +10,17 @@ var FormBuilder = function(parent_element, form_object){ /* (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 * */ @@ -23,49 +28,53 @@ 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-]+)$/ - } + built_form: null // Element correspondant au formulaire construit + }; -/* FORMATTE L'OBJET DE DESCRIPTION DU FORMULAIRE + +/* DEFINITION DES ATTRIBUTS STATIQUES * */ -FormBuilder.formatFormObject = function(object){ +FormBuilder.regex = { + regex_input_key: /^\/\^(.+)\$\/$/, // Regex associée à une "regex" incluse dans une clé + regex_ouput_value: /\{(\$[1-9])\}/, // Regex associée à la valeur du dernier match de "regex" - /* (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; + primitive_ouput_value: /\{([a-z-]+)\}/g, // Regex associée à une variable primitif à remplacer + primitive_input_key: /^\$([a-z-]+)$/, // Regex associée à la clé d'une variable primitive + array_output_set: /^\{\{([a-z-]+)\}\}$/, // Regex associée à un tableau à remplacer + array_output_value: /\{([a-z-]+)\.([a-z-]+)\}/g, // Regex associée à une valeur de tableau à remplacer (primitif) + array_input_key: /^\$\$([a-z-]+)$/ // Regex associée à la clé d'un tableau }; +FormBuilder.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 */ +]; + +FormBuilder.ignore_rec = [ // Attributs à ne pas lancer récursivement (car inutile) + 'parent', /* ne pas lancer récursivement sur parent car sinon récursion infinie */ + 'scope' /* ne pas lancer sur scope, car fait partie des méta-données */ +], + + + +/************************************************************/ +/* __ __ _____ _____ _ _ ___ ____ ____ */ +/* | \/ | ____|_ _| | | |/ _ \| _ \/ ___| */ +/* | |\/| | _| | | | |_| | | | | | | \___ \ */ +/* | | | | |___ | | | _ | |_| | |_| |___) | */ +/* |_| |_|_____| |_| |_| |_|\___/|____/|____/ */ +/************************************************************/ /* AJOUTE UNE DEFINITION * @@ -74,12 +83,166 @@ FormBuilder.formatFormObject = function(object){ */ FormBuilder.prototype.add_definition = function(def_object){ + /* [1] On ajoute la définition + =========================================================*/ for( var key in def_object ) this.defs_object[key] = def_object[key]; }; +/* ON CONSTRUIT L'OBJET (avant la construction) +* +* @scope for( key in object ){ + [OPT] Objet contenant les variables à passer +* +*/ +FormBuilder.prototype.build = function(scope){ + /* [0] Gestion du paramètres + =========================================================*/ + scope = (scope == null) ? {} : scope; + + /* [1] On formatte l'objet + =========================================================*/ + // - Ajout des références children[n].parent vers élément parent + // - Ajout des références element.node_link vers définition (en fonction de element.node) + this.built_form = FormBuilder.formatFormObject(this.form_object, this.defs_object); + + + /* [2] On remplace les valeurs + =========================================================*/ + this.built_form = FormBuilder.replaceStatements(this.form_object, scope); +}; + + + + +/************************************************/ +/* ____ _____ _ _____ ___ ____ */ +/* / ___|_ _|/ \|_ _|_ _/ ___| */ +/* \___ \ | | / _ \ | | | | | */ +/* ___) || |/ ___ \| | | | |___ */ +/* |____/ |_/_/ \_\_| |___\____| */ +/************************************************/ + +/* FORMATTE L'OBJET DE DESCRIPTION DU FORMULAIRE +* +* @object Objet dans lequel remplacer les valeurs +* @defs Objet de définition des nodes +* +* +* @desc +* 1. Ajoute l'attribut PARENT aux enfants pour qu'ils puisse accéder à l'élément parent +* 2. Ajout l'attribut NODE_LINK aux éléments afin de lier leur définition en fonction de la valeur de 'node' +* +*/ +FormBuilder.formatFormObject = function(object, defs){ + + /* [1] Si a l'attribut 'node' + =========================================================*/ + if( object.hasOwnProperty('node') && typeof object.node == 'string' ){ + + /* On cherche une définition */ + var found_def = FormBuilder.fetchNodeDefinition(object.node, defs); + + // Si on trouve + if( found_def !== null ){ + + // 1. On inclus la définition dans l'attribut 'node_link' + object.node_link = found_def.def; + + // 2. On ajoute les matches dans l'attribut 'scope' + if( found_def.hasOwnProperty('scope') ) + object.scope = found_def.scope; + + } + + + } + + + /* [2] Pour chaque enfant, s'il y a + =========================================================*/ + if( object.hasOwnProperty('children') ){ + + for( var child in object.children ){ + + /* On ajoute le parent + on lance récursivement */ + object.children[child].parent = object; + FormBuilder.formatFormObject(object.children[child], defs); + + } + + } + + return object; +}; + + +/* CHERCHE UNE DEFINITION CORRESPONDANT A L'ATTRIBUT 'node' +* +* @node Nom du node pour lequel trouver la définition +* @defs Objet de définition +* +* @return node_definition Retourne la définition pour le 'node' en question +* ou NULL si on ne trouve rien +* +*/ +FormBuilder.fetchNodeDefinition = function(node, defs){ + /* [0] Initialisation + =========================================================*/ + var m = null, key, i, regex; + r = FormBuilder.regex.regex_input_key; + + + /* [1] Si la définition existe, on la retourne + =========================================================*/ + if( defs != null && defs.hasOwnProperty(node) ){ + + return { def: defs.node, scope: null }; + + + /* [2] Sinon, on cherche une REGEX + =========================================================*/ + }else{ + + // Pour chaque définition + for( key in defs ){ + + /* (2.1) On regarde s'il n'y a pas de REGEX dans la clé + ---------------------------------------------------------*/ + if( r.test(key) ){ + + // On construit la regex + regex = new RegExp( key.slice(1, -1) ); + + /* (1) Si la regex match */ + if( (m=regex.test(node)) ){ + + /* (2) On récupère les 'match' */ + matches = {}; + + for( i = 1 ; i < RegExp.length && i < 10 ; i++ ) + matches['$'+i] = RegExp['$'+i]; + + /* (3) On renvoie le lien + le scope */ + return { def: defs[key], scope: matches }; + + } + + + } + + } + + } + + + // Si on a rien trouvé, on retourne NULL + return null; +}; + + /* REMPLACE RECURSIVEMENT LES VALEURS DE @OBJECT AVEC LE @SCOPE -> RECURSIF * * @object Objet dans lequel remplacer les valeurs @@ -89,12 +252,21 @@ FormBuilder.prototype.add_definition = function(def_object){ * */ FormBuilder.replaceStatements = function(object, scope){ - /* [0] Initialisation =========================================================*/ + /* (1) Paramètres */ + object = (object instanceof Object) ? object : {}; + scope = (scope instanceof Object) ? scope : {}; + + /* (2) Variables */ var key, r, tmpr, m; var next_scope = scope; + /* (3) On récupère le scope s'il est dans l'attribut 'scope' */ + if( object.hasOwnProperty('scope') && object.scope instanceof Object ) + for( key in object.scope ) + next_scope[key] = object.scope[key]; + /* [1] On remplace les valeurs =========================================================*/ @@ -102,18 +274,17 @@ FormBuilder.replaceStatements = function(object, scope){ /* [1.1] Si c'est une string, on regarde s'il faut remplacer =========================================================*/ - if( key != 'parent' && typeof object[key] == 'string' ){ + if( FormBuilder.ignore_rec.indexOf(key) < 0 && 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; + m = null, r = FormBuilder.regex.array_output_set; var m_arr = []; /* (1.2) Si ça match */ - m = r.exec(object[key]); - if( m !== null ) + if( m = r.exec(object[key]) ) m_arr.push( m[1] ); /* (1.3) Pour chaque match */ @@ -125,6 +296,7 @@ FormBuilder.replaceStatements = function(object, scope){ // {2} on attribue le tableau // object[key] = scope[m_arr[m]]; + console.log('arr', m_arr[m], scope[m_arr[m]]); } @@ -136,22 +308,22 @@ FormBuilder.replaceStatements = function(object, scope){ /* (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; + m = null, r = FormBuilder.regex.primitive_ouput_value; var m_pri = []; /* (1.2) Tant que ça match */ - while( ( m=r.exec(object[key]) ) !== null ) + 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' ); + console.log('pri', m_pri[m], scope[m_pri[m]]); object[key] = object[key].replace(tmpr, scope[m_pri[m]]); } @@ -161,26 +333,61 @@ FormBuilder.replaceStatements = function(object, scope){ continue; - /* (2.3) On cherche toutes les valeurs de TABLEAUX à remplacer + /* (2.3) On cherche toutes les variables REGEX à remplacer + ---------------------------------------------------------*/ + /* (1.1) On récupère les remplacements REGEX */ + m = null, r = FormBuilder.regex.regex_ouput_value, + lasti = -1; + var m_reg = []; + + /* (1.2) Tant que ça match */ + var max = 10; + while( (m=r.exec(object[key])) !== null && max > 0 ){ + // si on boucle, on sort + if( lasti >= r.lastIndex ) break; + lasti = r.lastIndex; + + m_reg.push( m[1] ); + } + + /* (1.3) Pour chaque match */ + for( m in m_reg ){ + // {1} Si la var n'est pas dans le scope // + if( !scope.hasOwnProperty(m_reg[m]) ) + scope[m_reg[m]] = ''; // on met une chaine vide + + // {2} on remplace toutes les occurences par la valeur // + tmpr = new RegExp( "\{\\$"+m_reg[m][1]+"\}", 'g' ); + console.log('reg', m_reg[m], scope); + object[key] = object[key].replace(tmpr, scope[m_reg[m]]); + + } + + /* (1.4) Si on a trouvé qqch, on passe à la clé suivante */ + if( m_reg.length > 0 ) + continue; + + + /* (2.4) 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; + m = null, r = FormBuilder.regex.array_output_value; var m_aval = []; /* (1.2) Tant que ça match */ - while( ( m=r.exec(object[key]) ) !== null ) + 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 + if( !scope.hasOwnProperty(m_aval[m]) ) + scope[m_aval[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]]); + tmpr = new RegExp( "/\{"+m_aval[m]+"\}/", 'g' ); + object[key].replace(tmpr, scope[m_aval[m]]); } @@ -196,32 +403,34 @@ FormBuilder.replaceStatements = function(object, scope){ /* (1) Ajout des variables de type '$nomVar' ---------------------------------------------------------*/ - if( FormBuilder.prototype.regex.primitive_input_key.test(key) ) + if( FormBuilder.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) ) + else if( FormBuilder.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' ){ + /* S'il ne s'agit d'un attribut qu'on peut parcourir */ + if( FormBuilder.ignore_rec.indexOf(key) < 0 ){ /* Si c'est un objet ou tableau, on lance récursivement */ - if( object[key] instanceof Object || object[key] instanceof Array ) + if( object[key] instanceof Object || object[key] instanceof Array ){ + object[key] = FormBuilder.replaceStatements(object[key], next_scope); + } + } } + return object; }; diff --git a/js/lib/form-builder/main-min.js b/js/lib/form-builder/main-min.js index ecbf6c7..10355c9 100644 --- a/js/lib/form-builder/main-min.js +++ b/js/lib/form-builder/main-min.js @@ -1 +1,5 @@ -document.body.innerHTML="";"use strict";var form={node:"h4",attributes:{"data-icon":"o","class":"new-contact color2"},children:[{node:"input:hidden",$name:"uid",$value:"{uid}"},{node:"input:hidden",$name:"call",$value:"{call}"},{node:"input:hidden",$name:"sms",$value:"{sms}"},{node:"input:hidden",$name:"countcall",$value:"{countcall}"},{node:"input:hidden",$name:"countsms",$value:"{countsms}"},{node:"input:text",$name:"number",$value:"{number}"},{node:"custom-select",$name:"existing",$$options:"{{options}}"}]}; +document.body.innerHTML="";"use strict"; +var default_definition={input:{node_type:"input",node_attr:"{__attributes__}"},"/^h([1-6])$/":{node_type:"h{$1}",node_attr:"{__attributes__}",node_children:"{__children__}"},br:{node_type:"br"},option:{node_type:"option",node_attr:"{__attributes__}",node_children:"{__children__}"},select:{node_type:"select",node_attr:"{__attributes__}",node_children:"{__children__}"},span:{node_type:"span",node_attr:"{__attributes__}",node_children:"{__children__}"}},custom_definition={"/^input:([a-z]+)$/":{node:"input", +attributes:{type:"{$1}","data-name":"{name}",value:"{value}",placeholder:"{placeholder}"},next_nodes:[{node:"br"}]},"custom-select":{node:"span",attributes:{"class":"select-container nobold"},children:[{node:"select",attributes:{"data-name":"{name}"},children:[{node:"option",attribute:{value:"{options.value}"},text:"{options.value}",repeat:"{{options}}"}]}],next_nodes:[{node:"br"}]}},form={node:"h4",attributes:{"data-icon":"o","class":"new-contact color2"},children:[{node:"input:hidden",$name:"uid", +$value:"{uid}"},{node:"input:hidden",$name:"call",$value:"{call}"},{node:"input:hidden",$name:"sms",$value:"{sms}"},{node:"input:hidden",$name:"countcall",$value:"{countcall}"},{node:"input:hidden",$name:"countsms",$value:"{countsms}"},{node:"input:hidden",$name:"total",$value:"{countcall} calls + {countsms} sms to {number}"},{node:"input:text",$name:"number",$value:"{number}"},{node:"custom-select",$name:"existing",$$options:"{{options}}"}]},fb=new FormBuilder(document.body,form);fb.add_definition(default_definition); +fb.add_definition(custom_definition);fb.build({uid:1,call:2,sms:3,countcall:4,countsms:5,number:"01 02 03 04 05",options:["a","b","c","d"]}); diff --git a/js/lib/form-builder/main.js b/js/lib/form-builder/main.js index b783ac7..af8bf3e 100644 --- a/js/lib/form-builder/main.js +++ b/js/lib/form-builder/main.js @@ -7,15 +7,15 @@ document.body.innerHTML = ''; var default_definition = { 'input': { node_type: 'input', node_attr: '{__attributes__}' }, - 'h/^([1-6])$/': { node_type: 'h{$1}', node_attr: '{__attributes__}', node_children: '{__children__}' }, - 'br': { node_type: 'br', }, + '/^h([1-6])$/': { node_type: 'h{$1}', node_attr: '{__attributes__}', node_children: '{__children__}' }, + 'br': { node_type: 'br' }, 'option': { node_type: 'option', node_attr: '{__attributes__}', node_children: '{__children__}' }, 'select': { node_type: 'select', node_attr: '{__attributes__}', node_children: '{__children__}' }, 'span': { node_type: 'span', node_attr: '{__attributes__}', node_children: '{__children__}' } }; var custom_definition = { - 'input:/^([a-z]+)$/': { + '/^input:([a-z]+)$/': { node: 'input', attributes: { 'type': '{$1}', @@ -58,6 +58,7 @@ var form = { { node: 'input:hidden', $name: 'sms', $value: '{sms}' }, { node: 'input:hidden', $name: 'countcall', $value: '{countcall}' }, { node: 'input:hidden', $name: 'countsms', $value: '{countsms}' }, + { node: 'input:hidden', $name: 'total', $value: '{countcall} calls + {countsms} sms to {number}' }, { node: 'input:text', $name: 'number', $value: '{number}' }, @@ -74,3 +75,12 @@ var form = { var fb = new FormBuilder(document.body, form); fb.add_definition(default_definition); fb.add_definition(custom_definition); +fb.build({ + uid: 1, + call: 2, + sms: 3, + countcall: 4, + countsms: 5, + number: '01 02 03 04 05', + options: ['a', 'b', 'c', 'd'] +});