From 6ab5dec529dd8dfd4c30380a813ee1a162e60e09 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Fri, 16 Sep 2016 16:52:41 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9veloppement=20premier=20jet=20(pas=20du?= =?UTF-8?q?=20tout=20abouti)=20form-builder.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/form-builder/behaviour.js | 135 +++++++++++++++++++ doc/form-builder/constraints-min.js | 1 + doc/form-builder/constraints.js | 12 ++ js/lib/form-builder-min.js | 5 +- js/lib/form-builder.js | 194 +++++++++++++--------------- js/lib/form-builder/main-min.js | 2 +- js/lib/form-builder/main.js | 18 +++ 7 files changed, 257 insertions(+), 110 deletions(-) create mode 100644 doc/form-builder/behaviour.js create mode 100644 doc/form-builder/constraints-min.js create mode 100644 doc/form-builder/constraints.js diff --git a/doc/form-builder/behaviour.js b/doc/form-builder/behaviour.js new file mode 100644 index 0000000..7e6a210 --- /dev/null +++ b/doc/form-builder/behaviour.js @@ -0,0 +1,135 @@ +//

+// +// \n+ +// \n+ +// \n+ +// +// \n+ +// \n+ +// +// +// +// \n+ +// +//     ou    \n+ +// +// +// +// +//

\n\n); + + +////////////// +// USE CASE // +////////////// + + +//////////////// +// PARAMETERS // +//////////////// +// {xx} - where 'xx' is a variable name which will be (literally) replaced by the $xx given parameter (if missing, by an empty string) +// note that the parameter in a higher level have to be preceeded by '$' +// /!\ warning: the variable name must only contain [ lowercase_letters, hyphens ] +// +// {{zz}} - where 'zz' is an array variable name which will be (for each item) replaced by the $$zz given array (see next statement) +// note that the parameter in a higher level have to be preceeded by '$$' +// +// {zz.xx} - where 'zz' is an array name + 'xx' is an index name of this array's items, it will be replaced by zz[0][xx], then zz[1][xx], etc +// note that this is the only case when the dot (.) is allowed in variable naming +// +// {__attributes__} - default variable name for the attributes +// {__children__} - default variable name for the children + +///////////////////////// +// REGURAL EXPRESSIONS // +///////////////////////// +// /^yy$/ - where '^yy$' is a regular expression, matches will be added to the input parameters named like so : '$1', '$2' +// note that it have to match the whole string and begin with '/^' and end with '$/' + + +//////////////////////// +// DEFAULT ATTRIBUTES // +//////////////////////// +// +// node - is a "key" of a definition that describes an element +// next_nodes - the set of the element's next elements +// prev_nodes - the set of the element's previous elements +// node_type - real node-type (to create element in javascript) +// node_attr - real attributes array (to create element in javascript) +// node_children - real children arary (to create element in javascript) +// text - overrides all to specify the text content corresponding of the element +// children - the set of the element's children (doesn't check if it is a container or not) +// attributes - attributes are replaced in a lower level +// listeners - contains the associations: 'eventName' => 'listenerFuncName' +// $xxx - where 'xxx' is a variable name that will be replaced in a lower level +// $$zzz - where 'zzz' is an array variable name that will be split in a lower level +// repeat - must contain a number or an array name (such as: "{{tabname}}") +// 1- if an array is given, the element will be repeated for each item of the array +// 2- if a number @n is given, the element will be repeated @n times + +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__}' } +}; + +var 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' }] + } +}; + +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}}' } + ] +}; + +// \n+ diff --git a/doc/form-builder/constraints-min.js b/doc/form-builder/constraints-min.js new file mode 100644 index 0000000..c820b42 --- /dev/null +++ b/doc/form-builder/constraints-min.js @@ -0,0 +1 @@ +function formatObject(a){for(var b in a)formatObject(a[b]),a[b].parent=a}; diff --git a/doc/form-builder/constraints.js b/doc/form-builder/constraints.js new file mode 100644 index 0000000..34fd7b7 --- /dev/null +++ b/doc/form-builder/constraints.js @@ -0,0 +1,12 @@ +"use strict"; + +/* [1] Gestion de la référence vers le parent +=========================================================*/ +function formatObject(object){ + + for( var i in object ){ + formatObject(object[i]); + object[i].parent = object; + } + +} diff --git a/js/lib/form-builder-min.js b/js/lib/form-builder-min.js index fad13a2..312f11f 100644 --- a/js/lib/form-builder-min.js +++ b/js/lib/form-builder-min.js @@ -1,2 +1,3 @@ -var default_definition={input:{html:""},"h/^([1-6])$/":{html:"{{__children__}}"},br:{html:"
"},option:{html:""},select:{html:""}},custom_definition={"input:/^([a-z]+)$/":{node:"input",attributes:{type:"{{$1}}","data-name":"{{name}}",value:"{{value}}",placeholder:"{{placeholder}}"},next_child:{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:text",$name:"number",$value:"{{number}}"}]}; +var FormBuilder=function(a,b){this.parent_element=a;this.form_object=b;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-]+)\}\}/g,array_output_value:/\{([a-z-]+)\.([a-z-]+)\}/g,array_input_key:/^\$\$([a-z-]+)$/}}; +FormBuilder.formatFormObject=function(a){if(a.hasOwnProperty("children"))for(var b in a.children)a.children[b].parent=a,FormBuilder.formatFormObject(a.children[b]);return a};FormBuilder.replaceStatements=function(a,b){for(var c in a)"string"==typeof a[c]&&(/a/.exec(a[c]),console.log(RegExp.$0));return a}; diff --git a/js/lib/form-builder.js b/js/lib/form-builder.js index 4d3a69e..b35687a 100644 --- a/js/lib/form-builder.js +++ b/js/lib/form-builder.js @@ -1,118 +1,98 @@ -//

-// -// \n+ -// \n+ -// \n+ -// -// \n+ -// \n+ -// -// -// -// \n+ -// -//     ou    \n+ -// -// -// -// -//

\n\n); +/* 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; -////////////// -// USE CASE // -////////////// - - -//////////////// -// PARAMETERS // -//////////////// -// {xx} - where 'xx' is a variable name which will be (literally) replaced by the $xx given parameter (if missing, by an empty string) -// note that the parameter in a higher level have to be preceeded by '$' -// /!\ warning: the variable name must only contain [ lowercase_letters, hyphens ] -// -// {{zz}} - where 'zz' is an array variable name which will be (for each item) replaced by the $$zz given array (see next statement) -// note that the parameter in a higher level have to be preceeded by '$$' -// -// {zz.xx} - where 'zz' is an array name + 'xx' is an index name of this array's items, it will be replaced by zz[0][xx], then zz[1][xx], etc -// note that this is the only case when the dot (.) is allowed in variable naming -// -// {__attributes__} - default variable name for the attributes -// {__children__} - default variable name for the children - -///////////////////////// -// REGURAL EXPRESSIONS // -///////////////////////// -// /^yy$/ - where '^yy$' is a regular expression, matches will be added to the input parameters named like so : '$1', '$2' -// note that it have to match the whole string and begin with '/^' and end with '$/' - - -//////////////////////// -// DEFAULT ATTRIBUTES // -//////////////////////// -// -// @node - is a "key" of a definition that describes an element -// @html - overrides all to specify the html content corresponding of the element -// @children - the set of the element's children (doesn't check if it is a container or not) -// @data - parameters to pass to a lower level -// @attributes - attributes are replaced in a lower level -// @listeners - contient les associations 'eventName' => 'listenerFuncName' -// $xxx - where 'xxx' is a variable name that will be replaced in a lower level -// $$zzz - where 'zzz' is an array variable name that will be split in a lower level - -var default_definition = { - 'input': { html: '' }, - 'h/^([1-6])$/': { html: '{__children__}' }, - 'br': { html: '
' }, - 'option': { html: '' }, - 'select': { html: '' }, - 'span': { html: '{__children__}' } + /* (3) On formatte l'objet (référence des 'children' vers le 'parent') */ + FormBuilder.formatFormObject(this.form_object); }; -var custom_definition = { - 'input:/^([a-z]+)$/': { - node: 'input', - attributes: { - 'type': '{$1}', - 'data-name': '{name}', - 'value': '{value}', - 'placeholder': '{placeholder}' }, - next_child: { 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}' }, - children: { html: '{options.value}' } } }, - next_child: { node: 'br' } }, +/* 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-]+)\}\}/g, + 'array_output_value': /\{([a-z-]+)\.([a-z-]+)\}/g, + 'array_input_key': /^\$\$([a-z-]+)$/ + } }; -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}' }, +/* FORMATTE L'OBJET DE DESCRIPTION DU FORMULAIRE +* +*/ +FormBuilder.formatFormObject = function(object){ - { node: 'custom-select', $name: 'number', $$options: '{{options}}' } - ] + /* (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; }; -// \n+ + +/* 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){ + + /* [1] Pour chaque attribut (value is string) + =========================================================*/ + for( var key in object ){ + + /* (1) Si la valeur est une string */ + if( typeof object[key] == 'string' ){ + + /* (2) On cherche toutes les variables à remplacer */ + var matches = []; + /a/.exec(object[key]); + console.log(RegExp.$0); + + + } + + } + + return object; +}; diff --git a/js/lib/form-builder/main-min.js b/js/lib/form-builder/main-min.js index 415d54a..ecbf6c7 100644 --- a/js/lib/form-builder/main-min.js +++ b/js/lib/form-builder/main-min.js @@ -1 +1 @@ -document.body.innerHTML=""; +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}}"}]}; diff --git a/js/lib/form-builder/main.js b/js/lib/form-builder/main.js index 6592bd4..807a973 100644 --- a/js/lib/form-builder/main.js +++ b/js/lib/form-builder/main.js @@ -1,3 +1,21 @@ /* [0] On efface le =========================================================*/ 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}}' } + ] +};