2015-06-01 21:22:56 +02:00
|
|
|
(function () {
|
|
|
|
|
var root = window || {};
|
|
|
|
|
root = root.GravJS = root.GravJS || {};
|
|
|
|
|
|
2015-08-19 17:27:34 +02:00
|
|
|
root.clickedButton = null;
|
|
|
|
|
$(document).on('click', 'button.task', function(e) {
|
|
|
|
|
root.clickedButton = e.target;
|
|
|
|
|
});
|
|
|
|
|
|
2015-06-01 21:22:56 +02:00
|
|
|
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);
|
|
|
|
|
|
2015-08-04 19:28:42 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-04 20:27:04 +02:00
|
|
|
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);
|
2015-08-04 19:28:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-04 20:27:04 +02:00
|
|
|
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);
|
2015-08-04 19:28:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-01 21:22:56 +02:00
|
|
|
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) {
|
2015-07-31 13:08:34 -07:00
|
|
|
$(element).on('change', function (value) {
|
2015-06-08 15:03:36 +02:00
|
|
|
toggleable.find('input').prop('checked', true);
|
|
|
|
|
toggleable.siblings('label').css('opacity', 1);
|
2015-06-01 21:22:56 +02:00
|
|
|
element.disabled(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
toggleable.find('input').on('change', function () {
|
2015-06-08 15:03:36 +02:00
|
|
|
var el = $(this),
|
|
|
|
|
on = el.is(':checked');
|
2015-06-01 21:22:56 +02:00
|
|
|
|
2015-06-08 15:03:36 +02:00
|
|
|
toggleable.siblings('label').css('opacity', on ? 1 : 0.7);
|
|
|
|
|
element.disabled(!on);
|
|
|
|
|
if (!on) {
|
2015-08-04 19:28:42 +02:00
|
|
|
element.el.attr('checked', false).prop('value', 0);
|
|
|
|
|
} else {
|
|
|
|
|
element.el.attr('checked', true).prop('value', 1);
|
2015-06-01 21:22:56 +02:00
|
|
|
}
|
|
|
|
|
});
|
2015-06-08 15:03:36 +02:00
|
|
|
|
2015-07-31 13:43:26 -07:00
|
|
|
var on = toggleable.find('input').is(':checked');
|
2015-06-08 15:03:36 +02:00
|
|
|
toggleable.siblings('label').css('opacity', on ? 1 : 0.7);
|
|
|
|
|
element.disabled(!on);
|
2015-08-04 19:28:42 +02:00
|
|
|
|
|
|
|
|
if (!on) {
|
|
|
|
|
element.el.attr('checked', false).prop('value', 0);
|
|
|
|
|
} else {
|
|
|
|
|
element.el.attr('checked', true).prop('value', 1);
|
|
|
|
|
}
|
2015-06-01 21:22:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2015-08-03 14:46:12 +02:00
|
|
|
|
2015-08-03 15:43:40 +02:00
|
|
|
//Refresh root.currentValues as toggleables have been initialized
|
|
|
|
|
root.currentValues = getState();
|
2015-06-01 21:22:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Form.factories = {};
|
|
|
|
|
|
2015-06-03 15:21:15 +02:00
|
|
|
Form.findElements = function(el, selector, notIn, notSelf) {
|
2015-06-01 21:22:56 +02:00
|
|
|
el = $(el);
|
2015-06-03 15:21:15 +02:00
|
|
|
notIn = notIn || selector,
|
|
|
|
|
notSelf = notSelf ? true : false;
|
|
|
|
|
|
2015-06-01 21:22:56 +02:00
|
|
|
return el.find(selector).filter(function() {
|
2015-06-03 15:21:15 +02:00
|
|
|
var parent = notSelf ? $(this) : $(this).parent();
|
|
|
|
|
nearestMatch = parent.closest(notIn);
|
2015-06-01 21:22:56 +02:00
|
|
|
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--) {
|
2015-08-19 21:00:52 -07:00
|
|
|
var e = elements[i].element,
|
|
|
|
|
isInDOM = $('body').find(e.el).length;
|
2015-06-01 21:22:56 +02:00
|
|
|
|
2015-08-19 21:00:52 -07:00
|
|
|
if (!all && (!isInDOM || !e.valid() || e.disabled())) {
|
2015-06-01 21:22:56 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$.extend(values, e.formValues());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return values;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Form.prototype.submit = function(ajax) {
|
|
|
|
|
var action = this.form.attr('action') || document.location,
|
|
|
|
|
method = this.form.attr('method') || 'POST',
|
2015-06-03 15:21:15 +02:00
|
|
|
values = {};
|
|
|
|
|
|
|
|
|
|
// Get form values that are not handled by JS framework
|
2015-07-31 09:24:35 +02:00
|
|
|
Form.findElements(this.form, 'input, textarea', '', false).each(function(input) {
|
2015-06-03 15:21:15 +02:00
|
|
|
var input = $(this),
|
|
|
|
|
name = input.attr('name'),
|
2015-08-06 10:43:51 -07:00
|
|
|
parent = input.parent('[data-grav-disabled]'),
|
2015-06-03 15:21:15 +02:00
|
|
|
value = input.val();
|
|
|
|
|
|
2015-08-06 10:43:51 -07:00
|
|
|
if (input.is(':disabled') || (parent && parent.data('grav-disabled') == 'true')) { return; }
|
|
|
|
|
|
2015-06-03 15:21:15 +02:00
|
|
|
if (name) {
|
|
|
|
|
values[name] = value;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$.extend(values, this.getValues());
|
2015-06-01 21:22:56 +02:00
|
|
|
|
2015-08-19 17:27:34 +02:00
|
|
|
if ($(root.clickedButton).attr('name') == 'task') {
|
|
|
|
|
values.task = $(root.clickedButton).attr('value');
|
|
|
|
|
if (values.task == 'saveas') {
|
|
|
|
|
values.lang = $(root.clickedButton).attr('lang');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-01 21:22:56 +02:00
|
|
|
if (!values.task) {
|
|
|
|
|
values.task = 'save';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ajax) {
|
|
|
|
|
var form = $('<form>').attr({ method: method, action: action });
|
|
|
|
|
|
|
|
|
|
for (var name in values) { if (values.hasOwnProperty(name)) {
|
|
|
|
|
$('<input>').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;
|
|
|
|
|
})();
|