(function () { var root = window || {}; root = root.GravJS = root.GravJS || {}; root.clickedButton = null; $(document).on('click', 'button.task', function(e) { root.clickedButton = e.target; }); function addTypes (form, factory) { var name = factory.getName(), types = factory.getTypes(); for (var i = types.length - 1; i >= 0; i--) { form.types[types[i]] = name; if (form.scanned) { scan(form, type); } } } function scan (form, type) { for (var i = form.elements.length - 1; i >= 0; i--) { if (!type || form.elements[i].type === type) { form.elements.splice(i, 1); } } if (Object.keys(form.types).length === 0 || (type && !form.types[type])) { return; } form.findElements().each(function () { var el = $(this), type = el.data(form.dataIndicator); if (type == 'textarea' || type == 'toggleable' || type == 'datetime') { var processSpan = function processSpan(element, toggleable) { var on = true; if (!toggleable) { on = $(element).find('input').is(':checked'); } $(element).find('label').css('opacity', on ? 1 : 0.7); $(element).siblings('label').css('opacity', on ? 1 : 0.7); if (!on) { $(element).find('input').attr('checked', false).prop('value', 0); } else { $(element).find('input').attr('checked', true).prop('value', 1); } var form_data = $(element).parent().siblings('.form-data'); if (on) { form_data.addClass('checked'); } else { form_data.removeClass('checked'); } form_data.css('opacity', on ? 1 : 0.6); form_data.find('textarea').css('opacity', on ? 1 : 0.6); form_data.find('input').css('opacity', on ? 1 : 0.6); }; var processToggleables = function processToggleables(element) { var elType = $(element)[0].tagName.toLowerCase(); if (elType == 'checkbox') { var on = $(element).is(':checked'); $(element).siblings('label').css('opacity', on ? 1 : 0.7); $(element).parent().siblings('label').css('opacity', on ? 1 : 0.7); if (!on) { $(element).attr('checked', false).prop('value', 0); } else { $(element).attr('checked', true).prop('value', 1); } var form_data = $(element).parent().parent().siblings('.form-data') form_data.css('opacity', on ? 1 : 0.6); form_data.find('textarea').css('opacity', on ? 1 : 0.6); form_data.find('input').css('opacity', on ? 1 : 0.6); } if (elType == 'span') { processSpan(element); } }; el.on('change input propertychange', function() { processToggleables(this); }); el.find('input').on('change', function() { processToggleables(this); }); if ($(el)[0].className == 'checkboxes toggleable') { var toggles = $(el).parent().siblings('.form-data').find('label'); toggles.on('click', function() { processSpan(el, true); }); } processToggleables(this); } if (form.types[type]) { var factory = form.factories[form.types[type]], element = new factory(el, form), name = element.name(); if (typeof form.toggleables[name] !== 'undefined') { linkToggle(element, form.toggleables[name]); delete form.toggleables[name]; } el.data('grav-field-instance', element); form.elements.push({ type: type, element: element }); } }); } function scanToggleable (form) { form.toggleables = {}; form.findElements('toggleable').each(function () { var el = $(this); form.toggleables[el.data('grav-field-name')] = el; }); } function linkToggle (element, toggleable) { $(element).on('change', function (value) { toggleable.find('input').prop('checked', true); toggleable.siblings('label').css('opacity', 1); element.disabled(false); }); toggleable.find('input').on('change', function () { var el = $(this), on = el.is(':checked'); toggleable.siblings('label').css('opacity', on ? 1 : 0.7); element.disabled(!on); if (!on) { element.el.attr('checked', false).prop('value', 0); } else { element.el.attr('checked', true).prop('value', 1); } }); var on = toggleable.find('input').is(':checked'); toggleable.siblings('label').css('opacity', on ? 1 : 0.7); element.disabled(!on); if (!on) { element.el.attr('checked', false).prop('value', 0); } else { element.el.attr('checked', true).prop('value', 1); } } var Form = function (el, options) { options = options || {}; this.form = $(el); this.form.data('grav-form-instance', this); this.form.on('submit', function (e) { this.submit(this.ajax); e.preventDefault(); return false; }.bind(this)); this.scanned = false; this.fieldIndicator = options.fieldIndicator || 'data-grav-field'; this.dataIndicator = options.dataIndicator || (this.fieldIndicator.indexOf('data-') === 0 ? this.fieldIndicator.substr(5) : 'grav-field'); this.ajax = options.ajax || false; this.elements = []; this.factories = {}; this.types = {}; if (typeof options.globalFactories === 'undefined' || options.globalFactories) { for (var name in Form.factories) { if (Form.factories.hasOwnProperty(name)) { this.registerFactory(Form.factories[name]); } } } scanToggleable(this); scan(this); this.scanned = true; //Refresh root.currentValues as toggleables have been initialized root.currentValues = getState(); }; Form.factories = {}; Form.findElements = function(el, selector, notIn, notSelf) { el = $(el); notIn = notIn || selector, notSelf = notSelf ? true : false; return el.find(selector).filter(function() { var parent = notSelf ? $(this) : $(this).parent(); nearestMatch = parent.closest(notIn); return nearestMatch.length == 0 || el.find(nearestMatch).length == 0; }); }; Form.registerFactory = function (factory, context) { context = context || Form.factories; context[factory.getName()] = factory; return true; }; Form.extendFactory = function (parentName, factory, context) { context = context || Form.factories; if (!context[parentName]) { return false; } return Form.registerFactory(factory.getName(), $.extend({}, context[parentName], factory)); }; Form.prototype.findElements = function(type) { var selector = '[' + this.fieldIndicator + (type ? '="' + type + '"' : '') + ']'; return Form.findElements(this.form, selector); }; Form.prototype.registerFactory = function(factory) { var registered = Form.registerFactory(factory, this.factories); if (registered) { addTypes(this, this.factories[factory.getName()]); } }; Form.prototype.extendFactory = function(parentName, factory) { var registered = Form.extendFactory(parentN, factory, this.factories); if (registered) { addTypes(this, this.factories[factory.getName()]); } }; Form.prototype.getElements = function() { if (!this.scanned) { scan(this); this.scanned = true; } return this.elements; }; Form.prototype.getValues = function(all) { var elements = this.getElements(), values = {}; for (var i = elements.length - 1; i >= 0; i--) { var e = elements[i].element, isInDOM = $('body').find(e.el).length; if (!all && (!isInDOM || !e.valid() || e.disabled())) { continue; } $.extend(values, e.formValues()); } return values; }; Form.prototype.submit = function(ajax) { // TODO: workaround, need to rework forms this.scanned = false; // force to rescan items var action = this.form.attr('action') || document.location, method = this.form.attr('method') || 'POST', values = {}; // Get form values that are not handled by JS framework Form.findElements(this.form, 'input, textarea', '', false).each(function(input) { var input = $(this), name = input.attr('name'), parent = input.parent('[data-grav-disabled]'), value = input.val(); if (input.is(':disabled') || (parent && parent.data('grav-disabled') == 'true')) { return; } if (name) { values[name] = value; } }); $.extend(values, this.getValues()); if ($(root.clickedButton).attr('name') == 'task') { values.task = $(root.clickedButton).attr('value'); if (values.task == 'saveas') { values.lang = $(root.clickedButton).attr('lang'); } if (values.task == 'switchlanguage') { values.lang = $(root.clickedButton).attr('lang'); values.redirect = $(root.clickedButton).attr('redirect'); } } if (!values.task) { values.task = 'save'; } if (!ajax) { var form = $('
').attr({ method: method, action: action }); for (var name in values) { if (values.hasOwnProperty(name)) { $('').attr({ type: 'hidden', name: name, value: values[name] }).appendTo(form); } } return form.appendTo('body').submit(); } else { return $.ajax({ method: method, url: action, data: values }); } }; root.Form = Form; })();