many fixes for ie7+ compatibility

This commit is contained in:
vitalets 2012-11-27 13:25:42 +04:00
parent 1e757b833f
commit 18f29820f3
7 changed files with 154 additions and 135 deletions

@ -14,8 +14,8 @@ Editableform based on Twitter Bootstrap
}); });
//buttons //buttons
$.fn.editableform.buttons = '<button type="submit" class="btn btn-primary"><i class="icon-ok icon-white"></i></button>'+ $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+
'<button type="button" class="btn clearfix"><i class="icon-ban-circle"></i></button>'; '<button type="button" class="btn editable-cancel"><i class="icon-ban-circle"></i></button>';
//error classes //error classes
$.fn.editableform.errorGroupClass = 'error'; $.fn.editableform.errorGroupClass = 'error';

@ -8,12 +8,12 @@ Editableform based on jQuery UI
this.$form = $($.fn.editableform.template); this.$form = $($.fn.editableform.template);
//buttons //buttons
this.$form.find('div.editable-buttons').append($.fn.editableform.buttons); this.$form.find('.editable-buttons').append($.fn.editableform.buttons);
this.$form.find('button[type=submit]').button({ this.$form.find('.editable-submit').button({
icons: { primary: "ui-icon-check" }, icons: { primary: "ui-icon-check" },
text: false text: false
}).removeAttr('title'); }).removeAttr('title');
this.$form.find('button[type=button]').button({ this.$form.find('.editable-cancel').button({
icons: { primary: "ui-icon-cancel" }, icons: { primary: "ui-icon-cancel" },
text: false text: false
}).removeAttr('title'); }).removeAttr('title');

@ -9,15 +9,24 @@
.editable-buttons { .editable-buttons {
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
vertical-align: top;
margin-left: 7px;
/* display-inline emulation for IE7*/
zoom: 1;
*display: inline;
} }
.editable-input { .editable-input {
vertical-align: top; vertical-align: top;
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
white-space: normal; /* reset white-space decalred in parent*/
/* display-inline emulation for IE7*/
zoom: 1;
*display: inline;
} }
.editable-buttons button { .editable-buttons .editable-cancel {
margin-left: 7px; margin-left: 7px;
} }
@ -28,7 +37,8 @@
.editableform-loading { .editableform-loading {
background: url('img/loading.gif') center center no-repeat; background: url('img/loading.gif') center center no-repeat;
height: 25px; height: 25px;
width: auto;
} }
.editable-inline .editableform-loading { .editable-inline .editableform-loading {
@ -39,7 +49,7 @@
max-width: 300px; max-width: 300px;
padding-top: 3px; padding-top: 3px;
margin: 0; margin: 0;
clear: both; width: auto;
} }
.editable-error { .editable-error {
@ -57,8 +67,8 @@
} }
.editable-clear { .editable-clear {
clear: both; clear: both;
float: right;
font-size: 0.9em; font-size: 0.9em;
text-decoration: none; text-decoration: none;
text-align: right;
} }

@ -8,7 +8,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
@uses textarea @uses textarea
**/ **/
(function ($) { (function ($) {
var EditableForm = function (element, options) { var EditableForm = function (element, options) {
this.options = $.extend({}, $.fn.editableform.defaults, options); this.options = $.extend({}, $.fn.editableform.defaults, options);
this.$element = $(element); //div (usually), containing form. not form tag! this.$element = $(element); //div (usually), containing form. not form tag!
@ -19,7 +19,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
constructor: EditableForm, constructor: EditableForm,
initInput: function() { //called once initInput: function() { //called once
var TypeConstructor, typeOptions; var TypeConstructor, typeOptions;
//create input of specified type //create input of specified type
if(typeof $.fn.editableform.types[this.options.type] === 'function') { if(typeof $.fn.editableform.types[this.options.type] === 'function') {
TypeConstructor = $.fn.editableform.types[this.options.type]; TypeConstructor = $.fn.editableform.types[this.options.type];
@ -34,7 +34,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
}, },
initTemplate: function() { initTemplate: function() {
this.$form = $($.fn.editableform.template); this.$form = $($.fn.editableform.template);
//buttons //buttons
this.$form.find('div.editable-buttons').append($.fn.editableform.buttons); this.$form.find('div.editable-buttons').append($.fn.editableform.buttons);
}, },
@ -47,54 +47,57 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
this.$loading = $($.fn.editableform.loading); this.$loading = $($.fn.editableform.loading);
this.$element.empty().append(this.$loading); this.$element.empty().append(this.$loading);
this.showLoading(); this.showLoading();
this.initTemplate(); this.initTemplate();
/** /**
Fired when rendering starts Fired when rendering starts
@event rendering @event rendering
@param {Object} event event object @param {Object} event event object
**/ **/
this.$element.triggerHandler('rendering'); this.$element.triggerHandler('rendering');
//render input //render input
$.when(this.input.render()) $.when(this.input.render())
.then($.proxy(function () { .then($.proxy(function () {
//input //input
this.$form.find('div.editable-input').append(this.input.$input); this.$form.find('div.editable-input').append(this.input.$input);
//clear link //"clear" link
if(this.input.$clear) { if(this.input.$clear) {
this.$form.find('div.editable-input').append(this.input.$clear); this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear));
} }
//attach 'cancel' handler
this.$form.find('button[type=button]').click($.proxy(this.cancel, this));
//append form to container //append form to container
this.$element.append(this.$form); this.$element.append(this.$form);
//attach 'cancel' handler
this.$form.find('.editable-cancel').click($.proxy(this.cancel, this));
// this.$form.find('.editable-buttons button').eq(1).click($.proxy(this.cancel, this));
if(this.input.error) { if(this.input.error) {
this.error(this.input.error); this.error(this.input.error);
this.$form.find('button[type=submit]').attr('disabled', true); this.$form.find('.editable-submit').attr('disabled', true);
this.input.$input.attr('disabled', true); this.input.$input.attr('disabled', true);
} else { } else {
this.error(false); this.error(false);
this.input.$input.removeAttr('disabled'); this.input.$input.removeAttr('disabled');
this.$form.find('button[type=submit]').removeAttr('disabled'); this.$form.find('.editable-submit').removeAttr('disabled');
this.input.value2input(this.value); this.input.value2input(this.value);
this.$form.submit($.proxy(this.submit, this)); this.$form.submit($.proxy(this.submit, this));
} }
/** /**
Fired when form is rendered Fired when form is rendered
@event rendered @event rendered
@param {Object} event event object @param {Object} event event object
**/ **/
this.$element.triggerHandler('rendered'); this.$element.triggerHandler('rendered');
this.showForm(); this.showForm();
}, this)); }, this));
}, },
cancel: function() { cancel: function() {
/** /**
Fired when form was cancelled by user Fired when form was cancelled by user
@event cancel @event cancel
@ -103,12 +106,18 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
this.$element.triggerHandler('cancel'); this.$element.triggerHandler('cancel');
}, },
showLoading: function() { showLoading: function() {
var fw, fh, iw, bh; var w;
//set loading size equal to form
if(this.$form) { if(this.$form) {
//set loading size equal to form
this.$loading.width(this.$form.outerWidth()); this.$loading.width(this.$form.outerWidth());
this.$loading.height(this.$form.outerHeight()); this.$loading.height(this.$form.outerHeight());
this.$form.hide(); this.$form.hide();
} else {
//stretch loading to fill container width
w = this.$loading.parent().width();
if(w) {
this.$loading.width(w);
}
} }
this.$loading.show(); this.$loading.show();
}, },
@ -124,11 +133,11 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
**/ **/
this.$element.triggerHandler('show'); this.$element.triggerHandler('show');
}, },
error: function(msg) { error: function(msg) {
var $group = this.$form.find('.control-group'), var $group = this.$form.find('.control-group'),
$block = this.$form.find('.editable-error-block'); $block = this.$form.find('.editable-error-block');
if(msg === false) { if(msg === false) {
$group.removeClass($.fn.editableform.errorGroupClass); $group.removeClass($.fn.editableform.errorGroupClass);
$block.removeClass($.fn.editableform.errorBlockClass).empty().hide(); $block.removeClass($.fn.editableform.errorBlockClass).empty().hide();
@ -137,15 +146,15 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
$block.addClass($.fn.editableform.errorBlockClass).text(msg).show(); $block.addClass($.fn.editableform.errorBlockClass).text(msg).show();
} }
}, },
submit: function(e) { submit: function(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
var error, var error,
//get value from input //get value from input
newValue = this.input.input2value(), newValue = this.input.input2value(),
newValueStr; newValueStr;
//validation //validation
if (error = this.validate(newValue)) { if (error = this.validate(newValue)) {
@ -153,14 +162,14 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
this.showForm(); this.showForm();
return; return;
} }
//value as string //value as string
newValueStr = this.input.value2str(newValue); newValueStr = this.input.value2str(newValue);
//if value not changed --> cancel //if value not changed --> cancel
/*jslint eqeq: true*/ /*jslint eqeq: true*/
if (newValueStr == this.input.value2str(this.value)) { if (newValueStr == this.input.value2str(this.value)) {
/*jslint eqeq: false*/ /*jslint eqeq: false*/
this.cancel(); this.cancel();
return; return;
} }
@ -175,36 +184,36 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
this.showForm(); this.showForm();
return; return;
} }
//clear error message //clear error message
this.error(false); this.error(false);
this.value = newValue; this.value = newValue;
/** /**
Fired when form is submitted Fired when form is submitted
@event save @event save
@param {Object} event event object @param {Object} event event object
@param {Object} params additional params @param {Object} params additional params
@param {mixed} params.newValue submitted value @param {mixed} params.newValue submitted value
@param {Object} params.response ajax response @param {Object} params.response ajax response
@example @example
$('#form-div').on('save'), function(e, params){ $('#form-div').on('save'), function(e, params){
if(params.newValue === 'username') {...} if(params.newValue === 'username') {...}
}); });
**/ **/
this.$element.triggerHandler('save', {newValue: newValue, response: response}); this.$element.triggerHandler('save', {newValue: newValue, response: response});
}, this)) }, this))
.fail($.proxy(function(xhr) { .fail($.proxy(function(xhr) {
this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'); this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
this.showForm(); this.showForm();
}, this)); }, this));
}, },
save: function(value) { save: function(value) {
var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this) : this.options.pk, var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this) : this.options.pk,
send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))), send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
params; params;
if (send) { //send to server if (send) { //send to server
this.showLoading(); this.showLoading();
@ -214,7 +223,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
value: value, value: value,
pk: pk pk: pk
}; };
//additional params //additional params
if(typeof this.options.params === 'function') { if(typeof this.options.params === 'function') {
$.extend(params, this.options.params.call(this, params)); $.extend(params, this.options.params.call(this, params));
@ -236,7 +245,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
} }
} }
}, },
validate: function (value) { validate: function (value) {
if (value === undefined) { if (value === undefined) {
value = this.value; value = this.value;
@ -245,38 +254,38 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
return this.options.validate.call(this, value); return this.options.validate.call(this, value);
} }
}, },
option: function(key, value) { option: function(key, value) {
this.options[key] = value; this.options[key] = value;
if(key === 'value') { if(key === 'value') {
this.setValue(value); this.setValue(value);
} }
}, },
setValue: function(value, convertStr) { setValue: function(value, convertStr) {
if(convertStr) { if(convertStr) {
this.value = this.input.str2value(value); this.value = this.input.str2value(value);
} else { } else {
this.value = value; this.value = value;
} }
} }
}; };
/* /*
Initialize editableform. Applied to jQuery object. Initialize editableform. Applied to jQuery object.
@method $().editableform(options) @method $().editableform(options)
@params {Object} options @params {Object} options
@example @example
var $form = $('&lt;div&gt;').editableform({ var $form = $('&lt;div&gt;').editableform({
type: 'text', type: 'text',
name: 'username', name: 'username',
url: '/post', url: '/post',
value: 'vitaliy' value: 'vitaliy'
}); });
//to display form you should call 'render' method //to display form you should call 'render' method
$form.editableform('render'); $form.editableform('render');
*/ */
$.fn.editableform = function (option) { $.fn.editableform = function (option) {
var args = arguments; var args = arguments;
@ -287,20 +296,20 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
if (!data) { if (!data) {
$this.data('editableform', (data = new EditableForm(this, options))); $this.data('editableform', (data = new EditableForm(this, options)));
} }
if (typeof option === 'string') { //call method if (typeof option === 'string') { //call method
data[option].apply(data, Array.prototype.slice.call(args, 1)); data[option].apply(data, Array.prototype.slice.call(args, 1));
} }
}); });
}; };
//keep link to constructor to allow inheritance //keep link to constructor to allow inheritance
$.fn.editableform.Constructor = EditableForm; $.fn.editableform.Constructor = EditableForm;
//defaults //defaults
$.fn.editableform.defaults = { $.fn.editableform.defaults = {
/* see also defaults for input */ /* see also defaults for input */
/** /**
Type of input. Can be <code>text|textarea|select|date|checklist</code> Type of input. Can be <code>text|textarea|select|date|checklist</code>
@ -318,12 +327,12 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
@default null @default null
@example @example
url: function(params) { url: function(params) {
if(params.value === 'abc') { if(params.value === 'abc') {
var d = new $.Deferred; var d = new $.Deferred;
return d.reject('field cannot be "abc"'); //returning error via deferred object return d.reject('field cannot be "abc"'); //returning error via deferred object
} else { } else {
someModel.set(params.name, params.value); //save data in some js model someModel.set(params.name, params.value); //save data in some js model
} }
} }
**/ **/
url:null, url:null,
@ -331,7 +340,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
Additional params for submit. Function can be used to calculate params dynamically Additional params for submit. Function can be used to calculate params dynamically
@example @example
params: function() { params: function() {
return { a: 1 }; return { a: 1 };
} }
@property params @property params
@ -382,54 +391,54 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
@default null @default null
@example @example
validate: function(value) { validate: function(value) {
if($.trim(value) == '') { if($.trim(value) == '') {
return 'This field is required'; return 'This field is required';
} }
} }
**/ **/
validate: null, validate: null,
/** /**
Success callback. Called when value successfully sent on server and response status = 200. Success callback. Called when value successfully sent on server and response status = 200.
Can be used to process json response. If this function returns string - means error occured and string is shown as error message. Can be used to process json response. If this function returns string - means error occured and string is shown as error message.
@property success @property success
@type function @type function
@default null @default null
@example @example
success: function(response, newValue) { success: function(response, newValue) {
if(!response.success) return response.msg; if(!response.success) return response.msg;
} }
**/ **/
success: function(response, newValue) {} success: function(response, newValue) {}
}; };
/* /*
Note: following params could redefined in engine: bootstrap or jqueryui: Note: following params could redefined in engine: bootstrap or jqueryui:
Classes 'control-group' and 'editable-error-block' must always present! Classes 'control-group' and 'editable-error-block' must always present!
*/ */
$.fn.editableform.template = '<form class="form-inline editableform">'+ $.fn.editableform.template = '<form class="form-inline editableform">'+
'<div class="control-group">' + '<div class="control-group">' +
'<div class="editable-input"></div><div class="editable-buttons"></div>'+ '<div><div class="editable-input"></div><div class="editable-buttons"></div></div>'+
'<div class="editable-error-block"></div>' + '<div class="editable-error-block"></div>' +
'</div>' + '</div>' +
'</form>'; '</form>';
//loading div
$.fn.editableform.loading = '<div class="editableform-loading"></div>';
//buttons
$.fn.editableform.buttons = '<button type="submit">ok</button>'+
'<button type="button">cancel</button>';
//error class attahced to control-group
$.fn.editableform.errorGroupClass = null;
//error class attahced to editable-error-block
$.fn.editableform.errorBlockClass = 'editable-error';
//input types //loading div
$.fn.editableform.types = {}; $.fn.editableform.loading = '<div class="editableform-loading"></div>';
//utils
$.fn.editableform.utils = {}; //buttons
$.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+
'<button type="button" class="editable-cancel">cancel</button>';
//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)); }(window.jQuery));

@ -35,7 +35,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
//create input of specified type. Input will be used for converting value, not in form //create input of specified type. Input will be used for converting value, not in form
if(typeof $.fn.editableform.types[this.options.type] === 'function') { if(typeof $.fn.editableform.types[this.options.type] === 'function') {
TypeConstructor = $.fn.editableform.types[this.options.type]; TypeConstructor = $.fn.editableform.types[this.options.type];
this.typeOptions = $.fn.editableform.utils.sliceObj(this.options, Object.keys(TypeConstructor.defaults)); this.typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
this.input = new TypeConstructor(this.typeOptions); this.input = new TypeConstructor(this.typeOptions);
} else { } else {
$.error('Unknown type: '+ this.options.type); $.error('Unknown type: '+ this.options.type);
@ -53,7 +53,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
//attach handler to close any container on escape //attach handler to close any container on escape
$(document).off('keyup.editable').on('keyup.editable', function (e) { $(document).off('keyup.editable').on('keyup.editable', function (e) {
if (e.which === 27) { if (e.which === 27) {
$('.editable-container').find('button[type=button]').click(); $('.editable-container').find('.editable-cancel').click();
} }
}); });
@ -65,7 +65,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
return; return;
} }
//close all other containers //close all other containers
$('.editable-container').find('button[type=button]').click(); $('.editable-container').find('.editable-cancel').click();
}); });
//add 'editable' class //add 'editable' class
@ -229,7 +229,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
} }
//hide all other editable containers. Required to work correctly with toggle = manual //hide all other editable containers. Required to work correctly with toggle = manual
$('.editable-container').find('button[type=button]').click(); $('.editable-container').find('.editable-cancel').click();
//show container //show container
this.container.show(); this.container.show();

@ -56,7 +56,7 @@ $(function(){
this.$input.datepicker(this.options.datepicker); this.$input.datepicker(this.options.datepicker);
if(this.options.clear) { if(this.options.clear) {
this.$clear = $('<a href="#">').addClass('editable-clear').html(this.options.clear).click($.proxy(function(e){ this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
this.clear(); this.clear();

@ -54,7 +54,7 @@ $(function(){
this.$input.datepicker(this.options.datepicker); this.$input.datepicker(this.options.datepicker);
if(this.options.clear) { if(this.options.clear) {
this.$clear = $('<a href="#">').addClass('editable-clear').html(this.options.clear).click($.proxy(function(e){ this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
this.clear(); this.clear();