morpheus.FormBuilder = function(options) { var that = this; this.prefix = _.uniqueId('form'); this.$form = $('
'); this.$form.attr('role', 'form').attr('id', this.prefix); this.vertical = options && options.vertical; if (!this.vertical) { this.titleClass = 'col-xs-12 control-label'; this.labelClass = 'col-xs-4 control-label'; this.$form.addClass('form-horizontal'); } else { this.labelClass = 'control-label'; this.titleClass = 'control-label'; } this.$form.on('submit', function(e) { e.preventDefault(); }); this.$form.on( 'dragover', function(e) { var node = $(e.originalEvent.srcElement).parent().parent() .prev(); if (node.is('select') && node.hasClass('file-input')) { $(e.originalEvent.srcElement).parent().css('border', '1px solid black'); e.preventDefault(); e.stopPropagation(); } }).on( 'dragenter', function(e) { var node = $(e.originalEvent.srcElement).parent().parent() .prev(); if (node.is('select') && node.hasClass('file-input')) { $(e.originalEvent.srcElement).parent().css('border', '1px solid black'); e.preventDefault(); e.stopPropagation(); } }).on('dragleave', function(e) { var node = $(e.originalEvent.srcElement).parent().parent().prev(); if (node.is('select') && node.hasClass('file-input')) { $(e.originalEvent.srcElement).parent().css('border', ''); e.preventDefault(); e.stopPropagation(); } }).on('drop', function(e) { var node = $(e.originalEvent.srcElement).parent().parent().prev(); if (node.is('select') && node.hasClass('file-input')) { $(e.originalEvent.srcElement).parent().css('border', ''); var name = node.attr('name'); name = name.substring(0, name.length - '_picker'.length); if (e.originalEvent.dataTransfer) { if (e.originalEvent.dataTransfer.files.length) { e.preventDefault(); e.stopPropagation(); var files = e.originalEvent.dataTransfer.files; that.setValue(name, files[0]); that.trigger('change', { name : name, value : files[0] }); } else { var url = e.originalEvent.dataTransfer.getData('URL'); e.preventDefault(); e.stopPropagation(); that.setValue(name, url); that.trigger('change', { name : name, value : url }); } } } }); // this.labelColumnDef = '4'; // this.fieldColumnDef = '8'; }; morpheus.FormBuilder.showProgressBar = function(options) { var content = []; content.push('
'); content.push('
'); content.push('
'); content .push('
'); content.push('
'); // col content.push('
'); content .push(''); content.push('
'); // col content.push('
'); // row if (options.subtitle) { content.push('
'); content.push('

'); content.push(options.subtitle); content.push('

'); content.push('
'); } content.push('
'); var $content = $(content.join('')); $content.find('[name=stop]').on('click', function(e) { options.stop(); e.preventDefault(); }); return morpheus.FormBuilder.showInDraggableDiv({ title : options.title, $content : $content }); }; morpheus.FormBuilder.showInDraggableDiv = function(options) { var width = options.width || '300px'; var html = []; html .push('
'); html .push('

' + options.title + '

'); html.push('
'); html.push('
'); var $div = $(html.join('')); var $content = $div.find('[name=content]'); $div.find('[name=header]').on('dblclick', function() { if ($content.css('display') === 'none') { $content.css('display', ''); } else { $content.css('display', 'none'); } }); options.$content.appendTo($content); $div.css('left', ($(window).width() / 2) - $content.outerWidth() / 2); $div.draggable({ handle : '[name=header]', containment : 'document' }); // $div.resizable(); $div.appendTo($(document.body)); return $div; }; morpheus.FormBuilder.promptForDataset = function(cb) { var formBuilder = new morpheus.FormBuilder(); formBuilder.append({ name : 'file', value : '', type : 'file', required : true, help : morpheus.DatasetUtil.DATASET_FILE_FORMATS }); var $modal; formBuilder.on('change', function(e) { var value = e.value; if (value !== '' && value != null) { $modal.modal('hide'); $modal.remove(); cb(value); } }); $modal = morpheus.FormBuilder.showInModal({ title : 'Dataset', html : formBuilder.$form, close : false }); }; morpheus.FormBuilder.showInModal = function(options) { var $div = morpheus.FormBuilder ._showInModal({ z : options.z, title : options.title, html : options.html, footer : options.close ? ('') : null, onClose : options.callback, backdrop : options.backdrop, size : options.size }); return $div; // if (options.draggable) { // $div.draggable({ // handle : $div.find(".modal-header") // }); // } }; morpheus.FormBuilder.showOkCancel = function(options) { options = $.extend({}, { ok : true }, options); var footer = []; if (options.ok) { footer .push(''); } if (options.apply) { footer .push(''); } footer .push(''); var $div = morpheus.FormBuilder._showInModal({ title : options.title, html : options.content, footer : footer.join(''), onClose : options.hiddenCallback, size : options.size }); // if (options.align === 'right') { // $div.css('left', $(window).width() // - $div.find('.modal-content').width() - 60); // } var $ok = $div.find('[name=ok]'); $ok.on('click', function(e) { options.okCallback(); $div.modal('hide'); }); if (options.focus) { $ok.focus(); } if (options.draggable) { $div.draggable({ handle : '.modal-header', containment : 'document' }); } // $div.on('click', '[name=apply]', function(e) { // options.okCallback(); // }); return $div; }; morpheus.FormBuilder.hasChanged = function(object, keyToUIElement) { var keys = _.keys(keyToUIElement); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = object[key]; var $element = keyToUIElement[key]; if (value !== morpheus.FormBuilder.getValue($element)) { return true; } } return false; }; morpheus.FormBuilder.getValue = function($element) { var list = $element.data('morpheus.checkbox-list'); if (list != null) { return list.val(); } if ($element.attr('type') === 'radio') { return $element.filter(':checked').val(); } if ($element.attr('type') === 'file') { return $element.data('files'); } return $element.attr('type') === 'checkbox' ? $element.prop('checked') ? true : false : $element.val(); }; morpheus.FormBuilder._showInModal = function(options) { var html = []; options = $.extend({}, { size : '' }, options); html.push(''); var $div = $(html.join('')); $div.on('mousewheel', function(e) { e.stopPropagation(); }); $div.find('.modal-body').html(options.html); $div.prependTo($(document.body)); $div.modal({ backdrop : options.backdrop === true ? true : false, }).on('hidden.bs.modal', function(e) { $div.remove(); if (options.onClose) { options.onClose(); } }); return $div; }; // morpheus.FormBuilder._showInModal = function(title, stuff, footer, // hiddenCallback) { // var html = []; // var id = _.uniqueId('dialog'); // html.push('
'); // $(document.body).prepend(html.join('')); // $('#' + id).html(stuff); // $('#' + id).dialog({ // modal : true, // resizable : true, // height : 'auto', // width : 400 // }).on('close', function(e) { // $(this).dialog('destroy'); // $(this).remove(); // if (hiddenCallback) { // hiddenCallback(); // } // }); // return id; // }; morpheus.FormBuilder.prototype = { appendContent : function($content) { this.$form.append($content); }, addSeparator : function() { var html = []; html.push('
'); if (!this.vertical) { html.push('
'); } html.push('
'); if (!this.vertical) { html.push('
'); } html.push('
'); this.$form.append(html.join('')); }, _append : function(html, field, isFieldStart) { var that = this; var required = field.required; var name = field.name; var type = field.type; if (type == 'separator') { html.push(this.vertical ? '
' : '
'); html.push('
'); html.push('
'); return; } var title = field.title; var disabled = field.disabled; var help = field.help; var value = field.value; var showLabel = field.showLabel; var col = ''; var labelColumn = ''; if (!this.vertical) { col = field.col || 'col-xs-8'; } if (showLabel === undefined) { showLabel = 'checkbox' !== type && 'button' !== type && 'radio' !== type; showLabel = showLabel || field.options !== undefined; } var id = that.prefix + '_' + name; if (title === undefined) { title = name.replace(/_/g, ' '); title = title[0].toUpperCase() + title.substring(1); } if (showLabel) { html.push(''); if (isFieldStart) { html.push('
'); } } else if (isFieldStart && !this.vertical) { html.push('
'); } if ('radio' === type) { if (field.options) { _.each(field.options, function(choice) { var isChoiceObject = _.isObject(choice) && choice.value !== undefined; var optionValue = isChoiceObject ? choice.value : choice; var optionText = isChoiceObject ? choice.name : choice; var selected = value === optionValue; html.push('
'); }); } else { html.push('
'); } } else if ('checkbox' === type) { html.push('
'); } else if ('checkbox-list' === type) { html.push('
'); } else if ('select' == type || type == 'bootstrap-select') { // if (field.multiple) { // field.type = 'bootstrap-select'; // type = 'bootstrap-select'; // } if (type == 'bootstrap-select') { html.push(''); if (field.type == 'bootstrap-select' && field.toggle) { html.push('

All | None

'); that.$form.on('click', '[name=' + name + '_all]', function(evt) { evt.preventDefault(); var $select = that.$form .find('[name=' + name + ']'); $select.selectpicker('val', $.map($select .find('option'), function(o) { return $(o).val(); })); $select.trigger('change'); }); that.$form.on('click', '[name=' + name + '_none]', function(evt) { evt.preventDefault(); var $select = that.$form .find('[name=' + name + ']'); $select.selectpicker('val', []); $select.trigger('change'); }); } } else if ('textarea' == type) { html.push(''); } else if ('button' == type) { html.push(''); } else if ('custom' === type) { html.push(value); } else if ('file' === type) { html .push(''); if (field.url !== false) { html.push('
'); html .push(''); html.push('
'); } html.push(''); // browse button clicked // select change that.$form .on('change', '[name=' + name + '_picker]', function(evt) { var $this = $(this); var val = $this.val(); var showTextInput = val === 'URL'; if ('Dropbox' === val) { var options = { success : function(files) { that.setValue(name, files[0].link); that.trigger('change', { name : name, value : files[0].link }); }, linkType : 'direct', multiselect : false }; Dropbox.choose(options); } else if ('My Computer' === val) { that.$form.find('[name=' + name + '_file]') .click(); } that.$form.find('[name=' + name + '_text]') .css('display', showTextInput ? '' : 'none'); }); // URL that.$form.on('keyup', '[name=' + name + '_text]', function(evt) { var text = $.trim($(this).val()); that.setValue(name, text); if (evt.which === 13) { that.trigger('change', { name : name, value : text }); } }); // browse file selected that.$form.on('change', '[name=' + name + '_file]', function(evt) { var files = evt.target.files; // FileList object that.setValue(name, files[0]); that.trigger('change', { name : name, value : files[0] }); }); } else { type = type == null ? 'text' : type; if (type === 'div') { html.push('
'); if (type === 'div') { html.push('
'); } } if (help !== undefined) { html.push(''); html.push(help); html.push(''); } }, append : function(fields) { var html = []; var that = this; var isArray = morpheus.Util.isArray(fields); if (!isArray) { fields = [ fields ]; } html.push('
'); _.each(fields, function(field, index) { that._append(html, field, index === 0); }); html.push('
'); html.push('
'); var $div = $(html.join('')); this.$form.append($div); var checkBoxLists = $div.find('.checkbox-list'); if (checkBoxLists.length > 0) { var checkBoxIndex = 0; _.each(fields, function(field) { // needs to already be in dom if (field.type === 'checkbox-list') { var list = new morpheus.CheckBoxList({ responsive : false, $el : $(checkBoxLists[checkBoxIndex]), items : field.options }); $(checkBoxLists[checkBoxIndex]).data( 'morpheus.checkbox-list', list); checkBoxIndex++; } }); } $div.find('.selectpicker').selectpicker({ iconBase : 'fa', tickIcon : 'fa-check', style : 'btn-default btn-sm' }); }, clear : function() { this.$form.empty(); }, getValue : function(name) { var $v = this.$form.find('[name=' + name + ']'); if ($v.length === 0) { $v = this.$form.find('[name=' + name + '_picker]'); } return morpheus.FormBuilder.getValue($v); }, setOptions : function(name, options, selectFirst) { var $select = this.$form.find('[name=' + name + ']'); var checkBoxList = $select.data('morpheus.checkbox-list'); if (checkBoxList) { checkBoxList.setItems(options); } else { var html = []; var selection = $select.val(); _.each(options, function(choice) { html.push(''); }); $select.html(html.join('')); $select.val(selection); if (selectFirst && $select.val() == null) { if ($select[0].options.length > 0) { $select.val($select[0].options[0].value); } } if ($select.hasClass('selectpicker')) { $select.selectpicker('refresh'); $select.selectpicker('render'); } } }, find : function(name) { return this.$form.find('[name=' + name + ']'); }, setHelpText : function(name, value) { var v = this.$form.find('[name=' + name + '_help]'); v.html(value); }, setValue : function(name, value) { var v = this.$form.find('[name=' + name + ']'); if (v.length === 0) { v = this.$form.find('[name=' + name + '_picker]'); if (v.attr('type') === 'file') { return v.data('files', value); } } var type = v.attr('type'); var list = v.data('morpheus.checkbox-list'); if (list) { list.setValue(value); } else { if (type === 'radio') { v.filter('[value=' + value + ']').prop('checked', true); } else if (type === 'checkbox') { v.prop('checked', value); } else { v.val(value); } if (v.hasClass('selectpicker')) { v.selectpicker('render'); } } }, setVisible : function(name, visible) { var $div = this.$form.find('[name=' + name + ']') .parents('.form-group'); if (visible) { $div.show(); } else { $div.hide(); } }, remove : function(name) { var $div = this.$form.find('[name=' + name + ']') .parents('.form-group'); $div.remove(); }, setEnabled : function(name, enabled) { var $div = this.$form.find('[name=' + name + ']'); $div.attr('disabled', !enabled); if (!enabled) { $div.parents('.form-group').find('label').addClass('text-muted'); } else { $div.parents('.form-group').find('label').removeClass('text-muted'); } } }; morpheus.Util.extend(morpheus.FormBuilder, morpheus.Events);