/********************************************* * Copyright (c) 2013 AnsibleWorks, Inc. * * FormGenerator * Pass in a form definition from FormDefinitions and out pops an html template. * See js/form-definitions.js for form example. For now produces a Twitter Bootstrap * horizontal form. * */ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) .factory('GenerateForm', [ '$location', '$cookieStore', '$compile', 'SearchWidget', 'PaginateWidget', 'Attr', 'Icon', 'Column', function($location, $cookieStore, $compile, SearchWidget, PaginateWidget, Attr, Icon, Column) { return { setForm: function(form) { this.form = form; }, attr: Attr, icon: Icon, has: function(key) { return (this.form[key] && this.form[key] != null && this.form[key] != undefined) ? true : false; }, inject: function(form, options) { // // Use to inject the form as html into the view. View MUST have an ng-bind for 'htmlTemplate'. // Returns scope of form. // var element; if (options.modal) { if (options.modal_body_id) { element = angular.element(document.getElementById(options.modal_body_id)); } else { // use default dialog element = angular.element(document.getElementById('form-modal-body')); } } else { element = angular.element(document.getElementById('htmlTemplate')); } this.mode = options.mode; this.modal = (options.modal) ? true : false; this.setForm(form); // Inject the html if (options.buildTree) { element.html(this.buildTree(options)); } else if (options.html) { element.html(options.html); } else { element.html(this.build(options)); } this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference // From here use 'scope' to manipulate the form, as the form is not in '$scope' $compile(element)(this.scope); if (!options.buildTree && !options.html) { // Reset the scope to prevent displaying old data from our last visit to this form for (var fld in form.fields) { this.scope[fld] = null; } for (var set in form.related) { this.scope[set] = null; } if ( ((!options.modal) && options.related) || this.form.forceListeners ) { this.addListeners(); } if (options.mode == 'add') { this.applyDefaults(); } } // Remove any lingering tooltip and popover
elements $('.tooltip').each( function(index) { $(this).remove(); }); $('.popover').each(function(index) { // remove lingering popover
. Seems to be a bug in TB3 RC1 $(this).remove(); }); if (options.modal) { this.scope.formModalActionDisabled = false; if (form) { this.scope.formHeader = (options.mode == 'add') ? form.addTitle : form.editTitle; //Default title for default modal } this.scope.formModalInfo = false //Disable info button for default modal if (options.modal_selector) { $(options.modal_selector).modal({ show: true, backdrop: 'static', keyboard: true }); $(options.modal_selector).on('shown.bs.modal', function() { $(options.modal_select + ' input:first').focus(); }); } else { $('#form-modal').modal({ show: true, backdrop: 'static', keyboard: true }); $('#form-modal').on('shown.bs.modal', function() { $('#form-modal input:first').focus(); }); } $(document).bind('keydown', function(e) { if (e.keyCode === 27) { if (options.modal_selector) { $(options.modal_selector).modal('hide'); } $('#prompt-modal').modal('hide'); $('#form-modal').modal('hide'); } }); } return this.scope; }, applyDefaults: function() { for (fld in this.form.fields) { if (this.form.fields[fld]['default'] || this.form.fields[fld]['default'] == 0) { if (this.form.fields[fld].type == 'select' && this.scope[fld + '_options']) { this.scope[fld] = this.scope[fld + '_options'][this.form.fields[fld]['default']]; } else { this.scope[fld] = this.form.fields[fld]['default']; } } } }, reset: function() { // The form field values cannot be reset with jQuery. Each field is tied to a model, so to clear the field // value, you have clear the model. this.scope[this.form.name + '_form'].$setPristine(); for (var fld in this.form.fields) { this.scope[fld] = ''; this.scope[fld + '_api_error'] = ''; if (this.form.fields[fld].sourceModel) { this.scope[this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField] = ''; this.scope[this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField + '_api_error'] = ''; } if ( this.form.fields[fld].type == 'lookup' && this.scope[this.form.name + '_form'][this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField] ) { this.scope[this.form.name + '_form'][this.form.fields[fld].sourceModel + '_' + this.form.fields[fld].sourceField].$setPristine(); } if (this.scope[this.form.name + '_form'][fld]) { this.scope[this.form.name + '_form'][fld].$setPristine(); } if (this.form.fields[fld].awPassMatch) { this.scope[this.form.name + '_form'][fld].$setValidity('awpassmatch', true); } if (this.form.fields[fld].ask) { this.scope[fld + '_ask'] = false; } } if (this.mode == 'add') { this.applyDefaults(); } }, addListeners: function() { if (this.modal) { $('.jqui-accordion-modal').accordion({ collapsible: false, heightStyle: 'content', active: 0 }); } else { $('.jqui-accordion').each( function(index) { var active = false; var list = $cookieStore.get('accordions'); var found = false; if (list) { var id = $(this).attr('id'); var base = ($location.path().replace(/^\//,'').split('/')[0]); for (var i=0; i < list.length && found == false; i++) { if (list[i].base == base && list[i].id == id) { found = true; active = list[i].active; } } } if (found == false && $(this).attr('data-open') == 'true') { active = 0; } $(this).accordion({ collapsible: true, heightStyle: 'content', active: active, activate: function( event, ui ) { $('.jqui-accordion').each( function(index) { var active = $(this).accordion('option', 'active'); var id = $(this).attr('id'); var base = ($location.path().replace(/^\//,'').split('/')[0]); var list = $cookieStore.get('accordions'); if (list == null || list == undefined) { list = []; } var found = false; for (var i=0; i < list.length && found == false; i++) { if ( list[i].base == base && list[i].id == id) { found = true; list[i].active = active; } } if (found == false) { list.push({ base: base, id: id, active: active }); } $cookieStore.put('accordions',list); }); } }); }); } }, genID: function() { var id = new Date(); return id.getTime(); }, headerField: function(fld, field, options) { var html = ''; if (field.label) { html += "\n"; } html += " element. var html = ''; for (var i=0; i < btn.position.length; i++) { if (btn.position[i].indexOf(topOrBottom) >= 0) { html += "\n"; if (field.ask) { html += ""; } html += "\n
\n"; } if (field.genMD5) { html += "\n
\n"; } // Add error messages if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) || field.awRequiredWhen ) { html += "
A value is required!
\n"; } if (field.type == "email") { html += "
A valid email address is required!
\n"; } if (field.awPassMatch) { html += "
Must match Password value
\n"; } html += "
\n"; html += "\n"; } //textarea fields if (field.type == 'textarea') { if (field.label !== false) { html += "' + "\n"; html += "
\n"; } // Variable editing if (fld == "variables" || fld == "extra_vars" || fld == 'inventory_variables') { html += "
Parse as: " + " YAML\n"; html += " JSON\n
\n"; } html += "