├── .nojekyll ├── .idea ├── .name ├── encodings.xml ├── vcs.xml ├── modules.xml └── NS.UI.Formbuilder.iml ├── .gitignore ├── assets ├── images │ ├── Datas.png │ ├── back.jpg │ ├── handle.png │ ├── loader.gif │ ├── thesaurus.png │ ├── down_arrow_white.png │ ├── favicon │ │ └── favicon.ico │ └── logout.svg ├── js │ ├── editionPageModule │ │ ├── views │ │ │ ├── loaders │ │ │ │ ├── GenericLoader.js │ │ │ │ ├── PositionEventsLoader.js │ │ │ │ ├── EcoreleveLoader.js │ │ │ │ ├── PositionLoader.js │ │ │ │ ├── EcollectionLoader.js │ │ │ │ ├── PositionTypesLoader.js │ │ │ │ ├── ContextLoader.js │ │ │ │ └── TrackLoader.js │ │ │ └── FieldViews.js │ │ ├── templates │ │ │ ├── FieldTemplateEditorOnly.html │ │ │ ├── OnBlurPage.html │ │ │ ├── FieldTemplate.html │ │ │ ├── GridRowActions.html │ │ │ ├── FormPanelView.html │ │ │ ├── GridRow.html │ │ │ └── EditionPageLayout.html │ │ ├── editor │ │ │ ├── AutoCompleteEditor.html │ │ │ ├── AutocompleteEditor.html │ │ │ ├── OnBlurEditor.html │ │ │ ├── NumberEditor.html │ │ │ ├── CheckboxEditor.html │ │ │ ├── AppearanceEditor.html │ │ │ ├── EditModeEditor.html │ │ │ ├── DataEntrySource.html │ │ │ ├── TreeEditor.html │ │ │ ├── LanguagesEditor.html │ │ │ ├── ChoicesEditorRow.html │ │ │ ├── ChoicesEditor.html │ │ │ ├── AppearanceEditor.js │ │ │ ├── EditModeEditor.js │ │ │ ├── DataEntrySource.js │ │ │ ├── CheckboxEditor.js │ │ │ ├── CustomTextEditor.js │ │ │ ├── AutoCompleteEditor.js │ │ │ ├── OnBlurEditor.js │ │ │ ├── ObjectPickerEditor.js │ │ │ ├── ChildFormEditor.js │ │ │ ├── NumberEditor.js │ │ │ ├── ChoicesEditor.js │ │ │ └── LanguagesEditor.js │ │ ├── collection │ │ │ ├── PositionEventsCollection.js │ │ │ ├── staticInputs │ │ │ │ ├── ContextStaticInputs.js │ │ │ │ └── TrackStatics.js │ │ │ ├── mandatoryInputs │ │ │ │ ├── ContextMandatoryInputs.js │ │ │ │ └── EcoreleveMandatory.js │ │ │ ├── CollectionExtention.js │ │ │ ├── PositionTypesCollection.js │ │ │ └── EcoreleveCollection.js │ │ └── models │ │ │ └── ExtraContextProperties │ │ │ ├── PositionTypesProperties.js │ │ │ ├── EcollectionProperties.js │ │ │ ├── GenericProperties.js │ │ │ ├── PositionProperties.js │ │ │ ├── PositionEventsProperties.js │ │ │ ├── TrackProperties.js │ │ │ ├── ReproProperties.js │ │ │ └── ExtraProperties.js │ ├── homePageModule │ │ ├── templates │ │ │ ├── RowControls.html │ │ │ ├── HomePageLayout.html │ │ │ ├── LeftPanelView.html │ │ │ └── GridView.html │ │ ├── layout │ │ │ └── HomePageLayout.js │ │ ├── models │ │ │ └── FormModel.js │ │ └── views │ │ │ └── LeftPanelView.js │ ├── auth.js │ ├── onblur-page.js │ ├── Translater.js │ ├── config.js │ └── formbuilder.js └── stylesheet │ ├── fonts │ ├── PROXIMANOVALIGHT.OTF │ ├── PROXIMA NOVA LIGHT.OTF │ ├── PROXIMANOVAREGULAR.OTF │ └── PROXIMA NOVA REGULAR.OTF │ ├── app │ ├── editionPage │ │ ├── all.less │ │ ├── components.less │ │ ├── modal.less │ │ └── grid.less │ ├── homePage │ │ ├── all.less │ │ └── leftPanel.less │ └── formbuilder.less │ ├── onblur-editor.less │ ├── components │ ├── all.less │ ├── form.less │ ├── spinner.less │ ├── common.less │ ├── scrollbar.less │ ├── pictos.less │ ├── modal.less │ ├── buttons.less │ ├── fields.less │ └── navbar.less │ ├── all.less │ └── mainStyles │ ├── position.less │ ├── generatedStyle.less │ ├── fonts.less │ └── main.less ├── fonts ├── PROXIMANOVALIGHT.OTF ├── PROXIMA NOVA LIGHT.OTF ├── PROXIMANOVAREGULAR.OTF └── PROXIMA NOVA REGULAR.OTF ├── ressources ├── autocomplete │ ├── units.json │ ├── example.json │ ├── keywords.json │ ├── users.json │ └── forms.json ├── fieldConfiguration │ └── preConfiguredField.json ├── templates │ └── templates.json ├── forms │ └── importExample.json └── plugins │ └── fullNameField.js ├── docs ├── Aide a la configuration et au developpement sur Formbuilder.docx └── deprecated │ ├── notes.md │ ├── index.md │ ├── dependancies.md │ ├── installation.md │ ├── examples │ └── awesomeField │ │ ├── AwesomeFieldView.js │ │ ├── AwesomeField.js │ │ └── AwesomeFieldView.html │ ├── modules.md │ ├── backend.md │ ├── events.md │ └── fields.md ├── package.json ├── README.md ├── index.html └── Gruntfile.js /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | NS.UI.Formbuilder -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | web.config 3 | compressed/ 4 | assets/js/app-config.js -------------------------------------------------------------------------------- /assets/images/Datas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/Datas.png -------------------------------------------------------------------------------- /assets/images/back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/back.jpg -------------------------------------------------------------------------------- /assets/images/handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/handle.png -------------------------------------------------------------------------------- /assets/images/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/loader.gif -------------------------------------------------------------------------------- /fonts/PROXIMANOVALIGHT.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/fonts/PROXIMANOVALIGHT.OTF -------------------------------------------------------------------------------- /ressources/autocomplete/units.json: -------------------------------------------------------------------------------- 1 | { 2 | "options" : [ 3 | "meters", "days", "months", "weeks", "percentage" 4 | ] 5 | } -------------------------------------------------------------------------------- /assets/images/thesaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/thesaurus.png -------------------------------------------------------------------------------- /fonts/PROXIMA NOVA LIGHT.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/fonts/PROXIMA NOVA LIGHT.OTF -------------------------------------------------------------------------------- /fonts/PROXIMANOVAREGULAR.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/fonts/PROXIMANOVAREGULAR.OTF -------------------------------------------------------------------------------- /ressources/autocomplete/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "options" : [ 3 | "yes", "no", "maybe", "Take a break" 4 | ] 5 | } -------------------------------------------------------------------------------- /fonts/PROXIMA NOVA REGULAR.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/fonts/PROXIMA NOVA REGULAR.OTF -------------------------------------------------------------------------------- /assets/images/down_arrow_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/down_arrow_white.png -------------------------------------------------------------------------------- /assets/images/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/images/favicon/favicon.ico -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/GenericLoader.js: -------------------------------------------------------------------------------- 1 | define([], function () { 2 | return { 3 | loadFormData: function() {} 4 | }; 5 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/PositionEventsLoader.js: -------------------------------------------------------------------------------- 1 | define([], function () { 2 | return { 3 | loadFormData: function() {} 4 | }; 5 | }); -------------------------------------------------------------------------------- /assets/stylesheet/fonts/PROXIMANOVALIGHT.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/stylesheet/fonts/PROXIMANOVALIGHT.OTF -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/EcoreleveLoader.js: -------------------------------------------------------------------------------- 1 | define([], function () { 2 | return { 3 | loadFormData: function() {} 4 | }; 5 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/PositionLoader.js: -------------------------------------------------------------------------------- 1 | define([], function () { 2 | return { 3 | loadFormData: function() {} 4 | }; 5 | }); -------------------------------------------------------------------------------- /assets/stylesheet/fonts/PROXIMA NOVA LIGHT.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/stylesheet/fonts/PROXIMA NOVA LIGHT.OTF -------------------------------------------------------------------------------- /assets/stylesheet/fonts/PROXIMANOVAREGULAR.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/stylesheet/fonts/PROXIMANOVAREGULAR.OTF -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/EcollectionLoader.js: -------------------------------------------------------------------------------- 1 | define([], function () { 2 | return { 3 | loadFormData: function() {} 4 | }; 5 | }); 6 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/PositionTypesLoader.js: -------------------------------------------------------------------------------- 1 | define([], function () { 2 | return { 3 | loadFormData: function() {} 4 | }; 5 | }); -------------------------------------------------------------------------------- /assets/stylesheet/fonts/PROXIMA NOVA REGULAR.OTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/assets/stylesheet/fonts/PROXIMA NOVA REGULAR.OTF -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/FieldTemplateEditorOnly.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | -------------------------------------------------------------------------------- /assets/stylesheet/app/editionPage/all.less: -------------------------------------------------------------------------------- 1 | @import url('layout.less'); 2 | @import url('formView.less'); 3 | @import url('components.less'); 4 | @import url('modal.less'); 5 | -------------------------------------------------------------------------------- /assets/js/homePageModule/templates/RowControls.html: -------------------------------------------------------------------------------- 1 |
4 |
-------------------------------------------------------------------------------- /assets/stylesheet/app/homePage/all.less: -------------------------------------------------------------------------------- 1 | // Collects all homepage less files 2 | 3 | #homePageRegion { 4 | height: 100%; 5 | } 6 | 7 | @import url('grid.less'); 8 | @import url('leftPanel.less'); 9 | -------------------------------------------------------------------------------- /docs/Aide a la configuration et au developpement sur Formbuilder.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturalsolutions/NS.UI.FormBuilder/HEAD/docs/Aide a la configuration et au developpement sur Formbuilder.docx -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /assets/js/homePageModule/templates/HomePageLayout.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 |
8 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/AutoCompleteEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/AutocompleteEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/OnBlurEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
-------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/NumberEditor.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /assets/stylesheet/onblur-editor.less: -------------------------------------------------------------------------------- 1 | .onblur-editor-modal { 2 | background: rgb(255, 255, 255); 3 | position: absolute; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | z-index: 100; 9 | } 10 | 11 | .onblur-editor { 12 | 13 | } -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/OnBlurPage.html: -------------------------------------------------------------------------------- 1 |
2 | Paramétrage de {{ message }} 3 |
4 | 5 | 6 |
-------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/CheckboxEditor.html: -------------------------------------------------------------------------------- 1 |
2 | checked<%}%> /> 3 | 4 |
-------------------------------------------------------------------------------- /docs/deprecated/notes.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | To run properly, your Formbuilder needs to be correctly configured (You must setup the config and app-config files) 4 | 5 | Make sure to have at least one existing context setted, otherwise you will not be able to use the formbuilder fully. 6 | 7 | Enjoy ! 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/deprecated/index.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | - [Application architecture](modules.md) 4 | 5 | - [Backbone events communication](events.md) 6 | 7 | - [How to add a new field type](fields.md) 8 | 9 | - [Dependancies](dependancies.md) 10 | 11 | - [Backend connection](backend.md) 12 | 13 | - [Notes](notes.md) 14 | -------------------------------------------------------------------------------- /.idea/NS.UI.Formbuilder.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/stylesheet/components/all.less: -------------------------------------------------------------------------------- 1 | @import url('common.less'); 2 | @import url('buttons.less'); 3 | @import url('fields.less'); 4 | @import url('modal.less'); 5 | @import url('navbar.less'); 6 | @import url('form.less'); 7 | @import url('spinner.less'); 8 | @import url('pictos.less'); 9 | @import url('scrollbar.less'); 10 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/FieldTemplate.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 |
<%= help %>
7 |
8 |
9 | -------------------------------------------------------------------------------- /ressources/autocomplete/keywords.json: -------------------------------------------------------------------------------- 1 | { 2 | "options": [ 3 | "scientific", 4 | "vertebral", 5 | "outarde", 6 | "MICELI", 7 | "prunelle", 8 | "nonspiral", 9 | "attuned", 10 | "crossbench", 11 | "organicismal", 12 | "abutment", 13 | "description", 14 | "manasic", 15 | "gauss", 16 | "bugong" 17 | ] 18 | } -------------------------------------------------------------------------------- /assets/stylesheet/all.less: -------------------------------------------------------------------------------- 1 | /* ********************************************* 2 | This file import all less file 3 | */ 4 | 5 | // Import comman styles 6 | @import url('mainStyles/main.less'); 7 | 8 | // Import components style 9 | @import url('components/all.less'); 10 | 11 | // Import app styles 12 | @import url('app/formbuilder.less'); 13 | 14 | @import url('onblur-editor.less'); 15 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/GridRowActions.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /assets/images/logout.svg: -------------------------------------------------------------------------------- 1 | 2 | log-out -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/AppearanceEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | <% var checked = model.get('atBeginingOfLine')? "checked": ""; %> 4 |
5 | /> 6 | 7 |
8 |
9 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/EditModeEditor.html: -------------------------------------------------------------------------------- 1 |
2 | <% for (var i in items) { 3 | var bit = items[i]; 4 | var bitId = id + bit; 5 | var checked = values[bit] ? "checked": null; 6 | %> 7 |
8 | /> 9 | 10 |
11 | <% } %> 12 |
13 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/DataEntrySource.html: -------------------------------------------------------------------------------- 1 |
2 | <% for (var i in items) { 3 | var bit = items[i]; 4 | var bitId = id + bit; 5 | var checked = values[bit] ? "checked": null; 6 | %> 7 |
8 | /> 9 | 10 |
11 | <% } %> 12 |
13 | -------------------------------------------------------------------------------- /ressources/autocomplete/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "options": [ 3 | "Keenan Amaral", 4 | "Bertha Litherland", 5 | "Hilary Krone,", 6 | "Nadine Wiesen", 7 | "Reid Saleh", 8 | "Theo Rehm", 9 | "Eldridge Engler", 10 | "Sherman Hellwig", 11 | "Jodee Koen", 12 | "In Bushey", 13 | "Adell Zhu", 14 | "Basil Leist", 15 | "Cyndi Grote", 16 | "Rosalina Hatfield", 17 | "Efren Grahn", 18 | "Edmund Morrison", 19 | "Anne Mair", 20 | "Genesis Smit", 21 | "Melodie Peach", 22 | "Carolina Mccardle" 23 | ] 24 | } -------------------------------------------------------------------------------- /assets/stylesheet/mainStyles/position.less: -------------------------------------------------------------------------------- 1 | 2 | // This file contains main CSS class for position and sizing 3 | 4 | // Position 5 | .center { text-align : center; } 6 | .fLeft { float : left; } 7 | .left { text-align : left !important; } 8 | .right { text-align : right !important; } 9 | 10 | // Sizing margin and ppading 11 | .noMargin { margin : 0 !important; } 12 | .noPadding { padding : 0 !important; } 13 | .noMarginLeft { margin-left : 0 !important; } 14 | .noMarginTop { margin-top : 0 !important; } -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/TreeEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading... (close & re-open)
13 |
14 | -------------------------------------------------------------------------------- /assets/stylesheet/app/editionPage/components.less: -------------------------------------------------------------------------------- 1 | .ui-autocomplete { 2 | background : white; 3 | list-style-type : none; 4 | color : black; 5 | z-index : 255; 6 | padding-left : 0; 7 | border : 1px #d9d9d9 solid; 8 | overflow: auto; 9 | max-height:300px; 10 | max-width: 350px !important; 11 | width: max-content !important; 12 | 13 | li { 14 | .exo !important; 15 | padding : 8px; 16 | &:hover { 17 | cursor : pointer; 18 | background : #bfddf5; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/LanguagesEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | <% 4 | var first = true; 5 | for (var lang in languages) { 6 | var options = languages[lang]; 7 | var langId = id + lang; 8 | var required = options.required; 9 | %> 10 | 14 | <% } %> 15 |
11 | 12 | 13 |
16 |
17 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/ChoicesEditorRow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | checked<% } %> /> 4 | 5 | <% for (var i in languages) { 6 | var lang = languages[i]; 7 | var value = choice[lang]; 8 | %> 9 | 10 | 11 | 12 | <% } %> 13 | 14 | 15 | 16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/deprecated/dependancies.md: -------------------------------------------------------------------------------- 1 | # Technologies used 2 | 3 | - jquery 4 | - jquery-ui 5 | - underscore 6 | - backbone 7 | - backbone-forms 8 | - bootstrapAdapter 9 | - backgrid 10 | - marionette 11 | - backbone.radio, see [events docs](events.md) 12 | - bootstrap 13 | - fuelux 14 | - blobjs 15 | - fancytree 16 | - i18n 17 | - font-awesome 18 | - moment 19 | - requirejs 20 | - perfect-scrollba 21 | - [typeahead](https://github.com/bassjobsen/Bootstrap-3-Typeahead.git) 22 | - jquery-simple-slider 23 | - autocompleteTreeview 24 | - rangeslider.js 25 | - bootstrap-select 26 | - sweetalert 27 | - [reneco-fonts](https://github.com/NaturalSolutions/RenecoFonts.git) 28 | - filesaver 29 | 30 | 31 | back to [summary](index.md) -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/ChoicesEditor.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | <% for (var i in languages) { 6 | var lang = languages[i]; 7 | %> 8 | 9 | <% } %> 10 | 11 | 12 | 13 | <% for (var i in choices) { 14 | var choice = choices[i]; 15 | %> 16 | <%= renderChoice(choice) %> 17 | <% } %> 18 |
 <%= lang.toUpperCase() %> 
19 |
20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /docs/deprecated/installation.md: -------------------------------------------------------------------------------- 1 | # Get the formbuilder rocks 2 | 3 | First you need to clone our repo (we'll publish on bower shortly): 4 | 5 | git clone https://github.com/NaturalSolutions/NS.UI.FormBuilder.git 6 | 7 | Install npm developpement tools 8 | 9 | (sudo) npm install 10 | 11 | Now you've to install library dependancies with bower 12 | 13 | bower install 14 | 15 | And to finish you can clean library folder with bower_clean task 16 | 17 | grunt bower_clean 18 | 19 | 20 | ## Compile style file 21 | 22 | Toget production style file run this grunt tash 23 | 24 | grunt less 25 | 26 | ## Compile JavaScript file 27 | 28 | If you want to compile JavaScript file you can use RequireJS optimizer like this 29 | 30 | rjs -o build/build.js 31 | 32 | 33 | back to [summary](index.md) 34 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/FormPanelView.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | <% for (var i in columns) { 8 | var col = columns[i]; 9 | %> 10 | 11 | <% } %> 12 | 13 | 14 | 15 |
type<%= col %>options
16 |
17 | 18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /assets/stylesheet/components/form.less: -------------------------------------------------------------------------------- 1 | input, select, textarea { 2 | border-radius : 2.5px !important; 3 | } 4 | 5 | 6 | .datepicker-editor { 7 | width: 100%; 8 | position: relative; 9 | 10 | button { 11 | height: 34px; 12 | width: 34px; 13 | 14 | margin-left: 2px; 15 | float : right; 16 | color : black; 17 | background : transparent; 18 | border : 1px #ddd solid; 19 | color : #ddd; 20 | } 21 | 22 | input { 23 | //width: calc(100% - 30px); 24 | width: 85%; 25 | height: 34px; 26 | } 27 | } 28 | 29 | .general-error { 30 | background : transparent; 31 | box-shadow : 0 0 0 1px #dbb1b1 inset,0 1px 2px 0 rgba(0,0,0,.05); 32 | color : #a94442; 33 | min-height : 1em; 34 | padding : 1em 1.5em; 35 | line-height: 1.3; 36 | display : none; 37 | 38 | h2 { 39 | text-align: left !important; 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /assets/stylesheet/components/spinner.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Spinner loading style 4 | // 5 | 6 | .spinner { 7 | width : 50px; 8 | height : 30px; 9 | text-align : center; 10 | font-size : 10px; 11 | line-height : 95px; 12 | margin-right: 10px; 13 | 14 | &.end { visibility: hidden; } 15 | 16 | &>div { 17 | background-color: #eee; 18 | height : 100%; 19 | width : 6px; 20 | display : inline-block; 21 | animation : stretchdelay 1.2s infinite ease-in-out; 22 | } 23 | 24 | .rect2 { animation-delay: -1.1s; } 25 | 26 | .rect3 { animation-delay: -1.0s; } 27 | 28 | .rect4 { animation-delay: -0.9s; } 29 | 30 | .rect5 { animation-delay: -0.8s; } 31 | 32 | } 33 | 34 | // Keyframe animation 35 | @keyframes stretchdelay { 36 | 0%, 40%, 100% { transform: scaleY(0.4); } 37 | 20% { transform: scaleY(1.0); } 38 | } -------------------------------------------------------------------------------- /docs/deprecated/examples/awesomeField/AwesomeFieldView.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is an example view for awesome field type 3 | * Put this file on view/fields forlder to add it on the application 4 | */ 5 | define([ 6 | 'jquery', 7 | 'underscore', 8 | 'backbone', 9 | 'editionPageModule/views/fieldViews/BaseView', 10 | 'text!editionPageModule/templates/fields/AwesomeFieldView.html' 11 | ], function($, _, Backbone, BaseView, viewTemplate) { 12 | 13 | var AwesomeFieldView = BaseView.extend({ 14 | 15 | initialize : function(options) { 16 | var opt = options; 17 | opt.template = viewTemplate; 18 | BaseView.prototype.initialize.apply(this, [opt]); 19 | }, 20 | 21 | render : function() { 22 | BaseView.prototype.render.apply(this, arguments); 23 | } 24 | 25 | }); 26 | 27 | return AwesomeFieldView; 28 | 29 | }); -------------------------------------------------------------------------------- /assets/stylesheet/mainStyles/generatedStyle.less: -------------------------------------------------------------------------------- 1 | .generate-columns(5); 2 | 3 | .generate-columns(@n, @i: 0) when (@i =< @n) { 4 | 5 | @num : @i * 5; 6 | 7 | .margin@{num} { margin : (@i * 5px) !important; } 8 | .marginBottom@{num} { margin-bottom : (@i * 5px) !important; } 9 | .marginTop@{num} { margin-top : (@i * 5px) !important; } 10 | .marginLeft@{num} { margin-left : (@i * 5px) !important; } 11 | .marginRight@{num} { margin-right : (@i * 5px) !important; } 12 | 13 | .padding@{num} { padding : (@i * 5px) !important; } 14 | .paddingBottom@{num} { padding-bottom : (@i * 5px) !important; } 15 | .paddingTop@{num} { padding-top : (@i * 5px) !important; } 16 | .paddingLeft@{num} { padding-left : (@i * 5px) !important; } 17 | .paddingRight@{num} { padding-right : (@i * 5px) !important; } 18 | 19 | .generate-columns(@n, (@i + 1)); 20 | } -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/ContextLoader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | './TrackLoader', 7 | './EcoreleveLoader', 8 | './EcollectionLoader', 9 | './PositionEventsLoader', 10 | './PositionTypesLoader', 11 | 'auth' 12 | ], function (TrackLoader, EcoreleveLoader, EcollectionLoader, PositionEventsLoader, PositionTypesLoader, auth) { 13 | 14 | var Loaders = { 15 | "track" : TrackLoader, 16 | "ecoreleve" : EcoreleveLoader, 17 | "ecollection" : EcollectionLoader, 18 | "positionevents" : PositionEventsLoader, 19 | "positiontypes" : PositionTypesLoader 20 | }; 21 | 22 | return { 23 | loadFormData: function(context, form, URLoptions) { 24 | var ctxLoader = Loaders[context]; 25 | if (!ctxLoader) return; 26 | 27 | ctxLoader.loadFormData(form, URLoptions, auth.userlanguage); 28 | } 29 | }; 30 | }); -------------------------------------------------------------------------------- /assets/js/auth.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'app-config' 3 | ], function($, AppConfig) { 4 | if (!AppConfig.portalAuth) { 5 | return { 6 | "username": AppConfig.username || "bob", 7 | "userlanguage": AppConfig.language || navigator.language || "fr" 8 | } 9 | } 10 | 11 | var authData = {}; 12 | $.ajax({ 13 | data: JSON.stringify({'securityKey': AppConfig.securityKey}), 14 | type: 'POST', 15 | url: AppConfig.config.options.URLOptions.security + "/isCookieValid", 16 | contentType: 'application/json', 17 | crossDomain: true, 18 | async: false, 19 | success: function(data) { 20 | authData = data; 21 | }, 22 | error: function(xhr) { 23 | authData.error = { 24 | status: xhr.status, 25 | statusText: xhr.statusText, 26 | responseText: xhr.responseText 27 | } 28 | } 29 | }); 30 | return authData; 31 | }); -------------------------------------------------------------------------------- /assets/js/onblur-page.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'vue', 3 | 'text!./editionPageModule/templates/OnBlurPage.html' 4 | ], function(Vue, tpl) { 5 | return { 6 | init: function(el) { 7 | el.innerHTML = tpl; 8 | return new Vue({ 9 | el: el, 10 | data: function() { 11 | return { 12 | message: 'OnBlur' 13 | } 14 | }, 15 | methods: { 16 | onBtnClick: function(name) { 17 | this.id = "test" 18 | this.message = name; 19 | this.$emit('complete', name); 20 | } 21 | }, 22 | mounted: function() { 23 | console.log('mounted'); 24 | }, 25 | destroyed: function() { 26 | console.log('destroyed'); 27 | } 28 | }) 29 | } 30 | } 31 | }); -------------------------------------------------------------------------------- /assets/stylesheet/app/editionPage/modal.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Modal style specific for edition page 4 | // 5 | 6 | #grid-modal { 7 | 8 | table { 9 | 10 | thead { 11 | 12 | tr { 13 | 14 | th { 15 | a { 16 | .exo; 17 | color : #333; 18 | } 19 | } 20 | 21 | } 22 | } 23 | 24 | tbody { 25 | 26 | tr { 27 | 28 | &:first-child { 29 | td:last-child { 30 | visibility: hidden !important; 31 | } 32 | } 33 | 34 | td { 35 | 36 | &:last-child:after { 37 | .reneco; 38 | content: "\e681"; 39 | text-align: center; 40 | color : #222; 41 | } 42 | } 43 | 44 | } 45 | } 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /docs/deprecated/examples/awesomeField/AwesomeField.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file show an example for new field type 3 | * If you want to add this field on the application, you have to put this content on the models/Fields.js file 4 | */ 5 | 6 | models.AwesomeField = models.BaseField.extend({ 7 | 8 | defaults : function() { 9 | return _.extend( {}, models.BaseField.prototype.defaults, { 10 | maxSize : 42 11 | }); 12 | }, 13 | 14 | schema: function() { 15 | return _.extend( {}, models.BaseField.prototype.schema, { 16 | maxSize: { 17 | type : 'Number', 18 | title : 'Max character size', 19 | editorClass : 'form-control', 20 | template : fieldTemplate 21 | } 22 | }) 23 | }, 24 | 25 | initialize: function(options) { 26 | models.BaseField.prototype.initialize.apply(this, arguments); 27 | } 28 | }, { 29 | 30 | type : "Awesome", 31 | section : 'standard', 32 | i18n : 'awesome' 33 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/PositionEventsCollection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | 'backbone', 8 | '../models/Fields', 9 | '../editor/CheckboxEditor', 10 | '../editor/NumberEditor', 11 | 'backbone.radio', 12 | '../../Translater', 13 | 'auth', 14 | 'text!../templates/FieldTemplate.html' 15 | ], function ($, Backbone, Fields, CheckboxEditor, NumberEditor, Radio, translater, auth, FieldTemplate) { 16 | 17 | var fieldTemplate = _.template(FieldTemplate); 18 | 19 | return { 20 | schemaExtention: { 21 | 22 | }, 23 | 24 | propertiesDefaultValues : { 25 | 26 | }, 27 | 28 | getExtractedDatas: function() { 29 | return {}; 30 | }, 31 | getSchemaExtention: function(){ 32 | return this.schemaExtention; 33 | }, 34 | initializeExtention: function () { 35 | return true; 36 | }, 37 | 38 | jsonExtention: function (originalForm) { 39 | return(this.propertiesDefaultValues); 40 | }, 41 | updateAttributesExtention: function () { 42 | return true; 43 | } 44 | }; 45 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/AppearanceEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'text!./AppearanceEditor.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, AppearanceTemplate) { 6 | return Backbone.Form.editors.Text.extend({ 7 | initialize: function(options) { 8 | this.options = options; 9 | Backbone.Form.editors.Text.prototype.initialize.call(this, options); 10 | }, 11 | 12 | render: function() { 13 | Backbone.Form.editors.Text.prototype.render.call(this); 14 | this.$el = $(_.template(AppearanceTemplate)({ 15 | id: this.options.id, 16 | model: this.model 17 | })); 18 | // fieldSize value for ecoreleve context can be set in pixels, disable max constraints 19 | if (this.model.get("context") == 'ecoreleve') { 20 | this.$el.find("[name='fieldSize']").attr("max", null); 21 | } 22 | this.$el.i18n(); 23 | this.setElement(this.$el); 24 | return this; 25 | } 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/GridRow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | <% for (var i in columns) { 4 | var col = columns[i]; 5 | if (!schema[col]) { %> 6 | 7 | <% } else if( model.get('mandatory') && (model.get('disabledFields').indexOf(col) > -1) ) { %> 8 | 9 | <% } else { %> 10 | 11 | <% } 12 | } %> 13 | 14 | <% if ( model.get('compulsory') || model.get('mandatory') ) { %> 15 | 16 | <% } else { %> 17 |
18 |
19 | <% } %> 20 | 21 | 22 | -------------------------------------------------------------------------------- /assets/js/homePageModule/layout/HomePageLayout.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'backbone', 3 | 'marionette', 4 | 'text!../templates/HomePageLayout.html', 5 | '../views/LeftPanelView', 6 | '../views/CenterGridPanelView' 7 | ], function(Backbone, Marionette, HomePageLayoutTemplate, LeftPanelView, CenterGridPanelView) { 8 | 9 | return Marionette.View.extend({ 10 | initialize : function(options) { 11 | console.log("********* initialize", options) 12 | this.URLOptions = options.URLOptions; 13 | this.paths = options.paths; 14 | }, 15 | 16 | template: HomePageLayoutTemplate, 17 | 18 | regions : { 19 | leftPanel : '#leftPanel', 20 | centerPanel : '#centerPanel' 21 | }, 22 | 23 | onRender : function() { 24 | // Create and render item views 25 | this.getRegion("leftPanel").show( new LeftPanelView({ 26 | URLOptions : this.URLOptions 27 | })); 28 | 29 | this.getRegion("centerPanel").show( new CenterGridPanelView({ 30 | URLOptions : this.URLOptions 31 | })); 32 | } 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /assets/stylesheet/mainStyles/fonts.less: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "ProximaNovaLight"; 3 | src: url("../fonts/PROXIMANOVALIGHT.OTF"); 4 | } 5 | 6 | @font-face { 7 | font-family: "ProximaNovaRegular"; 8 | src: url("../fonts/PROXIMANOVAREGULAR.OTF"); 9 | } 10 | 11 | .exo { font-family: 'ProximaNovaLight', sans-serif !important; font-weight: 300; } 12 | .font { font-family: "Segoe UI Light","Helvetica Neue","Segoe UI","Segoe WP",sans-serif !important; } 13 | .fa { font-family : FontAwesome !important; } 14 | 15 | .reneco { 16 | font-family : 'reneco'; 17 | speak : none; 18 | font-style : normal; 19 | font-weight : normal; 20 | font-variant : normal; 21 | text-transform : none; 22 | line-height : 1; 23 | -webkit-font-smoothing: antialiased; 24 | } 25 | 26 | // Color section 27 | 28 | .transparent { background : transparent !important; } 29 | .new { background : rgba(0, 255, 0, 0.5) !important; } 30 | .change { background : rgba(255, 165, 0, 0.5); } 31 | .delete { background : rgba(255, 0, 0, 0.5); } 32 | .grey { background : #aaa; } -------------------------------------------------------------------------------- /docs/deprecated/modules.md: -------------------------------------------------------------------------------- 1 | # Application structure 2 | 3 | The application is composed of two modules built with MarionetteJS based on the same architecture : 4 | 5 | - A router with routes and controllers action matching 6 | - A controller 7 | - A layout split in regions 8 | - A view for each region 9 | - A model collection 10 | - One or many models 11 | 12 | **Each module follows this folder architecture** 13 | 14 | - collection 15 | - controller 16 | - layout 17 | - modals (modals view) 18 | - models 19 | - router 20 | - templates (underscore templates) 21 | - view (Marionette views) 22 | 23 | ## Homepage module 24 | 25 | The homepage module contains a grid with all forms list and a search form for 26 | apply some filter on the grid. 27 | 28 | ![homepage](http://img4.hostingpics.net/pics/865244FormBuilderGoogleChrome.jpg) 29 | 30 | ## Edition page module 31 | 32 | The edition page module allow to edit a form and save or export it. 33 | 34 | **If you want to use only the edition module see our [edition-only](https://github.com/NaturalSolutions/NS.UI.FormBuilder/tree/edition-only) branch.** 35 | 36 | ![editionPage](http://img4.hostingpics.net/pics/463955FormBuilderGoogleChrome2.jpg) 37 | 38 | back to [summary](index.md) 39 | -------------------------------------------------------------------------------- /assets/js/homePageModule/templates/LeftPanelView.html: -------------------------------------------------------------------------------- 1 |
2 | 23 |
24 |

Formulaires édités récemment

25 |
26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /ressources/fieldConfiguration/preConfiguredField.json: -------------------------------------------------------------------------------- 1 | { 2 | "Text": { 3 | 4 | "FirstName": { 5 | "validators" : ["required"], 6 | "type" : "Text", 7 | "title" : "Mon fichier", 8 | "editorClass" : "", 9 | "fieldClass" : "" 10 | }, 11 | 12 | "Title": { 13 | "type" : "Text", 14 | "title" : "Titre", 15 | "editorClass" : "", 16 | "fieldClass" : "", 17 | "endOfLine" : true 18 | } 19 | 20 | }, 21 | 22 | "LongText": { 23 | 24 | "Note": { 25 | "validators" : ["required"], 26 | "type" : "TextArea", 27 | "title" : "Note", 28 | "editorClass" : "", 29 | "fieldClass" : "", 30 | "multiple" : true 31 | } 32 | }, 33 | 34 | "Numeric": { 35 | 36 | "Your age": { 37 | "validators" : ["required"], 38 | "type" : "Numeric", 39 | "title" : "Your age", 40 | "editorClass" : "", 41 | "fieldClass" : "", 42 | "minValue" : 3, 43 | "maxValue" : 99, 44 | "precision" : 1, 45 | "unity" : "year" 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /docs/deprecated/examples/awesomeField/AwesomeFieldView.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 7 | 23 |
24 |
25 |
26 | 27 |
28 |
29 |
-------------------------------------------------------------------------------- /assets/js/homePageModule/templates/GridView.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |

11 |
12 |
13 | Import 14 |
15 |
16 | Ajouter 17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
 
31 |
32 |
33 |
34 |
35 | -------------------------------------------------------------------------------- /assets/stylesheet/components/common.less: -------------------------------------------------------------------------------- 1 | @orange: #DE7710; 2 | @darkorange: #E0411A; 3 | @gray: #59514F; 4 | @gray2: #40322F; 5 | @grid_bg: #342623; 6 | @grid_fg: #493A35; 7 | @grid_gray: #7B6C69; 8 | @search_bg: #EDEDED; 9 | @row_header: #8C8A8D; 10 | @row_bg: #F0E9F0; 11 | @row_hover_bg: #444; 12 | @border_color: #6d615f; 13 | @td_color: white; 14 | @red: #F2154A; 15 | @red2: #A21132; 16 | 17 | .gradiant { 18 | background: @orange; 19 | background: -webkit-linear-gradient(-90deg, @darkorange, @orange); 20 | background: -o-linear-gradient(-90deg, @darkorange, @orange); 21 | background: -moz-linear-gradient(-90deg, @darkorange, @orange); 22 | background: linear-gradient(-90deg, @darkorange, @orange); 23 | } 24 | 25 | .invertGradiant { 26 | background: @orange; 27 | background: -webkit-linear-gradient(-90deg, @orange, @darkorange); 28 | background: -o-linear-gradient(-90deg, @orange, @darkorange); 29 | background: -moz-linear-gradient(-90deg, @orange, @darkorange); 30 | background: linear-gradient(-90deg, @orange, @darkorange); 31 | } 32 | 33 | .redGradiant { 34 | background: @red; 35 | background: -webkit-linear-gradient(-90deg, @red2, @red); 36 | background: -o-linear-gradient(-90deg, @red2, @red); 37 | background: -moz-linear-gradient(-90deg, @red2, @red); 38 | background: linear-gradient(-90deg, @red2, @red); 39 | } 40 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/staticInputs/ContextStaticInputs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | './TrackStatics' 7 | ], function (TrackStatics) { 8 | 9 | /** 10 | * EmptyStatics is a dummy StaticInput object that does nothing. 11 | * If need static inputs for a specific context, add "context" key to 12 | * staticInputs object, and make it implement this skeleton 13 | */ 14 | var EmptyStatics = { 15 | getStaticInputs: function() {return {};}, 16 | getCompulsoryInputs: function() {return [];}, 17 | applyRules: function(form, json) {return json;}, 18 | initializeStatics: function() {return true;} 19 | }; 20 | 21 | var staticInputs = { 22 | "track" : TrackStatics 23 | }; 24 | 25 | var ContextStaticInputs = { 26 | getStaticMode : function (currentContext) { 27 | if (!currentContext) { 28 | console.warn("getStaticMode without context", window.context); 29 | } 30 | 31 | var staticMode = staticInputs[window.context]; 32 | if (currentContext) 33 | staticMode = staticInputs[currentContext]; 34 | if (!staticMode) 35 | staticMode = EmptyStatics; 36 | return staticMode; 37 | } 38 | }; 39 | 40 | return ContextStaticInputs; 41 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/PositionTypesProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | return { 7 | extraProperties: {}, 8 | exceptions: { 9 | hide: {} 10 | }, 11 | 12 | getExtraPropertiesDefaults: function(inputType, avoid) { 13 | var toret = {}; 14 | if (!avoid) 15 | toret = this.getExtraPropertiesDefaults("all", true); 16 | 17 | $.each(this.extraProperties, function(index, value) { 18 | if (index == inputType) { 19 | toret = _.extend(toret, value.defaults); 20 | return(toret); 21 | } 22 | }); 23 | 24 | return(toret); 25 | }, 26 | 27 | getExtraPropertiesSchema: function(inputType, avoid) { 28 | var toret = {}; 29 | if (!avoid) 30 | toret = this.getExtraPropertiesSchema("all", true); 31 | 32 | $.each(this.extraProperties, function(index, value) { 33 | if (index == inputType) { 34 | toret = _.extend(toret, value.schema); 35 | return(toret); 36 | } 37 | }); 38 | 39 | return(toret); 40 | }, 41 | 42 | getHideExceptionForProperty: function(input, property) 43 | { 44 | return(this.exceptions.hide[input] && this.exceptions.hide[input][property]); 45 | }, 46 | 47 | initializeStatics: function () { 48 | return(true); 49 | } 50 | }; 51 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/mandatoryInputs/ContextMandatoryInputs.js: -------------------------------------------------------------------------------- 1 | define([ 2 | './EcoreleveMandatory' 3 | ], function (EcoreleveMandatory) { 4 | 5 | /** 6 | * EmptyStatics is a dummy StaticInput object that does nothing. 7 | * If need static inputs for a specific context, add "context" key to 8 | * staticInputs object, and make it implement this skeleton 9 | */ 10 | var EmptyMandatory = { 11 | getMandatoryInputs: function() {return this.mandatoryInputsWithConf; }, 12 | initializeMandatory: function() {return true;}, 13 | mandatoryInputsWithConf: { 14 | inputsList: [], 15 | inputsConf : {}, 16 | inputsDisabledFields : {} 17 | } 18 | }; 19 | 20 | var MandatoryInputs = { 21 | "ecoreleve" : EcoreleveMandatory 22 | }; 23 | 24 | var ContextMandatoryInputs = { 25 | getMandatoryMode : function (currentContext) { 26 | 27 | if (!currentContext) { 28 | console.warn("getMandatoryMode without context", window.context); 29 | } 30 | 31 | var mandatoryMode = MandatoryInputs[window.context]; 32 | if (currentContext) 33 | mandatoryMode = MandatoryInputs[currentContext]; 34 | if (!mandatoryMode) 35 | mandatoryMode = EmptyMandatory; 36 | return mandatoryMode; 37 | } 38 | }; 39 | 40 | return ContextMandatoryInputs; 41 | }); -------------------------------------------------------------------------------- /assets/js/Translater.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'marionette', 'auth', 'i18n', 'i18n-jquery', 'i18n-xhr' 3 | ], function($, _, Marionette, auth, i18n, i18njQuery, i18nXhr) { 4 | var t = { 5 | loaded: false, 6 | init: function() { 7 | var lang = auth.userlanguage ||navigator.language || 8 | navigator.userLanguagenavigator.language || 9 | navigator.userLanguage || 'en'; 10 | 11 | i18n.use(i18nXhr); 12 | i18n.init({ 13 | lng : lang, 14 | fallbackLng: 'fr', 15 | async: false, 16 | getAsync: false, 17 | backend: { 18 | loadPath: 'ressources/locales/{{lng}}/{{ns}}.json' 19 | } 20 | }, _.bind(function() { 21 | i18njQuery.init(i18n, $, { 22 | tName: 't', 23 | handleName: 'i18n', 24 | selector: 'data-i18n' 25 | }); 26 | this.loaded = true; 27 | }, this)); 28 | }, 29 | isKeyValid: function(key) { 30 | return typeof key === "string" && 31 | key.indexOf(" ") === -1; 32 | }, 33 | 34 | getValueFromKey : function(key, opts) { 35 | if (!this.isKeyValid(key)) 36 | return key; 37 | 38 | return $.t(key, opts); 39 | } 40 | }; 41 | 42 | t.init(); 43 | return t; 44 | }); 45 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/loaders/TrackLoader.js: -------------------------------------------------------------------------------- 1 | define(['jquery'], function ($) { 2 | return { 3 | loadFormData: function(form, urls, lang) { 4 | if (form.fields.unity) { 5 | if (lang !== 'fr') { 6 | // todo the way units are handled, language specific units cannot work: 7 | // localized value is stored in database, we cannot match translations 8 | console.warn("disregarding language for fetching units, not implemented (forced 'fr')"); 9 | lang = 'fr'; 10 | } 11 | this.loadUnits(form.fields.unity, urls.unities + "/track/" + lang); 12 | } 13 | }, 14 | 15 | loadUnits: function(field, url) { 16 | $.ajax({ 17 | type : 'GET', 18 | url : url, 19 | contentType : 'application/json', 20 | crossDomain : true, 21 | success: function(data) { 22 | var jsondata = JSON.parse(data); 23 | var units = []; 24 | $.each(jsondata.unities, function (index, value) { 25 | units.push(value); 26 | }); 27 | field.editor.setOptions(units); 28 | }, 29 | error: function (xhr) { 30 | console.log(xhr); 31 | } 32 | }); 33 | } 34 | }; 35 | }); 36 | -------------------------------------------------------------------------------- /ressources/templates/templates.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id" : 1, 3 | "name" : "Template 1", 4 | "labelFr" : "Template 1", 5 | "labelEn" : "Template 1", 6 | "creationDate" : "Template 1", 7 | "modificationDate" : "Template 1", 8 | "descriptionEn" : "Template 1", 9 | "descriptionFr" : "Template 1", 10 | "keywordsFr" : ["template"], 11 | "keywordsEn" : ["template"], 12 | "schema": { 13 | "Field1": { 14 | "validators" : [], 15 | "labelFr" : "Label en français", 16 | "labelEn" : "Label en anglais", 17 | "editMode" : 7, 18 | "name" : "Field1", 19 | "readonly" : false, 20 | "editorClass" : "", 21 | "fieldClassEdit" : "", 22 | "fieldClassDisplay" : "", 23 | "fieldSize" : "", 24 | "endOfLine" : false, 25 | "linkedFieldTable" : "", 26 | "linkedFieldIdentifyingColumn": "", 27 | "linkedField" : "", 28 | "formIdentifyingColumn" : "", 29 | "linkedFieldset" : "", 30 | "defaultValue" : "", 31 | "help" : "Write some text", 32 | "size" : "0;255", 33 | "type" : "Text" 34 | } 35 | }, 36 | "fieldsets": [] 37 | }] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formBuilder", 3 | "version": "1.1.1", 4 | "description": "", 5 | "main": "assets/js/config.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/NaturalSolutions/NS.UI.FormBuilder.git" 9 | }, 10 | "author": "NaturalSolutions", 11 | "license": "ISC", 12 | "bugs": { 13 | "url": "https://github.com/NaturalSolutions/NS.UI.FormBuilder/issues" 14 | }, 15 | "homepage": "https://github.com/NaturalSolutions/NS.UI.FormBuilder", 16 | "devDependencies": { 17 | "grunt": "^0.4.5", 18 | "grunt-cli": "^1.2.0", 19 | "grunt-contrib-copy": "^1.0.0", 20 | "grunt-contrib-less": "^0.11.0", 21 | "grunt-contrib-watch": "^0.6.1", 22 | "webpack": "^3.8.1" 23 | }, 24 | "dependencies": { 25 | "@naturalsolutions/renecofonts": "^1.3.0", 26 | "backbone": "^1.3.3", 27 | "backbone-forms": "^0.14.1", 28 | "backbone.marionette": "3.5.1", 29 | "backbone.radio": "^2.0.0", 30 | "backgrid": "0.3.5", 31 | "blobjs": "^1.1.1", 32 | "bootstrap": "3.2.0", 33 | "file-saver": "^1.3.3", 34 | "i18next": "^10.2.1", 35 | "i18next-xhr-backend": "^1.5.0", 36 | "jquery": "2.1.4", 37 | "jquery-i18next": "^1.2.1", 38 | "jquery-slimscroll": "1.3.8", 39 | "jquery-ui-dist": "1.12.1", 40 | "jquery.fancytree": "^2.26.0", 41 | "lodash": "3.10.1", 42 | "moment": "2.18.1", 43 | "requirejs": "2.3.5", 44 | "sweetalert": "2.1.0", 45 | "text": "requirejs/text", 46 | "vue": "^2.5.17" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/EcollectionProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | return { 7 | extraProperties: {}, 8 | exceptions: { 9 | hide: {} 10 | }, 11 | 12 | getExtraPropertiesDefaults: function(inputType, avoid) { 13 | var toret = {}; 14 | if (!avoid) 15 | toret = this.getExtraPropertiesDefaults("all", true); 16 | 17 | $.each(this.extraProperties, function(index, value) { 18 | if (index == inputType) { 19 | toret = _.extend(toret, value.defaults); 20 | return(toret); 21 | } 22 | }); 23 | 24 | return(toret); 25 | }, 26 | 27 | getExtraPropertiesSchema: function(inputType, avoid) { 28 | var toret = {}; 29 | if (!avoid) 30 | toret = this.getExtraPropertiesSchema("all", true); 31 | 32 | $.each(this.extraProperties, function(index, value) { 33 | if (index == inputType) { 34 | toret = _.extend(toret, value.schema); 35 | return(toret); 36 | } 37 | }); 38 | 39 | return(toret); 40 | }, 41 | 42 | getHideExceptionForProperty: function(input, property) { 43 | return(this.exceptions.hide[input] && this.exceptions.hide[input][property]); 44 | } 45 | }; 46 | }); -------------------------------------------------------------------------------- /assets/stylesheet/components/scrollbar.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Override scroll bar style 4 | // 5 | 6 | .slimScrollDiv { 7 | // slimScroll applies provided height param to child, 8 | // it's not cool if we use "calc()", it needs to be 100% anyway. 9 | & > :first-child { 10 | height: 100% !important; 11 | overflow: auto !important; 12 | } 13 | } 14 | 15 | .slimScrollRail { 16 | //display: block !important; 17 | background : #ddd; 18 | display: none !important; //test 19 | } 20 | 21 | #settingPanel { 22 | .slimScrollRail, .scroll { 23 | height: 80% !important 24 | } 25 | .slimScrollRail { 26 | background: #000 !important; 27 | } 28 | } 29 | 30 | .slimScrollBar { 31 | background: #fff !important; 32 | transition: opacity ease 120ms; 33 | display: none !important; //test 34 | &:hover { 35 | cursor: pointer; 36 | opacity: 0.65 !important; 37 | } 38 | } 39 | 40 | #centerPanel { 41 | .scrollBar { 42 | display: block !important; 43 | } 44 | .slimScrollRail { 45 | background-color: #4d4d4d !important; 46 | opacity: 1 !important; 47 | } 48 | } 49 | 50 | /* CUSTOM SCROLL BAR */ 51 | ::-webkit-scrollbar-thumb { 52 | background: #fa8f23; 53 | width: 10px; 54 | border: 2px solid #8f8f8f; 55 | margin: 5px; 56 | border-radius: 25px; 57 | } 58 | ::-webkit-scrollbar{ 59 | background: #8f8f8f; 60 | width: 12px; 61 | height: 15px; 62 | margin: 5px; 63 | cursor: pointer; 64 | border-radius: 25px; 65 | } -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/GenericProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | return { 7 | extraProperties: {}, 8 | exceptions: { 9 | hide: {} 10 | }, 11 | 12 | getExtraPropertiesDefaults: function(inputType, avoid) { 13 | var toret = {}; 14 | if (!avoid) 15 | toret = this.getExtraPropertiesDefaults("all", true); 16 | 17 | $.each(this.extraProperties, function(index, value) { 18 | if (index == inputType) { 19 | toret = _.extend(toret, value.defaults); 20 | return(toret); 21 | } 22 | }); 23 | 24 | return(toret); 25 | }, 26 | 27 | getExtraPropertiesSchema: function(inputType, avoid) { 28 | var toret = {}; 29 | if (!avoid) 30 | toret = this.getExtraPropertiesSchema("all", true); 31 | 32 | $.each(this.extraProperties, function(index, value){ 33 | if (index == inputType) { 34 | toret = _.extend(toret, value.schema); 35 | return(toret); 36 | } 37 | }); 38 | 39 | return(toret); 40 | }, 41 | 42 | getHideExceptionForProperty: function(input, property) { 43 | return this.exceptions.hide[input] && this.exceptions.hide[input][property]; 44 | }, 45 | 46 | initializeStatics: function () { 47 | return true; 48 | } 49 | }; 50 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/PositionProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | return { 7 | extraProperties: {}, 8 | exceptions: { 9 | hide: {} 10 | }, 11 | 12 | getExtraPropertiesDefaults: function(inputType, avoid) { 13 | var toret = {}; 14 | if (!avoid) 15 | toret = this.getExtraPropertiesDefaults("all", true); 16 | 17 | $.each(this.extraProperties, function(index, value) { 18 | if (index == inputType) { 19 | toret = _.extend(toret, value.defaults); 20 | return(toret); 21 | } 22 | }); 23 | 24 | return(toret); 25 | }, 26 | 27 | getExtraPropertiesSchema: function(inputType, avoid) { 28 | var toret = {}; 29 | if (!avoid) 30 | toret = this.getExtraPropertiesSchema("all", true); 31 | 32 | $.each(this.extraProperties, function(index, value) { 33 | if (index == inputType) { 34 | toret = _.extend(toret, value.schema); 35 | return(toret); 36 | } 37 | }); 38 | 39 | return(toret); 40 | }, 41 | 42 | getHideExceptionForProperty: function(input, property) 43 | { 44 | return(this.exceptions.hide[input] && this.exceptions.hide[input][property]); 45 | }, 46 | 47 | initializeStatics: function () { 48 | return(true); 49 | } 50 | }; 51 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/PositionEventsProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | return { 7 | extraProperties: {}, 8 | exceptions: { 9 | hide: {} 10 | }, 11 | 12 | getExtraPropertiesDefaults: function(inputType, avoid) { 13 | var toret = {}; 14 | if (!avoid) 15 | toret = this.getExtraPropertiesDefaults("all", true); 16 | 17 | $.each(this.extraProperties, function(index, value) { 18 | if (index == inputType) { 19 | toret = _.extend(toret, value.defaults); 20 | return(toret); 21 | } 22 | }); 23 | 24 | return(toret); 25 | }, 26 | 27 | getExtraPropertiesSchema: function(inputType, avoid) { 28 | var toret = {}; 29 | if (!avoid) 30 | toret = this.getExtraPropertiesSchema("all", true); 31 | 32 | $.each(this.extraProperties, function(index, value) { 33 | if (index == inputType) { 34 | toret = _.extend(toret, value.schema); 35 | return(toret); 36 | } 37 | }); 38 | 39 | return(toret); 40 | }, 41 | 42 | getHideExceptionForProperty: function(input, property) 43 | { 44 | return(this.exceptions.hide[input] && this.exceptions.hide[input][property]); 45 | }, 46 | 47 | initializeStatics: function () { 48 | return(true); 49 | } 50 | }; 51 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FormBuilder Front-End 2 | 3 | Installation 4 | ------------ 5 | 6 | ``` 7 | npm install -g yarn 8 | yarn install 9 | cp assets/js/app-config.example.js assets/js/app-config.js 10 | grunt 11 | ``` 12 | 13 | Configuration 14 | ------------- 15 | 16 | main config file: `assets/js/app-config.js` 17 | 18 | * portalAuth : if set to true, use portalURL for authentification, leave to false if not sure 19 | * portalURL : "http://path/to/your/portal/" 20 | * thesaurusWSPath : "http://path/to/thesaurus/webservices/" 21 | * positionWSPath : "http://path/to/position/webservices/" 22 | * other stuff: see app-config.example.js for reference 23 | 24 | Context options 25 | --------------- 26 | * topcontext: "reneco" or something else (reneco hardwires) 27 | * defaults: provide default value-sets for context-specific config. if none is specified below context options, value-set from default will be used. 28 | * editColumns 29 | * [...] (see app-config.example.js) 30 | * contexts: list of available contexts (by object key). Every absent context option implies defaults will be used for missing option key 31 | 32 | Available input types 33 | --------------------- 34 | See app-config.example.js 35 | 36 | Lancer IIS 37 | --------------------- 38 | * Clic droit sur "Default Web_Site" -> ajouter une application 39 | * Alias -> "Fomrbuilder" | Chemin d'accès physique -> ".../NS.UI.Formbuilder/" 40 | 41 | Possible Error 42 | --------------------- 43 | 44 | ### grunt[10388]: c:\ws\src\node_contextify.cc:635: Assertion `args[1]->IsString()' failed. 45 | npm install natives 46 | 47 | ### Uncaught Error: Script error for "vue", needed by: onblur-page 48 | npm install 49 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/TrackProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | return { 7 | extraProperties: {}, 8 | exceptions: { 9 | hide: { 10 | AutocompleteField : { 11 | triggerlength : true 12 | } 13 | } 14 | }, 15 | 16 | getExtraPropertiesDefaults: function(inputType, avoid) { 17 | var toret = {}; 18 | if (!avoid) 19 | toret = this.getExtraPropertiesDefaults("all", true); 20 | 21 | $.each(this.extraProperties, function(index, value) { 22 | if (index == inputType) { 23 | toret = _.extend(toret, value.defaults); 24 | return(toret); 25 | } 26 | }); 27 | 28 | return(toret); 29 | }, 30 | 31 | getExtraPropertiesSchema: function(inputType, avoid) { 32 | var toret = {}; 33 | if (!avoid) 34 | toret = this.getExtraPropertiesSchema("all", true); 35 | 36 | $.each(this.extraProperties, function(index, value) { 37 | if (index == inputType) { 38 | toret = _.extend(toret, value.schema); 39 | return(toret); 40 | } 41 | }); 42 | 43 | return(toret); 44 | }, 45 | 46 | getHideExceptionForProperty: function(input, property) { 47 | return(this.exceptions.hide[input] && this.exceptions.hide[input][property]); 48 | }, 49 | 50 | initializeStatics: function () { 51 | return(true); 52 | } 53 | }; 54 | }); -------------------------------------------------------------------------------- /docs/deprecated/backend.md: -------------------------------------------------------------------------------- 1 | # Back end connection 2 | 3 | Currently the Formbuilder can works only on the client-side but some functionnalities like save a form on a database require a back end. 4 | We developped a back end for the formbuilder. 5 | 6 | See [back end repo](https://github.com/NaturalSolutions/NS.Server.FormBuilder) 7 | 8 | ## URL 9 | 10 | To connect fron and back end you have to specify these URL. 11 | 12 | ### autocompleteURL 13 | 14 | URL for autocomplete ressources 15 | 16 | **default value** : ressources/autocomplete/ 17 | 18 | ### translationURL 19 | 20 | i18n traduction URL 21 | 22 | **default value ** : ressources/locales/ 23 | 24 | ### keywordAutocomplete 25 | 26 | Form keywords list URL 27 | 28 | **default value** : ressources/autocomplete/keywords.json 29 | 30 | ### protocolAutocomplete 31 | 32 | Form list autocomplete URL 33 | 34 | **default value** : ressources/autocomplete/protocols.json 35 | 36 | ### unitURL 37 | 38 | Unity list url provider 39 | 40 | **default value** : ressources/autocomplete/units.json 41 | 42 | ### preConfiguredField 43 | 44 | pre-configurated provider URL. 45 | 46 | A configurated field is a field saved by use for a future use. 47 | 48 | For example user create a firstName field because it will be present in many forms. 49 | 50 | **default value** : ressources/fieldConfiguration/preConfiguredField.json 51 | 52 | ### fieldConfigurationURL 53 | 54 | Wich to send pre-configurated field. Send a POST request so in client side mode (without back end connection) it won't work. 55 | 56 | **default value** : configurationSaved 57 | 58 | ### linkedFields 59 | 60 | Return all linked fields 61 | 62 | **default value** : ressources/linkedFields/linkedFields.json 63 | 64 | back to [summary](index.md) 65 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/mandatoryInputs/EcoreleveMandatory.js: -------------------------------------------------------------------------------- 1 | /* 2 | mandatoryInputsWithConf is an object 3 | { 4 | "inputsList" : [], //list of mandatory input for a context 5 | "inputsConf" : {}, //inputsConf[ inputsMandatory[i] ] to have acces to the input configuration 6 | "inputsDisableFields" : {} // inputsDisabledFields [ inputMandatory[i] ] to have acces to the disabled field for one input 7 | } 8 | */ 9 | 10 | 11 | define(['jquery'], function ($) { 12 | var EcoreleveMandatory = { 13 | 14 | mandatoryInputsWithConf: { 15 | inputsList: [ 16 | "Comments" 17 | ], 18 | inputsConf : { 19 | "Comments": { 20 | "id": 1, 21 | "translations" : { 22 | "fr" : { 23 | "Help": "", 24 | "Language" : "fr", 25 | "Name" : "Commentaires" 26 | }, 27 | "en" : { 28 | "Help": "", 29 | "Language" : "en", 30 | "Name" : "Comments" 31 | } 32 | }, 33 | "name": "Comments", 34 | "type": "TextArea" 35 | } 36 | }, 37 | inputsDisabledFields : { 38 | "Comments" :[ 39 | "name" 40 | ] 41 | } 42 | }, 43 | 44 | getMandatoryInputs: function() { 45 | return EcoreleveMandatory.mandatoryInputsWithConf; 46 | }, 47 | 48 | initializeMandatory: function () { 49 | return true; 50 | } 51 | }; 52 | 53 | return EcoreleveMandatory; 54 | }); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | FormBuilder 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |   FormBuilder 22 | 23 | | 24 |
25 |
all
26 | 27 |
28 |
29 | 30 | 31 | Logout 32 | 33 |
34 |
35 | 37 | 40 | 41 | | 42 | 43 |
44 |
45 | 46 |
47 |
48 |
49 | 50 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/EditModeEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'tools', 'text!./EditModeEditor.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, tools, EditModeTemplate) { 6 | return Backbone.Form.editors.Number.extend({ 7 | events: { 8 | 'change input': 'updateValue' 9 | }, 10 | 11 | initialize: function(options) { 12 | this.options = options; 13 | Backbone.Form.editors.Number.prototype.initialize.call(this, options); 14 | }, 15 | 16 | render: function() { 17 | Backbone.Form.editors.Number.prototype.render.call(this); 18 | this.dictValues = tools.binWeight.toDict(this.value); 19 | this.$el = $(_.template(EditModeTemplate)({ 20 | id: this.options.id, 21 | values: this.dictValues, 22 | items: tools.binWeight.items 23 | })); 24 | this.$el.i18n(); 25 | this.setElement(this.$el); 26 | return this; 27 | }, 28 | 29 | updateValue: function(e) { 30 | this.dictValues[$(e.target).data("bit")] = e.target.checked; 31 | this.$el.find("label[for='" + e.target.id + "']").toggleClass("checked"); 32 | this.setValue(tools.binWeight.toValue(this.dictValues), true); 33 | }, 34 | 35 | getValue: function() { 36 | return this.value; 37 | }, 38 | 39 | setValue: function(value, triggerChange) { 40 | this.value = value; 41 | if (triggerChange) { 42 | if (this.model && this.model.view && this.model.view.setValue) { 43 | this.model.view.setValue(this.options.key, value); 44 | } else if (triggerChange && this.model) { 45 | this.model.set(this.options.key, value, {trigger: true}); 46 | } 47 | } 48 | } 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/DataEntrySource.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'tools', 'text!./DataEntrySource.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, tools, EditModeTemplate) { 6 | return Backbone.Form.editors.Number.extend({ 7 | events: { 8 | 'change input': 'updateValue' 9 | }, 10 | 11 | initialize: function(options) { 12 | this.options = options; 13 | Backbone.Form.editors.Number.prototype.initialize.call(this, options); 14 | }, 15 | 16 | render: function() { 17 | Backbone.Form.editors.Number.prototype.render.call(this); 18 | this.dictValues = tools.binWeightSource.toDictSource(this.value); 19 | this.$el = $(_.template(EditModeTemplate)({ 20 | id: this.options.id, 21 | values: this.dictValues, 22 | items: tools.binWeightSource.items 23 | })); 24 | this.$el.i18n(); 25 | this.setElement(this.$el); 26 | return this; 27 | }, 28 | 29 | updateValue: function(e) { 30 | this.dictValues[$(e.target).data("bit")] = e.target.checked; 31 | this.$el.find("label[for='" + e.target.id + "']").toggleClass("checked"); 32 | this.setValue(tools.binWeightSource.toValueSource(this.dictValues), true); 33 | }, 34 | 35 | getValue: function() { 36 | return this.value; 37 | }, 38 | 39 | setValue: function(value, triggerChange) { 40 | this.value = value; 41 | if (triggerChange) { 42 | if (this.model && this.model.view && this.model.view.setValue) { 43 | this.model.view.setValue(this.options.key, value); 44 | } else if (triggerChange && this.model) { 45 | this.model.set(this.options.key, value, {trigger: true}); 46 | } 47 | } 48 | } 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/ReproProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | 'backbone', 8 | '../../editor/OnBlurEditor', 9 | 'text!../../templates/FieldTemplate.html' 10 | ], function ($, Backbone, OnBlurEditor, FieldTemplate) { 11 | 12 | var fieldTemplate = _.template(FieldTemplate); 13 | 14 | return { 15 | extraProperties: { 16 | all:{ 17 | schema: { 18 | onBlur: { 19 | type: OnBlurEditor, 20 | title: "on Blur", 21 | template: fieldTemplate 22 | } 23 | } 24 | } 25 | }, 26 | 27 | getExtraPropertiesDefaults: function(inputType, avoid){ 28 | var toret = {}; 29 | if (!avoid) 30 | toret = this.getExtraPropertiesDefaults("all", true); 31 | 32 | $.each(this.extraProperties, function(index, value){ 33 | if (index == inputType) 34 | { 35 | toret = _.extend(toret, value.defaults); 36 | return toret; 37 | } 38 | }); 39 | 40 | return toret; 41 | }, 42 | 43 | getExtraPropertiesSchema: function(inputType, avoid){ 44 | var toret = {}; 45 | if (!avoid) 46 | toret = this.getExtraPropertiesSchema("all", true); 47 | 48 | $.each(this.extraProperties, function(index, value){ 49 | if (index == inputType) 50 | { 51 | toret = _.extend(toret, value.schema); 52 | return toret; 53 | } 54 | }); 55 | 56 | return toret; 57 | }, 58 | 59 | getHideExceptionForProperty: function(input, property) { 60 | return this.exceptions.hide[input] && this.exceptions.hide[input][property]; 61 | } 62 | }; 63 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/CheckboxEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'text!./CheckboxEditor.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, CheckboxTemplate) { 6 | return Backbone.Form.editors.Base.extend({ 7 | initialize: function(options) { 8 | this.options = options; 9 | this.options.schema = this.options.schema === undefined ? _.pick(options, 'editorClass', 'fieldClass', 'iconClass', 'title') : this.options.schema; 10 | Backbone.Form.editors.Base.prototype.initialize.call(this, options); 11 | }, 12 | 13 | render: function() { 14 | this.value = (typeof this.value == 'boolean') ? this.value : false; 15 | this.$el = $(_.template(CheckboxTemplate)({ 16 | id : this.options.id, 17 | name : this.options.key, 18 | editorClass : this.options.schema.editorClass || '', 19 | fieldClass : this.options.schema.fieldClass || 'form-group', 20 | iconClass : this.options.iconClass || '', 21 | value : this.value, 22 | title : this.schema.title == undefined ? this.key : this.schema.title 23 | })); 24 | 25 | // subscribe handlers from schema on input change 26 | if (this.options.schema.handlers) { 27 | var handlers = this.options.schema.handlers; 28 | for (var i in handlers) { 29 | this.$el.find("input").on("change", _.bind(function(e) { 30 | handlers[i](e.target.checked, this); 31 | }, this)); 32 | } 33 | } 34 | this.setElement(this.$el); 35 | return this; 36 | }, 37 | 38 | getValue: function() { 39 | return this.$el.find('input').is(':checked'); 40 | }, 41 | 42 | setValue: function(value) { 43 | this.$el.find('input').prop('checked', value); 44 | } 45 | }); 46 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/CustomTextEditor.js: -------------------------------------------------------------------------------- 1 | //For ecoreleve only if you use it in another application please implements TODO 2 | define([ 3 | 'jquery', 'lodash', 'backbone', 4 | 'backbone-forms' 5 | ], function($, _, Backbone) { 6 | return Backbone.Form.editors.Text.extend({ 7 | events: { 8 | 'change': 'applyEventRules', 9 | 'blur': 'applyEventRules', 10 | }, 11 | 12 | initialize: function(options) { 13 | var inputValue = options.model.get(options.key); 14 | var ruledValue = this.applyBeforeRules(inputValue); 15 | options.model.set(options.key, ruledValue, {silent: true}); 16 | Backbone.Form.editors.Text.prototype.initialize.call(this, options); 17 | }, 18 | applyBeforeRules: function(str){ 19 | str = this.replaceSpace(str) 20 | str = this.titleIt(str); 21 | return str; 22 | }, 23 | 24 | applyEventRules : function(e) { 25 | var value = e.currentTarget.value; 26 | var val = this.replaceSpace(value) 27 | val = this.titleIt(value); 28 | this.model.set(this.key, val); 29 | }, 30 | 31 | 32 | 33 | replaceSpace: function(str) { 34 | str = str.trim(); //remove leading and trailing space 35 | str = str.replace(/\s+/g, " "); //remove consecutive space and replace it by one space 36 | if(str) { 37 | return str.split(' ').join('_'); //replace remaining space by _ 38 | } 39 | else { 40 | return str 41 | } 42 | }, 43 | 44 | titleIt: function(str) { 45 | if (str) { 46 | if(str.length == 1 ) { 47 | str = str.charAt(0).toUpperCase(); 48 | } 49 | else if (str.length > 1) { 50 | str = str.charAt(0).toUpperCase() + str.slice(1); 51 | } 52 | } 53 | return str; 54 | } 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/AutoCompleteEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'text!./AutocompleteEditor.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, AutocompleteTemplate) { 6 | return Backbone.Form.editors.Text.extend({ 7 | events: { 8 | 'change input': 'updateValue' 9 | }, 10 | 11 | initialize: function(options) { 12 | this.options = options; 13 | Backbone.Form.editors.Text.prototype.initialize.call(this, options); 14 | }, 15 | 16 | getValue: function() { 17 | console.log("getValue ACE"); 18 | return this.$el.find("input").val(); 19 | }, 20 | 21 | render: function() { 22 | Backbone.Form.editors.Text.prototype.render.call(this); 23 | this.$el = $(_.template(AutocompleteTemplate)({ 24 | id: this.options.id, 25 | model: this.model, 26 | value: this.value 27 | })); 28 | 29 | var that = this; 30 | this.$el.find("input").autocomplete({ 31 | minLength: 1, 32 | source : function(request, response){ 33 | var rx = new RegExp("^" + request.term, "i"); 34 | response($.grep(that.options.model.parameters,function(val){return rx.test(val);})); 35 | } 36 | }); 37 | 38 | this.$el.i18n(); 39 | this.setElement(this.$el); 40 | 41 | if (this.value) 42 | this.$el.find('input').val(this.value); 43 | 44 | return this; 45 | }, 46 | 47 | updateValue: function(e) { 48 | this.setValue(this.$el.find('input').val()); 49 | }, 50 | 51 | getValue: function() { 52 | return this.value; 53 | }, 54 | 55 | setValue: function(value) { 56 | this.value = value; 57 | this.model.view.setValue(this.options.key, value, undefined, true); 58 | this.model.set(this.options.key, value, {trigger: true}); 59 | } 60 | }); 61 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/OnBlurEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | "jquery", 3 | "lodash", 4 | "backbone", 5 | "text!./OnBlurEditor.html", 6 | "../../onblur-page", 7 | "backbone-forms" 8 | ], function ($, _, Backbone, OnBlurEditorTemplate, onBlurPage) { 9 | return Backbone.Form.editors.Base.extend({ 10 | template: OnBlurEditorTemplate, 11 | initialize: function (options) { 12 | this.options = options; 13 | Backbone.Form.editors.Base.prototype.initialize.call(this, options); 14 | }, 15 | 16 | render: function () { 17 | this.$el = $(_.template(OnBlurEditorTemplate)({ 18 | id: this.options.id, 19 | name: this.options.key, 20 | editorClass: this.options.schema.editorClass || "", 21 | value: this.value 22 | })); 23 | this.setElement(this.$el); 24 | return this; 25 | }, 26 | 27 | events: { 28 | "click .js-btn-onblur": "onBlur" 29 | }, 30 | 31 | onBlur: function () { 32 | var self = this; 33 | console.log("this.value: ", this.value); 34 | var el = document.createElement("div"); 35 | el.className = "onblur-editor onblur-editor-modal"; 36 | document.getElementsByTagName("body")[0].append(el); 37 | var vm = onBlurPage.init(el); 38 | vm.$on("complete", function (value) { 39 | console.log("tu as choisi: " + value); 40 | self.value = value; 41 | self.setValue(value, true); 42 | vm.$el.remove(); 43 | vm.$destroy(); 44 | }); 45 | }, 46 | 47 | getValue: function () { 48 | console.log("getValue", this.value); 49 | return this.value; 50 | }, 51 | 52 | setValue: function (value) { 53 | console.log("setValue", value); 54 | this.value = value; 55 | this.$el.find("input").val(value); 56 | if (this.model && this.model.view && this.model.view.setValue) { 57 | console.log('la') 58 | this.model.view.setValue(this.options.key, value); 59 | } else if (this.model) { 60 | console.log('ici') 61 | this.model.set(this.options.key, value, {trigger: true}); 62 | } 63 | } 64 | }); 65 | }); -------------------------------------------------------------------------------- /assets/stylesheet/components/pictos.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Pictos classes 4 | // We use reneco-fonts : https://github.com/NaturalSolutions/RenecoFonts 5 | // 6 | 7 | *[class^="picto"] { .reneco; } 8 | 9 | .picto-date:before { content: "\e67a"; } 10 | 11 | .picto-textarea:before { content: "\e63d"; } 12 | 13 | .picto-text:before { content: "\e63b"; } 14 | 15 | .picto-select:before { content: "\e654"; } 16 | 17 | .picto-numericrange:before { content: "\e63e"; } 18 | 19 | .picto-radio:before { content: "\e641"; } 20 | 21 | .picto-number:before { content : '\e63c'; } 22 | 23 | .picto-thesaurus:before { content: '\e696'; } 24 | 25 | .picto-subform:before { content : '\e639'; } 26 | 27 | .picto-childform:before { content : '\e639'; } 28 | 29 | .picto-file:before { content: "\e643"; } 30 | 31 | .picto-hidden:before { content: "\e644"; } 32 | 33 | .picto-autocompletetreeview:before { content : "\e646"; } 34 | 35 | .picto-checkbox:before { content : '\e63f'; } 36 | 37 | .picto-horizontalline:before { content: "\e649"; } 38 | 39 | .picto-pattern:before { content : "\e645"; } 40 | 41 | .picto-objectpicker:before { content : "\e915"; } 42 | 43 | .picto-treeview:before { content : "\e647"; } 44 | 45 | .picto-autocomplete:before { content : "\e648"; } 46 | 47 | .picto-decimal:before { content : "\e914"; } 48 | 49 | .picto-position:before { content : "\e663"; } 50 | 51 | .picto-imagefile:before { content : "\e913"; } 52 | 53 | .picto-subformgrid:before { content : "\e674"; } 54 | 55 | .picto-presentation:before { content : "\e601"; } 56 | 57 | .picto-droplist:before { content : "\e691"; } 58 | 59 | -------------------------------------------------------------------------------- /assets/stylesheet/app/formbuilder.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Main component style 4 | // 5 | 6 | #mainRegion { 7 | height : 100%; 8 | width : 200%; 9 | 10 | 11 | &>div:first-child { 12 | height : 100%; 13 | } 14 | 15 | .copy, .trash, .wrench { text-decoration: none; } 16 | 17 | .content { 18 | background : #fff; 19 | height : ~"calc(100% - 62px)"; 20 | 21 | // Main class for three parts 22 | .bootstrap-select { 23 | 24 | background : transparent; 25 | 26 | .dropdown-menu { 27 | padding-top : 0; 28 | padding-bottom : 0; 29 | border-color : #333; 30 | border-radius : 0; 31 | } 32 | 33 | .selectpicker { 34 | background : #222; 35 | border-radius : 0; 36 | border-color : #333; 37 | text-shadow : none; 38 | color : #555; 39 | margin-top : 0; 40 | .exo; 41 | 42 | li { 43 | background: #111; 44 | color: #000; 45 | .exo; 46 | 47 | &:hover { 48 | color: #111; 49 | background: #000; 50 | } 51 | 52 | a { 53 | background: transparent; 54 | } 55 | 56 | } 57 | 58 | } 59 | 60 | } 61 | } 62 | 63 | 64 | 65 | } 66 | 67 | body { 68 | &>.container-fluid { 69 | padding: 0 !important; 70 | margin: 0 !important; 71 | height: calc(~"100% - 55px"); // remove header's height 72 | position: relative; 73 | 74 | &>.row { 75 | margin-left: 0; 76 | margin-right: 0; 77 | } 78 | } 79 | } 80 | 81 | #leftSection{ 82 | height: 100%; 83 | &>div { 84 | height: 100%; 85 | } 86 | padding: 0; 87 | } 88 | 89 | #rightSection{ 90 | height: 100%; 91 | &>div { 92 | height: 100%; 93 | } 94 | padding: 0; 95 | } 96 | 97 | 98 | @import url('editionPage/all.less'); 99 | @import url('homePage/all.less'); 100 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/ObjectPickerEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'backbone-forms' 4 | ], function ($, _, Backbone) { 5 | return Backbone.Form.editors.Select.extend({ 6 | events: { 7 | 'change': 'applyConfiguration' 8 | }, 9 | 10 | /* 11 | options is used by backbone.Form to build select 12 | it's an Array of object 13 | each object should be like that 14 | */ 15 | defaultSchemaObjectInOptions: { 16 | val: '', //value send to server 17 | label: '', //value displayed in front 18 | wsUrl: '', //link for autocomplete 19 | }, 20 | 21 | initialize: function (options) { 22 | this.options = options; 23 | Backbone.Form.editors.Select.prototype.initialize.call(this, options); 24 | this.checkConfig(); //TODO blocking if config not ok ? 25 | this.buildObjConf(); 26 | 27 | }, 28 | 29 | checkConfig: function () { 30 | var config = this.schema.options; 31 | var error = false; 32 | 33 | for (var i = 0; i < config.length; i++) { 34 | var item = config[i]; 35 | for (var key in this.defaultSchemaObjectInOptions) { 36 | if (!(key in item)) { 37 | error = true; 38 | break; 39 | } 40 | } 41 | 42 | if (error) { 43 | console.warn(" missing key " + key + " in item : ", item) 44 | break; 45 | } 46 | } 47 | 48 | }, 49 | 50 | buildObjConf: function() { 51 | var config = this.schema.options; 52 | this.confObj = {} 53 | for (var i = 0; i < config.length; i++) { 54 | var item = config[i]; 55 | this.confObj[item.val] = item; 56 | } 57 | }, 58 | 59 | applyConfiguration: function (e) { 60 | 61 | if (e && 'delegateTarget' in e && 'selectedOptions' in e.delegateTarget && e.delegateTarget.selectedOptions[0]) { 62 | var value = e.delegateTarget.selectedOptions[0].value 63 | 64 | var updateObj = { 65 | name: this.confObj[value].val, 66 | objectType: this.confObj[value].val , 67 | wsUrl :this.confObj[value].wsUrl, 68 | } 69 | 70 | this.model.set( 71 | updateObj, 72 | { trigger: false }); 73 | } 74 | else { 75 | console.warn("hum something wrong with event send") 76 | } 77 | } 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/CollectionExtention.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | 'backbone', 8 | '../models/Fields', 9 | 'backbone.radio', 10 | '../../Translater', 11 | '../editor/CheckboxEditor', 12 | 'app-config', 13 | './EcoreleveCollection', 14 | './TrackCollection', 15 | './PositionTypesCollection', 16 | './PositionEventsCollection' 17 | ], function ($, Backbone, Fields, Radio, Translater, CheckboxEditor, AppConfig, 18 | EcoreleveCollection, TrackCollection, PositionTypesCollection, 19 | PositionEventsCollection) { 20 | 21 | /** 22 | * EmptyStatics is a dummy CollectionExtension object that does nothing. 23 | * If need extension for a specific context, add "context" key to 24 | * Extentions object, and make it implement this skeleton 25 | */ 26 | var EmptyExtension = { 27 | schemaExtention: function() {return {};}, 28 | propertiesDefaultValues: function() {return {};}, 29 | getSchemaExtention: function() {return {};}, 30 | initializeExtention: function() {return {};}, 31 | jsonExtention: function() {return {};} 32 | }; 33 | 34 | var collectionExtensions = { 35 | "track" : TrackCollection, 36 | "ecoreleve" : EcoreleveCollection, 37 | "positiontypes": PositionTypesCollection, 38 | "positionevents": PositionEventsCollection 39 | }; 40 | 41 | return { 42 | started: false, 43 | schemaExtention: {}, 44 | propertiesDefaultValues : {}, 45 | parameters: {}, 46 | 47 | initAllExtensions: function(options) { 48 | if (this.started) { 49 | return; 50 | } 51 | 52 | this.started = true; 53 | for (var i in collectionExtensions) { 54 | var ext = collectionExtensions[i]; 55 | ext.initializeExtention(options); 56 | } 57 | }, 58 | 59 | getModeExtention : function (currentContext, callback) { 60 | var extentionMode = collectionExtensions[window.context]; 61 | if (currentContext) 62 | extentionMode = collectionExtensions[currentContext]; 63 | if (!extentionMode) 64 | return EmptyExtension; 65 | 66 | if (callback && extentionMode.withCallback) { 67 | extentionMode.withCallback(callback); 68 | } 69 | return extentionMode; 70 | } 71 | }; 72 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/ChildFormEditor.js: -------------------------------------------------------------------------------- 1 | //For ecoreleve only if you use it in another application please implements TODO 2 | define([ 3 | 'jquery', 'lodash', 'backbone', 4 | 'backbone-forms' 5 | ], function($, _, Backbone) { 6 | return Backbone.Form.editors.Select.extend({ 7 | events: { 8 | 'change': 'applyConfiguration' 9 | }, 10 | 11 | renderOptions: function(options) { 12 | Backbone.Form.editors.Select.prototype.renderOptions.call(this, options); 13 | //store options used for building select in object for used it 14 | this.myOptionsResult = options; 15 | }, 16 | 17 | applyConfiguration: function(e) { 18 | //option is selected 19 | //we automaticaly set property : name, childForm, childFormName 20 | //TODO use context and check ObjectPickerEditor for some clue on embed configuration 21 | if (e && 'delegateTarget' in e && 'selectedOptions' in e.delegateTarget && e.delegateTarget.selectedOptions[0]) { 22 | var value = e.delegateTarget.selectedOptions[0].value 23 | var filteredOption = this.myOptionsResult.filter(function(item) { return item.val == value}); 24 | 25 | if (filteredOption.length == 1 ) { 26 | //set value to store 27 | var updateObj = { 28 | name : filteredOption[0].val, 29 | childForm : filteredOption[0].id, 30 | childFormName : filteredOption[0].val 31 | } 32 | //update model with value 33 | this.model.set( 34 | updateObj, 35 | { trigger: false }); 36 | } 37 | 38 | //from here model will not be updated 39 | if( filteredOption.length == 0 ) { 40 | //impossible case it's same ''datasource'' so if you select one value you have at least one value 41 | console.warn("IMPOSSIBRU") 42 | 43 | } 44 | if( filteredOption.length > 1 ) { 45 | console.warn("You have more than one result that's not good") 46 | console.warn("You should have only one protocol with this name (check your database): ",value) 47 | } 48 | 49 | } 50 | else { 51 | console.warn("hum something wrong with event send") 52 | } 53 | } 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/NumberEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'text!./NumberEditor.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, NumberTemplate) { 6 | return Backbone.Form.editors.Number.extend({ 7 | template: NumberTemplate, 8 | initialize: function(options) { 9 | this.options = options; 10 | Backbone.Form.editors.Number.prototype.initialize.call(this, options); 11 | }, 12 | 13 | render: function() { 14 | this.$el = $(_.template(NumberTemplate)({ 15 | id : this.options.id, 16 | name : this.options.key, 17 | min : typeof(this.options.schema.min) == 'number'? this.options.schema.min: null, 18 | max : typeof(this.options.schema.max) == 'number'? this.options.schema.max: null, 19 | editorClass : this.options.schema.editorClass || '', 20 | value : this.value, 21 | })); 22 | this.setElement(this.$el); 23 | return this; 24 | } 25 | 26 | // render: function() { 27 | // this.value = (typeof this.value == 'boolean') ? this.value : false; 28 | // this.$el = $(_.template(CheckboxTemplate)({ 29 | // id : this.options.id, 30 | // name : this.options.key, 31 | // editorClass : this.options.schema.editorClass || '', 32 | // fieldClass : this.options.schema.fieldClass || 'form-group', 33 | // iconClass : this.options.iconClass || '', 34 | // value : this.value, 35 | // title : this.schema.title == undefined ? this.key : this.schema.title 36 | // })); 37 | // 38 | // // subscribe handlers from schema on input change 39 | // if (this.options.schema.handlers) { 40 | // var handlers = this.options.schema.handlers; 41 | // for (var i in handlers) { 42 | // this.$el.find("input").on("change", _.bind(function(e) { 43 | // handlers[i](e.target.checked); 44 | // }, this)); 45 | // } 46 | // } 47 | // this.setElement(this.$el); 48 | // return this; 49 | // }, 50 | // 51 | // getValue: function() { 52 | // return this.$el.find('input').is(':checked'); 53 | // }, 54 | // 55 | // setValue: function(value) { 56 | // this.$el.find('input').prop('checked', value); 57 | // } 58 | }); 59 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/models/ExtraContextProperties/ExtraProperties.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | './TrackProperties', 8 | './EcoreleveProperties', 9 | './EcollectionProperties', 10 | './PositionEventsProperties', 11 | './PositionTypesProperties', 12 | './PositionProperties', 13 | './ReproProperties' 14 | ], function ($, TrackProperties, EcoreleveProperties, EcollectionProperties, PositionEventsProperties, PositionTypesProperties, 15 | PositionProperties, ReproProperties) { 16 | 17 | var contextExtraProperties = { 18 | "track" : TrackProperties, 19 | "ecoreleve" : EcoreleveProperties, 20 | "ecollection" : EcollectionProperties, 21 | "positionevents" : PositionEventsProperties, 22 | "positiontypes" : PositionTypesProperties, 23 | "position" : PositionProperties, 24 | "repro" : ReproProperties 25 | }; 26 | 27 | return { 28 | extraProperties: {}, 29 | exceptions: { 30 | hide: {} 31 | }, 32 | 33 | getExtraPropertiesDefaults: function(inputType, avoid) { 34 | var toret = {}; 35 | if (!avoid) 36 | toret = this.getExtraPropertiesDefaults("all", true); 37 | 38 | $.each(this.extraProperties, function(index, value) { 39 | if (index == inputType) { 40 | toret = _.extend(toret, value.defaults); 41 | return(toret); 42 | } 43 | }); 44 | 45 | return(toret); 46 | }, 47 | 48 | getExtraPropertiesSchema: function(inputType, avoid) { 49 | var toret = {}; 50 | if (!avoid) 51 | toret = this.getExtraPropertiesSchema("all", true); 52 | 53 | $.each(this.extraProperties, function(index, value) { 54 | if (index == inputType) { 55 | toret = _.extend(toret, value.schema); 56 | return(toret); 57 | } 58 | }); 59 | 60 | return(toret); 61 | }, 62 | 63 | getHideExceptionForProperty: function(input, property) { 64 | return(this.exceptions.hide[input] && this.exceptions.hide[input][property]); 65 | }, 66 | 67 | getPropertiesContext : function (currentContext) { 68 | var propertiesContext = contextExtraProperties[window.context]; 69 | if (currentContext) 70 | propertiesContext = contextExtraProperties[currentContext]; 71 | if (!propertiesContext) 72 | return this; 73 | return propertiesContext; 74 | } 75 | }; 76 | }); -------------------------------------------------------------------------------- /assets/js/config.js: -------------------------------------------------------------------------------- 1 | 2 | require.config({ 3 | 4 | paths: { 5 | backbone : "../../node_modules/backbone/backbone", 6 | blobjs : "../../node_modules/blobjs/Blob.min", 7 | bootstrap : "../../node_modules/bootstrap/dist/js/bootstrap.min", 8 | fancytree : "../../node_modules/jquery.fancytree/dist/modules/jquery.fancytree", 9 | "jquery.fancytree.ui-deps" : "../../node_modules/jquery.fancytree/dist/modules/jquery.fancytree.ui-deps", 10 | filesaver : "../../node_modules/file-saver/FileSaver.min", 11 | i18n : "../../node_modules/i18next/i18next.min", 12 | "i18n-xhr" : "../../node_modules/i18next-xhr-backend/i18nextXHRBackend.min", 13 | "i18n-jquery" : "../../node_modules/jquery-i18next/dist/umd/jquery-i18next.min", 14 | jquery : "../../node_modules/jquery/dist/jquery.min", 15 | "jquery-ui" : "../../node_modules/jquery-ui-dist/jquery-ui.min", 16 | requirejs : "../../node_modules/requirejs/require", 17 | "backbone-forms" : "../../node_modules/backbone-forms/distribution.amd/backbone-forms.min", 18 | "backbone.radio" : "../../node_modules/backbone.radio/build/backbone.radio.min", 19 | sweetalert : "../../node_modules/sweetalert/dist/sweetalert.min", 20 | marionette : '../../node_modules/backbone.marionette/lib/backbone.marionette.min', 21 | backgrid : '../../node_modules/backgrid/lib/backgrid.min', 22 | moment : '../../node_modules/moment/moment', 23 | slimScroll : '../../node_modules/jquery-slimScroll/jquery.slimscroll.min', 24 | 'lodash' : '../../node_modules/lodash/index', 25 | 'text' : '../../node_modules/text/text', 26 | 'tools' : './tools', 27 | 'vue' : '../../node_modules/vue/dist/vue', 28 | }, 29 | 30 | map: { 31 | "*": { 32 | "underscore": "lodash" 33 | } 34 | } 35 | }); 36 | 37 | define([ 38 | 'jquery', 'lodash', 'backbone', 'Translater', 'app-config' 39 | ], function($, _, Backbone, Translater, AppConfig) { 40 | 41 | require(['jquery', 'Translater', 'formbuilder', 'moment', 'lodash'], function($, Translater, formbuilder) { 42 | formbuilder.start(AppConfig.config.options); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /ressources/forms/importExample.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mon premier formulaire", 3 | "descriptionFr": "Mon premier formulaire", 4 | "descriptionEn": "My first form", 5 | "keywordsEn": [ 6 | "form" 7 | ], 8 | "keywordsFr": [ 9 | "formulaire" 10 | ], 11 | "labelFr": "Mon premier formulaire", 12 | "labelEn": "My first form", 13 | 14 | "schema": { 15 | "Name": { 16 | "id": 1, 17 | "labelFr" : "Nom", 18 | "labelEn" : "Name", 19 | "name" : "name", 20 | "readonly" : false, 21 | "editorClass" : "", 22 | "fieldClassEdit" : "", 23 | "fieldClassDisplay" : "", 24 | "fieldSize" : "Etroit", 25 | "endOfLine" : false, 26 | "defaultValue" : "", 27 | "help" : "Enter your name", 28 | "size" : 255, 29 | "type" : "Text", 30 | "validators" : ["required"] 31 | }, 32 | "Age": { 33 | "validators" : [], 34 | "id" : 2, 35 | "labelFr" : "Votre age", 36 | "labelEn" : "Your age", 37 | "name" : "age", 38 | "readonly" : false, 39 | "editorClass" : "", 40 | "fieldClassEdit" : "", 41 | "fieldClassDisplay" : "", 42 | "fieldSize" : "", 43 | "endOfLine" : false, 44 | "help" : "Enter your age", 45 | "decimal" : true, 46 | "defaultValue" : 10, 47 | "minValue" : 0, 48 | "maxValue" : 100, 49 | "precision" : 1, 50 | "unity" : "year", 51 | "type" : "NumericRange" 52 | }, 53 | "Folder": { 54 | "validators" : [], 55 | "id" : 4, 56 | "labelFr" : "Choisisser un dossier", 57 | "labelEn" : "Choose a folder", 58 | "name" : "folder", 59 | "readonly" : false, 60 | "editorClass" : "", 61 | "fieldClassEdit" : "", 62 | "fieldClassDisplay" : "", 63 | "fieldSize" : "", 64 | "endOfLine" : false, 65 | "defaultNode" : 0, 66 | "multipleSelection" : true, 67 | "hierarchicSelection" : false, 68 | "webServiceURL" : "", 69 | "type" : "TreeView" 70 | } 71 | }, 72 | "fieldsets": [] 73 | } 74 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/views/FieldViews.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'lodash', 4 | 'backbone', 5 | 'tools', 6 | "./FieldViewBase" 7 | ], function($, _, Backbone, tools, BaseView) { 8 | 9 | // TreeView does some prep work for underlying "TreeEditor" fields 10 | var TreeView = BaseView.extend({ 11 | events: _.extend(BaseView.prototype.events, { 12 | "change input[name='webServiceURL']": "urlChanged" 13 | }), 14 | 15 | urlChanged: function(e) { 16 | // preload new(?) url 17 | tools.loadTree(e.target.value); 18 | 19 | // tell user to reload form 20 | tools.swal("info", "editGrid.urlChanged", "editGrid.urlChangedMessage"); 21 | }, 22 | 23 | initialize: function(options) { 24 | // set aside url for autocompTree fields by key, will be used by editor 25 | var wsURL; 26 | if (options.model) { 27 | wsURL = options.model.get("webServiceURL"); 28 | } 29 | if (wsURL) { 30 | // this is hacky behavior, two things would be better: 31 | // * embed wsURL into autocomptree editor in some way, which would make more sense 32 | // * or at least embed wsUrl into defaultNode schema's options, and not directly in model 33 | options.model.defaultNode = wsURL; 34 | // pre-load url 35 | tools.loadTree(wsURL); 36 | } 37 | 38 | BaseView.prototype.initialize.apply(this, [options]); 39 | } 40 | }); 41 | 42 | 43 | return { 44 | AutocompleteFieldView: BaseView, 45 | BaseView: BaseView, 46 | CheckBoxFieldView: BaseView, 47 | ChildFormFieldView: BaseView, 48 | DateFieldView: BaseView, 49 | DecimalFieldView: BaseView, 50 | FileFieldView: BaseView, 51 | NumberFieldView: BaseView, 52 | NumericRangeFieldView: BaseView, 53 | ObjectPickerFieldView: BaseView, 54 | PatternFieldView: BaseView, 55 | PresentationFieldView: BaseView, 56 | RadioFieldView: BaseView, 57 | SelectFieldView: BaseView, 58 | StateBoxFieldView : BaseView, 59 | SubFormGridFieldView: BaseView, 60 | TextAreaFieldView: BaseView, 61 | TextFieldView: BaseView, 62 | 63 | // these do not have a TreeEditor (see Fields.js) 64 | // probably todo around the corner if we want to keep these generic treeviews 65 | AutocompleteTreeViewFieldView: BaseView, 66 | TreeViewFieldView: BaseView, 67 | 68 | // actual Fields that hold a Tree field (see Fields.js, defaultNode) 69 | PositionFieldView: TreeView, 70 | ThesaurusFieldView: TreeView, 71 | DropListFieldView: TreeView 72 | }; 73 | }); 74 | -------------------------------------------------------------------------------- /assets/stylesheet/components/modal.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Modal style 4 | // For some modal view we use the sweet-alert library : http://t4t5.github.io/sweetalert/ 5 | // 6 | 7 | // sweet alert style 8 | .swal-model { 9 | padding-bottom: 36px; 10 | button { 11 | .exo; 12 | } 13 | h2 { 14 | font-weight: 100; 15 | .exo; 16 | } 17 | label { 18 | .exo; 19 | } 20 | p { 21 | .exo; 22 | } 23 | } 24 | 25 | // Main modal style 26 | .modal { 27 | background: transparent; 28 | margin-top: 100px; 29 | 30 | label { 31 | .exo; 32 | font-weight: 500; 33 | } 34 | 35 | input { 36 | .exo; 37 | } 38 | 39 | h2 { 40 | color : #575757; 41 | font-size : 30px; 42 | text-align : center; 43 | font-weight : 600; 44 | text-transform: none; 45 | position : relative; 46 | margin : 25px 0; 47 | padding : 0; 48 | line-height : 25px; 49 | display : block; 50 | .exo; 51 | } 52 | 53 | button { 54 | margin-top : 5px; 55 | &.col-md-2 { 56 | height: 34px; 57 | line-height: 0; 58 | } 59 | } 60 | 61 | .control { 62 | display : block; 63 | height : 34px; 64 | padding : 6px 12px; 65 | font-size : 14px; 66 | line-height : 1.42857143; 67 | color : #555; 68 | background-color : #fff; 69 | background-image : none; 70 | border : 1px solid #ccc; 71 | border-radius : 4px; 72 | -webkit-box-shadow : inset 0 1px 1px rgba(0,0,0,.075); 73 | box-shadow : inset 0 1px 1px rgba(0,0,0,.075); 74 | -webkit-transition : border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s; 75 | -o-transition : border-color ease-in-out .15s,box-shadow ease-in-out .15s; 76 | transition : border-color ease-in-out .15s,box-shadow ease-in-out .15s; 77 | } 78 | } 79 | 80 | // Save and export modal 81 | #saveModal, #exportModal { 82 | h2 { 83 | .exo; 84 | } 85 | textarea { resize: none; height : 60px; max-height: 60px; } 86 | label > i { color : #888; } 87 | .modal-body { 88 | padding-bottom: 25px; 89 | overflow-x : hidden; 90 | .row-fluid:nth-child(even){ 91 | margin-bottom: 5px; 92 | } 93 | } 94 | } 95 | 96 | // Import modal style 97 | #importModal { 98 | .btn-success { 99 | padding-top: 5px !important; 100 | } 101 | input { 102 | margin-left: 0; 103 | width: 82.7%; 104 | } 105 | 106 | 107 | 108 | #importProtocolFileText { float : left;} 109 | } -------------------------------------------------------------------------------- /assets/stylesheet/mainStyles/main.less: -------------------------------------------------------------------------------- 1 | html, body { 2 | width : 100%; 3 | height : 100%; 4 | margin : 0; 5 | padding : 0; 6 | overflow : hidden; 7 | background : #111; 8 | } 9 | 10 | 11 | 12 | // --------------------------------------------------------------------- 13 | // Main classes 14 | // --------------------------------------------------------------------- 15 | 16 | 17 | .col0 { width : 0px !important; overflow: hidden;} 18 | .diff { margin-bottom : 150px; } 19 | .text { line-height : 30px; font-size : 20px; } 20 | .marginLeft10 { margin-left : 10px !important; } 21 | .advanced { display : none; } 22 | 23 | .form-group { margin-bottom: 0px !important; } 24 | 25 | 26 | .table { tr { background : white; } } 27 | .bordered { border : 2px #aaa solid; background : #fff; } 28 | .required { color : red; &:before { content : "*"; } } 29 | 30 | 31 | .ui-sortable-helper { cursor : move !important; * { cursor : move !important; }} 32 | 33 | .toggle { 34 | background-color : rgb(238, 238, 238); 35 | display : none; 36 | background-position : initial initial; 37 | background-repeat : initial initial; 38 | } 39 | 40 | .form-control{ 41 | &.col-md-10 { 42 | width : 83.333333333% !important; 43 | } 44 | } 45 | 46 | .find { 47 | height : 34px; 48 | } 49 | 50 | .form-group { 51 | &.row { 52 | .col-md-2 { 53 | height: 40px !important; 54 | } 55 | } 56 | } 57 | 58 | .displayValue { 59 | height: 16px; 60 | line-height: 16px !important; 61 | } 62 | 63 | .itemList { 64 | float : left; 65 | vertical-align : middle; 66 | padding-top : 5px; 67 | padding-right : 5px; 68 | } 69 | 70 | .element { 71 | .row { 72 | margin-left: 0; 73 | margin-right: 0; 74 | } 75 | } 76 | 77 | .swal-modal { 78 | width: 525px; 79 | 80 | .swal-text, .swal-footer { 81 | text-align: center; 82 | } 83 | .swal-title { 84 | margin-bottom: 25px; 85 | } 86 | 87 | button { 88 | height: auto !important; 89 | } 90 | 91 | .swal-button { 92 | &.danger { 93 | background-color: rgb(221, 107, 85); 94 | color: white; 95 | } 96 | 97 | &.swal-button--obsolete { 98 | background-color: #4f73b3; 99 | color: white; 100 | } 101 | } 102 | 103 | .swalSelect { 104 | .important { 105 | font-size: 1.2em; 106 | font-weight: bold; 107 | margin-bottom: 10px; 108 | } 109 | 110 | label { 111 | font-weight: normal; 112 | margin-right: 15px; 113 | } 114 | } 115 | } 116 | 117 | @import url('fonts.less'); 118 | @import url('position.less'); 119 | @import url('generatedStyle.less'); 120 | -------------------------------------------------------------------------------- /ressources/autocomplete/forms.json: -------------------------------------------------------------------------------- 1 | { 2 | "options": [ 3 | "morbi odio odio elementum", 4 | "pretium nisl ut volutpat", 5 | "ut nulla", 6 | "ultrices phasellus", 7 | "varius integer ac", 8 | "massa quis augue luctus tincidunt", 9 | "vel", 10 | "pellentesque quisque porta volutpat", 11 | "consequat", 12 | "orci luctus", 13 | "orci vehicula condimentum", 14 | "turpis sed ante vivamus tortor", 15 | "sit amet", 16 | "fusce consequat nulla nisl", 17 | "a suscipit nulla", 18 | "tincidunt ante vel ipsum", 19 | "non mattis", 20 | "ullamcorper purus sit", 21 | "est et tempus semper est", 22 | "quis tortor id nulla ultrices", 23 | "nisl nunc nisl duis", 24 | "erat quisque", 25 | "nulla pede ullamcorper augue", 26 | "fusce lacus purus", 27 | "pede justo lacinia eget", 28 | "nam ultrices libero non", 29 | "proin risus", 30 | "ut dolor morbi vel lectus", 31 | "eget", 32 | "nulla ac", 33 | "congue risus semper porta", 34 | "ipsum dolor sit", 35 | "nunc vestibulum ante ipsum primis", 36 | "neque sapien", 37 | "vivamus", 38 | "rhoncus aliquam lacus", 39 | "potenti nullam porttitor lacus at", 40 | "at", 41 | "massa", 42 | "erat volutpat in", 43 | "erat vestibulum sed magna", 44 | "in faucibus orci luctus", 45 | "primis in faucibus orci luctus", 46 | "at", 47 | "nam nulla integer", 48 | "libero", 49 | "sed accumsan felis", 50 | "donec pharetra", 51 | "donec semper sapien a", 52 | "tempor turpis nec euismod scelerisque", 53 | "convallis", 54 | "nulla suspendisse potenti cras", 55 | "non", 56 | "in felis", 57 | "ut nunc vestibulum ante", 58 | "id mauris vulputate", 59 | "est donec odio justo", 60 | "consectetuer adipiscing", 61 | "arcu adipiscing molestie hendrerit at", 62 | "viverra eget congue eget", 63 | "tortor eu pede", 64 | "sociis natoque penatibus", 65 | "consequat nulla nisl nunc", 66 | "a pede posuere nonummy integer", 67 | "tortor risus dapibus", 68 | "arcu sed", 69 | "sodales scelerisque", 70 | "quam fringilla rhoncus", 71 | "lobortis", 72 | "accumsan", 73 | "viverra dapibus nulla suscipit", 74 | "nulla elit", 75 | "suspendisse", 76 | "augue aliquam erat volutpat in", 77 | "aliquam quis", 78 | "consequat nulla nisl nunc nisl", 79 | "varius", 80 | "in faucibus orci luctus et", 81 | "nunc viverra dapibus", 82 | "aliquet massa id lobortis", 83 | "leo rhoncus sed vestibulum sit", 84 | "at nunc", 85 | "nisl aenean", 86 | "nulla ut", 87 | "ultrices aliquet maecenas leo", 88 | "porttitor lorem id ligula suspendisse", 89 | "at turpis donec posuere metus", 90 | "dis parturient montes nascetur", 91 | "platea dictumst", 92 | "ut ultrices vel augue", 93 | "a libero nam", 94 | "metus", 95 | "suspendisse", 96 | "velit id", 97 | "mi pede", 98 | "velit nec nisi", 99 | "dictumst", 100 | "integer a", 101 | "nisl venenatis lacinia aenean", 102 | "nisl ut volutpat" 103 | ] 104 | } -------------------------------------------------------------------------------- /docs/deprecated/events.md: -------------------------------------------------------------------------------- 1 | # Events documentation 2 | 3 | We use backbone radio for communication between and inside module. 4 | 5 | In this page we explain event sequences for an use case. 6 | 7 | # User wants to delete form 8 | 9 | These events use **homepage channel**. 10 | 11 | * **delete form** 12 | * Send by CenterGridPanelView 13 | * Received by HomePageController 14 | * Data : ID of the form to remove 15 | * **formDeleted** 16 | * Send by HomePageController 17 | * Received by CenterGridPanelView 18 | * Data : if form has been deleted 19 | 20 | # User click on a row in the main panel grid 21 | 22 | These events pass through **grid channel**. 23 | 24 | * **rowClicked** 25 | * Send by ClickableRow (see CenterGridPanelView onRender method) 26 | * Received by CenterGridPanelView 27 | * Data : jQuery clicked element 28 | 29 | # User use search form on the home page 30 | 31 | These events pass through **grid channel**. 32 | 33 | * **search** 34 | * Send by leftPanelView 35 | * Rceive by CenterGridPanelView 36 | * Data : searchData user typed data 37 | 38 | # User exports a form 39 | 40 | These events pass through **form channel**. 41 | 42 | * **export** 43 | * Send by FormPanelView 44 | * Rceived by EditionPageController 45 | * Data filename for futur created file 46 | * **exportFinished** 47 | * Send by EditionPageController 48 | * Send by FormPanelView 49 | * Data : if form has correcly been exported 50 | 51 | # User imports a form 52 | 53 | These events pass through **form, global** and **editionPage channels**. 54 | 55 | The global chennel allow communication betweens module through formbuilder main app object. 56 | 57 | * **formImported** : global channel 58 | * Send by CenterGridPanelView 59 | * Received by formbuilder 60 | * Data : JSON form parsed data 61 | 62 | 63 | * **formImported** : editionPage channel 64 | * Send by : formbuilder 65 | * Received by : EditionPageRouter 66 | * Data : JSON form parsed data 67 | 68 | 69 | * **import** : form channel 70 | * Send by : EditionPageRouter 71 | * Received by : EditionPageController 72 | * Data : JSON form parsed data 73 | 74 | 75 | * **formToEdit** : form channel 76 | * Send by : EditionPageController 77 | * Rceived by : FormPanelView 78 | * Data : JSON form parsed data 79 | 80 | # User wants to edit a form properties 81 | 82 | These events pass through **form channel**. 83 | 84 | * **editForm** 85 | * Send by : FormPanelView 86 | * Received by : EditionPageLayout 87 | * Data : form to edit 88 | 89 | # User wants to edit a form field properties 90 | 91 | These events pass through **form channel**. 92 | 93 | * **editModel** 94 | * Send by : BaseView or herited view like TextFieldView 95 | * Received by : EditionPageController 96 | * Data : ID of model to edit 97 | 98 | 99 | * **initFieldSetting** 100 | * Send by : EditionPageController 101 | * Received by : EditionPageLayout 102 | * Data : some data configuration to init setting view 103 | 104 | # User wants to remove a field 105 | 106 | These events pass through **form channel**. 107 | 108 | * **remove** 109 | * Send by : BaseView or herited view like TextFieldView 110 | * Received by : FieldCollection 111 | * Data : ID of model to edit 112 | 113 | This event trigger a simple backbone event. FormPanelView is listening **remove** FieldCollection event to update itself. 114 | 115 | 116 | 117 | back to [summary](index.md) 118 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | var fancytreeSkin = "skin-win8"; 3 | var fancyTreeSkinsDir = "node_modules/jquery.fancytree/dist"; 4 | 5 | var cssLibs = [ 6 | "node_modules/autocompTree/Scripts/skin-win7/ui.fancytree.min.css", 7 | "node_modules/bootstrap/dist/css/bootstrap-theme.css", 8 | "node_modules/bootstrap/dist/css/bootstrap.css", 9 | "node_modules/backbone-forms/distribution/templates/bootstrap3.css", 10 | "node_modules/@naturalsolutions/renecofonts/style.css", 11 | "node_modules/jquery.fancytree/dist/" + fancytreeSkin + "/ui.fancytree.min.css", 12 | "assets/stylesheet/sweetalert.css" 13 | ]; 14 | 15 | var cssMain = [ 16 | "assets/stylesheet/all.less" 17 | ]; 18 | 19 | var renecoFontsDir = "node_modules/@naturalsolutions/renecofonts/fonts/"; 20 | 21 | grunt.initConfig({ 22 | // LESS file compilation 23 | // This instruction is launched with grunt watch 24 | less: { 25 | dev: { 26 | options: { 27 | paths: ["stylesheet"], 28 | cleancss: false, 29 | sourceMap: false, 30 | compress : false, 31 | dumpLineNumbers: "all", 32 | sourceMapFilename: 'compressed/formbuilder.css.map', 33 | sourceMapRootpath: '' 34 | }, 35 | files: { 36 | "compressed/libs/libs.min.css": cssLibs, 37 | "compressed/formbuilder.min.css": cssMain 38 | } 39 | }, 40 | dist: { 41 | options: { 42 | paths: ["stylesheet"], 43 | cleancss: true, 44 | sourceMap: false, 45 | compress : true, 46 | sourceMapFilename: 'compressed/formbuilder.css.map', 47 | sourceMapRootpath: '' 48 | }, 49 | files: { 50 | "compressed/libs/libs.min.css": cssLibs, 51 | "compressed/formbuilder.min.css": cssMain 52 | } 53 | } 54 | }, 55 | 56 | copy: { 57 | fonts: { 58 | files: [ 59 | { 60 | src: '**', 61 | cwd: renecoFontsDir, 62 | dest: 'compressed/libs/fonts/', 63 | expand: true, 64 | flatten: true 65 | } 66 | ] 67 | }, 68 | 69 | fancyTreeSkin: { 70 | files: [ 71 | { 72 | src: fancytreeSkin + "/**", 73 | cwd: fancyTreeSkinsDir, 74 | dest: 'compressed/', 75 | expand: true 76 | } 77 | ] 78 | } 79 | }, 80 | 81 | // Watch less file changes for compile 82 | watch: { 83 | stylesheet: { 84 | files: ['assets/stylesheet/**/*.less'], 85 | tasks: ['less:dev'] 86 | } 87 | } 88 | }); 89 | 90 | grunt.registerTask('default', 'dev'); 91 | grunt.registerTask('dev', ['less:dev', 'copy']); 92 | grunt.registerTask('prod', ['less:dist', 'copy']); 93 | grunt.registerTask('build', 'prod'); 94 | 95 | grunt.loadNpmTasks('grunt-contrib-less'); 96 | grunt.loadNpmTasks('grunt-contrib-watch'); 97 | grunt.loadNpmTasks('grunt-contrib-copy'); 98 | } 99 | -------------------------------------------------------------------------------- /assets/js/homePageModule/models/FormModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', '../../Translater' 3 | ], function($, _, Backbone, translater) { 4 | return Backbone.Model.extend({ 5 | 6 | /** 7 | * Attributes default values 8 | * @type {Object} 9 | */ 10 | defaults: { 11 | name : translater.getValueFromKey('form.new'), 12 | creationDate : new Date(), 13 | modificationDate : null, 14 | curStatus : 1, 15 | editStatus : '', 16 | translations : {}, 17 | schema : {}, 18 | tag : '', 19 | obsolete : false, 20 | propagate : false, 21 | isTemplate : false, 22 | context : window.context || "", 23 | state : 1, 24 | originalID : null, 25 | initialID : null, 26 | readonly : false, 27 | 28 | // display attributes 29 | creationDateDisplay : "", 30 | modificationDateDisplay : "" 31 | }, 32 | 33 | /** 34 | * Model constructor 35 | */ 36 | initialize : function() { 37 | _.bindAll(this, 'toJSON'); 38 | 39 | var creationDate = this.get('creationDate'), 40 | modificationDate = this.get('modificationDate'); 41 | 42 | if (creationDate != null) { 43 | creationDate = creationDate.toString(); 44 | this.set('creationDateDisplay', creationDate.substring(0, creationDate.length - 11)); 45 | } 46 | if (modificationDate != null) { 47 | modificationDate = modificationDate.toString(); 48 | this.set('modificationDateDisplay', modificationDate.substring(0, modificationDate.length - 11)); 49 | } 50 | this.set('editStatus', creationDate == modificationDate ? 'created': 'modified'); 51 | 52 | if (this.defaults.context = "" && window.context) 53 | this.defaults.context = window.context; 54 | // this.set('context',window.context); REMOVE IT BUG FOR ALL CONTEXT need to know why 55 | }, 56 | 57 | toJSON : function() { 58 | var schema = this.get('schema'); 59 | _.map(schema, function(el) { 60 | el.validators = []; 61 | return el; 62 | }); 63 | this.set('schema', schema); 64 | 65 | // todo send this.attributes.toJSON()? 66 | return { 67 | id : this.get('id'), 68 | name : this.get('name'), 69 | creationDate : this.get('creationDate'), 70 | modificationDate : this.get('modificationDate'), 71 | curStatus : this.get('curStatus'), 72 | translations : this.get('translations'), 73 | schema : this.get('schema'), 74 | tag : this.get('tag'), 75 | isTemplate : this.get('isTemplate'), 76 | obsolete : this.get('obsolete'), 77 | propagate : this.get('propagate'), 78 | context : this.get('context'), 79 | state : this.get('state'), 80 | originalID : this.get('originalID'), 81 | initialID : this.get('initialID'), 82 | readonly : this.get('readonly') 83 | } 84 | } 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/PositionTypesCollection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | 'backbone', 8 | '../models/Fields', 9 | '../editor/CheckboxEditor', 10 | '../editor/NumberEditor', 11 | 'backbone.radio', 12 | '../../Translater', 13 | 'auth', 14 | 'text!../templates/FieldTemplate.html' 15 | ], function ($, Backbone, Fields, CheckboxEditor, NumberEditor, Radio, translater, auth, FieldTemplate) { 16 | 17 | var fieldTemplate = _.template(FieldTemplate); 18 | 19 | return { 20 | extensionData: null, 21 | schemaExtention: { 22 | 23 | }, 24 | 25 | propertiesDefaultValues : { 26 | 27 | }, 28 | 29 | getExtractedDatas: function() { 30 | return {}; 31 | }, 32 | getSchemaExtention: function(options){ 33 | if (this.extensionData) { 34 | return this.extensionData; 35 | } 36 | if (options) { 37 | this.initializeExtention(options); 38 | } 39 | return this.schemaExtention; 40 | }, 41 | initializeExtention: function (options) { 42 | this.getPositionDatas(options); 43 | }, 44 | 45 | jsonExtention: function (originalForm) { 46 | return(this.propertiesDefaultValues); 47 | }, 48 | updateAttributesExtention: function () { 49 | return true; 50 | }, 51 | 52 | setSelectValues: function(datas, schema) 53 | { 54 | var getJSONForSelectOptions = function(valuesArray) 55 | { 56 | $.each(valuesArray, function(index, value){ 57 | valuesArray[index] = {label: value, val: value}; 58 | }); 59 | return(valuesArray); 60 | }; 61 | 62 | if (datas) 63 | { 64 | var that = this; 65 | $.each(JSON.parse(datas), function(index, value) 66 | { 67 | var values = []; 68 | for(var ind in value) 69 | values.push(ind); 70 | 71 | var valtoset = getJSONForSelectOptions(values.sort()); 72 | 73 | if (schema[index.substr(0,1).toLowerCase()+index.substr(1)]) 74 | schema[index.substr(0,1).toLowerCase()+index.substr(1)].options = valtoset; 75 | else 76 | { 77 | var arrayToSet = []; 78 | $.each(valtoset, function(index, value){ 79 | if(value.val) 80 | value = value.val; 81 | arrayToSet.push(value); 82 | }); 83 | 84 | that[index.substr(0,1).toLowerCase()+index.substr(1)] = arrayToSet; 85 | } 86 | }); 87 | } 88 | 89 | return (schema); 90 | }, 91 | 92 | getPositionDatas: function (options) { 93 | if (!this.extensionData) { 94 | $.ajax({ 95 | data: JSON.stringify({'datas' : this.getExtractedDatas()}), 96 | type: 'POST', 97 | url: options.paths.positionWSPath + "/getTypes", 98 | contentType: 'application/json', 99 | crossDomain: true, 100 | async: true, 101 | success: _.bind(function (data) { 102 | this.extensionData = this.setSelectValues(data, this.schemaExtention); 103 | if (this.callback) { 104 | this.callback(this.extensionData); 105 | } 106 | this.callback = null; 107 | }, this), 108 | error: _.bind(function (xhr) { 109 | console.log("error ! " + xhr); 110 | }, this) 111 | }); 112 | } 113 | 114 | return this.extensionData; 115 | }, 116 | 117 | withCallback: function(callback) { 118 | // we have data available, just apply the callback 119 | if (this.extensionData) { 120 | callback(this.extensionData); 121 | } else { 122 | // no data available yet, save for a brighter day 123 | this.callback = callback; 124 | } 125 | } 126 | }; 127 | }); -------------------------------------------------------------------------------- /assets/js/formbuilder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Run the application 3 | * At start we run HomePageRouter to display homepage 4 | */ 5 | 6 | define([ 7 | 'backbone', 8 | 'lodash', 9 | 'jquery', 10 | 'marionette', 11 | './router', 12 | 'app-config', 13 | 'auth', 14 | 'tools', 15 | 'i18n' 16 | ], function(Backbone, _, $, Marionette, Router, AppConfig, auth, tools) { 17 | 18 | var FormbuilderApp = new Marionette.Application(); 19 | var MainView = Marionette.View.extend({ 20 | el: "#mainRegion", 21 | template: _.template( 22 | '
\n' + 23 | '
'), 24 | regions: { 25 | leftRegion: { 26 | el: '#leftSection', 27 | replaceElement: false 28 | }, 29 | rightRegion: { 30 | el: '#rightSection', 31 | replaceElement: false 32 | } 33 | } 34 | }); 35 | FormbuilderApp.on('start', function() { 36 | 37 | //Si on est sur la version dev, alors on change la couleur et le texte formbuilder pour pouvoir différencier de la vrai app 38 | if(window.location.pathname.split('/')[1].length > 11){ 39 | $('a.title').text('(DevMode)'+$('a.title').text()) 40 | $('header').css('background-color','rgb(189, 33, 0);') 41 | $('#contextSwitcher').css('background-color','rgb(154, 34, 8);') 42 | } 43 | 44 | if (auth.error) { 45 | var redirectHome = function() { 46 | window.location.href = AppConfig.portalURL; 47 | }; 48 | 49 | switch (auth.error.status) { 50 | case 400: 51 | tools.swal("error", "error.cookieCheck", "error.serverAvailable", null, redirectHome); 52 | break; 53 | case 502: 54 | default: 55 | tools.swal("error", "error.cookieCheck", "error.serverDown", null, redirectHome); 56 | break; 57 | } 58 | return; 59 | } 60 | 61 | if (auth.username) { 62 | $("header .user").text(auth.username); 63 | $("header .icons.last").removeClass("hidden"); 64 | } 65 | if (auth.userlanguage) { 66 | $("header .lang").text(auth.userlanguage.toUpperCase()); 67 | } 68 | 69 | // start main view & router 70 | this.rootView = new MainView(); 71 | this.router = new Router( 72 | this.rootView.getRegion('leftRegion'), 73 | this.rootView.getRegion('rightRegion')); 74 | 75 | // start routing 76 | Backbone.history.start(); 77 | 78 | $(".logout").click(function(){ 79 | var delete_cookie = function(name) { 80 | document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 81 | }; 82 | 83 | delete_cookie(AppConfig.cookieName); 84 | setTimeout(function(){window.location.replace(AppConfig.portalURL);},200) 85 | }); 86 | 87 | /* TODO position needs to specify GetTree now, so the loop has been removed ... 88 | // preload trees 89 | $.each(AppConfig.paths, function(key, url){ 90 | tools.loadTree(url); 91 | }); 92 | */ 93 | tools.loadTree(AppConfig.paths.thesaurusWSPath); 94 | tools.loadTree(AppConfig.paths.positionWSPath + "/GetTree") 95 | 96 | // preload form names 97 | $.each(AppConfig.contexts, function(ctx) { 98 | tools.loadForms(ctx); 99 | }); 100 | 101 | // replace all with inline tags 102 | tools.inlineSvg('img.svg'); 103 | 104 | // translate header 105 | $("body > header").i18n(); 106 | }); 107 | 108 | return FormbuilderApp; 109 | }); 110 | -------------------------------------------------------------------------------- /assets/js/editionPageModule/editor/ChoicesEditor.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'lodash', 'backbone', 3 | 'text!./ChoicesEditor.html', 'text!./ChoicesEditorRow.html', 4 | 'backbone-forms' 5 | ], function($, _, Backbone, ChoicesTemplate, ChoiceRow) { 6 | return Backbone.Form.editors.Text.extend({ 7 | events: { 8 | 'change input': 'updateValue', 9 | 'click .deleteOption': 'deleteOption', 10 | 'click .addBtn': 'addOption' 11 | }, 12 | 13 | // used if this.model.columnDefaults is not there 14 | defaultFallback: { 15 | isDefaultValue: false, 16 | value: '' 17 | }, 18 | 19 | languagesFallback: ['fr', 'en'], 20 | 21 | initialize: function(options) { 22 | this.options = options; 23 | Backbone.Form.editors.Text.prototype.initialize.call(this, options); 24 | 25 | this.languages = this.schema.languages; 26 | if (!this.languages) { 27 | this.languages = this.languagesFallback; 28 | } 29 | }, 30 | 31 | reorderValues: function(updateElem) { 32 | _.each(this.value, _.bind(function(e, i) { 33 | if (updateElem) { 34 | this.$el.find("tr[data-index='" + e.id + "']") 35 | .attr("data-index", i); 36 | } 37 | e.id = i; 38 | }, this)); 39 | }, 40 | 41 | renderChoice: function(choice) { 42 | return _.template(ChoiceRow)({ 43 | choice: choice, 44 | languages: this.languages 45 | }); 46 | }, 47 | 48 | render: function() { 49 | this.reorderValues(); 50 | this.$el = $(_.template(ChoicesTemplate)({ 51 | id : this.options.id, 52 | editorClass : this.options.schema.editorClass || '', 53 | fieldClass : this.options.schema.fieldClass || 'form-group', 54 | iconClass : this.options.iconClass || '', 55 | choices : this.value, 56 | languages : this.languages, 57 | renderChoice: this.renderChoice, 58 | title : this.schema.title == undefined ? this. key : this.schema.title 59 | })); 60 | this.setElement(this.$el); 61 | return this; 62 | }, 63 | 64 | updateValue: function(e) { 65 | var value = e.target.value; 66 | switch (e.target.type) { 67 | case "checkbox": 68 | value = e.target.checked; 69 | break; 70 | } 71 | 72 | var index = $(e.target).closest("tr.choice").data("index"); 73 | var name = $(e.target).data("name"); 74 | this.value[index][name] = value; 75 | }, 76 | 77 | 78 | addOption: function() { 79 | var newChoice = this.options.model.columnDefaults; 80 | if (!newChoice) { 81 | newChoice = this.defaultFallback; 82 | } 83 | newChoice = _.clone(newChoice); 84 | 85 | _.each(this.languages, function(e) { 86 | if (!newChoice[e]) 87 | newChoice[e] = ''; 88 | }); 89 | 90 | newChoice.id = this.value.length; 91 | this.value.push(newChoice); 92 | this.$el.find("table").append(this.renderChoice(newChoice)); 93 | }, 94 | 95 | deleteOption: function(e) { 96 | var $row = $(e.target).closest("tr.choice"); 97 | this.value.splice($row.data("index"), 1); 98 | this.reorderValues(true); 99 | $row.remove(); 100 | }, 101 | 102 | getValue: function() { 103 | return this.value; 104 | }, 105 | 106 | setValue: function(value) { 107 | this.value = value; 108 | } 109 | }); 110 | }); -------------------------------------------------------------------------------- /assets/stylesheet/app/homePage/leftPanel.less: -------------------------------------------------------------------------------- 1 | #leftPanel { 2 | background: white; 3 | height: 100%; 4 | overflow: hidden; 5 | padding: 0; 6 | 7 | & > div { 8 | height: 100%; 9 | } 10 | 11 | .row { 12 | width: 100%; 13 | margin: 0; 14 | padding: 28px 32px; 15 | } 16 | 17 | .row.search { 18 | background: #ededed; 19 | .actions { 20 | text-align: center; 21 | width: 100%; 22 | margin: 15px 0 0; 23 | } 24 | 25 | .form-group { 26 | margin: 12px 0; 27 | 28 | label { 29 | color: #bbb; 30 | margin: 5px 0; 31 | } 32 | 33 | input, select { 34 | border: none; 35 | border-bottom: 1px solid #bbb; 36 | background: none; 37 | outline: none; 38 | box-shadow: none; 39 | 40 | &:focus, &:hover { 41 | border-bottom-color: #888; 42 | } 43 | } 44 | } 45 | 46 | .search-box { 47 | width: 100%; 48 | position: relative; 49 | 50 | span.close { 51 | opacity: .45; 52 | position: absolute; 53 | right: 10px; 54 | top: 5px; 55 | padding: 5px; 56 | 57 | font-size: 12px; 58 | font-family: 'reneco', sans-serif !important; 59 | color: #555; 60 | &:hover { 61 | text-decoration: none; 62 | color: @orange !important; 63 | } 64 | } 65 | 66 | input:-webkit-autofill { 67 | -webkit-box-shadow: 0 0 0 30px #ededed inset !important; 68 | } 69 | 70 | input#search { 71 | outline: none; 72 | box-shadow: none; 73 | font-family: 'reneco', sans-serif !important; 74 | border-radius: 19px !important; 75 | background: #ededed; 76 | 77 | &:focus, &:hover { 78 | border-color: @orange; 79 | } 80 | &::placeholder { 81 | font-style: italic; 82 | } 83 | &:focus { 84 | border-color: @orange !important; 85 | &::placeholder { 86 | color: @orange; 87 | } 88 | } 89 | } 90 | } 91 | 92 | .ui-autocomplete { 93 | // width: 100% !important; 94 | background-color: white !important; 95 | border: none; 96 | color: black; 97 | .exo; 98 | 99 | li { 100 | .exo; 101 | } 102 | .ui-state-focus { 103 | color : white; 104 | } 105 | } 106 | } 107 | 108 | .row.edited { 109 | background: white; 110 | font-family: 'ProximaNovaLight', sans-serif !important; 111 | position: relative; 112 | height: ~"calc(100% - 231px)"; 113 | 114 | h3 { 115 | padding: 0 0 22px; 116 | margin: 0; 117 | } 118 | 119 | .recentlyEdited { 120 | overflow-y: auto !important; 121 | div { 122 | padding: 4px 0; 123 | border-bottom: 1px solid #dddddd; 124 | font-size: 14px; 125 | /* text-transform: uppercase; */ 126 | 127 | &.modified::before, &.created::before { 128 | font-family: reneco, sans-serif; 129 | color: @orange; 130 | vertical-align: bottom; 131 | padding: 0 20px 0 7px; 132 | } 133 | &.modified::before { 134 | content: '\e669'; 135 | } 136 | &.created::before { 137 | content: '\e65d'; 138 | } 139 | 140 | &:hover { 141 | cursor: pointer; 142 | background: #dddddd; 143 | } 144 | } 145 | 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /assets/stylesheet/components/buttons.less: -------------------------------------------------------------------------------- 1 | // 2 | // Button style 3 | // 4 | 5 | @import url('./common.less'); 6 | 7 | input[type="submit"].reneco { color : white; } 8 | 9 | [data-context="all"] { 10 | .actions { 11 | display: none !important; 12 | } 13 | } 14 | 15 | [data-topcontext="reneco"] { 16 | #import, #export { 17 | display: none !important; 18 | } 19 | } 20 | 21 | [data-readonly="true"] { 22 | .actions, #rowControls, .action:not(.btnOk):not(.actionBack) { 23 | display: none !important; 24 | } 25 | } 26 | 27 | 28 | .action { 29 | .exo; 30 | box-sizing: content-box; 31 | display: inline-block; 32 | padding: 7px 30px; 33 | border-radius: 20px; 34 | .invertGradiant; 35 | font-size: 13px; 36 | font-weight: bold; 37 | text-transform: uppercase; 38 | color: white; 39 | 40 | &.red { 41 | .redGradiant; 42 | } 43 | 44 | &.gray { 45 | background: @gray; 46 | } 47 | &:hover { 48 | cursor: pointer; 49 | } 50 | } 51 | 52 | button.reneco2 { 53 | line-height : initial !important; 54 | overflow : initial !important; 55 | padding: 8px !important; 56 | margin: 5px !important; 57 | width: 100% !important; 58 | } 59 | 60 | button.reneco, button.reneco2 { 61 | .exo; 62 | border : none; 63 | box-shadow : none !important; 64 | outline : none !important; 65 | border-radius : 2.8px; 66 | height : 35px; 67 | line-height : 35px; 68 | padding : 0 !important; 69 | overflow : hidden; 70 | color : white; 71 | 72 | &:hover { 73 | cursor: pointer; 74 | } 75 | 76 | &:hover, &:active, &:focus, &:visited { 77 | color : white; 78 | box-shadow : none !important; 79 | outline : none !important; 80 | * { color : white; } 81 | } 82 | 83 | &.red { 84 | background : #892833; 85 | label:last-child { 86 | background: #702029; 87 | } 88 | } 89 | 90 | &.grey { 91 | background : #484647; 92 | label:last-child { 93 | background : #3d3b3c; 94 | } 95 | } 96 | 97 | &.transparent { 98 | background : transparent !important; 99 | box-shadow : none; 100 | outline : none; 101 | border : 2px #555 solid !important; 102 | color : #555 !important; 103 | padding-top : 7px; 104 | padding-bottom : 7px; 105 | margin-left : 16px; 106 | min-width : 130px; 107 | height : 45px !important; 108 | margin-top : 30px !important; 109 | margin-bottom : 30px; 110 | } 111 | 112 | label { 113 | .exo; 114 | color : white; 115 | display : inline-block; 116 | float : left; 117 | border : none !important; 118 | box-shadow : none !important; 119 | 120 | &:hover { 121 | cursor: pointer; 122 | } 123 | 124 | &:first-child { 125 | padding-left : 10px; 126 | padding-right : 10px; 127 | text-transform: uppercase; 128 | } 129 | 130 | &:last-child:not(.empty) { 131 | height : 35px; 132 | width : 40px; 133 | float : right; 134 | position : relative; 135 | left : 1px; 136 | font-size : 20px; 137 | overflow : hidden; 138 | } 139 | } 140 | 141 | &.small { 142 | width : 40px; 143 | height : 40px; 144 | text-align : center; 145 | line-height : 45px; 146 | span { 147 | font-size : 20px; 148 | } 149 | } 150 | 151 | &.dark { 152 | background-color: rgb(22, 22, 23); 153 | color : white; 154 | } 155 | 156 | &.round { 157 | width : 50px; 158 | height : 50px; 159 | background : #444; 160 | border-radius: 50px; 161 | color : white; 162 | text-align : center; 163 | font-size : 18px; 164 | transition : all 0.2s ease-in; 165 | box-shadow : 0 0 2px #222; 166 | &:hover { 167 | background : #aaa; 168 | font-size : 20px; 169 | color : #222; 170 | } 171 | } 172 | } 173 | 174 | -------------------------------------------------------------------------------- /assets/stylesheet/components/fields.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Field style 4 | // 5 | 6 | // remove shadow 7 | .formField, .form-control { 8 | input, textarea, select { 9 | outline: none; 10 | box-shadow: none; 11 | } 12 | } 13 | 14 | .form-control { 15 | height: 32px; 16 | padding: 5px 10px; 17 | font-size: 13px; 18 | } 19 | 20 | // checkbox custom field 21 | // We hide the input and replace with before icon, we use reneco fonts https://github.com/NaturalSolutions/RenecoFonts 22 | .checkboxField { 23 | position: relative; 24 | height: 21px; 25 | 26 | input { 27 | position: absolute; 28 | opacity: 0; 29 | height: 1px; 30 | width: 0 !important; 31 | &:focus + label { 32 | border-bottom-color: inherit; 33 | } 34 | & + label { 35 | color: inherit; 36 | font-size: inherit; 37 | font-weight: normal; 38 | border-bottom: solid 1px transparent; 39 | padding-right: 4px; 40 | margin-bottom: 0; 41 | &:before { 42 | .reneco; 43 | content: "\e640"; 44 | vertical-align: -1px; 45 | margin-right: 8px; 46 | } 47 | } 48 | 49 | &:not(:disabled) { 50 | &:focus + label, &:active + label { 51 | border-bottom-color: #aaa; 52 | } 53 | } 54 | 55 | &:not(:checked) { 56 | & + label { 57 | opacity: 0.6; 58 | } 59 | &:not(:disabled) + label:hover { 60 | opacity: 1; 61 | } 62 | } 63 | 64 | &:checked+label:before { 65 | .reneco; 66 | content: "\e63f" 67 | } 68 | } 69 | } 70 | 71 | // checkbox custom field 72 | .radioField { 73 | input { 74 | display : none; 75 | 76 | &+label { 77 | color : #aaa; 78 | font-size : 16px; 79 | &:before { 80 | .reneco; 81 | content: "\e642"; 82 | } 83 | } 84 | 85 | &:checked+label:before { 86 | .reneco; 87 | content: "\e641" 88 | } 89 | } 90 | } 91 | 92 | .form-control:focus { 93 | border-color: #66afe9; 94 | outline: 0; 95 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6); 96 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6); 97 | } 98 | 99 | .neverHasShadow(@color) { 100 | outline : none !important; 101 | box-shadow : none !important; 102 | border-color: @color !important; 103 | 104 | &:hover, &:active, &:visited, &:focus, &:blur { 105 | box-shadow : none !important; 106 | border-color: @color !important; 107 | outline : none !important; 108 | } 109 | } 110 | 111 | .bootstrap-select .btn:focus { 112 | outline: none !important; 113 | } 114 | 115 | // override bootstrap select style 116 | // bootstrap select library : http://silviomoreto.github.io/bootstrap-select/ 117 | .bootstrap-select { 118 | box-shadow: none; 119 | border-radius: 2.5px; 120 | background : transparent !important; 121 | 122 | .caret { 123 | color : white; 124 | } 125 | 126 | .btn { 127 | background : #292c2e !important; 128 | border-color : transparent !important; 129 | .neverHasShadow(#292c2e); 130 | span { 131 | .exo; 132 | color : white; 133 | text-shadow: none; 134 | } 135 | } 136 | 137 | .btn-default { 138 | border : none !important; 139 | box-shadow: none !important; 140 | } 141 | 142 | button { 143 | span {.exo;} 144 | } 145 | 146 | .selectpicker { 147 | border : none; 148 | background : #222; 149 | color : white; 150 | box-shadow: none; 151 | &:focus, &:active { 152 | box-shadow: none; 153 | } 154 | } 155 | 156 | .dropdown-menu { 157 | padding: 0; 158 | 159 | ul { 160 | li { 161 | .neverHasShadow(#292c2e); 162 | background : #292c2e !important; 163 | .exo; 164 | a { 165 | background : #292c2e !important; 166 | .neverHasShadow(#292c2e); 167 | } 168 | &:hover { 169 | background : #222 !important; 170 | a, span { background : #222 !important; } 171 | } 172 | span { 173 | .neverHasShadow(#292c2e); 174 | &.text { 175 | .exo; 176 | font-size : 16px; 177 | color : white; 178 | } 179 | } 180 | &.selected { 181 | .neverHasShadow(#292c2e); 182 | background : #292c2e; 183 | } 184 | } 185 | } 186 | } 187 | } 188 | 189 | .slider-field { 190 | .slider { 191 | width : ~'calc(100% - 100px)'; 192 | } 193 | } 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /assets/stylesheet/app/editionPage/grid.less: -------------------------------------------------------------------------------- 1 | .grid { 2 | height: 100%; 3 | overflow: auto; 4 | 5 | table { 6 | width: 100%; 7 | table-layout: fixed; 8 | text-align: center; 9 | 10 | &.header tr td { 11 | height: 50px; 12 | min-height: 50px; 13 | max-height: 50px; 14 | background: @grid_bg; 15 | border: none; 16 | border-right: 1px solid @grid_fg; 17 | padding: 5px; 18 | font-weight: bold; 19 | } 20 | 21 | .rows td.type { 22 | .reneco; 23 | color: white; 24 | font-size: 20px; 25 | } 26 | 27 | tr { 28 | color: white; 29 | &.static { 30 | td { 31 | background: @grid_fg; 32 | border: 1px solid @grid_bg; 33 | color: #aaa !important; 34 | 35 | &.handle { 36 | background: @grid_fg; 37 | } 38 | } 39 | } 40 | 41 | &[data-readonly="true"].handle { 42 | cursor: default; 43 | } 44 | 45 | &.validationError { 46 | td { 47 | background: #803917; 48 | &.handle { 49 | background: url("../assets/images/handle.png") #803917 no-repeat 2px center; 50 | } 51 | } 52 | } 53 | 54 | &.selected { 55 | td { 56 | background: #151110; 57 | 58 | &.handle { 59 | background: url("../assets/images/handle.png") #151110 no-repeat 2px center; 60 | font-weight: bold; 61 | color: @orange; 62 | } 63 | } 64 | } 65 | 66 | td { 67 | background: @grid_bg; 68 | border: 1px solid @grid_fg; 69 | 70 | overflow: hidden; 71 | height: 60px; 72 | padding: 5px 5px; 73 | text-align: center; 74 | 75 | &.handle { 76 | background: url("../assets/images/handle.png") @grid_bg no-repeat 2px center; 77 | cursor: move; 78 | } 79 | 80 | width: 10%; 81 | max-width: 10%; 82 | min-width: 10%; 83 | 84 | &.type { 85 | width: 50px; 86 | max-width: 50px; 87 | min-width: 50px; 88 | } 89 | 90 | &.editMode { 91 | padding-top: 2px; 92 | padding-bottom: 1px; 93 | width: 18%; 94 | max-width: 18%; 95 | min-width: 18%; 96 | } 97 | 98 | &.options { 99 | width: 28%; 100 | max-width: 28%; 101 | min-width: 28%; 102 | 103 | &:hover { 104 | cursor: default; 105 | } 106 | 107 | div { 108 | display: inline-block; 109 | width: 48%; 110 | padding: 8px 0; 111 | text-align: center; 112 | font-weight: bold; 113 | 114 | &::before { 115 | .reneco; 116 | font-size: 25px; 117 | margin-right: 8px; 118 | } 119 | 120 | &.settings::before { 121 | content: '\e657'; 122 | vertical-align: -6px; 123 | } 124 | 125 | &.languages::before { 126 | content: '\e6a8'; 127 | vertical-align: -6px; 128 | } 129 | 130 | &:hover { 131 | cursor: pointer; 132 | color: @orange; 133 | } 134 | } 135 | } 136 | 137 | .checkboxField { 138 | white-space: nowrap; 139 | label { 140 | overflow: hidden; 141 | } 142 | } 143 | 144 | .editModeEditor { 145 | position: relative; 146 | padding: 4px 0 0 3px; 147 | 148 | .checkboxField { 149 | display: inline-block; 150 | width: 48%; 151 | } 152 | } 153 | 154 | .appearanceEditor { 155 | .checkboxField { 156 | margin-top: 5px; 157 | } 158 | } 159 | 160 | input, select, option, div, span { 161 | text-align: left; 162 | 163 | &.error { 164 | border-bottom: 3px dashed red !important; 165 | &.settings, &.languages { 166 | margin-top: 3px; 167 | } 168 | } 169 | } 170 | 171 | option { 172 | color: black; 173 | } 174 | 175 | input, select { 176 | height: 20px; 177 | } 178 | 179 | input, select { 180 | &[disabled]:hover { 181 | cursor: default !important; 182 | } 183 | } 184 | 185 | input:not([type="checkbox"]), select { 186 | border: none; 187 | border-bottom: 1px solid #bbb; 188 | background: none; 189 | width: 100%; 190 | color: white; 191 | padding: 0; 192 | 193 | &[disabled] { 194 | cursor: default !important; 195 | color: #ddd; 196 | } 197 | 198 | &:not([disabled]):focus, &:not([disabled]):hover { 199 | border-bottom-color: white; 200 | outline: none; 201 | box-shadow: none; 202 | } 203 | } 204 | } 205 | } 206 | 207 | } 208 | } -------------------------------------------------------------------------------- /assets/stylesheet/components/navbar.less: -------------------------------------------------------------------------------- 1 | // 2 | // Header style 3 | // 4 | @import url('common.less'); 5 | 6 | header { 7 | position: relative; 8 | min-width: 540px; 9 | 10 | .exo; 11 | 12 | height : 55px; 13 | background : @orange; 14 | line-height : 50px; 15 | margin-bottom : 0 !important; 16 | 17 | // application icon 18 | .reneco-formbuildersmall { 19 | font-size: 20px; 20 | position : relative; 21 | top : 1px; 22 | } 23 | 24 | // Left corner icons : user and online status 25 | .icons { 26 | float : left; 27 | height : 50px; 28 | overflow : hidden; 29 | margin-top: 4.5px; 30 | 31 | &:first-child { 32 | width : 135px; 33 | margin-top: 1.5px; 34 | &:after { 35 | .exo; 36 | color : white; 37 | content : "online"; 38 | position : relative; 39 | top : -3px; 40 | left : -28px; 41 | font-size : 20px; 42 | } 43 | .reneco-cloud2 { 44 | color : white; 45 | font-size : 33px; 46 | font-weight: 100; 47 | } 48 | 49 | .reneco-checked { 50 | position : relative; 51 | left : -37px; 52 | top : 2px; 53 | color : white; 54 | background : #66b32d; 55 | border-radius: 50px; 56 | padding : 8px; 57 | font-size: 10px; 58 | } 59 | 60 | } 61 | 62 | &.last { 63 | width : 30px; 64 | height : 30px; 65 | text-align : center; 66 | 67 | .reneco-user { 68 | color : #ffffff; 69 | font-size : 24px; 70 | position : relative; 71 | // top : 8px; 72 | } 73 | } 74 | } 75 | 76 | // navbar text 77 | .title, .mode, .user, .status, .lang { 78 | color : white; 79 | text-decoration : none; 80 | font-weight : 300; 81 | font-size : 20px; 82 | margin-left : 7px; 83 | margin-right : 7px; 84 | } 85 | 86 | .lang { 87 | font-size: 18px; 88 | } 89 | 90 | // navbar separator 91 | .pipe { 92 | color : white; 93 | font-weight : 300; 94 | font-size : 25px; 95 | margin: 0 7px; 96 | vertical-align: -2px; 97 | } 98 | 99 | .pull-right { 100 | margin-right: 8px; 101 | } 102 | 103 | #contextSwitcher { 104 | display: inline-block; 105 | position: relative; 106 | vertical-align: top; 107 | z-index: 100; 108 | min-width: 100px; 109 | max-width: 250px; 110 | min-height: 55px; 111 | max-height: 55px; 112 | overflow: hidden; 113 | background: #f19e3570; 114 | border-bottom: 1px solid white; 115 | font-size: 15px; 116 | 117 | &:hover:not(.disabled) { 118 | cursor: pointer; 119 | border: none; 120 | background: @orange; 121 | max-height: none; 122 | } 123 | 124 | &.single { 125 | cursor: default; 126 | background: none; 127 | .headerWhiteArrow { 128 | display: none; 129 | } 130 | } 131 | 132 | .context, .selected { 133 | padding: 0 30px 0 12px; 134 | text-transform: uppercase; 135 | 136 | &.default { 137 | font-style: italic; 138 | &:before { 139 | content: '* ' 140 | } 141 | } 142 | } 143 | 144 | .context { 145 | width: 100%; 146 | border-bottom: 1px solid transparent; 147 | &.selected, &:hover { 148 | font-weight: bold; 149 | background: #f19e3570; 150 | border-bottom: 1px solid white; 151 | } 152 | } 153 | 154 | .selected { 155 | text-transform: uppercase; 156 | font-weight: bold; 157 | } 158 | 159 | .headerWhiteArrow { 160 | position: absolute; 161 | top: 16px; 162 | right: 3px; 163 | } 164 | 165 | &.disabled { 166 | .selected { 167 | cursor: default; 168 | } 169 | .headerWhiteArrow { 170 | display: none; 171 | } 172 | } 173 | } 174 | 175 | a.logout { 176 | font-size: 20px; 177 | margin-left: 7px; 178 | margin-right: 4px; 179 | padding: 10px; 180 | width: 20px; 181 | color: white; 182 | 183 | &:hover { 184 | text-decoration: none; 185 | } 186 | 187 | span { 188 | margin-right: 5px; 189 | } 190 | 191 | img, svg { 192 | width: 20px; 193 | vertical-align: -2px; 194 | } 195 | 196 | &:hover path, &:hover polygon { 197 | stroke-width: 6px; 198 | } 199 | } 200 | } -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/EcoreleveCollection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define([ 6 | 'jquery', 7 | 'backbone', 8 | '../models/Fields', 9 | '../editor/CheckboxEditor', 10 | '../editor/NumberEditor', 11 | 'backbone.radio', 12 | '../../Translater', 13 | 'auth', 14 | 'text!../templates/FieldTemplate.html' 15 | ], function ($, Backbone, Fields, CheckboxEditor, NumberEditor, Radio, translater, auth, FieldTemplate) { 16 | 17 | var fieldTemplate = _.template(FieldTemplate); 18 | var customNumberEditor = NumberEditor.extend({ 19 | render: function(){ 20 | NumberEditor.prototype.render.call(this); 21 | this.$el.append('
'); 22 | if(this.form.data.isgrid){ 23 | this.form.afterRender = function(){ 24 | var nbFixedColEditor = this.getEditor('nbFixedCol'); 25 | nbFixedColEditor.$el.parent().parent().removeClass('hidden'); 26 | }; 27 | } 28 | return this; 29 | } 30 | }); 31 | return { 32 | schemaExtention: { 33 | name : { 34 | type : "Text", 35 | title : translater.getValueFromKey('form.name'), 36 | template : fieldTemplate, 37 | validators : [{ 38 | type : 'required', 39 | message : translater.getValueFromKey('form.validationspe') 40 | }, 41 | function noSpaceAllowed(value) { 42 | if( value.indexOf(' ') > -1 ) { 43 | return { 44 | type : "No space allowed", 45 | message : translater.getValueFromKey('schema.nospaceallowed') 46 | } 47 | } 48 | }, 49 | function test(value) { 50 | if (value.length > 250) { 51 | return { 52 | type: 'String too wide', 53 | message: translater.getValueFromKey('schema.maxlength250') 54 | }; 55 | } 56 | }] 57 | }, 58 | author : { 59 | type : 'Hidden', 60 | title : translater.getValueFromKey('form.author'), 61 | template : fieldTemplate 62 | }, 63 | isgrid : { 64 | type : CheckboxEditor, 65 | template : fieldTemplate, 66 | fieldClass : "checkBoxEditor form-group", 67 | title : translater.getValueFromKey('form.isgrid'), 68 | handlers: [function(value, input){ 69 | //handlers are called on input change 70 | var nbFixedColEditor = input.form.getEditor('nbFixedCol'); 71 | if(input.getValue()){ 72 | nbFixedColEditor.$el.parent().parent().removeClass('hidden'); 73 | } else{ 74 | nbFixedColEditor.$el.parent().parent().addClass('hidden'); 75 | nbFixedColEditor.setValue(''); 76 | } 77 | }] 78 | }, 79 | ishiddenprotocol : { 80 | type : CheckboxEditor, 81 | template : fieldTemplate, 82 | fieldClass : "checkBoxEditor form-group", 83 | title : translater.getValueFromKey('form.ishiddenprotocol') 84 | }, 85 | hideprotocolname : { 86 | type : CheckboxEditor, 87 | template : fieldTemplate, 88 | fieldClass : "checkBoxEditor form-group", 89 | title : translater.getValueFromKey('form.hideprotocolname') 90 | }, 91 | defaultforfieldactivity : { 92 | type : CheckboxEditor, 93 | template : fieldTemplate, 94 | fieldClass : "checkBoxEditor form-group", 95 | title : translater.getValueFromKey('form.defaultforfieldactivity') 96 | }, 97 | nbFixedCol: { 98 | type: customNumberEditor, 99 | min: 0, 100 | template: fieldTemplate, 101 | fieldClass: 'hidden', 102 | title: translater.getValueFromKey('schema.nbFixedCol'), 103 | validators: [function checkValue(value) { 104 | if (value < 0) { 105 | return { 106 | type: 'Invalid number', 107 | message: translater.getValueFromKey('schema.nbFixedColMinValue') 108 | }; 109 | } 110 | }] 111 | }, 112 | }, 113 | 114 | getExtractedDatas: function() {return {};}, 115 | getSchemaExtention: function(){ 116 | return this.schemaExtention; 117 | }, 118 | initializeExtention: function () { 119 | return true; 120 | }, 121 | 122 | jsonExtention: function (originalForm) { 123 | if (originalForm) { 124 | originalForm.author = auth.username; 125 | } 126 | return { 127 | author : auth.username, 128 | isgrid : "", 129 | ishiddenprotocol: "", 130 | hideprotocolname: "", 131 | defaultforfieldactivity: "", 132 | nbFixedCol: "" 133 | }; 134 | }, 135 | updateAttributesExtention: function () {return true;} 136 | }; 137 | }); -------------------------------------------------------------------------------- /assets/js/editionPageModule/templates/EditionPageLayout.html: -------------------------------------------------------------------------------- 1 |
2 |
Retour
3 |
4 | <%= collection.name %> 5 |
6 | <% if (collection.readonly) { %> 7 |
8 | ( 9 | 10 | - 11 |
12 | 13 |
14 | ) 15 |
16 | <% } %> 17 | <% if (formUrl) { %> 18 | 23 | <% } %> 24 | 25 |
Tout sauvegarder
26 |
27 | 28 |
29 |
30 |
31 |
32 |

33 | Caractéristiques du formulaire 34 |

35 |
36 |
37 |
38 |
39 | 40 |
41 | <% if (collection.parentForms && collection.parentForms.length > 0) { %> 42 |
43 |
44 | 45 |
46 |
47 | 55 |
56 |
57 | <% } %> 58 | <% if (context === 'track') { %> 59 |
60 | 61 | 62 |
add file
63 |
64 |
65 | <% } %> 66 | <% if (collection.versions && collection.versions.length > 0) { %> 67 |
68 |
69 | 70 |
71 |
72 | 73 | <% 74 | var timestamp = "newer"; 75 | for (var i in collection.versions) { 76 | f = collection.versions[i]; 77 | url = formBaseUrl + f.id; 78 | if (f.id === collection.id) { 79 | timestamp = "this"; 80 | } else if (timestamp === "this") { 81 | timestamp = "older"; 82 | } 83 | %> 84 | 85 | 86 | 87 | 90 | 91 | <% } %> 92 |
<%= f.id %> 88 | <%= f.modificationDate %> 89 |
93 |
94 |
95 | <% } %> 96 |
97 |
98 |
99 |
100 | 101 | 102 | <% for (var i in fieldTypes) { 103 | field = fieldTypes[i]; %> 104 | 109 | <% } %> 110 | 111 |
108 |
112 |
113 |
114 |
115 |
Tout sauvegarder
116 |
117 |
118 |
119 |
120 |

121 |
122 |
123 |
OK
124 |
125 |
126 |
127 | -------------------------------------------------------------------------------- /ressources/plugins/fullNameField.js: -------------------------------------------------------------------------------- 1 | var formBuilder = (function(app) { 2 | 3 | // Model 4 | app.models.FullNameField = app.models.BaseField.extend({ 5 | defaults : { 6 | required : true, 7 | label : 'Your fullname', 8 | firstName : { 9 | defaultValue: "", 10 | hint : "Write your name", 11 | size : 255 12 | }, 13 | lastName : { 14 | defaultValue: "", 15 | hint : "Write your firstname", 16 | size : 255 17 | } 18 | }, 19 | 20 | initialize : function(options) { 21 | app.models.BaseField.prototype.initialize.apply(this, arguments); 22 | _.extend(this.constructor.schema, app.models.BaseField.schema); 23 | }, 24 | 25 | getXML : function() { 26 | var xml = app.models.BaseField.prototype.getXML.apply(this, arguments); 27 | return xml + '' + 28 | ' ' + this.get('firstName')['defaultValue'] + '' + 29 | ' ' + this.get('firstName')['hint'] + '' + 30 | ' ' + this.get('firstName')['size'] + '' + 31 | ''+ 32 | '' + 33 | ' ' + this.get('lastName')['defaultValue'] + '' + 34 | ' ' + this.get('lastName')['hint'] + '' + 35 | ' ' + this.get('lastName')['size'] + '' + 36 | '' 37 | } 38 | }, { 39 | type : "FullName", 40 | xmlTag : 'field_fullName', 41 | schema : { 42 | firstName : { 43 | defaultValue: { type : "string", display: "Default value", section : "advanced" }, 44 | hint : { type : "string" }, 45 | size : { type : "integer"} 46 | }, 47 | lastName : { 48 | defaultValue: { type : "string", display: "Default value", section : "advanced" }, 49 | hint : { type : "string" }, 50 | size : { type : "integer"} 51 | } 52 | 53 | } 54 | }); 55 | 56 | _.defaults(app.models.FullNameField.prototype.defaults, app.models.BaseField.prototype.defaults); 57 | 58 | // View 59 | app.views.FullNameFieldView = app.views.BaseView.extend({ 60 | events: function() { 61 | return _.extend({}, app.views.BaseView.prototype.events); 62 | }, 63 | render : function() { 64 | app.views.BaseView.prototype.render.apply(this, arguments); 65 | }, 66 | }, { 67 | templateSrc: '
' + 68 | ' '+ 71 | ' '+ 80 | '
' + 81 | '
' + 82 | ' " value="<%= firstName["defaultValue"] %>" /> '+ 83 | ' " value="<%= lastName["defaultValue"] %>" /> '+ 84 | '
' 85 | }); 86 | 87 | // setting view 88 | app.views.FullNameFieldEditView = Backbone.View.extend({ 89 | initialize: function() { 90 | this.template = _.template(this.constructor.templateSrc); 91 | }, 92 | render: function() { 93 | var renderedContent = this.template(this.model.toJSON()); 94 | $(this.el).html(renderedContent); 95 | return this; 96 | } 97 | }, { 98 | templateSrc : '<% _.each(["firstName", "lastName"], function(el){ var obj = eval(el); %>' + 99 | ' <% _.each(["defaultValue", "hint", "size"], function(subEl) { %>' + 100 | '
' + 101 | '
'+ 102 | ' ' + 103 | '
' + 104 | '
' + 105 | ' " placeholder="<%= el + " " + subEl %>" value="<%= obj[subEl] %>" />' + 106 | '
' + 107 | '
' + 108 | ' <% }) %>'+ 109 | '<% }); %>' 110 | }); 111 | 112 | return app; 113 | 114 | })(formBuilder); -------------------------------------------------------------------------------- /assets/js/editionPageModule/collection/staticInputs/TrackStatics.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by David on 22/12/2015. 3 | */ 4 | 5 | define(['jquery'], function ($) { 6 | var TrackStatics = { 7 | staticInputs: { 8 | "Individual": { 9 | "id": 0, 10 | "validators": [], 11 | "labelFr": "Individu", 12 | "labelEn": "Individual", 13 | "name": "Individual", 14 | "editMode": 3, 15 | "editorClass": "", 16 | "fieldClassEdit": "", 17 | "fieldClassDisplay": "", 18 | "atBeginingOfLine": true, 19 | "fieldSize": "6", 20 | "linkedFieldset": "", 21 | "linkedFieldTable": null, 22 | "linkedField": null, 23 | "defaultValue": "", 24 | "help": "Bird ring", 25 | "triggerlength": 2, 26 | "url": "", 27 | "isSQL": false, 28 | "order": 0, 29 | "type": "Autocomplete" 30 | }, 31 | "Egg": { 32 | "id": 0, 33 | "validators": [], 34 | "labelFr": "Oeuf", 35 | "labelEn": "Egg", 36 | "name": "Egg", 37 | "editMode": 3, 38 | "editorClass": "", 39 | "fieldClassEdit": "", 40 | "fieldClassDisplay": "", 41 | "atBeginingOfLine": true, 42 | "fieldSize": "6", 43 | "linkedFieldset": "", 44 | "linkedFieldTable": "", 45 | "linkedField": "", 46 | "defaultValue": "", 47 | "help": "Egg ring", 48 | "triggerlength": 3, 49 | "url": "unknowWebService", 50 | "isSQL": false, 51 | "order": 0, 52 | "type": "Autocomplete" 53 | }, 54 | "UserReadonly": { 55 | "id": 0, 56 | "validators": [], 57 | "labelFr": "Utilisateur", 58 | "labelEn": "User", 59 | "name": "UserReadonly", 60 | "editMode": 1, 61 | "editorClass": "", 62 | "fieldClassEdit": "", 63 | "fieldClassDisplay": "", 64 | "atBeginingOfLine": true, 65 | "fieldSize": "6", 66 | "linkedFieldset": "", 67 | "linkedFieldTable": "", 68 | "linkedField": "", 69 | "defaultValue": "", 70 | "isDefaultSQL": true, 71 | "help": "", 72 | "valuesize": "0;255", 73 | "order": 1, 74 | "type": "Text" 75 | }, 76 | "eventDate": { 77 | "id": 0, 78 | "validators": [], 79 | "labelFr": "Date de saisie", 80 | "labelEn": "Event date", 81 | "name": "eventDate", 82 | "editMode": 3, 83 | "editorClass": "", 84 | "fieldClassEdit": "", 85 | "fieldClassDisplay": "", 86 | "atBeginingOfLine": true, 87 | "fieldSize": 6, 88 | "linkedFieldset": "", 89 | "linkedFieldTable": "", 90 | "linkedField": "", 91 | "defaultValue": "", 92 | "isDefaultSQL": false, 93 | "help": "", 94 | "valuesize": "0;20", 95 | "format": "dd/mm/yyyy", 96 | "order": 2, 97 | "type": "Date" 98 | }, 99 | "TSai_PK_ID": { 100 | "id": 0, 101 | "validators": [], 102 | "labelFr": "TSai_PK_ID", 103 | "labelEn": "TSai_PK_ID", 104 | "name": "TSai_PK_ID", 105 | "editMode": 5, 106 | "editorClass": "", 107 | "fieldClassEdit": "", 108 | "fieldClassDisplay": "", 109 | "atBeginingOfLine": true, 110 | "fieldSize": "6", 111 | "linkedFieldset": "", 112 | "linkedFieldTable": "", 113 | "linkedField": "", 114 | "defaultValue": "", 115 | "isDefaultSQL": true, 116 | "help": "", 117 | "valuesize": "0;20", 118 | "order": 3, 119 | "type": "Text" 120 | } 121 | }, 122 | 123 | compulsoryInputs: [ 124 | "Individual", 125 | "Egg", 126 | "UserReadonly", 127 | "eventDate", 128 | "TSai_PK_ID" 129 | ], 130 | 131 | getStaticInputs: function() { 132 | var toret = TrackStatics.staticInputs; 133 | $.each(toret, function(index, value){ 134 | if (!value.id) 135 | value.id = 0; 136 | }); 137 | return toret; 138 | }, 139 | 140 | getCompulsoryInputs: function() { 141 | return TrackStatics.compulsoryInputs; 142 | }, 143 | 144 | applyRules: function(form, json) { 145 | var savedSchema = json.schema; 146 | var toret = json; 147 | var toadd = []; 148 | 149 | delete toret.schema; 150 | 151 | $.each(savedSchema, function(index, value){ 152 | if (!(value.name.toLowerCase() == "egg" && json.typeIndividus.toLowerCase().indexOf("oeuf") == -1) 153 | && !(value.name.toLowerCase() == "individual" && json.typeIndividus.toLowerCase().indexOf("oeuf") != -1) 154 | && !(json.groupe.toLowerCase() == "null" && (value.name.toLowerCase() == "egg" || value.name.toLowerCase() == "individual"))) 155 | { 156 | toadd.push(index); 157 | } 158 | }); 159 | 160 | toret.schema = {}; 161 | 162 | $.each(toadd, function(index, value){ 163 | if (index + 1 != savedSchema[value].order) 164 | savedSchema[value].order -= 1; 165 | toret.schema[value] = savedSchema[value]; 166 | }); 167 | 168 | return toret; 169 | }, 170 | 171 | initializeStatics: function () { 172 | return true; 173 | } 174 | }; 175 | 176 | return TrackStatics; 177 | }); -------------------------------------------------------------------------------- /docs/deprecated/fields.md: -------------------------------------------------------------------------------- 1 | # How to add a new field type 2 | 3 | The Formbuilder is built so that anybody can add a field type. 4 | 5 | To add a new field you can follow these step : 6 | 7 | ## Step 1 : create the model class 8 | 9 | All available field type are in [Field.js](https://github.com/NaturalSolutions/NS.UI.FormBuilder/blob/master/assets/js/editionPageModule/models/Fields.js) file. 10 | 11 | If you want to add a field you hace to inerit from BaseField class : 12 | 13 | models.AwesomeField = models.BaseField.extend({ 14 | ... 15 | }); 16 | 17 | ## Step 2 : define schema for backbone forms 18 | 19 | The formbuilder is based on backbone-forms and we use schema definiton to generate form, see [backbone-forms documentation](https://github.com/powmedia/backbone-forms). 20 | 21 | For example for our Awesome field we have one properties **maximum characters size** so : 22 | 23 | models.AwesomeField = models.BaseField.extend({ 24 | ... 25 | schema : function() { 26 | return _.extend( {}, models.BaseField.prototype.schema, { 27 | maxSize: { 28 | type : 'Integer', 29 | title : 'Max character size', 30 | editorClass : 'form-control', 31 | template : fieldTemplate 32 | }, 33 | }); 34 | } 35 | ... 36 | }); 37 | 38 | Each field extend BaseField schema. We fixed some common properties like ID, name, required, etc ... 39 | 40 | ### Class properties 41 | 42 | For each field we specify some class properties : 43 | 44 | - **type** : the field type name for example awesome 45 | - **section** : allow ro group field in semantic group for example : standard field, autocomplete field ... 46 | - **i18n** : allow to translate field label in the edition page left panel 47 | 48 | So we have : 49 | 50 | models.AwesomeField = models.BaseField.extend({ 51 | ... 52 | }, { 53 | type : 'Awesome', 54 | section : 'standard', 55 | i18n : 'awesome' 56 | }); 57 | 58 | 59 | **These properties are required.** 60 | 61 | For more information about class properties with backbone see [extend documentation](http://backbonejs.org/#Model-extend) 62 | 63 | ## Step 3 : specify default value 64 | 65 | Like schema properties you have to specify your field default value : 66 | 67 | models.AwesomeField = models.BaseField.extend({ 68 | 69 | default : function() { 70 | return _.extend( {}, models.BaseField.prototype.default, { 71 | maxSize : 42 72 | }); 73 | } 74 | 75 | }); 76 | 77 | ## Step 4 : create a view for your field 78 | 79 | Now your model is defined you have to create a view for represent graphicly your field. 80 | First you have to create a field in [view/fieldViews folder](https://github.com/NaturalSolutions/NS.UI.FormBuilder/tree/master/assets/js/editionPageModule/views/fieldViews). 81 | This file must be named (for our example) AwesomeFieldView.js. 82 | 83 | Your view must inherit from [BaseView](https://github.com/NaturalSolutions/NS.UI.FormBuilder/blob/master/assets/js/editionPageModule/views/fieldViews/BaseView.js) : 84 | 85 | var AwesomeFieldView = BaseView.extend({ 86 | initialize : function(options) { 87 | var opt = options; 88 | opt.template = viewTemplate; 89 | BaseView.prototype.initialize.apply(this, [opt]); 90 | }, 91 | render : function() { 92 | BaseView.prototype.render.apply(this, arguments); 93 | } 94 | }); 95 | 96 | It's the minimal code for your view, after your can extens event like that : 97 | 98 | events: function() { 99 | return _.extend(BaseView.prototype.events, { 100 | 'click button' : 'callback', 101 | }); 102 | } 103 | 104 | 105 | ## Step5 : create a template 106 | 107 | Now you have to create a template for your view. 108 | Your template must be placed in [templates/fields folder](https://github.com/NaturalSolutions/NS.UI.FormBuilder/tree/master/assets/js/editionPageModule/templates/fields) and 109 | must be name like **AwesomeFieldView.html**. 110 | 111 | For example we can create a simple template 112 | 113 |
114 |
115 | 119 | 135 |
136 |
137 |
138 | 139 |
140 |
141 |
142 | 143 | 144 | You awesome field is displayed as a text field with a maxlength : 145 | 146 | maxlength="<%= maxSize %>" 147 | 148 | ## Step 6 : translation 149 | 150 | To finish you have to add your file in each translation files in [ressources/locales folder](https://github.com/NaturalSolutions/NS.UI.FormBuilder/tree/master/ressources/locales). 151 | 152 | For example for our field we have to add 153 | 154 | "fields" : { 155 | ... 156 | "awesome" : "Awesome field" 157 | } 158 | 159 | ## Step 7 : enjoy ! 160 | 161 | Now if all is good your field appears in the left panel in the edition page (remember the section that you choose). 162 | 163 | ![in the widget panel](http://img4.hostingpics.net/pics/616810FormBuilderGoogleChrome3.jpg) 164 | 165 | ![Your view](http://img4.hostingpics.net/pics/703471FormBuilderGoogleChrome4.jpg) 166 | 167 | ## Get full code 168 | 169 | If you want to add that awesome field on the application or get this code check [examples folder](https://github.com/NaturalSolutions/NS.UI.FormBuilder/tree/master/docs/examples) 170 | 171 | back to [summary](index.md) -------------------------------------------------------------------------------- /assets/js/homePageModule/views/LeftPanelView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 'marionette', '../../editionPageModule/collection/CollectionExtention', 3 | 'text!../templates/LeftPanelView.html', 'i18n', 'jquery-ui' 4 | ], function($, Marionette, CollectionExtention, LeftPanelViewTemplate) { 5 | 6 | /** 7 | * Left panel view in the homepage layout, contains form to filter grid on the center view 8 | */ 9 | var LeftPanelView = Backbone.Marionette.View.extend({ 10 | 11 | template : LeftPanelViewTemplate, 12 | 13 | events : { 14 | 'click #searchBtn' : 'runSearch', 15 | 'click .search-box .close' : 'clearForm', 16 | 'keypress form input' : 'keypressed' 17 | }, 18 | 19 | initialize : function(options, readonly) { 20 | this.gridChannel = Backbone.Radio.channel('grid'); 21 | this.gridChannel.on('contextChanged', this.setCustomSearchInputs, this); 22 | this.gridChannel.on('refresh', this.runSearch, this); 23 | this.URLOptions = options.URLOptions; 24 | }, 25 | 26 | keypressed: function(e) { 27 | if (e.keyCode === 13) { 28 | this.runSearch(); 29 | } 30 | }, 31 | 32 | runSearch : function() { 33 | var values = {}; 34 | $.each(this.$el.find('form').serializeArray(), function(i, field) { 35 | if (field.value !== "") { 36 | values[field.name] = field.value; 37 | } 38 | }); 39 | 40 | if (!$.isEmptyObject(values)) { 41 | this.gridChannel.trigger('search', values); 42 | } else { 43 | this.gridChannel.trigger('resetCollection'); 44 | } 45 | }, 46 | 47 | /** 48 | * addCustomSearchInput inserts a custom search input in search section. 49 | * @param type - select / number / string 50 | * @param id - html id 51 | * @param title - label of input 52 | * @param options - for select input, list of options {0: {val, label},...} 53 | */ 54 | addCustomSearchInput: function(type, id, title, options) { 55 | var $label = $("