/** Form with single input element, two buttons and two states: normal/loading. Applied as jQuery method to DIV tag (not to form tag!) Editableform is linked with one of input types, e.g. 'text' or 'select'. @class editableform @uses text @uses textarea **/ (function ($) { var EditableForm = function (element, options) { this.options = $.extend({}, $.fn.editableform.defaults, options); this.$element = $(element); //div, containing form. Not form tag! Not editable-element. this.initInput(); }; EditableForm.prototype = { constructor: EditableForm, initInput: function() { //called once var TypeConstructor, typeOptions; //create input of specified type if(typeof $.fn.editableform.types[this.options.type] === 'function') { TypeConstructor = $.fn.editableform.types[this.options.type]; typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults)); this.input = new TypeConstructor(typeOptions); } else { $.error('Unknown type: '+ this.options.type); return; } this.value = this.input.str2value(this.options.value); }, initTemplate: function() { this.$form = $($.fn.editableform.template); }, initButtons: function() { this.$form.find('.editable-buttons').append($.fn.editableform.buttons); }, /** Renders editableform @method render **/ render: function() { this.$loading = $($.fn.editableform.loading); this.$element.empty().append(this.$loading); this.showLoading(); //init form template and buttons this.initTemplate(); if(this.options.showbuttons) { this.initButtons(); } else { this.$form.find('.editable-buttons').remove(); } /** Fired when rendering starts @event rendering @param {Object} event event object **/ this.$element.triggerHandler('rendering'); //render input $.when(this.input.render()) .then($.proxy(function () { //input this.$form.find('div.editable-input').append(this.input.$input); //automatically submit inputs when no buttons shown if(!this.options.showbuttons) { this.input.autosubmit(); } //"clear" link if(this.input.$clear) { this.$form.find('div.editable-input').append($('
text|textarea|select|date|checklist
@property type
@type string
@default 'text'
**/
type: 'text',
/**
Url for submit, e.g. '/post'
If function - it will be called instead of ajax. Function can return deferred object to run fail/done callbacks.
@property url
@type string|function
@default null
@example
url: function(params) {
if(params.value === 'abc') {
var d = new $.Deferred;
return d.reject('field cannot be "abc"'); //returning error via deferred object
} else {
someModel.set(params.name, params.value); //save data in some js model
}
}
**/
url:null,
/**
Additional params for submit. Function can be used to calculate params dynamically
@example
params: function(params) {
return { a: 1 };
}
@property params
@type object|function
@default null
**/
params:null,
/**
Name of field. Will be submitted on server. Can be taken from id
attribute
@property name
@type string
@default null
**/
name: null,
/**
Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. {id: 1, lang: 'en'}
.
Can be calculated dinamically via function.
@property pk
@type string|object|function
@default null
**/
pk: null,
/**
Initial value. If not defined - will be taken from element's content.
For __select__ type should be defined (as it is ID of shown text).
@property value
@type string|object
@default null
**/
value: null,
/**
Strategy for sending data on server. Can be auto|always|never
.
When 'auto' data will be sent on server only if pk defined, otherwise new value will be stored in element.
@property send
@type string
@default 'auto'
**/
send: 'auto',
/**
Function for client-side validation. If returns string - means validation not passed and string showed as error.
@property validate
@type function
@default null
@example
validate: function(value) {
if($.trim(value) == '') {
return 'This field is required';
}
}
**/
validate: null,
/**
Success callback. Called when value successfully sent on server and **response status = 200**.
Usefull to work with json response. For example, if your backend response can be {success: true}
or {success: false, msg: "server error"}
you can check it inside this callback.
If it returns **string** - means error occured and string is shown as error message.
If it returns **object like** {newValue: <something>}
- it overwrites value, submitted by user.
Otherwise newValue simply rendered into element.
@property success
@type function
@default null
@example
success: function(response, newValue) {
if(!response.success) return response.msg;
}
**/
success: function(response, newValue) {},
/**
Additional options for ajax request.
List of values: http://api.jquery.com/jQuery.ajax
@property ajaxOptions
@type object
@default null
**/
ajaxOptions: null,
/**
Wether to show buttons or not.
Form without buttons can be submitted by Enter (depends on input), by onblur = 'submit' or manually (via submit api method)
@property showbuttons
@type boolean
@default true
**/
showbuttons: false
/*todo:
Submit strategy. Can be normal|never
submitmode='never'
usefull for turning into classic form several inputs and submitting them together manually.
Works pretty with showbuttons=false
@property submitmode
@type string
@default normal
*/
// submitmode: 'normal'
};
/*
Note: following params could redefined in engine: bootstrap or jqueryui:
Classes 'control-group' and 'editable-error-block' must always present!
*/
$.fn.editableform.template = '';
//loading div
$.fn.editableform.loading = '';
//buttons
$.fn.editableform.buttons = ''+
'';
//error class attahced to control-group
$.fn.editableform.errorGroupClass = null;
//error class attahced to editable-error-block
$.fn.editableform.errorBlockClass = 'editable-error';
//input types
$.fn.editableform.types = {};
//utils
$.fn.editableform.utils = {};
}(window.jQuery));