Merge branch 'release-1.1.0'
This commit is contained in:
CHANGELOG.txtREADME.mdgrunt.jspackage.json
src
containers
editable-form
editable-form-bootstrap.jseditable-form-jqueryui.jseditable-form-utils.jseditable-form.csseditable-form.js
element
inputs
test
@ -1,6 +1,17 @@
|
|||||||
X-editable changelog
|
X-editable changelog
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.1.0 Nov 27, 2012
|
||||||
|
----------------------------
|
||||||
|
[enh #11] icon cancel changed to 'cross' (tarciozemel)
|
||||||
|
[enh] added support for IE7+ (vitalets)
|
||||||
|
[enh #9] 'name' or 'id' is not required anymore (vitalets)
|
||||||
|
[enh] 'clear' button added in date and dateui (vitalets)
|
||||||
|
[enh] form template changed: added DIV.editable-input, DIV.editable.buttons and $.fn.editableform.buttons (vitalets)
|
||||||
|
[enh] new input type: checklist (vitalets)
|
||||||
|
[enh] updated docs: inputs dropdown menu, global templates section (vitalets)
|
||||||
|
|
||||||
|
|
||||||
Version 1.0.1 Nov 22, 2012
|
Version 1.0.1 Nov 22, 2012
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@ -13,7 +13,7 @@ Your feedback is very appreciated!
|
|||||||
## Contribution
|
## Contribution
|
||||||
A few steps how to start contributing:
|
A few steps how to start contributing:
|
||||||
|
|
||||||
1.[Fork X-editable](https://github.com/vitalets/x-editable/fork)
|
1.[Fork X-editable](https://github.com/vitalets/x-editable/fork) and pull the latest changes from <code>dev</code> branch
|
||||||
|
|
||||||
2.Arrange local directory structure. It should be:
|
2.Arrange local directory structure. It should be:
|
||||||
**x-editable**
|
**x-editable**
|
||||||
@ -57,7 +57,8 @@ Or use grunt's _qunit_ task <code>grunt test</code>. For that you also need to [
|
|||||||
5.To build lib + docs:
|
5.To build lib + docs:
|
||||||
* run <code>grunt build</code> in **lib** directory
|
* run <code>grunt build</code> in **lib** directory
|
||||||
* run <code>build data-docs-dist</code> in **gh-pages** directory
|
* run <code>build data-docs-dist</code> in **gh-pages** directory
|
||||||
You will get distributive in **lib/dist** and updated docs in **gh-pages/*.html**.
|
You will get distributive in **lib/dist** and updated docs in **gh-pages/*.html**.
|
||||||
|
Do not edit **index.html** and **docs.html** directly! Instead look at [Handlebars](https://github.com/wycats/handlebars.js) templates in **generator/templates**.
|
||||||
|
|
||||||
6.Commit changes on <code>dev</code> branch and make pull request as usual.
|
6.Commit changes on <code>dev</code> branch and make pull request as usual.
|
||||||
|
|
||||||
|
4
grunt.js
4
grunt.js
@ -38,9 +38,11 @@ function getFiles() {
|
|||||||
containers+'editable-container.js',
|
containers+'editable-container.js',
|
||||||
lib+'element/editable-element.js',
|
lib+'element/editable-element.js',
|
||||||
inputs+'abstract.js',
|
inputs+'abstract.js',
|
||||||
|
inputs+'list.js',
|
||||||
inputs+'text.js',
|
inputs+'text.js',
|
||||||
inputs+'textarea.js',
|
inputs+'textarea.js',
|
||||||
inputs+'select.js'
|
inputs+'select.js',
|
||||||
|
inputs+'checklist.js'
|
||||||
];
|
];
|
||||||
|
|
||||||
//common css files
|
//common css files
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "X-editable",
|
"name": "X-editable",
|
||||||
"title": "X-editable",
|
"title": "X-editable",
|
||||||
"description": "In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery",
|
"description": "In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"homepage": "http://github.com/vitalets/x-editable",
|
"homepage": "http://github.com/vitalets/x-editable",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Vitaliy Potapov",
|
"name": "Vitaliy Potapov",
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
.editable-container,
|
.editable-container {
|
||||||
.editable-container.popover {
|
|
||||||
width: auto;
|
|
||||||
white-space: nowrap; /* without this rule buttons wrap input in non-static elements */
|
|
||||||
max-width: none; /* without this rule poshytip does not stretch */
|
max-width: none; /* without this rule poshytip does not stretch */
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-container.popover {
|
||||||
|
/* width: 300px;*/ /* debug */
|
||||||
|
width: auto; /* without this rule popover does not stretch */
|
||||||
}
|
}
|
@ -3,11 +3,19 @@ Editableform based on Twitter Bootstrap
|
|||||||
*/
|
*/
|
||||||
(function ($) {
|
(function ($) {
|
||||||
|
|
||||||
//form template
|
$.extend($.fn.editableform.Constructor.prototype, {
|
||||||
$.fn.editableform.template = '<form class="form-inline editableform"><div class="control-group">' +
|
initTemplate: function() {
|
||||||
' <button type="submit" class="btn btn-primary"><i class="icon-ok icon-white"></i></button> <button type="button" class="btn clearfix"><i class="icon-ban-circle"></i></button>' +
|
this.$form = $($.fn.editableform.template);
|
||||||
'<div style="clear:both"><span class="help-block editable-error-block"></span></div>' +
|
this.$form.find('.editable-error-block').addClass('help-block');
|
||||||
'</div></form>';
|
|
||||||
|
//buttons
|
||||||
|
this.$form.find('div.editable-buttons').append($.fn.editableform.buttons);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//buttons
|
||||||
|
$.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 editable-cancel"><i class="icon-remove"></i></button>';
|
||||||
|
|
||||||
//error classes
|
//error classes
|
||||||
$.fn.editableform.errorGroupClass = 'error';
|
$.fn.editableform.errorGroupClass = 'error';
|
||||||
|
@ -4,27 +4,23 @@ Editableform based on jQuery UI
|
|||||||
(function ($) {
|
(function ($) {
|
||||||
|
|
||||||
$.extend($.fn.editableform.Constructor.prototype, {
|
$.extend($.fn.editableform.Constructor.prototype, {
|
||||||
initTemplate: function() {
|
initTemplate: function() {
|
||||||
this.$form = $($.fn.editableform.template);
|
this.$form = $($.fn.editableform.template);
|
||||||
|
|
||||||
//init buttons
|
//buttons
|
||||||
this.$form.find('button[type=submit]').button({
|
this.$form.find('.editable-buttons').append($.fn.editableform.buttons);
|
||||||
icons: { primary: "ui-icon-check" },
|
this.$form.find('.editable-submit').button({
|
||||||
text: false
|
icons: { primary: "ui-icon-check" },
|
||||||
});
|
text: false
|
||||||
this.$form.find('button[type=button]').button({
|
}).removeAttr('title');
|
||||||
icons: { primary: "ui-icon-cancel" },
|
this.$form.find('.editable-cancel').button({
|
||||||
text: false
|
icons: { primary: "ui-icon-closethick" },
|
||||||
});
|
text: false
|
||||||
}
|
}).removeAttr('title');
|
||||||
|
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//form template
|
|
||||||
$.fn.editableform.template = '<form class="editableform"><div class="control-group">' +
|
|
||||||
' <button type="submit" style="height: 24px">submit</button> <button type="button" style="height: 24px">cancel</button></div>' +
|
|
||||||
'<div class="editable-error-block"></div>' +
|
|
||||||
'</form>';
|
|
||||||
|
|
||||||
//error classes
|
//error classes
|
||||||
$.fn.editableform.errorGroupClass = null;
|
$.fn.editableform.errorGroupClass = null;
|
||||||
$.fn.editableform.errorBlockClass = 'ui-state-error';
|
$.fn.editableform.errorBlockClass = 'ui-state-error';
|
||||||
|
@ -2,104 +2,120 @@
|
|||||||
* EditableForm utilites
|
* EditableForm utilites
|
||||||
*/
|
*/
|
||||||
(function ($) {
|
(function ($) {
|
||||||
$.extend($.fn.editableform, {
|
$.fn.editableform.utils = {
|
||||||
utils: {
|
/**
|
||||||
/**
|
* classic JS inheritance function
|
||||||
* classic JS inheritance function
|
*/
|
||||||
*/
|
inherit: function (Child, Parent) {
|
||||||
inherit: function (Child, Parent) {
|
var F = function() { };
|
||||||
var F = function() { };
|
F.prototype = Parent.prototype;
|
||||||
F.prototype = Parent.prototype;
|
Child.prototype = new F();
|
||||||
Child.prototype = new F();
|
Child.prototype.constructor = Child;
|
||||||
Child.prototype.constructor = Child;
|
Child.superclass = Parent.prototype;
|
||||||
Child.superclass = Parent.prototype;
|
},
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set caret position in input
|
* set caret position in input
|
||||||
* see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
|
* see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
|
||||||
*/
|
*/
|
||||||
setCursorPosition: function(elem, pos) {
|
setCursorPosition: function(elem, pos) {
|
||||||
if (elem.setSelectionRange) {
|
if (elem.setSelectionRange) {
|
||||||
elem.setSelectionRange(pos, pos);
|
elem.setSelectionRange(pos, pos);
|
||||||
} else if (elem.createTextRange) {
|
} else if (elem.createTextRange) {
|
||||||
var range = elem.createTextRange();
|
var range = elem.createTextRange();
|
||||||
range.collapse(true);
|
range.collapse(true);
|
||||||
range.moveEnd('character', pos);
|
range.moveEnd('character', pos);
|
||||||
range.moveStart('character', pos);
|
range.moveStart('character', pos);
|
||||||
range.select();
|
range.select();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function to parse JSON in *single* quotes. (jquery automatically parse only double quotes)
|
* function to parse JSON in *single* quotes. (jquery automatically parse only double quotes)
|
||||||
* That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}">
|
* That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}">
|
||||||
* safe = true --> means no exception will be thrown
|
* safe = true --> means no exception will be thrown
|
||||||
* for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery
|
* for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery
|
||||||
*/
|
*/
|
||||||
tryParseJson: function(s, safe) {
|
tryParseJson: function(s, safe) {
|
||||||
if (typeof s === 'string' && s.length && s.match(/^\{.*\}$/)) {
|
if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) {
|
||||||
if (safe) {
|
if (safe) {
|
||||||
try {
|
try {
|
||||||
/*jslint evil: true*/
|
|
||||||
s = (new Function('return ' + s))();
|
|
||||||
/*jslint evil: false*/
|
|
||||||
} catch (e) {} finally {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*jslint evil: true*/
|
/*jslint evil: true*/
|
||||||
s = (new Function('return ' + s))();
|
s = (new Function('return ' + s))();
|
||||||
/*jslint evil: false*/
|
/*jslint evil: false*/
|
||||||
|
} catch (e) {} finally {
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/*jslint evil: true*/
|
||||||
|
s = (new Function('return ' + s))();
|
||||||
|
/*jslint evil: false*/
|
||||||
}
|
}
|
||||||
return s;
|
}
|
||||||
},
|
return s;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* slice object by specified keys
|
* slice object by specified keys
|
||||||
*/
|
*/
|
||||||
sliceObj: function(obj, keys, caseSensitive /* default: false */) {
|
sliceObj: function(obj, keys, caseSensitive /* default: false */) {
|
||||||
var key, keyLower, newObj = {};
|
var key, keyLower, newObj = {};
|
||||||
|
|
||||||
if (!$.isArray(keys) || !keys.length) {
|
|
||||||
return newObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < keys.length; i++) {
|
|
||||||
key = keys[i];
|
|
||||||
if (obj.hasOwnProperty(key)) {
|
|
||||||
newObj[key] = obj[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(caseSensitive === true) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//when getting data-* attributes via $.data() it's converted to lowercase.
|
|
||||||
//details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery
|
|
||||||
//workaround is code below.
|
|
||||||
keyLower = key.toLowerCase();
|
|
||||||
if (obj.hasOwnProperty(keyLower)) {
|
|
||||||
newObj[key] = obj[keyLower];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!$.isArray(keys) || !keys.length) {
|
||||||
return newObj;
|
return newObj;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
for (var i = 0; i < keys.length; i++) {
|
||||||
* exclude complex objects from $.data() before pass to config
|
key = keys[i];
|
||||||
*/
|
if (obj.hasOwnProperty(key)) {
|
||||||
getConfigData: function($element) {
|
newObj[key] = obj[key];
|
||||||
var data = {};
|
}
|
||||||
$.each($element.data(), function(k, v) {
|
|
||||||
if(typeof v !== 'object' || (v && typeof v === 'object' && v.constructor === Object)) {
|
if(caseSensitive === true) {
|
||||||
data[k] = v;
|
continue;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return data;
|
//when getting data-* attributes via $.data() it's converted to lowercase.
|
||||||
}
|
//details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery
|
||||||
}
|
//workaround is code below.
|
||||||
});
|
keyLower = key.toLowerCase();
|
||||||
|
if (obj.hasOwnProperty(keyLower)) {
|
||||||
|
newObj[key] = obj[keyLower];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newObj;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exclude complex objects from $.data() before pass to config
|
||||||
|
*/
|
||||||
|
getConfigData: function($element) {
|
||||||
|
var data = {};
|
||||||
|
$.each($element.data(), function(k, v) {
|
||||||
|
if(typeof v !== 'object' || (v && typeof v === 'object' && v.constructor === Object)) {
|
||||||
|
data[k] = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
|
objectKeys: function(o) {
|
||||||
|
if (Object.keys) {
|
||||||
|
return Object.keys(o);
|
||||||
|
} else {
|
||||||
|
if (o !== Object(o)) {
|
||||||
|
throw new TypeError('Object.keys called on a non-object');
|
||||||
|
}
|
||||||
|
var k=[], p;
|
||||||
|
for (p in o) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(o,p)) {
|
||||||
|
k.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
}(window.jQuery));
|
}(window.jQuery));
|
@ -1,11 +1,44 @@
|
|||||||
.editableform,
|
.editableform {
|
||||||
.editableform div.control-group {
|
margin-bottom: 0; /* overwrites bootstrap margin */
|
||||||
margin-bottom: 0;
|
}
|
||||||
|
|
||||||
|
.editableform .control-group {
|
||||||
|
margin-bottom: 0; /* overwrites bootstrap margin */
|
||||||
|
white-space: nowrap; /* prevent wrapping buttons on new line */
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-buttons {
|
||||||
|
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 {
|
||||||
|
vertical-align: top;
|
||||||
|
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 */
|
||||||
|
white-space: normal; /* reset white-space decalred in parent*/
|
||||||
|
/* display-inline emulation for IE7*/
|
||||||
|
zoom: 1;
|
||||||
|
*display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-buttons .editable-cancel {
|
||||||
|
margin-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for jquery-ui buttons need set height to look more pretty*/
|
||||||
|
.editable-buttons button.ui-button {
|
||||||
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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 {
|
||||||
@ -14,29 +47,40 @@
|
|||||||
|
|
||||||
.editable-error-block {
|
.editable-error-block {
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
margin-top: 3px;
|
margin: 5px 0 0 0;
|
||||||
margin-bottom: 0;
|
width: auto;
|
||||||
clear: both;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*add padding for jquery ui*/
|
||||||
|
.editable-error-block.ui-state-error {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.editable-error {
|
.editable-error {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editableform input,
|
|
||||||
.editableform select,
|
|
||||||
.editableform textarea {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
|
|
||||||
}
|
|
||||||
|
|
||||||
.editableform textarea {
|
.editableform textarea {
|
||||||
height: 150px; /*default height for textarea*/
|
height: 150px; /*default height for textarea*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.editableform .editable-date {
|
.editableform .editable-date {
|
||||||
float: left;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0 0 9px 0;
|
margin: 0;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* checklist vertical alignment */
|
||||||
|
.editable-checklist label input[type="checkbox"],
|
||||||
|
.editable-checklist label span {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-clear {
|
||||||
|
clear: both;
|
||||||
|
font-size: 0.9em;
|
||||||
|
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!
|
||||||
@ -17,13 +17,13 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
|||||||
|
|
||||||
EditableForm.prototype = {
|
EditableForm.prototype = {
|
||||||
constructor: EditableForm,
|
constructor: EditableForm,
|
||||||
initInput: function() {
|
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];
|
||||||
typeOptions = $.fn.editableform.utils.sliceObj(this.options, Object.keys(TypeConstructor.defaults));
|
typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
|
||||||
this.input = new TypeConstructor(typeOptions);
|
this.input = new TypeConstructor(typeOptions);
|
||||||
} else {
|
} else {
|
||||||
$.error('Unknown type: '+ this.options.type);
|
$.error('Unknown type: '+ this.options.type);
|
||||||
@ -34,6 +34,9 @@ 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
|
||||||
|
this.$form.find('div.editable-buttons').append($.fn.editableform.buttons);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
Renders editableform
|
Renders editableform
|
||||||
@ -44,48 +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 () {
|
||||||
//place input
|
//input
|
||||||
this.$form.find('div.control-group').prepend(this.input.$input);
|
this.$form.find('div.editable-input').append(this.input.$input);
|
||||||
//attach 'cancel' handler
|
|
||||||
this.$form.find('button[type=button]').click($.proxy(this.cancel, this));
|
//"clear" link
|
||||||
|
if(this.input.$clear) {
|
||||||
|
this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear));
|
||||||
|
}
|
||||||
|
|
||||||
//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
|
||||||
@ -94,20 +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, ih;
|
var w;
|
||||||
//set loading size equal to form
|
|
||||||
if(this.$form) {
|
if(this.$form) {
|
||||||
fh = this.$form.outerHeight() || 0;
|
//set loading size equal to form
|
||||||
fw = this.$form.outerWidth() || 0;
|
this.$loading.width(this.$form.outerWidth());
|
||||||
ih = (this.input && this.input.$input.outerHeight()) || 0;
|
this.$loading.height(this.$form.outerHeight());
|
||||||
iw = (this.input && this.input.$input.outerWidth()) || 0;
|
|
||||||
if(fh || ih) {
|
|
||||||
this.$loading.height(fh > ih ? fh : ih);
|
|
||||||
}
|
|
||||||
if(fw || iw) {
|
|
||||||
this.$loading.width(fw > iw ? fw : iw);
|
|
||||||
}
|
|
||||||
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();
|
||||||
},
|
},
|
||||||
@ -123,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();
|
||||||
@ -136,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)) {
|
||||||
@ -152,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;
|
||||||
}
|
}
|
||||||
@ -174,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();
|
||||||
|
|
||||||
@ -213,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));
|
||||||
@ -235,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;
|
||||||
@ -244,27 +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') {
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue: function(value, convertStr) {
|
||||||
|
if(convertStr) {
|
||||||
|
this.value = this.input.str2value(value);
|
||||||
|
} else {
|
||||||
|
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 = $('<div>').editableform({
|
var $form = $('<div>').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;
|
||||||
@ -275,22 +296,22 @@ 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</code>
|
Type of input. Can be <code>text|textarea|select|date|checklist</code>
|
||||||
|
|
||||||
@property type
|
@property type
|
||||||
@type string
|
@type string
|
||||||
@ -306,20 +327,20 @@ 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,
|
||||||
/**
|
/**
|
||||||
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
|
||||||
@ -379,7 +400,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
|||||||
/**
|
/**
|
||||||
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
|
||||||
@ -392,26 +413,32 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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"><div class="control-group">' +
|
$.fn.editableform.template = '<form class="form-inline editableform">'+
|
||||||
' <button type="submit">Ok</button> <button type="button">Cancel</button></div>' +
|
'<div class="control-group">' +
|
||||||
|
'<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>' +
|
||||||
'</form>';
|
'</form>';
|
||||||
|
|
||||||
//loading div
|
|
||||||
$.fn.editableform.loading = '<div class="editableform-loading"></div>';
|
|
||||||
|
|
||||||
//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));
|
@ -29,17 +29,13 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//name must be defined
|
//name
|
||||||
this.options.name = this.options.name || this.$element.attr('id');
|
this.options.name = this.options.name || this.$element.attr('id');
|
||||||
if (!this.options.name) {
|
|
||||||
$.error('You must define name (or id) for Editable element');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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);
|
||||||
@ -57,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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -69,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
|
||||||
@ -233,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();
|
||||||
|
@ -18,6 +18,7 @@ To create your own input you should inherit from this class.
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
this.options = $.extend({}, defaults, options);
|
this.options = $.extend({}, defaults, options);
|
||||||
this.$input = null;
|
this.$input = null;
|
||||||
|
this.$clear = null;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ To create your own input you should inherit from this class.
|
|||||||
|
|
||||||
if (this.options.placeholder) {
|
if (this.options.placeholder) {
|
||||||
this.$input.attr('placeholder', this.options.placeholder);
|
this.$input.attr('placeholder', this.options.placeholder);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,6 +111,15 @@ To create your own input you should inherit from this class.
|
|||||||
if(this.$input.is(':visible')) {
|
if(this.$input.is(':visible')) {
|
||||||
this.$input.focus();
|
this.$input.focus();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creares input.
|
||||||
|
|
||||||
|
@method clear()
|
||||||
|
**/
|
||||||
|
clear: function() {
|
||||||
|
this.$input.val(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
157
src/inputs/checklist.js
Normal file
157
src/inputs/checklist.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
List of checkboxes. Internally value stored as javascript array of values.
|
||||||
|
|
||||||
|
@class checklist
|
||||||
|
@extends list
|
||||||
|
@final
|
||||||
|
@example
|
||||||
|
<a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-original-title="Select options"></a>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
$('#options').editable({
|
||||||
|
value: [2, 3],
|
||||||
|
source: [
|
||||||
|
{value: 1, text: 'option1'},
|
||||||
|
{value: 2, text: 'option2'},
|
||||||
|
{value: 3, text: 'option3'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
**/
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
var Checklist = function (options) {
|
||||||
|
this.init('checklist', options, Checklist.defaults);
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.editableform.utils.inherit(Checklist, $.fn.editableform.types.list);
|
||||||
|
|
||||||
|
$.extend(Checklist.prototype, {
|
||||||
|
renderList: function() {
|
||||||
|
var $label, $div;
|
||||||
|
if(!$.isArray(this.sourceData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i=0; i<this.sourceData.length; i++) {
|
||||||
|
$label = $('<label>').append($('<input>', {
|
||||||
|
type: 'checkbox',
|
||||||
|
value: this.sourceData[i].value,
|
||||||
|
name: this.options.name
|
||||||
|
}))
|
||||||
|
.append($('<span>').text(' '+this.sourceData[i].text));
|
||||||
|
|
||||||
|
$('<div>').append($label).appendTo(this.$input);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
value2str: function(value) {
|
||||||
|
return $.isArray(value) ? value.join($.trim(this.options.separator)) : '';
|
||||||
|
},
|
||||||
|
|
||||||
|
//parse separated string
|
||||||
|
str2value: function(str) {
|
||||||
|
var reg, value = null;
|
||||||
|
if(typeof str === 'string' && str.length) {
|
||||||
|
reg = new RegExp('\\s*'+$.trim(this.options.separator)+'\\s*');
|
||||||
|
value = str.split(reg);
|
||||||
|
} else if($.isArray(str)) {
|
||||||
|
value = str;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
|
//set checked on required checkboxes
|
||||||
|
value2input: function(value) {
|
||||||
|
var $checks = this.$input.find('input[type="checkbox"]');
|
||||||
|
$checks.removeAttr('checked');
|
||||||
|
if($.isArray(value) && value.length) {
|
||||||
|
$checks.each(function(i, el) {
|
||||||
|
if($.inArray($(el).val(), value) !== -1) {
|
||||||
|
$(el).attr('checked', 'checked');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
input2value: function() {
|
||||||
|
var checked = [];
|
||||||
|
this.$input.find('input:checked').each(function(i, el) {
|
||||||
|
checked.push($(el).val());
|
||||||
|
});
|
||||||
|
return checked;
|
||||||
|
},
|
||||||
|
|
||||||
|
//collect text of checked boxes
|
||||||
|
value2htmlFinal: function(value, element) {
|
||||||
|
var selected = [], item, i, html = '';
|
||||||
|
if($.isArray(value) && value.length <= this.options.limit) {
|
||||||
|
for(i=0; i<value.length; i++){
|
||||||
|
item = this.itemByVal(value[i]);
|
||||||
|
if(item) {
|
||||||
|
selected.push($('<div>').text(item.text).html());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html = selected.join(this.options.viewseparator);
|
||||||
|
} else {
|
||||||
|
html = this.options.limitText.replace('{checked}', $.isArray(value) ? value.length : 0).replace('{count}', this.sourceData.length);
|
||||||
|
}
|
||||||
|
$(element).html(html);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Checklist.defaults = $.extend({}, $.fn.editableform.types.list.defaults, {
|
||||||
|
/**
|
||||||
|
@property tpl
|
||||||
|
@default <div></div>
|
||||||
|
**/
|
||||||
|
tpl:'<div></div>',
|
||||||
|
|
||||||
|
/**
|
||||||
|
@property inputclass
|
||||||
|
@type string
|
||||||
|
@default span2 editable-checklist
|
||||||
|
**/
|
||||||
|
inputclass: 'span2 editable-checklist',
|
||||||
|
|
||||||
|
/**
|
||||||
|
Separator of values in string when sending to server
|
||||||
|
|
||||||
|
@property separator
|
||||||
|
@type string
|
||||||
|
@default ', '
|
||||||
|
**/
|
||||||
|
separator: ',',
|
||||||
|
/**
|
||||||
|
Separator of text when display as element content.
|
||||||
|
|
||||||
|
@property viewseparator
|
||||||
|
@type string
|
||||||
|
@default '<br>'
|
||||||
|
**/
|
||||||
|
viewseparator: '<br>',
|
||||||
|
/**
|
||||||
|
Maximum number of items shown as element content.
|
||||||
|
If checked more items - <code>limitText</code> will be shown.
|
||||||
|
|
||||||
|
@property limit
|
||||||
|
@type integer
|
||||||
|
@default 4
|
||||||
|
**/
|
||||||
|
limit: 4,
|
||||||
|
/**
|
||||||
|
Text shown when count of checked items is greater than <code>limit</code> parameter.
|
||||||
|
You can use <code>{checked}</code> and <code>{count}</code> placeholders.
|
||||||
|
|
||||||
|
@property limitText
|
||||||
|
@type string
|
||||||
|
@default 'Selected {checked} of {count}'
|
||||||
|
**/
|
||||||
|
limitText: 'Selected {checked} of {count}'
|
||||||
|
});
|
||||||
|
|
||||||
|
$.fn.editableform.types.checklist = Checklist;
|
||||||
|
|
||||||
|
}(window.jQuery));
|
@ -5,6 +5,7 @@ For localization you can include js file from here: https://github.com/eternicod
|
|||||||
|
|
||||||
@class date
|
@class date
|
||||||
@extends abstract
|
@extends abstract
|
||||||
|
@final
|
||||||
@example
|
@example
|
||||||
<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
|
<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
|
||||||
<script>
|
<script>
|
||||||
@ -53,6 +54,14 @@ $(function(){
|
|||||||
render: function () {
|
render: function () {
|
||||||
Date.superclass.render.call(this);
|
Date.superclass.render.call(this);
|
||||||
this.$input.datepicker(this.options.datepicker);
|
this.$input.datepicker(this.options.datepicker);
|
||||||
|
|
||||||
|
if(this.options.clear) {
|
||||||
|
this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.clear();
|
||||||
|
}, this));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
value2html: function(value, element) {
|
value2html: function(value, element) {
|
||||||
@ -81,7 +90,12 @@ $(function(){
|
|||||||
},
|
},
|
||||||
|
|
||||||
activate: function() {
|
activate: function() {
|
||||||
}
|
},
|
||||||
|
|
||||||
|
clear: function() {
|
||||||
|
this.$input.data('datepicker').date = null;
|
||||||
|
this.$input.find('.active').removeClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -130,7 +144,16 @@ $(function(){
|
|||||||
weekStart: 0,
|
weekStart: 0,
|
||||||
startView: 0,
|
startView: 0,
|
||||||
autoclose: false
|
autoclose: false
|
||||||
}
|
},
|
||||||
|
/**
|
||||||
|
Text shown as clear date button.
|
||||||
|
If <code>false</code> clear button will not be rendered.
|
||||||
|
|
||||||
|
@property clear
|
||||||
|
@type boolean|string
|
||||||
|
@default 'x clear'
|
||||||
|
**/
|
||||||
|
clear: '× clear'
|
||||||
});
|
});
|
||||||
|
|
||||||
$.fn.editableform.types.date = Date;
|
$.fn.editableform.types.date = Date;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
jQuery UI Datepicker.
|
jQuery UI Datepicker.
|
||||||
Description and examples: http://jqueryui.com/datepicker.
|
Description and examples: http://jqueryui.com/datepicker.
|
||||||
Do not use it together with bootstrap-datepicker.
|
This input is also accessible as **date** type. Do not use it together with __bootstrap-datepicker__ as both apply <code>$().datepicker()</code> method.
|
||||||
|
|
||||||
@class dateui
|
@class dateui
|
||||||
@extends abstract
|
@extends abstract
|
||||||
|
@final
|
||||||
@example
|
@example
|
||||||
<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
|
<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
|
||||||
<script>
|
<script>
|
||||||
@ -51,6 +52,14 @@ $(function(){
|
|||||||
render: function () {
|
render: function () {
|
||||||
DateUI.superclass.render.call(this);
|
DateUI.superclass.render.call(this);
|
||||||
this.$input.datepicker(this.options.datepicker);
|
this.$input.datepicker(this.options.datepicker);
|
||||||
|
|
||||||
|
if(this.options.clear) {
|
||||||
|
this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.clear();
|
||||||
|
}, this));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
value2html: function(value, element) {
|
value2html: function(value, element) {
|
||||||
@ -99,7 +108,11 @@ $(function(){
|
|||||||
},
|
},
|
||||||
|
|
||||||
activate: function() {
|
activate: function() {
|
||||||
}
|
},
|
||||||
|
|
||||||
|
clear: function() {
|
||||||
|
this.$input.datepicker('setDate', null);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -149,7 +162,16 @@ $(function(){
|
|||||||
firstDay: 0,
|
firstDay: 0,
|
||||||
changeYear: true,
|
changeYear: true,
|
||||||
changeMonth: true
|
changeMonth: true
|
||||||
}
|
},
|
||||||
|
/**
|
||||||
|
Text shown as clear date button.
|
||||||
|
If <code>false</code> clear button will not be rendered.
|
||||||
|
|
||||||
|
@property clear
|
||||||
|
@type boolean|string
|
||||||
|
@default 'x clear'
|
||||||
|
**/
|
||||||
|
clear: '× clear'
|
||||||
});
|
});
|
||||||
|
|
||||||
$.fn.editableform.types.dateui = DateUI;
|
$.fn.editableform.types.dateui = DateUI;
|
||||||
|
254
src/inputs/list.js
Normal file
254
src/inputs/list.js
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/**
|
||||||
|
List - abstract class for inputs that have source option loaded from js array or via ajax
|
||||||
|
|
||||||
|
@class list
|
||||||
|
@extends abstract
|
||||||
|
**/
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
var List = function (options) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.editableform.utils.inherit(List, $.fn.editableform.types.abstract);
|
||||||
|
|
||||||
|
$.extend(List.prototype, {
|
||||||
|
render: function () {
|
||||||
|
List.superclass.render.call(this);
|
||||||
|
var deferred = $.Deferred();
|
||||||
|
this.error = null;
|
||||||
|
this.sourceData = null;
|
||||||
|
this.prependData = null;
|
||||||
|
this.onSourceReady(function () {
|
||||||
|
this.renderList();
|
||||||
|
deferred.resolve();
|
||||||
|
}, function () {
|
||||||
|
this.error = this.options.sourceError;
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
|
},
|
||||||
|
|
||||||
|
html2value: function (html) {
|
||||||
|
return null; //can't set value by text
|
||||||
|
},
|
||||||
|
|
||||||
|
value2html: function (value, element) {
|
||||||
|
var deferred = $.Deferred();
|
||||||
|
this.onSourceReady(function () {
|
||||||
|
this.value2htmlFinal(value, element);
|
||||||
|
deferred.resolve();
|
||||||
|
}, function () {
|
||||||
|
List.superclass.value2html(this.options.sourceError, element);
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
|
},
|
||||||
|
|
||||||
|
// ------------- additional functions ------------
|
||||||
|
|
||||||
|
onSourceReady: function (success, error) {
|
||||||
|
//if allready loaded just call success
|
||||||
|
if($.isArray(this.sourceData)) {
|
||||||
|
success.call(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try parse json in single quotes (for double quotes jquery does automatically)
|
||||||
|
try {
|
||||||
|
this.options.source = $.fn.editableform.utils.tryParseJson(this.options.source, false);
|
||||||
|
} catch (e) {
|
||||||
|
error.call(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//loading from url
|
||||||
|
if (typeof this.options.source === 'string') {
|
||||||
|
var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
|
||||||
|
cache;
|
||||||
|
|
||||||
|
if (!$(document).data(cacheID)) {
|
||||||
|
$(document).data(cacheID, {});
|
||||||
|
}
|
||||||
|
cache = $(document).data(cacheID);
|
||||||
|
|
||||||
|
//check for cached data
|
||||||
|
if (cache.loading === false && cache.sourceData) { //take source from cache
|
||||||
|
this.sourceData = cache.sourceData;
|
||||||
|
success.call(this);
|
||||||
|
return;
|
||||||
|
} else if (cache.loading === true) { //cache is loading, put callback in stack to be called later
|
||||||
|
cache.callbacks.push($.proxy(function () {
|
||||||
|
this.sourceData = cache.sourceData;
|
||||||
|
success.call(this);
|
||||||
|
}, this));
|
||||||
|
|
||||||
|
//also collecting error callbacks
|
||||||
|
cache.err_callbacks.push($.proxy(error, this));
|
||||||
|
return;
|
||||||
|
} else { //no cache yet, activate it
|
||||||
|
cache.loading = true;
|
||||||
|
cache.callbacks = [];
|
||||||
|
cache.err_callbacks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
//loading sourceData from server
|
||||||
|
$.ajax({
|
||||||
|
url: this.options.source,
|
||||||
|
type: 'get',
|
||||||
|
cache: false,
|
||||||
|
data: this.options.name ? {name: this.options.name} : {},
|
||||||
|
dataType: 'json',
|
||||||
|
success: $.proxy(function (data) {
|
||||||
|
cache.loading = false;
|
||||||
|
this.sourceData = this.makeArray(data);
|
||||||
|
if($.isArray(this.sourceData)) {
|
||||||
|
this.doPrepend();
|
||||||
|
//store result in cache
|
||||||
|
cache.sourceData = this.sourceData;
|
||||||
|
success.call(this);
|
||||||
|
$.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields
|
||||||
|
} else {
|
||||||
|
error.call(this);
|
||||||
|
$.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
|
||||||
|
}
|
||||||
|
}, this),
|
||||||
|
error: $.proxy(function () {
|
||||||
|
cache.loading = false;
|
||||||
|
error.call(this);
|
||||||
|
$.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
|
||||||
|
}, this)
|
||||||
|
});
|
||||||
|
} else { //options as json/array
|
||||||
|
this.sourceData = this.makeArray(this.options.source);
|
||||||
|
if($.isArray(this.sourceData)) {
|
||||||
|
this.doPrepend();
|
||||||
|
success.call(this);
|
||||||
|
} else {
|
||||||
|
error.call(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
doPrepend: function () {
|
||||||
|
if(this.options.prepend === null || this.options.prepend === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$.isArray(this.prependData)) {
|
||||||
|
//try parse json in single quotes
|
||||||
|
this.options.prepend = $.fn.editableform.utils.tryParseJson(this.options.prepend, true);
|
||||||
|
if (typeof this.options.prepend === 'string') {
|
||||||
|
this.options.prepend = {'': this.options.prepend};
|
||||||
|
}
|
||||||
|
this.prependData = this.makeArray(this.options.prepend);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($.isArray(this.prependData) && $.isArray(this.sourceData)) {
|
||||||
|
this.sourceData = this.prependData.concat(this.sourceData);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
renders input list
|
||||||
|
*/
|
||||||
|
renderList: function() {
|
||||||
|
// this method should be overwritten in child class
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
set element's html by value
|
||||||
|
*/
|
||||||
|
value2htmlFinal: function(value, element) {
|
||||||
|
// this method should be overwritten in child class
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}]
|
||||||
|
*/
|
||||||
|
makeArray: function(data) {
|
||||||
|
var count, obj, result = [], iterateEl;
|
||||||
|
if(!data || typeof data === 'string') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($.isArray(data)) { //array
|
||||||
|
iterateEl = function (k, v) {
|
||||||
|
obj = {value: k, text: v};
|
||||||
|
if(count++ >= 2) {
|
||||||
|
return false;// exit each if object has more than one value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(var i = 0; i < data.length; i++) {
|
||||||
|
if(typeof data[i] === 'object') {
|
||||||
|
count = 0;
|
||||||
|
$.each(data[i], iterateEl);
|
||||||
|
if(count === 1) {
|
||||||
|
result.push(obj);
|
||||||
|
} else if(count > 1 && data[i].hasOwnProperty('value') && data[i].hasOwnProperty('text')) {
|
||||||
|
result.push(data[i]);
|
||||||
|
} else {
|
||||||
|
//data contains incorrect objects
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push({value: data[i], text: data[i]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { //object
|
||||||
|
$.each(data, function (k, v) {
|
||||||
|
result.push({value: k, text: v});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
//search for item by particular value
|
||||||
|
itemByVal: function(val) {
|
||||||
|
if($.isArray(this.sourceData)) {
|
||||||
|
for(var i=0; i<this.sourceData.length; i++){
|
||||||
|
/*jshint eqeqeq: false*/
|
||||||
|
if(this.sourceData[i].value == val) {
|
||||||
|
/*jshint eqeqeq: true*/
|
||||||
|
return this.sourceData[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
List.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||||
|
/**
|
||||||
|
Source data for list. If string - considered ajax url to load items. Otherwise should be an array.
|
||||||
|
Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br>
|
||||||
|
For compability it also supports format <code>{value1: "text1", value2: "text2" ...}</code> but it does not guarantee elements order.
|
||||||
|
|
||||||
|
@property source
|
||||||
|
@type string|array|object
|
||||||
|
@default null
|
||||||
|
**/
|
||||||
|
source:null,
|
||||||
|
/**
|
||||||
|
Data automatically prepended to the begining of dropdown list.
|
||||||
|
|
||||||
|
@property prepend
|
||||||
|
@type string|array|object
|
||||||
|
@default false
|
||||||
|
**/
|
||||||
|
prepend:false,
|
||||||
|
/**
|
||||||
|
Error message when list cannot be loaded (e.g. ajax error)
|
||||||
|
|
||||||
|
@property sourceError
|
||||||
|
@type string
|
||||||
|
@default Error when loading list
|
||||||
|
**/
|
||||||
|
sourceError: 'Error when loading list'
|
||||||
|
});
|
||||||
|
|
||||||
|
$.fn.editableform.types.list = List;
|
||||||
|
|
||||||
|
}(window.jQuery));
|
@ -1,8 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
Select (dropdown) input
|
Select (dropdown)
|
||||||
|
|
||||||
@class select
|
@class select
|
||||||
@extends abstract
|
@extends list
|
||||||
|
@final
|
||||||
@example
|
@example
|
||||||
<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-original-title="Select status"></a>
|
<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-original-title="Select status"></a>
|
||||||
<script>
|
<script>
|
||||||
@ -25,160 +26,10 @@ $(function(){
|
|||||||
this.init('select', options, Select.defaults);
|
this.init('select', options, Select.defaults);
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.editableform.utils.inherit(Select, $.fn.editableform.types.abstract);
|
$.fn.editableform.utils.inherit(Select, $.fn.editableform.types.list);
|
||||||
|
|
||||||
$.extend(Select.prototype, {
|
$.extend(Select.prototype, {
|
||||||
render: function () {
|
renderList: function() {
|
||||||
Select.superclass.render.call(this);
|
|
||||||
var deferred = $.Deferred();
|
|
||||||
this.error = null;
|
|
||||||
this.sourceData = null;
|
|
||||||
this.prependData = null;
|
|
||||||
this.onSourceReady(function () {
|
|
||||||
this.renderOptions();
|
|
||||||
deferred.resolve();
|
|
||||||
}, function () {
|
|
||||||
this.error = this.options.sourceError;
|
|
||||||
deferred.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise();
|
|
||||||
},
|
|
||||||
|
|
||||||
html2value: function (html) {
|
|
||||||
return null; //it's not good idea to set value by text for SELECT. Better set NULL
|
|
||||||
},
|
|
||||||
|
|
||||||
value2html: function (value, element) {
|
|
||||||
var deferred = $.Deferred();
|
|
||||||
this.onSourceReady(function () {
|
|
||||||
var i, text = '';
|
|
||||||
if($.isArray(this.sourceData)) {
|
|
||||||
for(i=0; i<this.sourceData.length; i++){
|
|
||||||
/*jshint eqeqeq: false*/
|
|
||||||
if(this.sourceData[i].value == value) {
|
|
||||||
/*jshint eqeqeq: true*/
|
|
||||||
text = this.sourceData[i].text;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Select.superclass.value2html(text, element);
|
|
||||||
deferred.resolve();
|
|
||||||
}, function () {
|
|
||||||
Select.superclass.value2html(this.options.sourceError, element);
|
|
||||||
deferred.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise();
|
|
||||||
},
|
|
||||||
|
|
||||||
// ------------- additional functions ------------
|
|
||||||
|
|
||||||
onSourceReady: function (success, error) {
|
|
||||||
//if allready loaded just call success
|
|
||||||
if($.isArray(this.sourceData)) {
|
|
||||||
success.call(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try parse json in single quotes (for double quotes jquery does automatically)
|
|
||||||
try {
|
|
||||||
this.options.source = $.fn.editableform.utils.tryParseJson(this.options.source, false);
|
|
||||||
} catch (e) {
|
|
||||||
error.call(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//loading from url
|
|
||||||
if (typeof this.options.source === 'string') {
|
|
||||||
var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
|
|
||||||
cache;
|
|
||||||
|
|
||||||
if (!$(document).data(cacheID)) {
|
|
||||||
$(document).data(cacheID, {});
|
|
||||||
}
|
|
||||||
cache = $(document).data(cacheID);
|
|
||||||
|
|
||||||
//check for cached data
|
|
||||||
if (cache.loading === false && cache.sourceData) { //take source from cache
|
|
||||||
this.sourceData = cache.sourceData;
|
|
||||||
success.call(this);
|
|
||||||
return;
|
|
||||||
} else if (cache.loading === true) { //cache is loading, put callback in stack to be called later
|
|
||||||
cache.callbacks.push($.proxy(function () {
|
|
||||||
this.sourceData = cache.sourceData;
|
|
||||||
success.call(this);
|
|
||||||
}, this));
|
|
||||||
|
|
||||||
//also collecting error callbacks
|
|
||||||
cache.err_callbacks.push($.proxy(error, this));
|
|
||||||
return;
|
|
||||||
} else { //no cache yet, activate it
|
|
||||||
cache.loading = true;
|
|
||||||
cache.callbacks = [];
|
|
||||||
cache.err_callbacks = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
//loading sourceData from server
|
|
||||||
$.ajax({
|
|
||||||
url: this.options.source,
|
|
||||||
type: 'get',
|
|
||||||
cache: false,
|
|
||||||
data: {name: this.options.name},
|
|
||||||
dataType: 'json',
|
|
||||||
success: $.proxy(function (data) {
|
|
||||||
cache.loading = false;
|
|
||||||
// this.options.source = data;
|
|
||||||
this.sourceData = this.makeArray(data);
|
|
||||||
if($.isArray(this.sourceData)) {
|
|
||||||
this.doPrepend();
|
|
||||||
//store result in cache
|
|
||||||
cache.sourceData = this.sourceData;
|
|
||||||
success.call(this);
|
|
||||||
$.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields
|
|
||||||
} else {
|
|
||||||
error.call(this);
|
|
||||||
$.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
|
|
||||||
}
|
|
||||||
}, this),
|
|
||||||
error: $.proxy(function () {
|
|
||||||
cache.loading = false;
|
|
||||||
error.call(this);
|
|
||||||
$.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
|
|
||||||
}, this)
|
|
||||||
});
|
|
||||||
} else { //options as json/array
|
|
||||||
this.sourceData = this.makeArray(this.options.source);
|
|
||||||
if($.isArray(this.sourceData)) {
|
|
||||||
this.doPrepend();
|
|
||||||
success.call(this);
|
|
||||||
} else {
|
|
||||||
error.call(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
doPrepend: function () {
|
|
||||||
if(this.options.prepend === null || this.options.prepend === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$.isArray(this.prependData)) {
|
|
||||||
//try parse json in single quotes
|
|
||||||
this.options.prepend = $.fn.editableform.utils.tryParseJson(this.options.prepend, true);
|
|
||||||
if (typeof this.options.prepend === 'string') {
|
|
||||||
this.options.prepend = {'': this.options.prepend};
|
|
||||||
}
|
|
||||||
this.prependData = this.makeArray(this.options.prepend);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($.isArray(this.prependData) && $.isArray(this.sourceData)) {
|
|
||||||
this.sourceData = this.prependData.concat(this.sourceData);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
renderOptions: function() {
|
|
||||||
if(!$.isArray(this.sourceData)) {
|
if(!$.isArray(this.sourceData)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -187,83 +38,24 @@ $(function(){
|
|||||||
this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text));
|
this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
value2htmlFinal: function(value, element) {
|
||||||
* convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}]
|
var text = '', item = this.itemByVal(value);
|
||||||
*/
|
if(item) {
|
||||||
makeArray: function(data) {
|
text = item.text;
|
||||||
var count, obj, result = [], iterateEl;
|
|
||||||
if(!data || typeof data === 'string') {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
Select.superclass.constructor.superclass.value2html(text, element);
|
||||||
if($.isArray(data)) { //array
|
}
|
||||||
iterateEl = function (k, v) {
|
|
||||||
obj = {value: k, text: v};
|
|
||||||
if(count++ >= 2) {
|
|
||||||
return false;// exit each if object has more than one value
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for(var i = 0; i < data.length; i++) {
|
|
||||||
if(typeof data[i] === 'object') {
|
|
||||||
count = 0;
|
|
||||||
$.each(data[i], iterateEl);
|
|
||||||
if(count === 1) {
|
|
||||||
result.push(obj);
|
|
||||||
} else if(count > 1 && data[i].hasOwnProperty('value') && data[i].hasOwnProperty('text')) {
|
|
||||||
result.push(data[i]);
|
|
||||||
} else {
|
|
||||||
//data contains incorrect objects
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result.push({value: i, text: data[i]});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //object
|
|
||||||
$.each(data, function (k, v) {
|
|
||||||
result.push({value: k, text: v});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Select.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
Select.defaults = $.extend({}, $.fn.editableform.types.list.defaults, {
|
||||||
/**
|
/**
|
||||||
@property tpl
|
@property tpl
|
||||||
@default <select></select>
|
@default <select></select>
|
||||||
**/
|
**/
|
||||||
tpl:'<select></select>',
|
tpl:'<select></select>'
|
||||||
/**
|
|
||||||
Source data for dropdown list. If string - considered ajax url to load items. Otherwise should be an array.
|
|
||||||
Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br>
|
|
||||||
For compability it also supports format <code>{value1: text1, value2: text2 ...}</code> but it does not guarantee elements order.
|
|
||||||
|
|
||||||
@property source
|
|
||||||
@type string|array|object
|
|
||||||
@default null
|
|
||||||
**/
|
|
||||||
source:null,
|
|
||||||
/**
|
|
||||||
Data automatically prepended to the begining of dropdown list.
|
|
||||||
|
|
||||||
@property prepend
|
|
||||||
@type string|array|object
|
|
||||||
@default false
|
|
||||||
**/
|
|
||||||
prepend:false,
|
|
||||||
/**
|
|
||||||
Error message shown when list cannot be loaded (e.g. ajax error)
|
|
||||||
|
|
||||||
@property sourceError
|
|
||||||
@type string
|
|
||||||
@default Error when loading options
|
|
||||||
**/
|
|
||||||
sourceError: 'Error when loading options'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$.fn.editableform.types.select = Select;
|
$.fn.editableform.types.select = Select;
|
||||||
|
|
||||||
}(window.jQuery));
|
}(window.jQuery));
|
@ -3,6 +3,7 @@ Text input
|
|||||||
|
|
||||||
@class text
|
@class text
|
||||||
@extends abstract
|
@extends abstract
|
||||||
|
@final
|
||||||
@example
|
@example
|
||||||
<a href="#" id="username" data-type="text" data-pk="1">awesome</a>
|
<a href="#" id="username" data-type="text" data-pk="1">awesome</a>
|
||||||
<script>
|
<script>
|
||||||
@ -24,8 +25,8 @@ $(function(){
|
|||||||
$.extend(Text.prototype, {
|
$.extend(Text.prototype, {
|
||||||
activate: function() {
|
activate: function() {
|
||||||
if(this.$input.is(':visible')) {
|
if(this.$input.is(':visible')) {
|
||||||
$.fn.editableform.utils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
|
||||||
this.$input.focus();
|
this.$input.focus();
|
||||||
|
$.fn.editableform.utils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ Textarea input
|
|||||||
|
|
||||||
@class textarea
|
@class textarea
|
||||||
@extends abstract
|
@extends abstract
|
||||||
|
@final
|
||||||
@example
|
@example
|
||||||
<a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a>
|
<a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a>
|
||||||
<script>
|
<script>
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
<script src="unit/select.js"></script>
|
<script src="unit/select.js"></script>
|
||||||
<script src="unit/textarea.js"></script>
|
<script src="unit/textarea.js"></script>
|
||||||
<script src="unit/api.js"></script>
|
<script src="unit/api.js"></script>
|
||||||
|
<script src="unit/checklist.js"></script>
|
||||||
<script>
|
<script>
|
||||||
if(fc.f === 'bootstrap') {
|
if(fc.f === 'bootstrap') {
|
||||||
loadJs('unit/date.js');
|
loadJs('unit/date.js');
|
||||||
|
@ -31,9 +31,11 @@ function getAssets(f, c, src, libs) {
|
|||||||
containers+'editable-container.js',
|
containers+'editable-container.js',
|
||||||
element+'editable-element.js',
|
element+'editable-element.js',
|
||||||
inputs+'abstract.js',
|
inputs+'abstract.js',
|
||||||
|
inputs+'list.js',
|
||||||
inputs+'text.js',
|
inputs+'text.js',
|
||||||
inputs+'textarea.js',
|
inputs+'textarea.js',
|
||||||
inputs+'select.js'
|
inputs+'select.js',
|
||||||
|
inputs+'checklist.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
css = [
|
css = [
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
var timeout = 200;
|
var timeout = 200;
|
||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
$.mockjaxSettings.responseTime = 50;
|
$.mockjaxSettings.responseTime = 50;
|
||||||
|
|
||||||
$.mockjax({
|
$.mockjax({
|
||||||
url: 'post.php',
|
url: 'post.php',
|
||||||
@ -23,6 +23,38 @@ $(function () {
|
|||||||
this.responseText = settings;
|
this.responseText = settings;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
window.groups = {
|
||||||
|
0: 'Guest',
|
||||||
|
1: 'Service',
|
||||||
|
2: 'Customer',
|
||||||
|
3: 'Operator',
|
||||||
|
4: 'Support',
|
||||||
|
5: 'Admin',
|
||||||
|
6: '',
|
||||||
|
'': 'Nothing'
|
||||||
|
};
|
||||||
|
|
||||||
|
//groups as array
|
||||||
|
window.groupsArr = [];
|
||||||
|
for(var i in groups) {
|
||||||
|
groupsArr.push({value: i, text: groups[i]});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.size = groupsArr.length;
|
||||||
|
|
||||||
|
$.mockjax({
|
||||||
|
url: 'groups.php',
|
||||||
|
responseText: groups
|
||||||
|
});
|
||||||
|
|
||||||
|
$.mockjax({
|
||||||
|
url: 'groups-error.php',
|
||||||
|
status: 500,
|
||||||
|
responseText: 'Internal Server Error'
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// usefull functions
|
// usefull functions
|
||||||
|
@ -3,7 +3,6 @@ $(function () {
|
|||||||
module("api", {
|
module("api", {
|
||||||
setup: function(){
|
setup: function(){
|
||||||
fx = $('#async-fixture');
|
fx = $('#async-fixture');
|
||||||
delete $.fn.editable.defaults.name;
|
|
||||||
$.support.transition = false;
|
$.support.transition = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
93
test/unit/checklist.js
Normal file
93
test/unit/checklist.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
$(function () {
|
||||||
|
|
||||||
|
module("checklist", {
|
||||||
|
setup: function(){
|
||||||
|
sfx = $('#qunit-fixture'),
|
||||||
|
fx = $('#async-fixture');
|
||||||
|
$.support.transition = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("should load options, set correct value and save new value", function () {
|
||||||
|
var sep = '-',
|
||||||
|
newValue,
|
||||||
|
e = $('<a href="#" data-type="checklist" data-url="post.php"></a>').appendTo(fx).editable({
|
||||||
|
pk: 1,
|
||||||
|
source: groupsArr,
|
||||||
|
value: [2, 3],
|
||||||
|
viewseparator: sep
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(e.text(), groups[2]+sep+groups[3], 'autotext ok');
|
||||||
|
|
||||||
|
e.click();
|
||||||
|
var p = tip(e);
|
||||||
|
equal(p.find('input[type="checkbox"]').length, groupsArr.length, 'checkboxes rendered');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').length, 2, 'checked count ok');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').eq(0).val(), 2, '1st checked');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').eq(1).val(), 3, '2nd checked');
|
||||||
|
|
||||||
|
//set new value
|
||||||
|
p.find('input[type="checkbox"]:checked').eq(0).click();
|
||||||
|
p.find('input[type="checkbox"]').first().click();
|
||||||
|
newValue = p.find('input[type="checkbox"]').first().val();
|
||||||
|
|
||||||
|
//submit
|
||||||
|
p.find('form').submit();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
ok(!p.is(':visible'), 'popup closed');
|
||||||
|
|
||||||
|
equal(e.data('editable').value.join(''), [newValue, 3].join(''), 'new value ok')
|
||||||
|
equal(e.text(), groups[newValue]+sep+groups[3], 'new text ok');
|
||||||
|
|
||||||
|
// open container again to see what checked
|
||||||
|
e.click()
|
||||||
|
p = tip(e);
|
||||||
|
|
||||||
|
equal(p.find('input[type="checkbox"]').length, groupsArr.length, 'checkboxes rendered');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').length, 2, 'checked count ok');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').eq(0).val(), newValue, '1st checked');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').eq(1).val(), 3, '2nd checked');
|
||||||
|
|
||||||
|
e.remove();
|
||||||
|
start();
|
||||||
|
}, timeout);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("limit option", function () {
|
||||||
|
var e = $('<a href="#" data-type="checklist" data-value="2,3" data-url="post.php"></a>').appendTo(fx).editable({
|
||||||
|
pk: 1,
|
||||||
|
source: groupsArr,
|
||||||
|
limit: 1,
|
||||||
|
limitText: '{checked} of {count}'
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(e.text(), '2 of '+groupsArr.length, 'autotext ok');
|
||||||
|
|
||||||
|
e.click();
|
||||||
|
var p = tip(e);
|
||||||
|
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').length, 2, 'checked count ok');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').eq(0).val(), 2, '1st checked');
|
||||||
|
equal(p.find('input[type="checkbox"]:checked').eq(1).val(), 3, '2nd checked');
|
||||||
|
|
||||||
|
//set new value
|
||||||
|
p.find('input[type="checkbox"]').first().click();
|
||||||
|
newValue = p.find('input[type="checkbox"]').first().val();
|
||||||
|
|
||||||
|
//submit
|
||||||
|
p.find('form').submit();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
ok(!p.is(':visible'), 'popup closed');
|
||||||
|
|
||||||
|
equal(e.text(), '3 of '+groupsArr.length, 'autotext ok');
|
||||||
|
|
||||||
|
e.remove();
|
||||||
|
start();
|
||||||
|
}, timeout);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
@ -122,7 +122,17 @@
|
|||||||
ok(!p.is(':visible'), 'popover closed');
|
ok(!p.is(':visible'), 'popover closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should not wrap buttons when parent has position:absolute", function () {
|
||||||
|
var d = $('<div style="position: absolute; top: 200px">').appendTo(fx),
|
||||||
|
e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(d).editable();
|
||||||
|
|
||||||
|
e.click();
|
||||||
|
var p = tip(e);
|
||||||
|
ok(p.find('button').offset().top < p.find('.editable-input').offset().top + p.find('.editable-input').height(), 'buttons top ok');
|
||||||
|
ok(p.find('button').offset().left > p.find('.editable-input').offset().left + p.find('.editable-input').width(), 'buttons left ok');
|
||||||
|
|
||||||
|
d.remove();
|
||||||
|
});
|
||||||
|
|
||||||
//unfortunatly, testing this feature does not always work in browsers. Tested manually.
|
//unfortunatly, testing this feature does not always work in browsers. Tested manually.
|
||||||
/*
|
/*
|
||||||
|
@ -5,7 +5,6 @@ $(function () {
|
|||||||
module("date", {
|
module("date", {
|
||||||
setup: function(){
|
setup: function(){
|
||||||
fx = $('#async-fixture');
|
fx = $('#async-fixture');
|
||||||
$.fn.editable.defaults.name = 'name1';
|
|
||||||
dpg = $.fn.datepicker.DPGlobal;
|
dpg = $.fn.datepicker.DPGlobal;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -14,7 +13,7 @@ $(function () {
|
|||||||
return dpg.formatDate(date, dpg.parseFormat(format), 'en');
|
return dpg.formatDate(date, dpg.parseFormat(format), 'en');
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncTest("popover should contain datepicker with value and save new entered date", function () {
|
asyncTest("container should contain datepicker with value and save new entered date", function () {
|
||||||
expect(9);
|
expect(9);
|
||||||
|
|
||||||
$.fn.editableform.types.date.defaults.datepicker.weekStart = 1;
|
$.fn.editableform.types.date.defaults.datepicker.weekStart = 1;
|
||||||
@ -130,5 +129,47 @@ $(function () {
|
|||||||
p.find('button[type=button]').click();
|
p.find('button[type=button]').click();
|
||||||
ok(!p.is(':visible'), 'popover closed');
|
ok(!p.is(':visible'), 'popover closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
asyncTest("clear button", function () {
|
||||||
|
var d = '15.05.1984',
|
||||||
|
e = $('<a href="#" data-type="date" data-pk="1" data-url="post-date-clear.php">'+d+'</a>').appendTo(fx).editable({
|
||||||
|
format: f,
|
||||||
|
clear: 'abc'
|
||||||
|
});
|
||||||
|
|
||||||
|
$.mockjax({
|
||||||
|
url: 'post-date-clear.php',
|
||||||
|
response: function(settings) {
|
||||||
|
equal(settings.data.value, '', 'submitted value correct');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(frmt(e.data('editable').value, 'dd.mm.yyyy'), d, 'value correct');
|
||||||
|
|
||||||
|
e.click();
|
||||||
|
var p = tip(e);
|
||||||
|
ok(p.find('.datepicker').is(':visible'), 'datepicker exists');
|
||||||
|
|
||||||
|
equal(frmt(e.data('editable').value, f), d, 'day set correct');
|
||||||
|
equal(p.find('td.day.active').text(), 15, 'day shown correct');
|
||||||
|
|
||||||
|
var clear = p.find('.editable-clear a');
|
||||||
|
equal(clear.text(), 'abc', 'clear link shown');
|
||||||
|
|
||||||
|
//click clear
|
||||||
|
clear.click();
|
||||||
|
ok(!p.find('td.day.active').length, 'no active day');
|
||||||
|
|
||||||
|
p.find('form').submit();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
ok(!p.is(':visible'), 'popover closed');
|
||||||
|
equal(e.data('editable').value, null, 'null saved to value');
|
||||||
|
equal(e.text(), e.data('editable').options.emptytext, 'empty text shown');
|
||||||
|
e.remove();
|
||||||
|
start();
|
||||||
|
}, timeout);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -5,7 +5,6 @@ $(function () {
|
|||||||
module("dateui", {
|
module("dateui", {
|
||||||
setup: function(){
|
setup: function(){
|
||||||
fx = $('#async-fixture');
|
fx = $('#async-fixture');
|
||||||
$.fn.editable.defaults.name = 'name1';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,7 +59,7 @@ $(function () {
|
|||||||
|
|
||||||
test("viewformat, init by value", function () {
|
test("viewformat, init by value", function () {
|
||||||
var dview = '15/05/1984',
|
var dview = '15/05/1984',
|
||||||
d = '1984-05-15',
|
d = '1984-05-15',
|
||||||
e = $('<a href="#" data-type="date" data-pk="1" data-weekstart="1" data-value="'+d+'"></a>').appendTo('#qunit-fixture').editable({
|
e = $('<a href="#" data-type="date" data-pk="1" data-weekstart="1" data-value="'+d+'"></a>').appendTo('#qunit-fixture').editable({
|
||||||
format: 'yyyy-mm-dd',
|
format: 'yyyy-mm-dd',
|
||||||
viewformat: 'dd/mm/yyyy'
|
viewformat: 'dd/mm/yyyy'
|
||||||
@ -80,6 +79,47 @@ $(function () {
|
|||||||
|
|
||||||
p.find('button[type=button]').click();
|
p.find('button[type=button]').click();
|
||||||
ok(!p.is(':visible'), 'popover closed');
|
ok(!p.is(':visible'), 'popover closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
asyncTest("clear button", function () {
|
||||||
|
var d = '15.05.1984',
|
||||||
|
f = 'dd.mm.yyyy',
|
||||||
|
e = $('<a href="#" data-type="date" data-pk="1" data-url="post-date-clear.php">'+d+'</a>').appendTo(fx).editable({
|
||||||
|
format: f,
|
||||||
|
clear: 'abc'
|
||||||
|
});
|
||||||
|
|
||||||
|
$.mockjax({
|
||||||
|
url: 'post-date-clear.php',
|
||||||
|
response: function(settings) {
|
||||||
|
equal(settings.data.value, '', 'submitted value correct');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(frmt(e.data('editable').value, 'dd.mm.yyyy'), d, 'value correct');
|
||||||
|
|
||||||
|
e.click();
|
||||||
|
var p = tip(e);
|
||||||
|
ok(p.find('.ui-datepicker').is(':visible'), 'datepicker exists');
|
||||||
|
|
||||||
|
equal(frmt(e.data('editable').value, f), d, 'day set correct');
|
||||||
|
equal(p.find('a.ui-state-active').text(), 15, 'day shown correct');
|
||||||
|
|
||||||
|
var clear = p.find('.editable-clear a');
|
||||||
|
equal(clear.text(), 'abc', 'clear link shown');
|
||||||
|
|
||||||
|
//click clear
|
||||||
|
clear.click();
|
||||||
|
p.find('form').submit();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
ok(!p.is(':visible'), 'popover closed');
|
||||||
|
equal(e.data('editable').value, null, 'null saved to value');
|
||||||
|
equal(e.text(), e.data('editable').options.emptytext, 'empty text shown');
|
||||||
|
e.remove();
|
||||||
|
start();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -1,42 +1,9 @@
|
|||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
window.groups = {
|
|
||||||
0: 'Guest',
|
|
||||||
1: 'Service',
|
|
||||||
2: 'Customer',
|
|
||||||
3: 'Operator',
|
|
||||||
4: 'Support',
|
|
||||||
5: 'Admin',
|
|
||||||
6: '',
|
|
||||||
'': 'Nothing'
|
|
||||||
};
|
|
||||||
|
|
||||||
//groups as array
|
|
||||||
window.groupsArr = [];
|
|
||||||
for(var i in groups) {
|
|
||||||
groupsArr.push({value: i, text: groups[i]});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.size = groupsArr.length;
|
|
||||||
|
|
||||||
$.mockjax({
|
|
||||||
url: 'groups.php',
|
|
||||||
responseText: groups
|
|
||||||
});
|
|
||||||
|
|
||||||
$.mockjax({
|
|
||||||
url: 'groups-error.php',
|
|
||||||
status: 500,
|
|
||||||
responseText: 'Internal Server Error'
|
|
||||||
});
|
|
||||||
|
|
||||||
module("select", {
|
module("select", {
|
||||||
setup: function(){
|
setup: function(){
|
||||||
sfx = $('#qunit-fixture'),
|
sfx = $('#qunit-fixture'),
|
||||||
fx = $('#async-fixture');
|
fx = $('#async-fixture');
|
||||||
$.fn.editable.defaults.name = 'name1';
|
|
||||||
//clear cache
|
|
||||||
$(document).removeData('groups.php-'+$.fn.editable.defaults.name);
|
|
||||||
$.support.transition = false;
|
$.support.transition = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -111,7 +78,7 @@ $(function () {
|
|||||||
|
|
||||||
test("load options from simple array", function () {
|
test("load options from simple array", function () {
|
||||||
var arr = ['q', 'w', 'x'],
|
var arr = ['q', 'w', 'x'],
|
||||||
e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo('#qunit-fixture').editable({
|
e = $('<a href="#" data-type="select" data-value="x" data-url="post.php">customer</a>').appendTo('#qunit-fixture').editable({
|
||||||
pk: 1,
|
pk: 1,
|
||||||
autotext: true,
|
autotext: true,
|
||||||
source: arr
|
source: arr
|
||||||
@ -122,7 +89,7 @@ $(function () {
|
|||||||
ok(p.is(':visible'), 'popover visible')
|
ok(p.is(':visible'), 'popover visible')
|
||||||
ok(p.find('select').length, 'select exists')
|
ok(p.find('select').length, 'select exists')
|
||||||
equal(p.find('select').find('option').length, arr.length, 'options loaded')
|
equal(p.find('select').find('option').length, arr.length, 'options loaded')
|
||||||
equal(p.find('select').val(), 2, 'selected value correct')
|
equal(p.find('select').val(), 'x', 'selected value correct')
|
||||||
p.find('button[type=button]').click();
|
p.find('button[type=button]').click();
|
||||||
ok(!p.is(':visible'), 'popover was removed');
|
ok(!p.is(':visible'), 'popover was removed');
|
||||||
})
|
})
|
||||||
@ -197,7 +164,7 @@ $(function () {
|
|||||||
}, timeout);
|
}, timeout);
|
||||||
})
|
})
|
||||||
|
|
||||||
asyncTest("popover should save new selected value", function () {
|
asyncTest("should save new selected value", function () {
|
||||||
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo(fx).editable({
|
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo(fx).editable({
|
||||||
pk: 1,
|
pk: 1,
|
||||||
source: groups
|
source: groups
|
||||||
@ -222,8 +189,8 @@ $(function () {
|
|||||||
e.remove();
|
e.remove();
|
||||||
start();
|
start();
|
||||||
}, timeout);
|
}, timeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("if new text is empty --> show emptytext on save", function () {
|
asyncTest("if new text is empty --> show emptytext on save", function () {
|
||||||
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo(fx).editable({
|
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').appendTo(fx).editable({
|
||||||
pk: 1,
|
pk: 1,
|
||||||
@ -278,8 +245,11 @@ $(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("cache request for same selects", function () {
|
asyncTest("cache request for same selects", function () {
|
||||||
var e = $('<a href="#" data-type="select" data-pk="1" data-value="2" data-url="post.php" data-source="groups-cache.php">customer</a>').appendTo(fx).editable(),
|
//clear cache
|
||||||
e1 = $('<a href="#" data-type="select" data-pk="1" data-value="2" data-url="post.php" data-source="groups-cache.php">customer</a>').appendTo(fx).editable(),
|
$(document).removeData('groups.php-name1');
|
||||||
|
|
||||||
|
var e = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="2" data-url="post.php" data-source="groups-cache.php">customer</a>').appendTo(fx).editable(),
|
||||||
|
e1 = $('<a href="#" data-type="select" data-pk="1" id="name1" data-value="2" data-url="post.php" data-source="groups-cache.php">customer</a>').appendTo(fx).editable(),
|
||||||
req = 0;
|
req = 0;
|
||||||
|
|
||||||
$.mockjax({
|
$.mockjax({
|
||||||
@ -323,6 +293,10 @@ $(function () {
|
|||||||
|
|
||||||
asyncTest("cache simultaneous requests", function () {
|
asyncTest("cache simultaneous requests", function () {
|
||||||
expect(4);
|
expect(4);
|
||||||
|
|
||||||
|
//clear cache
|
||||||
|
$(document).removeData('groups.php-name1');
|
||||||
|
|
||||||
var req = 0;
|
var req = 0;
|
||||||
$.mockjax({
|
$.mockjax({
|
||||||
url: 'groups-cache-sim.php',
|
url: 'groups-cache-sim.php',
|
||||||
@ -333,9 +307,9 @@ $(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var e = $('<a href="#" data-type="select" data-pk="1" data-value="1" data-url="post.php" data-source="groups-cache-sim.php"></a>').appendTo(fx).editable(),
|
var e = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="1" data-url="post.php" data-source="groups-cache-sim.php"></a>').appendTo(fx).editable(),
|
||||||
e1 = $('<a href="#" data-type="select" data-pk="1" data-value="2" data-url="post.php" data-source="groups-cache-sim.php"></a>').appendTo(fx).editable(),
|
e1 = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="2" data-url="post.php" data-source="groups-cache-sim.php"></a>').appendTo(fx).editable(),
|
||||||
e2 = $('<a href="#" data-type="select" data-pk="1" data-value="3" data-url="post.php" data-source="groups-cache-sim.php"></a>').appendTo(fx).editable();
|
e2 = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="3" data-url="post.php" data-source="groups-cache-sim.php"></a>').appendTo(fx).editable();
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
|
||||||
@ -354,6 +328,10 @@ $(function () {
|
|||||||
|
|
||||||
asyncTest("cache simultaneous requests (loading error)", function () {
|
asyncTest("cache simultaneous requests (loading error)", function () {
|
||||||
expect(4);
|
expect(4);
|
||||||
|
|
||||||
|
//clear cache
|
||||||
|
$(document).removeData('groups.php-name1');
|
||||||
|
|
||||||
var req = 0;
|
var req = 0;
|
||||||
$.mockjax({
|
$.mockjax({
|
||||||
url: 'groups-cache-sim-err.php',
|
url: 'groups-cache-sim-err.php',
|
||||||
@ -364,9 +342,9 @@ $(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var e = $('<a href="#" data-type="select" data-pk="1" data-value="1" data-autotext="always" data-url="post.php" data-source="groups-cache-sim-err.php">35</a>').appendTo(fx).editable(),
|
var e = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="1" data-autotext="always" data-url="post.php" data-source="groups-cache-sim-err.php">35</a>').appendTo(fx).editable(),
|
||||||
e1 = $('<a href="#" data-type="select" data-pk="1" data-value="2" data-autotext="always" data-url="post.php" data-source="groups-cache-sim-err.php">35</a>').appendTo(fx).editable(),
|
e1 = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="2" data-autotext="always" data-url="post.php" data-source="groups-cache-sim-err.php">35</a>').appendTo(fx).editable(),
|
||||||
e2 = $('<a href="#" data-type="select" data-pk="1" data-value="3" data-autotext="always" data-url="post.php" data-source="groups-cache-sim-err.php">6456</a>').appendTo(fx).editable(),
|
e2 = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="3" data-autotext="always" data-url="post.php" data-source="groups-cache-sim-err.php">6456</a>').appendTo(fx).editable(),
|
||||||
errText = $.fn.editableform.types.select.defaults.sourceError;
|
errText = $.fn.editableform.types.select.defaults.sourceError;
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
@ -3,7 +3,6 @@ $(function () {
|
|||||||
module("text", {
|
module("text", {
|
||||||
setup: function() {
|
setup: function() {
|
||||||
fx = $('#async-fixture');
|
fx = $('#async-fixture');
|
||||||
$.fn.editable.defaults.name = 'name1';
|
|
||||||
$.support.transition = false;
|
$.support.transition = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,8 +5,8 @@ $(function () {
|
|||||||
|
|
||||||
module("textarea", {
|
module("textarea", {
|
||||||
setup: function(){
|
setup: function(){
|
||||||
fx = $('#async-fixture'),
|
fx = $('#async-fixture');
|
||||||
$.fn.editable.defaults.name = 'name1';
|
$.support.transition = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user