Merge branch 'release-1.2.0'
This commit is contained in:
commit
e969ccf436
CHANGELOG.txtREADME.mdgrunt.jspackage.json
src
containers
editable-form
element
inputs-ext/address
inputs
test
@ -2,6 +2,34 @@ X-editable changelog
|
||||
=============================
|
||||
|
||||
|
||||
Version 1.2.0 Dec 6, 2012
|
||||
----------------------------
|
||||
[enh #36] 'submit' method: added 'ajaxOptions' property to modify ajax request (vitalets)
|
||||
[enh] inputs now internally use 'value2submit' method instead of previous 'value2str' (vitalets)
|
||||
[enh] editableContainer removed from docs (vitalets)
|
||||
[enh] editableContainer: removed 'autohide' option and 'cancel' event. Use 'hidden' event instead (vitalets)
|
||||
[enh] 'hidden' event: added param 'reason' that points to reason caused hiding (vitalets)
|
||||
[enh] 'select' submit by enter (vitalets)
|
||||
[bug #37] fix incorrectly shown datepicker in jquery 1.7.1 + webkit (vitalets)
|
||||
[enh] added url param 'jquery' to run tests in different versions of jquery, e.g. '&jquery=1.7.2' (vitalets)
|
||||
[enh] 'enablefocus' option removed. More efficient to use 'save/hide' events to set focus to any element (vitalets)
|
||||
[enh] 'init' event was added due to removal of render event (vitalets)
|
||||
[enh] 'render' event was removed, use 'display' callback instead (vitalets)
|
||||
[enh] 'checklist' submit value as array, not comma separated string (vitalets)
|
||||
[enh] 'checklist' was refactored: options 'viewseparator', 'limit', 'limitText' are supressed by 'display' callback (vitalets)
|
||||
[enh] new option: 'display' callback. Makes far more flexible rendering value into element's text. (vitalets)
|
||||
[bug] fix typos (atrophic)
|
||||
[enh] all callbacks scope changed to element (vitalets)
|
||||
[enh] new option: 'savenochange' to save or cancel value when it was not changed in form (vitalets)
|
||||
[enh] composite pk can be defined as JSON in data-pk attribute (vitalets)
|
||||
[enh #30] new option 'sourceCache' true|false to disable cache for select (vitalets)
|
||||
[bug #34] inputclass span* broken with fluid bootstrap layout. Classes changed to 'input-*'. (vitalets)
|
||||
[enh] utils now added to $.fn.editableutils instead of $.fn.editableform.utils (vitalets)
|
||||
[enh] input types now added to $.fn.editabletypes instead of $.fn.editableform.types (vitalets)
|
||||
[enh] playground and tests now use requirejs (vitalets)
|
||||
[bug #27] 'today' button toggle bug in bootstrap-datepicker (vitalets)
|
||||
|
||||
|
||||
Version 1.1.1 Nov 30, 2012
|
||||
----------------------------
|
||||
[enh] 'showbuttons' option to hide buttons in form (vitalets)
|
||||
@ -29,7 +57,7 @@ Version 1.0.1 Nov 22, 2012
|
||||
[enh] contribution guide in README.md (vitalets)
|
||||
[enh #7] 'shown', 'hidden' events added (vitalets)
|
||||
[enh #1] params can be a function to calculate it dynamically (vitalets)
|
||||
[enh #6] do not preventDetault() in click when toggle='manual'. This allows to have clickable links (vitalets)
|
||||
[enh #6] do not preventDefault() in click when toggle='manual'. This allows to have clickable links (vitalets)
|
||||
[bug #3] should not mark element with unsave css if url is user's function (vitalets)
|
||||
|
||||
|
||||
@ -48,13 +76,13 @@ Here list of differences to help you to upgrade your application:
|
||||
[change] 'toggle' option value can be only click|manual (not toggling element id). In case of 'manual' you should write handler calling 'show' method.
|
||||
[change] 'validate' option cannot be defined as object anymore.
|
||||
[change] events 'init', 'update', 'shown', 'hidden' removed. Events 'save', 'cancel' added. Event 'render' remains.
|
||||
[change] input's optiom 'template' renamed to 'tpl' (to exclude conflict with container's template).
|
||||
[change] value can be stored internaly as object (previously was always string). Usefull for date inupt.
|
||||
[change] input's option 'template' renamed to 'tpl' (to exclude conflict with container's template).
|
||||
[change] value can be stored internally as object (previously was always string). Useful for date input.
|
||||
[change] 'error' callback option is removed. 'success' callback remained.
|
||||
[enh] 'source' option in select can be array of structure [{value: 1, text: 'abc'}, {...}]. This allows to keep ordering of items in dropdown list. Previous format is supported for compability.
|
||||
[enh] 'source' option in select can be array of structure [{value: 1, text: 'abc'}, {...}]. This allows to keep ordering of items in dropdown list. Previous format is supported for compatibility.
|
||||
[enh] api method 'setValue' to set manually value of editable.
|
||||
[change] locales directory is excluded from bootstrap-datepicker input. If you need localization you should jus download corresponding file from github.
|
||||
[change] date and dateui specific options can be set only via 'datepicker' option in first level of config (previously it was possible to set some options directly in config, e.g. weekStart).
|
||||
[change] if 'url' option defined as function - it is used as submit method instead of ajax (previously it was dynamically return url string and ajax occured anyway)
|
||||
[change] if 'url' option defined as function - it is used as submit method instead of ajax (previously it was dynamically return url string and ajax occurred anyway)
|
||||
|
||||
Also all known bugs of bootstrap-editable were closed.
|
||||
Also all known bugs of bootstrap-editable were closed.
|
||||
|
@ -7,7 +7,7 @@ It is a new life of [bootstrap-editable plugin](http://github.com/vitalets/boots
|
||||
See **http://vitalets.github.com/x-editable**
|
||||
|
||||
## Reporting issues
|
||||
When creating issues please provide jsFiddle example. You can just fork [this fiddle](http://jsfiddle.net/xBB5x/5/) as starting point.
|
||||
When creating issues please provide jsFiddle example. You can easily fork one of templates: [bootstrap](http://jsfiddle.net/xBB5x/25/), [jqueryui](http://jsfiddle.net/xBB5x/24/), [plain](http://jsfiddle.net/xBB5x/23/).
|
||||
Your feedback is very appreciated!
|
||||
|
||||
## Contribution
|
||||
@ -19,7 +19,7 @@ A few steps how to start contributing:
|
||||
**x-editable**
|
||||
| -- **lib** (repo related to <code>dev</code> and <code>master</code> branches)
|
||||
| -- **gh-pages** (repo related to <code>gh-pages</code> branch for docs & demo)
|
||||
| -- **playground** (simple node-server and html page for testing, [playground.zip](https://github.com/downloads/vitalets/x-editable/playground.zip))
|
||||
| -- **playground** (simple node-server and html page for testing, [playground_1.2.zip](https://github.com/downloads/vitalets/x-editable/playground_1.2.zip), **updated in 1.2.0!**)
|
||||
|
||||
To make it easy follow this script ( _assuming you have [nodejs](http://nodejs.org) installed_ ).
|
||||
Please replace <code><your-github-name></code> with your name:
|
||||
@ -43,7 +43,7 @@ npm install
|
||||
cd ..
|
||||
|
||||
#playground
|
||||
#download playground.zip from https://github.com/downloads/vitalets/x-editable/playground.zip
|
||||
#download playground.zip from https://github.com/downloads/vitalets/x-editable/playground_1.2.zip
|
||||
unzip playground.zip
|
||||
cd playground
|
||||
npm install
|
||||
|
46
grunt.js
46
grunt.js
@ -100,10 +100,19 @@ module.exports = function(grunt) {
|
||||
|
||||
//module for testing
|
||||
var module = '';
|
||||
//module = '&module=textarea';
|
||||
// module = '&module=textarea';
|
||||
//module = '&module=select';
|
||||
//module = '&module=text';
|
||||
|
||||
var qunit_testover = [];
|
||||
['bootstrap', 'jqueryui', 'plain'].forEach(function(f){
|
||||
['popup', 'inline'].forEach(function(c){
|
||||
['1.6.4', '1.7.1', '1.7.2', '1.8.2', '1.8.3'].forEach(function(jqver) {
|
||||
qunit_testover.push('http://localhost:8000/test/index.html?f='+f+'&c='+c+'&jquery='+jqver+module);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
//get js and css for different builds
|
||||
var files = getFiles();
|
||||
|
||||
@ -133,8 +142,9 @@ module.exports = function(grunt) {
|
||||
plain: [
|
||||
'http://localhost:8000/test/index.html?f=plain&c=popup'+module,
|
||||
'http://localhost:8000/test/index.html?f=plain&c=inline'+module
|
||||
]
|
||||
// files: ['test/index.html']
|
||||
],
|
||||
//test all builds under several versions of jquery
|
||||
testover: qunit_testover
|
||||
},
|
||||
server: {
|
||||
port: 8000,
|
||||
@ -208,38 +218,14 @@ module.exports = function(grunt) {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//compress does not work properly for MAC OS (see https://github.com/vitalets/bootstrap-editable/issues/19)
|
||||
//zip will be created manually
|
||||
/*
|
||||
compress: {
|
||||
zip: {
|
||||
options: {
|
||||
mode: "zip",
|
||||
//TODO: unfortunatly here <%= dist_source %> and <config:dist_source> does not work
|
||||
basePath: "dist"
|
||||
},
|
||||
files: {
|
||||
"<%= dist %>/bootstrap-editable-v<%= pkg.version %>.zip": ["<%= dist_source %>/ **", "<%= dist %>/libs/ **"]
|
||||
}
|
||||
},
|
||||
tgz: {
|
||||
options: {
|
||||
mode: "tgz",
|
||||
basePath: "dist"
|
||||
},
|
||||
files: {
|
||||
"<%= dist %>/bootstrap-editable-v<%= pkg.version %>.tar.gz": ["<%= dist_source %>/ **", "<%= dist %>/libs/ **"]
|
||||
}
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
uglify: {}
|
||||
});
|
||||
|
||||
//test task
|
||||
grunt.registerTask('test', 'lint server qunit:bootstrap');
|
||||
grunt.registerTask('testall', 'lint server qunit');
|
||||
grunt.registerTask('testall', 'lint server qunit:bootstrap qunit:jqueryui qunit:plain');
|
||||
grunt.registerTask('testover', 'lint server qunit:testover');
|
||||
|
||||
// Default task.
|
||||
// grunt.registerTask('default', 'lint qunit');
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "X-editable",
|
||||
"title": "X-editable",
|
||||
"description": "In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery",
|
||||
"version": "1.1.1",
|
||||
"version": "1.2.0",
|
||||
"homepage": "http://github.com/vitalets/x-editable",
|
||||
"author": {
|
||||
"name": "Vitaliy Potapov",
|
||||
|
@ -1,5 +1,5 @@
|
||||
.editable-container {
|
||||
max-width: none; /* without this rule poshytip does not stretch */
|
||||
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
|
||||
}
|
||||
|
||||
.editable-container.popover {
|
||||
@ -10,4 +10,8 @@
|
||||
.editable-container.editable-inline {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.editable-container.ui-widget {
|
||||
font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
|
||||
}
|
@ -20,7 +20,7 @@ Applied as jQuery method.
|
||||
init: function(element, options) {
|
||||
this.$element = $(element);
|
||||
//todo: what is in priority: data or js?
|
||||
this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableform.utils.getConfigData(this.$element), options);
|
||||
this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableutils.getConfigData(this.$element), options);
|
||||
this.splitOptions();
|
||||
this.initContainer();
|
||||
|
||||
@ -75,12 +75,15 @@ Applied as jQuery method.
|
||||
},
|
||||
|
||||
initForm: function() {
|
||||
this.formOptions.scope = this.$element[0]; //set scope of form callbacks to element
|
||||
this.$form = $('<div>')
|
||||
.editableform(this.formOptions)
|
||||
.on({
|
||||
save: $.proxy(this.save, this),
|
||||
cancel: $.proxy(this.cancel, this),
|
||||
show: $.proxy(this.setPosition, this), //re-position container every time form is shown (after loading state)
|
||||
cancel: $.proxy(function(){
|
||||
this.hide('cancel');
|
||||
}, this),
|
||||
show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state)
|
||||
rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown
|
||||
rendered: $.proxy(function(){
|
||||
/**
|
||||
@ -119,7 +122,7 @@ Applied as jQuery method.
|
||||
/**
|
||||
Shows container with form
|
||||
@method show()
|
||||
@param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
|
||||
@param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
|
||||
**/
|
||||
show: function (closeAll) {
|
||||
this.$element.addClass('editable-open');
|
||||
@ -143,8 +146,9 @@ Applied as jQuery method.
|
||||
/**
|
||||
Hides container with form
|
||||
@method hide()
|
||||
@param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|undefined (=manual)</code>
|
||||
**/
|
||||
hide: function() {
|
||||
hide: function(reason) {
|
||||
if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) {
|
||||
return;
|
||||
}
|
||||
@ -154,9 +158,17 @@ Applied as jQuery method.
|
||||
Fired when container was hidden. It occurs on both save or cancel.
|
||||
|
||||
@event hidden
|
||||
@param {Object} event event object
|
||||
@param {object} event event object
|
||||
@param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|undefined (=manual)</code>
|
||||
@example
|
||||
$('#username').on('hidden', function(e, reason) {
|
||||
if(reason === 'save' || reason === 'cancel') {
|
||||
//auto-open next editable
|
||||
$(this).closest('tr').next().find('.editable').editable('show');
|
||||
}
|
||||
});
|
||||
**/
|
||||
this.$element.triggerHandler('hidden');
|
||||
this.$element.triggerHandler('hidden', reason);
|
||||
},
|
||||
|
||||
/* internal hide method. To be overwritten in child classes */
|
||||
@ -167,7 +179,7 @@ Applied as jQuery method.
|
||||
/**
|
||||
Toggles container visibility (show / hide)
|
||||
@method toggle()
|
||||
@param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
|
||||
@param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
|
||||
**/
|
||||
toggle: function(closeAll) {
|
||||
if(this.tip && this.tip().is(':visible')) {
|
||||
@ -185,23 +197,8 @@ Applied as jQuery method.
|
||||
//tbd in child class
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
if(this.options.autohide) {
|
||||
this.hide();
|
||||
}
|
||||
/**
|
||||
Fired when form was cancelled by user
|
||||
|
||||
@event cancel
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$element.triggerHandler('cancel');
|
||||
},
|
||||
|
||||
save: function(e, params) {
|
||||
if(this.options.autohide) {
|
||||
this.hide();
|
||||
}
|
||||
this.hide('save');
|
||||
/**
|
||||
Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance
|
||||
|
||||
@ -262,8 +259,8 @@ Applied as jQuery method.
|
||||
*/
|
||||
closeOthers: function(element) {
|
||||
$('.editable-open').each(function(i, el){
|
||||
//do nothing with passed element
|
||||
if(el === element) {
|
||||
//do nothing with passed element and it's children
|
||||
if(el === element || $(el).find(element).length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -276,7 +273,7 @@ Applied as jQuery method.
|
||||
}
|
||||
|
||||
if(ec.options.onblur === 'cancel') {
|
||||
$el.data('editableContainer').hide();
|
||||
$el.data('editableContainer').hide('onblur');
|
||||
} else if(ec.options.onblur === 'submit') {
|
||||
$el.data('editableContainer').tip().find('form').submit();
|
||||
}
|
||||
@ -350,7 +347,7 @@ Applied as jQuery method.
|
||||
**/
|
||||
placement: 'top',
|
||||
/**
|
||||
Wether to hide container on save/cancel.
|
||||
Whether to hide container on save/cancel.
|
||||
|
||||
@property autohide
|
||||
@type boolean
|
||||
@ -365,6 +362,7 @@ Applied as jQuery method.
|
||||
@property onblur
|
||||
@type string
|
||||
@default 'cancel'
|
||||
@since 1.1.1
|
||||
**/
|
||||
onblur: 'cancel'
|
||||
};
|
||||
|
@ -43,10 +43,6 @@
|
||||
innerHide: function () {
|
||||
this.$form.hide(this.options.anim, $.proxy(function() {
|
||||
this.$element.show();
|
||||
//return focus on element
|
||||
if (this.options.enablefocus) {
|
||||
this.$element.focus();
|
||||
}
|
||||
}, this));
|
||||
},
|
||||
|
||||
@ -57,8 +53,7 @@
|
||||
|
||||
//defaults
|
||||
$.fn.editableContainer.defaults = $.extend({}, $.fn.editableContainer.defaults, {
|
||||
anim: 'fast',
|
||||
enablefocus: false
|
||||
anim: 'fast'
|
||||
});
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
$.extend(this.containerOptions, {
|
||||
trigger: 'manual',
|
||||
selector: false,
|
||||
content: 'dfgh'
|
||||
content: ' '
|
||||
});
|
||||
this.call(this.containerOptions);
|
||||
},
|
||||
|
@ -2,10 +2,11 @@
|
||||
* EditableForm utilites
|
||||
*/
|
||||
(function ($) {
|
||||
$.fn.editableform.utils = {
|
||||
//utils
|
||||
$.fn.editableutils = {
|
||||
/**
|
||||
* classic JS inheritance function
|
||||
*/
|
||||
*/
|
||||
inherit: function (Child, Parent) {
|
||||
var F = function() { };
|
||||
F.prototype = Parent.prototype;
|
||||
@ -116,6 +117,13 @@
|
||||
return k;
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
method to escape html.
|
||||
**/
|
||||
escape: function(str) {
|
||||
return $('<div>').text(str).html();
|
||||
}
|
||||
};
|
||||
}(window.jQuery));
|
@ -16,6 +16,8 @@
|
||||
*display: inline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.editable-input {
|
||||
vertical-align: top;
|
||||
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
||||
@ -31,8 +33,9 @@
|
||||
}
|
||||
|
||||
/*for jquery-ui buttons need set height to look more pretty*/
|
||||
.editable-buttons button.ui-button {
|
||||
.editable-buttons button.ui-button-icon-only {
|
||||
height: 24px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.editableform-loading {
|
||||
@ -79,6 +82,10 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.editable-checklist label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.editable-clear {
|
||||
clear: both;
|
||||
font-size: 0.9em;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
Form with single input element, two buttons and two states: normal/loading.
|
||||
Applied as jQuery method to DIV tag (not to form tag!)
|
||||
Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown.
|
||||
Editableform is linked with one of input types, e.g. 'text', 'select' etc.
|
||||
|
||||
@class editableform
|
||||
@uses text
|
||||
@ -9,9 +9,12 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
var EditableForm = function (element, options) {
|
||||
var EditableForm = function (div, options) {
|
||||
this.options = $.extend({}, $.fn.editableform.defaults, options);
|
||||
this.$element = $(element); //div, containing form. Not form tag! Not editable-element.
|
||||
this.$div = $(div); //div, containing form. Not form tag! Not editable-element.
|
||||
if(!this.options.scope) {
|
||||
this.options.scope = this;
|
||||
}
|
||||
this.initInput();
|
||||
};
|
||||
|
||||
@ -21,9 +24,9 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
var TypeConstructor, typeOptions;
|
||||
|
||||
//create input of specified type
|
||||
if(typeof $.fn.editableform.types[this.options.type] === 'function') {
|
||||
TypeConstructor = $.fn.editableform.types[this.options.type];
|
||||
typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
|
||||
if(typeof $.fn.editabletypes[this.options.type] === 'function') {
|
||||
TypeConstructor = $.fn.editabletypes[this.options.type];
|
||||
typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
|
||||
this.input = new TypeConstructor(typeOptions);
|
||||
} else {
|
||||
$.error('Unknown type: '+ this.options.type);
|
||||
@ -45,7 +48,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
**/
|
||||
render: function() {
|
||||
this.$loading = $($.fn.editableform.loading);
|
||||
this.$element.empty().append(this.$loading);
|
||||
this.$div.empty().append(this.$loading);
|
||||
this.showLoading();
|
||||
|
||||
//init form template and buttons
|
||||
@ -61,7 +64,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
@event rendering
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$element.triggerHandler('rendering');
|
||||
this.$div.triggerHandler('rendering');
|
||||
|
||||
//render input
|
||||
$.when(this.input.render())
|
||||
@ -80,21 +83,23 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
}
|
||||
|
||||
//append form to container
|
||||
this.$element.append(this.$form);
|
||||
|
||||
this.$div.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) {
|
||||
this.error(this.input.error);
|
||||
this.$form.find('.editable-submit').attr('disabled', true);
|
||||
this.input.$input.attr('disabled', true);
|
||||
//prevent form from submitting
|
||||
this.$form.submit(function(e){ e.preventDefault(); });
|
||||
} else {
|
||||
this.error(false);
|
||||
this.input.$input.removeAttr('disabled');
|
||||
this.$form.find('.editable-submit').removeAttr('disabled');
|
||||
this.input.value2input(this.value);
|
||||
//attach submit handler
|
||||
this.$form.submit($.proxy(this.submit, this));
|
||||
}
|
||||
|
||||
@ -103,7 +108,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
@event rendered
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$element.triggerHandler('rendered');
|
||||
this.$div.triggerHandler('rendered');
|
||||
|
||||
this.showForm();
|
||||
}, this));
|
||||
@ -114,7 +119,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
@event cancel
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$element.triggerHandler('cancel');
|
||||
this.$div.triggerHandler('cancel');
|
||||
},
|
||||
showLoading: function() {
|
||||
var w;
|
||||
@ -133,16 +138,18 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
this.$loading.show();
|
||||
},
|
||||
|
||||
showForm: function() {
|
||||
showForm: function(activate) {
|
||||
this.$loading.hide();
|
||||
this.$form.show();
|
||||
this.input.activate();
|
||||
if(activate !== false) {
|
||||
this.input.activate();
|
||||
}
|
||||
/**
|
||||
Fired when form is shown
|
||||
@event show
|
||||
@param {Object} event event object
|
||||
**/
|
||||
this.$element.triggerHandler('show');
|
||||
this.$div.triggerHandler('show');
|
||||
},
|
||||
|
||||
error: function(msg) {
|
||||
@ -163,8 +170,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
e.preventDefault();
|
||||
|
||||
var error,
|
||||
newValue = this.input.input2value(), //get new value from input
|
||||
newValueStr;
|
||||
newValue = this.input.input2value(); //get new value from input
|
||||
|
||||
//validation
|
||||
if (error = this.validate(newValue)) {
|
||||
@ -173,25 +179,29 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
return;
|
||||
}
|
||||
|
||||
//value as string
|
||||
newValueStr = this.input.value2str(newValue);
|
||||
|
||||
//if value not changed --> cancel
|
||||
/*jslint eqeq: true*/
|
||||
if (newValueStr == this.input.value2str(this.value)) {
|
||||
if (!this.options.savenochange && this.input.value2str(newValue) == this.input.value2str(this.value)) {
|
||||
/*jslint eqeq: false*/
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
//sending data to server
|
||||
$.when(this.save(newValueStr))
|
||||
$.when(this.save(newValue))
|
||||
.done($.proxy(function(response) {
|
||||
//run success callback
|
||||
var res = typeof this.options.success === 'function' ? this.options.success.call(this, response, newValue) : null;
|
||||
var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null;
|
||||
|
||||
//if success callback returns string --> show error
|
||||
if(res && typeof res === 'string') {
|
||||
//if success callback returns false --> keep form open and do not activate input
|
||||
if(res === false) {
|
||||
this.error(false);
|
||||
this.showForm(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//if success callback returns string --> keep form open, show error and activate input
|
||||
if(typeof res === 'string') {
|
||||
this.error(res);
|
||||
this.showForm();
|
||||
return;
|
||||
@ -218,7 +228,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
if(params.newValue === 'username') {...}
|
||||
});
|
||||
**/
|
||||
this.$element.triggerHandler('save', {newValue: newValue, response: response});
|
||||
this.$div.triggerHandler('save', {newValue: newValue, response: response});
|
||||
}, this))
|
||||
.fail($.proxy(function(xhr) {
|
||||
this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
|
||||
@ -226,10 +236,16 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
}, this));
|
||||
},
|
||||
|
||||
save: function(value) {
|
||||
var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this) : this.options.pk,
|
||||
save: function(newValue) {
|
||||
//convert value for submitting to server
|
||||
var submitValue = this.input.value2submit(newValue);
|
||||
|
||||
//try parse composite pk defined as json string in data-pk
|
||||
this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true);
|
||||
|
||||
var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk,
|
||||
send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
|
||||
params, ajaxOptions;
|
||||
params;
|
||||
|
||||
if (send) { //send to server
|
||||
this.showLoading();
|
||||
@ -237,30 +253,29 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
//standard params
|
||||
params = {
|
||||
name: this.options.name || '',
|
||||
value: value,
|
||||
value: submitValue,
|
||||
pk: pk
|
||||
};
|
||||
|
||||
//additional params
|
||||
if(typeof this.options.params === 'function') {
|
||||
$.extend(params, this.options.params.call(this, params));
|
||||
$.extend(params, this.options.params.call(this.options.scope, params));
|
||||
} else {
|
||||
//try parse json in single quotes (from data-params attribute)
|
||||
this.options.params = $.fn.editableform.utils.tryParseJson(this.options.params, true);
|
||||
this.options.params = $.fn.editableutils.tryParseJson(this.options.params, true);
|
||||
$.extend(params, this.options.params);
|
||||
}
|
||||
|
||||
if(typeof this.options.url === 'function') { //user's function
|
||||
return this.options.url.call(this, params);
|
||||
} else { //send ajax to server and return deferred object
|
||||
ajaxOptions = $.extend({
|
||||
return this.options.url.call(this.options.scope, params);
|
||||
} else {
|
||||
//send ajax to server and return deferred object
|
||||
return $.ajax($.extend({
|
||||
url : this.options.url,
|
||||
data : params,
|
||||
type : 'post',
|
||||
dataType: 'json'
|
||||
}, this.options.ajaxOptions);
|
||||
|
||||
return $.ajax(ajaxOptions);
|
||||
}, this.options.ajaxOptions));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -270,7 +285,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
value = this.value;
|
||||
}
|
||||
if (typeof this.options.validate === 'function') {
|
||||
return this.options.validate.call(this, value);
|
||||
return this.options.validate.call(this.options.scope, value);
|
||||
}
|
||||
},
|
||||
|
||||
@ -377,7 +392,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
name: null,
|
||||
/**
|
||||
Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. <code>{id: 1, lang: 'en'}</code>.
|
||||
Can be calculated dinamically via function.
|
||||
Can be calculated dynamically via function.
|
||||
|
||||
@property pk
|
||||
@type string|object|function
|
||||
@ -418,7 +433,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
validate: null,
|
||||
/**
|
||||
Success callback. Called when value successfully sent on server and **response status = 200**.
|
||||
Usefull to work with json response. For example, if your backend response can be <code>{success: true}</code>
|
||||
Useful to work with json response. For example, if your backend response can be <code>{success: true}</code>
|
||||
or <code>{success: false, msg: "server error"}</code> you can check it inside this callback.
|
||||
If it returns **string** - means error occured and string is shown as error message.
|
||||
If it returns **object like** <code>{newValue: <something>}</code> - it overwrites value, submitted by user.
|
||||
@ -440,28 +455,44 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
@property ajaxOptions
|
||||
@type object
|
||||
@default null
|
||||
@since 1.1.1
|
||||
**/
|
||||
ajaxOptions: null,
|
||||
/**
|
||||
Wether to show buttons or not.
|
||||
Whether to show buttons or not.
|
||||
Form without buttons can be auto-submitted by input or by onblur = 'submit'.
|
||||
@example
|
||||
ajaxOptions: {
|
||||
method: 'PUT',
|
||||
dataType: 'xml'
|
||||
}
|
||||
|
||||
@property showbuttons
|
||||
@type boolean
|
||||
@default true
|
||||
@since 1.1.1
|
||||
**/
|
||||
showbuttons: true
|
||||
|
||||
/*todo:
|
||||
Submit strategy. Can be <code>normal|never</code>
|
||||
<code>submitmode='never'</code> usefull for turning into classic form several inputs and submitting them together manually.
|
||||
Works pretty with <code>showbuttons=false</code>
|
||||
showbuttons: true,
|
||||
/**
|
||||
Scope for callback methods (success, validate).
|
||||
If <code>null</code> means editableform instance itself.
|
||||
|
||||
@property submitmode
|
||||
@type string
|
||||
@default normal
|
||||
*/
|
||||
// submitmode: 'normal'
|
||||
@property scope
|
||||
@type DOMElement|object
|
||||
@default null
|
||||
@since 1.2.0
|
||||
@private
|
||||
**/
|
||||
scope: null,
|
||||
/**
|
||||
Whether to save or cancel value when it was not changed but form was submitted
|
||||
|
||||
@property savenochange
|
||||
@type boolean
|
||||
@default false
|
||||
@since 1.2.0
|
||||
**/
|
||||
savenochange: false
|
||||
};
|
||||
|
||||
/*
|
||||
@ -482,15 +513,9 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
|
||||
$.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
|
||||
//error class attached to control-group
|
||||
$.fn.editableform.errorGroupClass = null;
|
||||
|
||||
//error class attahced to editable-error-block
|
||||
//error class attached to editable-error-block
|
||||
$.fn.editableform.errorBlockClass = 'editable-error';
|
||||
|
||||
//input types
|
||||
$.fn.editableform.types = {};
|
||||
//utils
|
||||
$.fn.editableform.utils = {};
|
||||
|
||||
}(window.jQuery));
|
@ -8,7 +8,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
|
||||
var Editable = function (element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableform.utils.getConfigData(this.$element), options);
|
||||
this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableutils.getConfigData(this.$element), options);
|
||||
this.init();
|
||||
};
|
||||
|
||||
@ -20,9 +20,6 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
doAutotext,
|
||||
finalize;
|
||||
|
||||
//initialization flag
|
||||
this.isInit = true;
|
||||
|
||||
//editableContainer must be defined
|
||||
if(!$.fn.editableContainer) {
|
||||
$.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)');
|
||||
@ -33,9 +30,9 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
this.options.name = this.options.name || this.$element.attr('id');
|
||||
|
||||
//create input of specified type. Input will be used for converting value, not in form
|
||||
if(typeof $.fn.editableform.types[this.options.type] === 'function') {
|
||||
TypeConstructor = $.fn.editableform.types[this.options.type];
|
||||
this.typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
|
||||
if(typeof $.fn.editabletypes[this.options.type] === 'function') {
|
||||
TypeConstructor = $.fn.editabletypes[this.options.type];
|
||||
this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
|
||||
this.input = new TypeConstructor(this.typeOptions);
|
||||
} else {
|
||||
$.error('Unknown type: '+ this.options.type);
|
||||
@ -47,13 +44,20 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
this.value = this.input.html2value($.trim(this.$element.html()));
|
||||
isValueByText = true;
|
||||
} else {
|
||||
/*
|
||||
value can be string when received from 'data-value' attribute
|
||||
for complext objects value can be set as json string in data-value attribute,
|
||||
e.g. data-value="{city: 'Moscow', street: 'Lenina'}"
|
||||
*/
|
||||
this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true);
|
||||
if(typeof this.options.value === 'string') {
|
||||
this.options.value = $.trim(this.options.value);
|
||||
this.value = this.input.str2value(this.options.value);
|
||||
} else {
|
||||
this.value = this.options.value;
|
||||
}
|
||||
this.value = this.input.str2value(this.options.value);
|
||||
}
|
||||
|
||||
//add 'editable' class
|
||||
//add 'editable' class to every editable element
|
||||
this.$element.addClass('editable');
|
||||
|
||||
//attach handler activating editable. In disabled mode it just prevent default action (useful for links)
|
||||
@ -81,29 +85,46 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
//if value was generated by text or value is empty, no sense to run autotext
|
||||
doAutotext = !isValueByText && this.value !== null && this.value !== undefined;
|
||||
doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length);
|
||||
$.when(doAutotext ? this.input.value2html(this.value, this.$element) : true).then($.proxy(function() {
|
||||
$.when(doAutotext ? this.render() : true).then($.proxy(function() {
|
||||
if(this.options.disabled) {
|
||||
this.disable();
|
||||
} else {
|
||||
this.enable();
|
||||
}
|
||||
/**
|
||||
Fired each time when element's text is rendered. Occurs on initialization and on each update of value.
|
||||
Can be used for display customization.
|
||||
Fired when element was initialized by editable method.
|
||||
|
||||
@event render
|
||||
@event init
|
||||
@param {Object} event event object
|
||||
@param {Object} editable editable instance
|
||||
@example
|
||||
$('#action').on('render', function(e, editable) {
|
||||
var colors = {0: "gray", 1: "green", 2: "blue", 3: "red"};
|
||||
$(this).css("color", colors[editable.value]);
|
||||
});
|
||||
@since 1.2.0
|
||||
**/
|
||||
this.$element.triggerHandler('render', this);
|
||||
this.isInit = false;
|
||||
this.$element.triggerHandler('init', this);
|
||||
}, this));
|
||||
},
|
||||
|
||||
/*
|
||||
Renders value into element's text.
|
||||
Can call custom display method from options.
|
||||
Can return deferred object.
|
||||
@method render()
|
||||
*/
|
||||
render: function() {
|
||||
//do not display anything
|
||||
if(this.options.display === false) {
|
||||
return;
|
||||
}
|
||||
//if it is input with source, we pass callback in third param to be called when source is loaded
|
||||
if(this.input.options.hasOwnProperty('source')) {
|
||||
return this.input.value2html(this.value, this.$element[0], this.options.display);
|
||||
//if display method defined --> use it
|
||||
} else if(typeof this.options.display === 'function') {
|
||||
return this.options.display.call(this.$element[0], this.value);
|
||||
//else use input's original value2html() method
|
||||
} else {
|
||||
return this.input.value2html(this.value, this.$element[0]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Enables editable
|
||||
@ -191,6 +212,11 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
* set emptytext if element is empty (reverse: remove emptytext if needed)
|
||||
*/
|
||||
handleEmpty: function () {
|
||||
//do not handle empty if we do not display anything
|
||||
if(this.options.display === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
var emptyClass = 'editable-empty';
|
||||
//emptytext shown only for enabled
|
||||
if(!this.options.disabled) {
|
||||
@ -211,7 +237,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
/**
|
||||
Shows container with form
|
||||
@method show()
|
||||
@param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
|
||||
@param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
|
||||
**/
|
||||
show: function (closeAll) {
|
||||
if(this.options.disabled) {
|
||||
@ -221,13 +247,11 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
//init editableContainer: popover, tooltip, inline, etc..
|
||||
if(!this.container) {
|
||||
var containerOptions = $.extend({}, this.options, {
|
||||
value: this.value,
|
||||
autohide: false //element will take care to show/hide container
|
||||
value: this.value
|
||||
});
|
||||
this.$element.editableContainer(containerOptions);
|
||||
this.$element.on({
|
||||
save: $.proxy(this.save, this),
|
||||
cancel: $.proxy(this.hide, this)
|
||||
save: $.proxy(this.save, this)
|
||||
});
|
||||
this.container = this.$element.data('editableContainer');
|
||||
} else if(this.container.tip().is(':visible')) {
|
||||
@ -246,17 +270,12 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
if(this.container) {
|
||||
this.container.hide();
|
||||
}
|
||||
|
||||
//return focus on element
|
||||
if (this.options.enablefocus && this.options.toggle === 'click') {
|
||||
this.$element.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Toggles container visibility (show / hide)
|
||||
@method toggle()
|
||||
@param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
|
||||
@param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
|
||||
**/
|
||||
toggle: function(closeAll) {
|
||||
if(this.container && this.container.tip().is(':visible')) {
|
||||
@ -271,13 +290,13 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
*/
|
||||
save: function(e, params) {
|
||||
//if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css.
|
||||
if(typeof this.options.url !== 'function' && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) {
|
||||
if(typeof this.options.url !== 'function' && this.options.display !== false && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) {
|
||||
this.$element.addClass('editable-unsaved');
|
||||
} else {
|
||||
this.$element.removeClass('editable-unsaved');
|
||||
}
|
||||
|
||||
this.hide();
|
||||
// this.hide();
|
||||
this.setValue(params.newValue);
|
||||
|
||||
/**
|
||||
@ -312,7 +331,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
Sets new value of editable
|
||||
@method setValue(value, convertStr)
|
||||
@param {mixed} value new value
|
||||
@param {boolean} convertStr wether to convert value from string to internal format
|
||||
@param {boolean} convertStr whether to convert value from string to internal format
|
||||
**/
|
||||
setValue: function(value, convertStr) {
|
||||
if(convertStr) {
|
||||
@ -323,10 +342,9 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
if(this.container) {
|
||||
this.container.option('value', this.value);
|
||||
}
|
||||
$.when(this.input.value2html(this.value, this.$element))
|
||||
$.when(this.render())
|
||||
.then($.proxy(function() {
|
||||
this.handleEmpty();
|
||||
this.$element.triggerHandler('render', this);
|
||||
}, this));
|
||||
},
|
||||
|
||||
@ -338,7 +356,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
if(this.container) {
|
||||
this.container.activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* EDITABLE PLUGIN DEFINITION
|
||||
@ -369,7 +387,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
$('#username, #fullname').editable('validate');
|
||||
// possible result:
|
||||
{
|
||||
username: "username is requied",
|
||||
username: "username is required",
|
||||
fullname: "fullname should be minimum 3 letters length"
|
||||
}
|
||||
**/
|
||||
@ -398,7 +416,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
this.each(function () {
|
||||
var $this = $(this), data = $this.data(datakey);
|
||||
if (data && data.value !== undefined && data.value !== null) {
|
||||
result[data.options.name] = data.input.value2str(data.value);
|
||||
result[data.options.name] = data.input.value2submit(data.value);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
@ -411,6 +429,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
@param {object} options
|
||||
@param {object} options.url url to submit data
|
||||
@param {object} options.data additional data to submit
|
||||
@param {object} options.ajaxOptions additional ajax options
|
||||
@param {function} options.error(obj) error handler (called on both client-side and server-side validation errors)
|
||||
@param {function} options.success(obj) success handler
|
||||
@returns {Object} jQuery object
|
||||
@ -421,21 +440,20 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
errors = this.editable('validate'),
|
||||
values;
|
||||
|
||||
if(typeof config.error !== 'function') {
|
||||
config.error = function() {};
|
||||
}
|
||||
|
||||
if($.isEmptyObject(errors)) {
|
||||
values = this.editable('getValue');
|
||||
if(config.data) {
|
||||
$.extend(values, config.data);
|
||||
}
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
}
|
||||
|
||||
$.ajax($.extend({
|
||||
url: config.url,
|
||||
data: values,
|
||||
type: 'POST',
|
||||
dataType: 'json'
|
||||
}).success(function(response) {
|
||||
}, config.ajaxOptions))
|
||||
.success(function(response) {
|
||||
//successful response
|
||||
if(typeof response === 'object' && response.id) {
|
||||
$elems.editable('option', 'pk', response.id);
|
||||
$elems.removeClass('editable-unsaved');
|
||||
@ -443,13 +461,20 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
config.success.apply($elems, arguments);
|
||||
}
|
||||
} else { //server-side validation error
|
||||
if(typeof config.error === 'function') {
|
||||
config.error.apply($elems, arguments);
|
||||
}
|
||||
}
|
||||
})
|
||||
.error(function(){ //ajax error
|
||||
if(typeof config.error === 'function') {
|
||||
config.error.apply($elems, arguments);
|
||||
}
|
||||
}).error(function(){ //ajax error
|
||||
config.error.apply($elems, arguments);
|
||||
});
|
||||
} else { //client-side validation error
|
||||
config.error.call($elems, {errors: errors});
|
||||
if(typeof config.error === 'function') {
|
||||
config.error.call($elems, {errors: errors});
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -505,7 +530,6 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
@default 'click'
|
||||
**/
|
||||
toggle: 'click',
|
||||
|
||||
/**
|
||||
Text shown when element is empty.
|
||||
|
||||
@ -515,7 +539,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
**/
|
||||
emptytext: 'Empty',
|
||||
/**
|
||||
Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Usefull for select and date.
|
||||
Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Useful for select and date.
|
||||
For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>.
|
||||
<code>auto</code> - text will be automatically set only if element is empty.
|
||||
<code>always|never</code> - always(never) try to set element's text.
|
||||
@ -526,22 +550,31 @@ Makes editable any HTML element on the page. Applied as jQuery method.
|
||||
**/
|
||||
autotext: 'auto',
|
||||
/**
|
||||
Wether to return focus on element after form is closed.
|
||||
This allows fully keyboard input.
|
||||
|
||||
@property enablefocus
|
||||
@type boolean
|
||||
@default false
|
||||
**/
|
||||
enablefocus: false,
|
||||
/**
|
||||
Initial value of input. Taken from <code>data-value</code> or element's text.
|
||||
|
||||
@property value
|
||||
@type mixed
|
||||
@default element's text
|
||||
**/
|
||||
value: null
|
||||
value: null,
|
||||
/**
|
||||
Callback to perform custom displaying of value in element's text.
|
||||
If <code>null</code>, default input's value2html() will be called.
|
||||
If <code>false</code>, no displaying methods will be called, element's text will no change.
|
||||
Runs under element's scope.
|
||||
Second parameter __sourceData__ is passed for inputs with source (select, checklist).
|
||||
|
||||
@property display
|
||||
@type function|boolean
|
||||
@default null
|
||||
@since 1.2.0
|
||||
@example
|
||||
display: function(value, sourceData) {
|
||||
var escapedValue = $('<div>').text(value).html();
|
||||
$(this).html('<b>'+escapedValue+'</b>');
|
||||
}
|
||||
**/
|
||||
display: null
|
||||
};
|
||||
|
||||
}(window.jQuery));
|
@ -26,19 +26,21 @@ $(function(){
|
||||
this.init('address', options, Address.defaults);
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(Address, $.fn.editableform.types.abstract);
|
||||
$.fn.editableutils.inherit(Address, $.fn.editabletypes.abstract);
|
||||
|
||||
$.extend(Address.prototype, {
|
||||
render: function() {
|
||||
Address.superclass.render.call(this);
|
||||
|
||||
// this.$input.
|
||||
},
|
||||
|
||||
|
||||
//standard way to show value in element. Used only if display option not defined.
|
||||
value2html: function(value, element) {
|
||||
var html = value.city + ', ' + value.street + ' st., bld. ' + value.building;
|
||||
$(element).text(html);
|
||||
if(!value) {
|
||||
$(element).empty();
|
||||
return;
|
||||
}
|
||||
var html = $('<div>').text(value.city).html() + ', ' + $('<div>').text(value.street).html() + ' st., bld. ' + $('<div>').text(value.building).html();
|
||||
$(element).html(html);
|
||||
},
|
||||
|
||||
html2value: function(html) {
|
||||
@ -59,11 +61,17 @@ $(function(){
|
||||
},
|
||||
|
||||
/*
|
||||
method for converting data before sent on server.
|
||||
As jQuery correctly sends objects via ajax, you can just return value
|
||||
converts value to string.
|
||||
It is used in internal comparing (not for sending to server).
|
||||
*/
|
||||
value2str: function(value) {
|
||||
return value;
|
||||
var str = '';
|
||||
if(value) {
|
||||
for(var k in value) {
|
||||
str = str + k + ':' + value[k] + ';';
|
||||
}
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
/*
|
||||
@ -94,14 +102,14 @@ $(function(){
|
||||
}
|
||||
});
|
||||
|
||||
Address.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
tpl: '<div><label><span>City: </span><input type="text" name="city" class="span2"></label></div>'+
|
||||
'<div><label><span>Street: </span><input type="text" name="street" class="span2"></label></div>'+
|
||||
'<div><label><span>Building: </span><input type="text" name="building" class="span1"></label></div>',
|
||||
Address.defaults = $.extend({}, $.fn.editabletypes.abstract.defaults, {
|
||||
tpl: '<div><label><span>City: </span><input type="text" name="city" class="input-small"></label></div>'+
|
||||
'<div><label><span>Street: </span><input type="text" name="street" class="input-small"></label></div>'+
|
||||
'<div><label><span>Building: </span><input type="text" name="building" class="input-mini"></label></div>',
|
||||
|
||||
inputclass: 'editable-address'
|
||||
});
|
||||
|
||||
$.fn.editableform.types.address = Address;
|
||||
$.fn.editabletypes.address = Address;
|
||||
|
||||
}(window.jQuery));
|
@ -6,11 +6,14 @@ To create your own input you should inherit from this class.
|
||||
**/
|
||||
(function ($) {
|
||||
|
||||
//types
|
||||
$.fn.editabletypes = {};
|
||||
|
||||
var Abstract = function () { };
|
||||
|
||||
Abstract.prototype = {
|
||||
/**
|
||||
Iinitializes input
|
||||
Initializes input
|
||||
|
||||
@method init()
|
||||
**/
|
||||
@ -46,8 +49,7 @@ To create your own input you should inherit from this class.
|
||||
@param {DOMElement} element
|
||||
**/
|
||||
value2html: function(value, element) {
|
||||
var html = this.escape(value);
|
||||
$(element).html(html);
|
||||
$(element).text(value);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -62,7 +64,7 @@ To create your own input you should inherit from this class.
|
||||
},
|
||||
|
||||
/**
|
||||
Converts value to string (for submiting to server)
|
||||
Converts value to string (for comparering)
|
||||
|
||||
@method value2str(value)
|
||||
@param {mixed} value
|
||||
@ -83,6 +85,17 @@ To create your own input you should inherit from this class.
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
Converts value for submitting to server
|
||||
|
||||
@method value2submit(value)
|
||||
@param {mixed} value
|
||||
@returns {mixed}
|
||||
**/
|
||||
value2submit: function(value) {
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
Sets value of input.
|
||||
|
||||
@ -114,11 +127,11 @@ To create your own input you should inherit from this class.
|
||||
},
|
||||
|
||||
/**
|
||||
Creares input.
|
||||
Creates input.
|
||||
|
||||
@method clear()
|
||||
**/
|
||||
clear: function() {
|
||||
clear: function() {
|
||||
this.$input.val(null);
|
||||
},
|
||||
|
||||
@ -130,7 +143,7 @@ To create your own input you should inherit from this class.
|
||||
},
|
||||
|
||||
/**
|
||||
attach handler to automatically submit form when value changed (usefull when buttons not shown)
|
||||
attach handler to automatically submit form when value changed (useful when buttons not shown)
|
||||
**/
|
||||
autosubmit: function() {
|
||||
|
||||
@ -148,12 +161,12 @@ To create your own input you should inherit from this class.
|
||||
tpl: '',
|
||||
/**
|
||||
CSS class automatically applied to input
|
||||
|
||||
|
||||
@property inputclass
|
||||
@type string
|
||||
@default span2
|
||||
@default input-medium
|
||||
**/
|
||||
inputclass: 'span2',
|
||||
inputclass: 'input-medium',
|
||||
/**
|
||||
Name attribute of input
|
||||
|
||||
@ -164,6 +177,6 @@ To create your own input you should inherit from this class.
|
||||
name: null
|
||||
};
|
||||
|
||||
$.extend($.fn.editableform.types, {abstract: Abstract});
|
||||
$.extend($.fn.editabletypes, {abstract: Abstract});
|
||||
|
||||
}(window.jQuery));
|
@ -27,7 +27,7 @@ $(function(){
|
||||
this.init('checklist', options, Checklist.defaults);
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(Checklist, $.fn.editableform.types.list);
|
||||
$.fn.editableutils.inherit(Checklist, $.fn.editabletypes.list);
|
||||
|
||||
$.extend(Checklist.prototype, {
|
||||
renderList: function() {
|
||||
@ -49,10 +49,8 @@ $(function(){
|
||||
},
|
||||
|
||||
value2str: function(value) {
|
||||
return $.isArray(value) ? value.join($.trim(this.options.separator)) : '';
|
||||
//it is also possible to sent as array
|
||||
//return value;
|
||||
},
|
||||
return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : '';
|
||||
},
|
||||
|
||||
//parse separated string
|
||||
str2value: function(str) {
|
||||
@ -95,19 +93,18 @@ $(function(){
|
||||
|
||||
//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);
|
||||
var html = [],
|
||||
/*jslint eqeq: true*/
|
||||
checked = $.grep(this.sourceData, function(o){
|
||||
return $.grep(value, function(v){ return v == o.value; }).length;
|
||||
});
|
||||
/*jslint eqeq: false*/
|
||||
if(checked.length) {
|
||||
$.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
|
||||
$(element).html(html.join('<br>'));
|
||||
} else {
|
||||
$(element).empty();
|
||||
}
|
||||
$(element).html(html);
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
@ -123,7 +120,7 @@ $(function(){
|
||||
}
|
||||
});
|
||||
|
||||
Checklist.defaults = $.extend({}, $.fn.editableform.types.list.defaults, {
|
||||
Checklist.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <div></div>
|
||||
@ -133,46 +130,20 @@ $(function(){
|
||||
/**
|
||||
@property inputclass
|
||||
@type string
|
||||
@default span2 editable-checklist
|
||||
@default editable-checklist
|
||||
**/
|
||||
inputclass: 'span2 editable-checklist',
|
||||
inputclass: 'editable-checklist',
|
||||
|
||||
/**
|
||||
Separator of values in string when sending to server
|
||||
Separator of values when reading from 'data-value' string
|
||||
|
||||
@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}'
|
||||
separator: ','
|
||||
});
|
||||
|
||||
$.fn.editableform.types.checklist = Checklist;
|
||||
$.fn.editabletypes.checklist = Checklist;
|
||||
|
||||
}(window.jQuery));
|
||||
|
@ -292,7 +292,7 @@
|
||||
.text(dates[this.language].months[month]+' '+year);
|
||||
this.picker.find('tfoot th.today')
|
||||
.text(dates[this.language].today)
|
||||
.toggle(this.todayBtn);
|
||||
.toggle(this.todayBtn !== false);
|
||||
this.updateNavArrows();
|
||||
this.fillMonths();
|
||||
var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
|
||||
@ -429,10 +429,7 @@
|
||||
break;
|
||||
case 'today':
|
||||
var date = new Date();
|
||||
date.setUTCHours(0);
|
||||
date.setUTCMinutes(0);
|
||||
date.setUTCSeconds(0);
|
||||
date.setUTCMilliseconds(0);
|
||||
date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
|
||||
|
||||
this.showMode(-2);
|
||||
var which = this.todayBtn == 'linked' ? null : 'view';
|
||||
@ -655,7 +652,17 @@
|
||||
if (dir) {
|
||||
this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
|
||||
}
|
||||
this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
|
||||
/*
|
||||
vitalets: fixing bug of very special conditions:
|
||||
jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
|
||||
Method show() does not set display css correctly and datepicker is not shown.
|
||||
Changed to .css('display', 'block') solve the problem.
|
||||
See https://github.com/vitalets/x-editable/issues/37
|
||||
|
||||
In jquery 1.7.2+ everything works fine.
|
||||
*/
|
||||
//this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
|
||||
this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
|
||||
this.updateNavArrows();
|
||||
}
|
||||
};
|
||||
@ -773,7 +780,7 @@
|
||||
val, filtered, part;
|
||||
setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
|
||||
setters_map['dd'] = setters_map['d'];
|
||||
date = UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
|
||||
date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
|
||||
if (parts.length == format.parts.length) {
|
||||
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
||||
val = parseInt(parts[i], 10);
|
||||
|
@ -27,7 +27,7 @@ $(function(){
|
||||
this.init('date', options, Date.defaults);
|
||||
|
||||
//set popular options directly from settings or data-* attributes
|
||||
var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format']);
|
||||
var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']);
|
||||
|
||||
//overriding datepicker config (as by default jQuery extend() is not recursive)
|
||||
this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker);
|
||||
@ -48,7 +48,7 @@ $(function(){
|
||||
this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat);
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(Date, $.fn.editableform.types.abstract);
|
||||
$.fn.editableutils.inherit(Date, $.fn.editabletypes.abstract);
|
||||
|
||||
$.extend(Date.prototype, {
|
||||
render: function () {
|
||||
@ -79,7 +79,11 @@ $(function(){
|
||||
|
||||
str2value: function(str) {
|
||||
return str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datepicker.language) : null;
|
||||
},
|
||||
},
|
||||
|
||||
value2submit: function(value) {
|
||||
return this.value2str(value);
|
||||
},
|
||||
|
||||
value2input: function(value) {
|
||||
this.$input.datepicker('update', value);
|
||||
@ -108,7 +112,7 @@ $(function(){
|
||||
|
||||
});
|
||||
|
||||
Date.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
Date.defaults = $.extend({}, $.fn.editabletypes.abstract.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <div></div>
|
||||
@ -165,6 +169,6 @@ $(function(){
|
||||
clear: '× clear'
|
||||
});
|
||||
|
||||
$.fn.editableform.types.date = Date;
|
||||
$.fn.editabletypes.date = Date;
|
||||
|
||||
}(window.jQuery));
|
||||
|
@ -27,7 +27,7 @@ $(function(){
|
||||
this.init('dateui', options, DateUI.defaults);
|
||||
|
||||
//set popular options directly from settings or data-* attributes
|
||||
var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format']);
|
||||
var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']);
|
||||
|
||||
//overriding datepicker config (as by default jQuery extend() is not recursive)
|
||||
this.options.datepicker = $.extend({}, DateUI.defaults.datepicker, directOptions, options.datepicker);
|
||||
@ -46,7 +46,7 @@ $(function(){
|
||||
this.options.datepicker.dateFormat = this.options.datepicker.format;
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(DateUI, $.fn.editableform.types.abstract);
|
||||
$.fn.editableutils.inherit(DateUI, $.fn.editabletypes.abstract);
|
||||
|
||||
$.extend(DateUI.prototype, {
|
||||
render: function () {
|
||||
@ -97,7 +97,11 @@ $(function(){
|
||||
} catch(e) {}
|
||||
|
||||
return d;
|
||||
},
|
||||
},
|
||||
|
||||
value2submit: function(value) {
|
||||
return this.value2str(value);
|
||||
},
|
||||
|
||||
value2input: function(value) {
|
||||
this.$input.datepicker('setDate', value);
|
||||
@ -125,7 +129,7 @@ $(function(){
|
||||
|
||||
});
|
||||
|
||||
DateUI.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
DateUI.defaults = $.extend({}, $.fn.editabletypes.abstract.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <div></div>
|
||||
@ -183,7 +187,7 @@ $(function(){
|
||||
clear: '× clear'
|
||||
});
|
||||
|
||||
$.fn.editableform.types.dateui = DateUI;
|
||||
$.fn.editableform.types.date = DateUI;
|
||||
$.fn.editabletypes.dateui = DateUI;
|
||||
$.fn.editabletypes.date = DateUI;
|
||||
|
||||
}(window.jQuery));
|
||||
|
@ -10,7 +10,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(List, $.fn.editableform.types.abstract);
|
||||
$.fn.editableutils.inherit(List, $.fn.editabletypes.abstract);
|
||||
|
||||
$.extend(List.prototype, {
|
||||
render: function () {
|
||||
@ -34,10 +34,15 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
return null; //can't set value by text
|
||||
},
|
||||
|
||||
value2html: function (value, element) {
|
||||
value2html: function (value, element, display) {
|
||||
var deferred = $.Deferred();
|
||||
this.onSourceReady(function () {
|
||||
this.value2htmlFinal(value, element);
|
||||
if(typeof display === 'function') {
|
||||
//custom display method
|
||||
display.call(element, value, this.sourceData);
|
||||
} else {
|
||||
this.value2htmlFinal(value, element);
|
||||
}
|
||||
deferred.resolve();
|
||||
}, function () {
|
||||
List.superclass.value2html(this.options.sourceError, element);
|
||||
@ -58,7 +63,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
|
||||
// try parse json in single quotes (for double quotes jquery does automatically)
|
||||
try {
|
||||
this.options.source = $.fn.editableform.utils.tryParseJson(this.options.source, false);
|
||||
this.options.source = $.fn.editableutils.tryParseJson(this.options.source, false);
|
||||
} catch (e) {
|
||||
error.call(this);
|
||||
return;
|
||||
@ -66,32 +71,35 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
|
||||
//loading from url
|
||||
if (typeof this.options.source === 'string') {
|
||||
var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
|
||||
cache;
|
||||
//try to get from cache
|
||||
if(this.options.sourceCache) {
|
||||
var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
|
||||
cache;
|
||||
|
||||
if (!$(document).data(cacheID)) {
|
||||
$(document).data(cacheID, {});
|
||||
}
|
||||
cache = $(document).data(cacheID);
|
||||
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 () {
|
||||
//check for cached data
|
||||
if (cache.loading === false && cache.sourceData) { //take source from cache
|
||||
this.sourceData = cache.sourceData;
|
||||
success.call(this);
|
||||
}, 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 = [];
|
||||
//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
|
||||
@ -102,23 +110,32 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
data: this.options.name ? {name: this.options.name} : {},
|
||||
dataType: 'json',
|
||||
success: $.proxy(function (data) {
|
||||
cache.loading = false;
|
||||
if(cache) {
|
||||
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
|
||||
if(cache) {
|
||||
//store result in cache
|
||||
cache.sourceData = this.sourceData;
|
||||
$.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
|
||||
if(cache) {
|
||||
$.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
|
||||
if(cache) {
|
||||
cache.loading = false;
|
||||
//run error callbacks for other fields
|
||||
$.each(cache.err_callbacks, function () { this.call(); });
|
||||
}
|
||||
}, this)
|
||||
});
|
||||
} else { //options as json/array
|
||||
@ -139,7 +156,7 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
|
||||
if(!$.isArray(this.prependData)) {
|
||||
//try parse json in single quotes
|
||||
this.options.prepend = $.fn.editableform.utils.tryParseJson(this.options.prepend, true);
|
||||
this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true);
|
||||
if (typeof this.options.prepend === 'string') {
|
||||
this.options.prepend = {'': this.options.prepend};
|
||||
}
|
||||
@ -220,19 +237,20 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
|
||||
});
|
||||
|
||||
List.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
List.defaults = $.extend({}, $.fn.editabletypes.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.
|
||||
|
||||
If source is **string**, results will be cached for fields with the same source and name. See also <code>sourceCache</code> option.
|
||||
|
||||
@property source
|
||||
@type string|array|object
|
||||
@default null
|
||||
**/
|
||||
source:null,
|
||||
/**
|
||||
Data automatically prepended to the begining of dropdown list.
|
||||
Data automatically prepended to the beginning of dropdown list.
|
||||
|
||||
@property prepend
|
||||
@type string|array|object
|
||||
@ -246,9 +264,19 @@ List - abstract class for inputs that have source option loaded from js array or
|
||||
@type string
|
||||
@default Error when loading list
|
||||
**/
|
||||
sourceError: 'Error when loading list'
|
||||
sourceError: 'Error when loading list',
|
||||
/**
|
||||
if <code>true</code> and source is **string url** - results will be cached for fields with the same source and name.
|
||||
Usefull for editable grids.
|
||||
|
||||
@property sourceCache
|
||||
@type boolean
|
||||
@default true
|
||||
@since 1.2.0
|
||||
**/
|
||||
sourceCache: true
|
||||
});
|
||||
|
||||
$.fn.editableform.types.list = List;
|
||||
$.fn.editabletypes.list = List;
|
||||
|
||||
}(window.jQuery));
|
@ -26,7 +26,7 @@ $(function(){
|
||||
this.init('select', options, Select.defaults);
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(Select, $.fn.editableform.types.list);
|
||||
$.fn.editableutils.inherit(Select, $.fn.editabletypes.list);
|
||||
|
||||
$.extend(Select.prototype, {
|
||||
renderList: function() {
|
||||
@ -37,6 +37,13 @@ $(function(){
|
||||
for(var i=0; i<this.sourceData.length; i++) {
|
||||
this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text));
|
||||
}
|
||||
|
||||
//enter submit
|
||||
this.$input.on('keydown.editable', function (e) {
|
||||
if (e.which === 13) {
|
||||
$(this).closest('form').submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
value2htmlFinal: function(value, element) {
|
||||
@ -48,13 +55,13 @@ $(function(){
|
||||
},
|
||||
|
||||
autosubmit: function() {
|
||||
this.$input.on('change', function(){
|
||||
this.$input.off('keydown.editable').on('change.editable', function(){
|
||||
$(this).closest('form').submit();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Select.defaults = $.extend({}, $.fn.editableform.types.list.defaults, {
|
||||
Select.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <select></select>
|
||||
@ -62,6 +69,6 @@ $(function(){
|
||||
tpl:'<select></select>'
|
||||
});
|
||||
|
||||
$.fn.editableform.types.select = Select;
|
||||
$.fn.editabletypes.select = Select;
|
||||
|
||||
}(window.jQuery));
|
@ -20,18 +20,18 @@ $(function(){
|
||||
this.init('text', options, Text.defaults);
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(Text, $.fn.editableform.types.abstract);
|
||||
$.fn.editableutils.inherit(Text, $.fn.editabletypes.abstract);
|
||||
|
||||
$.extend(Text.prototype, {
|
||||
activate: function() {
|
||||
if(this.$input.is(':visible')) {
|
||||
this.$input.focus();
|
||||
$.fn.editableform.utils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
||||
$.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Text.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
Text.defaults = $.extend({}, $.fn.editabletypes.abstract.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <input type="text">
|
||||
@ -47,6 +47,6 @@ $(function(){
|
||||
placeholder: null
|
||||
});
|
||||
|
||||
$.fn.editableform.types.text = Text;
|
||||
$.fn.editabletypes.text = Text;
|
||||
|
||||
}(window.jQuery));
|
||||
|
@ -21,7 +21,7 @@ $(function(){
|
||||
this.init('textarea', options, Textarea.defaults);
|
||||
};
|
||||
|
||||
$.fn.editableform.utils.inherit(Textarea, $.fn.editableform.types.abstract);
|
||||
$.fn.editableutils.inherit(Textarea, $.fn.editabletypes.abstract);
|
||||
|
||||
$.extend(Textarea.prototype, {
|
||||
render: function () {
|
||||
@ -60,13 +60,13 @@ $(function(){
|
||||
|
||||
activate: function() {
|
||||
if(this.$input.is(':visible')) {
|
||||
$.fn.editableform.utils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
||||
$.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
|
||||
this.$input.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Textarea.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
|
||||
Textarea.defaults = $.extend({}, $.fn.editabletypes.abstract.defaults, {
|
||||
/**
|
||||
@property tpl
|
||||
@default <textarea></textarea>
|
||||
@ -74,9 +74,9 @@ $(function(){
|
||||
tpl:'<textarea></textarea>',
|
||||
/**
|
||||
@property inputclass
|
||||
@default span3
|
||||
@default input-large
|
||||
**/
|
||||
inputclass:'span3',
|
||||
inputclass: 'input-large',
|
||||
/**
|
||||
Placeholder attribute of input. Shown when input is empty.
|
||||
|
||||
@ -87,6 +87,6 @@ $(function(){
|
||||
placeholder: null
|
||||
});
|
||||
|
||||
$.fn.editableform.types.textarea = Textarea;
|
||||
$.fn.editabletypes.textarea = Textarea;
|
||||
|
||||
}(window.jQuery));
|
||||
}(window.jQuery));
|
||||
|
@ -3,55 +3,25 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test X-editable</title>
|
||||
|
||||
<!-- jquery -->
|
||||
<script src="libs/jquery/jquery-1.8.2.js"></script>
|
||||
|
||||
<!-- qunit -->
|
||||
<link rel="stylesheet" href="libs/qunit/qunit-1.10.0.css" type="text/css" media="screen" />
|
||||
<script src="libs/qunit/qunit-1.10.0.js"></script>
|
||||
|
||||
<!-- mockjax -->
|
||||
<script src="libs/mockjax/jquery.mockjax.js"></script>
|
||||
<script src="mocks.js"></script>
|
||||
|
||||
<script src="loader.js"></script>
|
||||
<script>
|
||||
var fc = getFC(),
|
||||
assets = getAssets(fc.f, fc.c, '../src/', 'libs/');
|
||||
loadAssets(assets.css, assets.js);
|
||||
|
||||
var fx, sfx;
|
||||
$(function () {
|
||||
$.fx.off = true;
|
||||
$.support.transition = false;
|
||||
});
|
||||
</script>
|
||||
window.onload = function() {
|
||||
QUnit.config.autostart = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- <script data-main="main.js" src="require-jquery.js"></script>-->
|
||||
<script data-main="main.js" src="require.js"></script>
|
||||
|
||||
<!-- qunit (should be included here, otherwise phantomjs hangs-up on several tests )-->
|
||||
<link rel="stylesheet" href="libs/qunit/qunit-1.10.0.css" type="text/css" media="screen" />
|
||||
<script src="libs/qunit/qunit-1.10.0.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
<div id="async-fixture"></div>
|
||||
</div>
|
||||
|
||||
<!-- unit tests -->
|
||||
<!-- You can also add "?module=[module]" URL to run only tests within that module-->
|
||||
<script src="unit/common.js"></script>
|
||||
<script src="unit/text.js"></script>
|
||||
<script src="unit/select.js"></script>
|
||||
<script src="unit/textarea.js"></script>
|
||||
<script src="unit/api.js"></script>
|
||||
<script src="unit/checklist.js"></script>
|
||||
<script>
|
||||
if(fc.f === 'bootstrap') {
|
||||
loadJs('unit/date.js');
|
||||
} else {
|
||||
loadJs('unit/dateui.js');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
294
test/loader.js
294
test/loader.js
@ -1,128 +1,170 @@
|
||||
/**
|
||||
* load requred js and css according to f (form) and c (container) parameters
|
||||
*/
|
||||
define(function () {
|
||||
|
||||
function loadCss(url) {
|
||||
var link = document.createElement("link");
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.href = url;
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
};
|
||||
|
||||
return {
|
||||
loadCss: loadCss,
|
||||
getConfig: function (baseUrl) {
|
||||
var params = this.getParams(),
|
||||
f = params.f,
|
||||
c = params.c,
|
||||
shim = {
|
||||
'containers/editable-container': {
|
||||
deps: ['require', 'editable-form/editable-form-utils', 'editable-form/editable-form'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("./editable-container.css"));
|
||||
}
|
||||
},
|
||||
'element/editable-element': {
|
||||
deps: ['require'], //here should be dynamically added container
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("./editable-element.css"));
|
||||
}
|
||||
},
|
||||
'editable-form/editable-form': {
|
||||
deps: ['require',
|
||||
'inputs/text',
|
||||
'inputs/textarea',
|
||||
'inputs/select',
|
||||
'inputs/checklist',
|
||||
'inputs-ext/address/address'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("./editable-form.css"));
|
||||
}
|
||||
},
|
||||
'inputs/select': ['inputs/list'],
|
||||
'inputs/checklist': ['inputs/list'],
|
||||
'inputs/list': ['inputs/abstract'],
|
||||
'inputs/text': ['inputs/abstract'],
|
||||
'inputs/textarea': ['inputs/abstract'],
|
||||
'inputs/abstract': ['editable-form/editable-form-utils'],
|
||||
|
||||
function getFC() {
|
||||
var url = window.location.href, f, c;
|
||||
if(url.match(/f=jqueryui/i)) {
|
||||
f = 'jqueryui';
|
||||
} else if(url.match(/f=plain/i)) {
|
||||
f = 'plain';
|
||||
} else { //bootstrap
|
||||
f = 'bootstrap';
|
||||
//bootstrap
|
||||
'bootstrap/js/bootstrap': {
|
||||
deps: ['require'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("../css/bootstrap.css"));
|
||||
}
|
||||
},
|
||||
'editable-form/editable-form-bootstrap': [
|
||||
'editable-form/editable-form',
|
||||
'bootstrap/js/bootstrap'
|
||||
],
|
||||
'containers/editable-popover': ['containers/editable-container',
|
||||
'bootstrap/js/bootstrap'
|
||||
],
|
||||
'inputs/date/date': {
|
||||
deps: ['require',
|
||||
'bootstrap/js/bootstrap',
|
||||
'inputs/abstract',
|
||||
'inputs/date/bootstrap-datepicker/js/bootstrap-datepicker'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("./bootstrap-datepicker/css/datepicker.css"));
|
||||
}
|
||||
},
|
||||
|
||||
//jqueryui
|
||||
'jqueryui/js/jquery-ui-1.9.1.custom': {
|
||||
deps: ['require'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("../css/redmond/jquery-ui-1.9.1.custom.css"));
|
||||
}
|
||||
},
|
||||
'editable-form/editable-form-jqueryui': [
|
||||
'editable-form/editable-form',
|
||||
'jqueryui/js/jquery-ui-1.9.1.custom'
|
||||
],
|
||||
'containers/editable-tooltip': ['containers/editable-container',
|
||||
'jqueryui/js/jquery-ui-1.9.1.custom'
|
||||
],
|
||||
'inputs/dateui/dateui': ['inputs/abstract'],
|
||||
|
||||
//plain
|
||||
//'inputs/dateui/dateui': ['inputs/abstract', 'inputs/date/bootstrap-datepicker/js/bootstrap-datepicker'],
|
||||
'containers/editable-poshytip': [
|
||||
'containers/editable-container',
|
||||
'poshytip/jquery.poshytip'
|
||||
],
|
||||
'poshytip/jquery.poshytip': {
|
||||
deps: ['require'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("./tip-yellowsimple/tip-yellowsimple.css"));
|
||||
}
|
||||
},
|
||||
'inputs/dateui/jquery-ui-datepicker/js/jquery-ui-1.9.1.custom': {
|
||||
deps: ['require'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("../css/redmond/jquery-ui-1.9.1.custom.css"));
|
||||
}
|
||||
},
|
||||
|
||||
//inline container
|
||||
'containers/editable-inline': ['containers/editable-container'],
|
||||
|
||||
//inputs-ext
|
||||
'inputs-ext/address/address': {
|
||||
deps: ['require', 'inputs/abstract'],
|
||||
init: function(require) {
|
||||
loadCss(require.toUrl("./address.css"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
modify shim for bootstrap, jqueryui or plain
|
||||
*/
|
||||
|
||||
if(f === 'bootstrap') {
|
||||
//bootstrap
|
||||
shim['editable-form/editable-form'].deps.push('inputs/date/date');
|
||||
shim['element/editable-element'].deps.push('editable-form/editable-form-bootstrap');
|
||||
shim['element/editable-element'].deps.push(c === 'popup' ? 'containers/editable-popover' : 'containers/editable-inline');
|
||||
} else if(f === 'jqueryui') {
|
||||
//jqueryui
|
||||
shim['editable-form/editable-form'].deps.push('inputs/dateui/dateui');
|
||||
shim['element/editable-element'].deps.push('editable-form/editable-form-jqueryui');
|
||||
shim['element/editable-element'].deps.push(c === 'popup' ? 'containers/editable-tooltip' : 'containers/editable-inline');
|
||||
} else {
|
||||
//plain
|
||||
shim['editable-form/editable-form'].deps.push('inputs/dateui/dateui');
|
||||
shim['inputs/dateui/dateui'].push('inputs/dateui/jquery-ui-datepicker/js/jquery-ui-1.9.1.custom');
|
||||
shim['element/editable-element'].deps.push(c === 'popup' ? 'containers/editable-poshytip' : 'containers/editable-inline');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return requirejs config
|
||||
*/
|
||||
|
||||
return {
|
||||
baseUrl: baseUrl,
|
||||
paths: {
|
||||
"bootstrap": "../test/libs/bootstrap221",
|
||||
"jqueryui": "../test/libs/jquery-ui-1.9.1.custom",
|
||||
"poshytip": "../test/libs/poshytip",
|
||||
"test": "../test"
|
||||
},
|
||||
shim: shim
|
||||
};
|
||||
},
|
||||
|
||||
getParams: function() {
|
||||
var url = window.location.href, f, c;
|
||||
if(url.match(/f=jqueryui/i)) {
|
||||
f = 'jqueryui';
|
||||
} else if(url.match(/f=plain/i)) {
|
||||
f = 'plain';
|
||||
} else {
|
||||
f = 'bootstrap';
|
||||
}
|
||||
c = url.match(/c=inline/i) ? 'inline' : 'popup';
|
||||
return {f: f, c: c};
|
||||
}
|
||||
}
|
||||
c = url.match(/c=inline/i) ? 'inline' : 'popup';
|
||||
return {f: f, c: c};
|
||||
}
|
||||
|
||||
function getAssets(f, c, src, libs) {
|
||||
var
|
||||
forms = src+'editable-form/',
|
||||
inputs = src+'inputs/',
|
||||
containers = src+'containers/',
|
||||
element = src+'element/',
|
||||
|
||||
bootstrap = libs+'bootstrap221/',
|
||||
jqueryui = libs+'jquery-ui-1.9.1.custom/',
|
||||
|
||||
js = [
|
||||
forms+'editable-form.js',
|
||||
forms+'editable-form-utils.js',
|
||||
containers+'editable-container.js',
|
||||
element+'editable-element.js',
|
||||
inputs+'abstract.js',
|
||||
inputs+'list.js',
|
||||
inputs+'text.js',
|
||||
inputs+'textarea.js',
|
||||
inputs+'select.js',
|
||||
inputs+'checklist.js'
|
||||
],
|
||||
|
||||
css = [
|
||||
forms+'editable-form.css',
|
||||
containers+'editable-container.css',
|
||||
element+'editable-element.css'
|
||||
];
|
||||
|
||||
|
||||
//tune js and css
|
||||
if(f==='jqueryui') {
|
||||
//core
|
||||
js.unshift(jqueryui+'js/jquery-ui-1.9.1.custom.js')
|
||||
css.unshift(jqueryui+'css/redmond/jquery-ui-1.9.1.custom.css');
|
||||
|
||||
//editable
|
||||
js.push(forms+'editable-form-jqueryui.js');
|
||||
js.push(getContainer('editable-tooltip.js'));
|
||||
|
||||
//date
|
||||
js.push(inputs+'dateui/dateui.js');
|
||||
|
||||
//style
|
||||
css.push('style.css');
|
||||
} else if(f==='plain') {
|
||||
//core
|
||||
js.unshift(libs+'poshytip/jquery.poshytip.js');
|
||||
css.unshift(libs+'poshytip/tip-yellowsimple/tip-yellowsimple.css');
|
||||
|
||||
//editable
|
||||
js.push(getContainer('editable-poshytip.js'));
|
||||
|
||||
//date
|
||||
js.push(inputs+'dateui/dateui.js');
|
||||
js.push(inputs+'dateui/jquery-ui-datepicker/js/jquery-ui-1.9.1.custom.js');
|
||||
css.unshift(inputs+'dateui/jquery-ui-datepicker/css/redmond/jquery-ui-1.9.1.custom.css');
|
||||
|
||||
//style
|
||||
css.push('style.css');
|
||||
/* bootstrap */
|
||||
} else {
|
||||
//core
|
||||
js.unshift(bootstrap+'js/bootstrap.js')
|
||||
css.unshift(bootstrap+'css/bootstrap.css');
|
||||
css.unshift(bootstrap+'css/bootstrap-responsive.css');
|
||||
|
||||
//editable
|
||||
js.push(forms+'editable-form-bootstrap.js');
|
||||
js.push(getContainer('editable-popover.js'));
|
||||
|
||||
//date
|
||||
js.push(inputs+'date/bootstrap-datepicker/js/bootstrap-datepicker.js');
|
||||
js.push(inputs+'date/date.js');
|
||||
css.push(inputs+'date/bootstrap-datepicker/css/datepicker.css');
|
||||
}
|
||||
|
||||
function getContainer(container) {
|
||||
return (c === 'inline') ? containers+'/editable-inline.js' : containers + container;
|
||||
}
|
||||
|
||||
//js.push('main.js');
|
||||
|
||||
return {css: css, js: js};
|
||||
}
|
||||
|
||||
|
||||
function loadAssets(css, js) {
|
||||
for(var i = 0; i < css.length; i++) {
|
||||
loadCss(css[i]);
|
||||
}
|
||||
|
||||
for(i = 0; i < js.length; i++) {
|
||||
loadJs(js[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function loadCss(url) {
|
||||
var link = document.createElement("link");
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.href = url;
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
}
|
||||
|
||||
function loadJs(url) {
|
||||
if(!url) return;
|
||||
var script = document.createElement("script");
|
||||
script.src = url;
|
||||
document.getElementsByTagName("head")[0].appendChild(script);
|
||||
}
|
||||
});
|
33
test/main.js
Normal file
33
test/main.js
Normal file
@ -0,0 +1,33 @@
|
||||
//detect version of jquery from url param, e.g. 'jquery=1.7.2'
|
||||
var jqver = decodeURIComponent((new RegExp('[?|&]' + 'jquery' + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
|
||||
jqurl = jqver ? "http://ajax.googleapis.com/ajax/libs/jquery/"+jqver+"/jquery.min.js" : "libs/jquery/jquery-1.8.2.min.js";
|
||||
|
||||
require(["loader", jqurl], function(loader) {
|
||||
|
||||
requirejs.config(loader.getConfig("../src"));
|
||||
|
||||
require(['element/editable-element',
|
||||
'test/libs/mockjax/jquery.mockjax'
|
||||
],
|
||||
function() {
|
||||
//disable effects
|
||||
$.fx.off = true;
|
||||
$.support.transition = false;
|
||||
|
||||
var params = loader.getParams();
|
||||
|
||||
require([
|
||||
'test/mocks',
|
||||
'test/unit/common',
|
||||
'test/unit/text',
|
||||
'test/unit/textarea',
|
||||
'test/unit/select',
|
||||
'test/unit/checklist',
|
||||
'test/unit/api',
|
||||
(params.f === 'bootstrap') ? 'test/unit/date' : 'test/unit/dateui'
|
||||
], function() {
|
||||
QUnit.load();
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
});
|
@ -57,7 +57,7 @@ $(function () {
|
||||
|
||||
});
|
||||
|
||||
// usefull functions
|
||||
// useful functions
|
||||
|
||||
function tip(e) {
|
||||
return e.data('editableContainer').tip();
|
||||
|
35
test/require.js
Normal file
35
test/require.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
Available via the MIT or new BSD license.
|
||||
see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
var requirejs,require,define;
|
||||
(function(Y){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function x(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function r(b,c){return da.call(b,c)}function i(b,c){return r(b,c)&&b[c]}function E(b,c){for(var d in b)if(r(b,d)&&c(b[d],d))break}function Q(b,c,d,i){c&&E(c,function(c,h){if(d||!r(b,h))i&&"string"!==typeof c?(b[h]||(b[h]={}),Q(b[h],
|
||||
c,d,i)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function Z(b){if(!b)return b;var c=Y;x(b.split("."),function(b){c=c[b]});return c}function J(b,c,d,i){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=i;d&&(c.originalError=d);return c}function ea(b){function c(a,g,v){var e,n,b,c,d,j,f,h=g&&g.split("/");e=h;var l=m.map,k=l&&l["*"];if(a&&"."===a.charAt(0))if(g){e=i(m.pkgs,g)?h=[g]:h.slice(0,h.length-1);g=a=e.concat(a.split("/"));
|
||||
for(e=0;g[e];e+=1)if(n=g[e],"."===n)g.splice(e,1),e-=1;else if(".."===n)if(1===e&&(".."===g[2]||".."===g[0]))break;else 0<e&&(g.splice(e-1,2),e-=2);e=i(m.pkgs,g=a[0]);a=a.join("/");e&&a===g+"/"+e.main&&(a=g)}else 0===a.indexOf("./")&&(a=a.substring(2));if(v&&(h||k)&&l){g=a.split("/");for(e=g.length;0<e;e-=1){b=g.slice(0,e).join("/");if(h)for(n=h.length;0<n;n-=1)if(v=i(l,h.slice(0,n).join("/")))if(v=i(v,b)){c=v;d=e;break}if(c)break;!j&&(k&&i(k,b))&&(j=i(k,b),f=e)}!c&&j&&(c=j,d=f);c&&(g.splice(0,d,
|
||||
c),a=g.join("/"))}return a}function d(a){z&&x(document.getElementsByTagName("script"),function(g){if(g.getAttribute("data-requiremodule")===a&&g.getAttribute("data-requirecontext")===j.contextName)return g.parentNode.removeChild(g),!0})}function y(a){var g=i(m.paths,a);if(g&&I(g)&&1<g.length)return d(a),g.shift(),j.require.undef(a),j.require([a]),!0}function f(a){var g,b=a?a.indexOf("!"):-1;-1<b&&(g=a.substring(0,b),a=a.substring(b+1,a.length));return[g,a]}function h(a,g,b,e){var n,u,d=null,h=g?g.name:
|
||||
null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(L+=1));a=f(a);d=a[0];a=a[1];d&&(d=c(d,h,e),u=i(p,d));a&&(d?k=u&&u.normalize?u.normalize(a,function(a){return c(a,h,e)}):c(a,h,e):(k=c(a,h,e),a=f(k),d=a[0],k=a[1],b=!0,n=j.nameToUrl(k)));b=d&&!u&&!b?"_unnormalized"+(M+=1):"";return{prefix:d,name:k,parentMap:g,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(d?d+"!"+k:k)+b}}function q(a){var g=a.id,b=i(k,g);b||(b=k[g]=new j.Module(a));return b}function s(a,g,b){var e=a.id,n=i(k,e);if(r(p,e)&&(!n||n.defineEmitComplete))"defined"===
|
||||
g&&b(p[e]);else q(a).on(g,b)}function C(a,g){var b=a.requireModules,e=!1;if(g)g(a);else if(x(b,function(g){if(g=i(k,g))g.error=a,g.events.error&&(e=!0,g.emit("error",a))}),!e)l.onError(a)}function w(){R.length&&(fa.apply(F,[F.length-1,0].concat(R)),R=[])}function A(a,g,b){var e=a.map.id;a.error?a.emit("error",a.error):(g[e]=!0,x(a.depMaps,function(e,c){var d=e.id,h=i(k,d);h&&(!a.depMatched[c]&&!b[d])&&(i(g,d)?(a.defineDep(c,p[d]),a.check()):A(h,g,b))}),b[e]=!0)}function B(){var a,g,b,e,n=(b=1E3*m.waitSeconds)&&
|
||||
j.startTime+b<(new Date).getTime(),c=[],h=[],f=!1,l=!0;if(!T){T=!0;E(k,function(b){a=b.map;g=a.id;if(b.enabled&&(a.isDefine||h.push(b),!b.error))if(!b.inited&&n)y(g)?f=e=!0:(c.push(g),d(g));else if(!b.inited&&(b.fetched&&a.isDefine)&&(f=!0,!a.prefix))return l=!1});if(n&&c.length)return b=J("timeout","Load timeout for modules: "+c,null,c),b.contextName=j.contextName,C(b);l&&x(h,function(a){A(a,{},{})});if((!n||e)&&f)if((z||$)&&!U)U=setTimeout(function(){U=0;B()},50);T=!1}}function D(a){r(p,a[0])||
|
||||
q(h(a[0],null,!0)).init(a[1],a[2])}function G(a){var a=a.currentTarget||a.srcElement,b=j.onScriptLoad;a.detachEvent&&!V?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=j.onScriptError;(!a.detachEvent||V)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function K(){var a;for(w();F.length;){a=F.shift();if(null===a[0])return C(J("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));D(a)}}var T,W,j,N,U,m={waitSeconds:7,
|
||||
baseUrl:"./",paths:{},pkgs:{},shim:{},map:{},config:{}},k={},X={},F=[],p={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=j.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m.config&&i(m.config,a.map.id)||{}},exports:p[a.map.id]}}};W=function(a){this.events=i(X,a.id)||{};this.map=a;this.shim=
|
||||
i(m.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};W.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=
|
||||
b)},fetch:function(){if(!this.fetched){this.fetched=!0;j.startTime=(new Date).getTime();var a=this.map;if(this.shim)j.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;S[a]||(S[a]=!0,j.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,n=this.factory;
|
||||
if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(H(n)){if(this.events.error)try{e=j.execCb(c,n,b,e)}catch(d){a=d}else e=j.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",C(this.error=a)}else e=n;this.exports=e;if(this.map.isDefine&&
|
||||
!this.ignore&&(p[c]=e,l.onResourceLoad))l.onResourceLoad(j,this.map,this.depMaps);delete k[c];this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=h(a.prefix);this.depMaps.push(d);s(d,"defined",t(this,function(e){var n,d;d=this.map.name;var v=this.map.parentMap?this.map.parentMap.name:null,f=j.makeRequire(a.parentMap,{enableBuildCallback:!0,
|
||||
skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,v,!0)})||""),e=h(a.prefix+"!"+d,this.map.parentMap),s(e,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=i(k,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",t(this,function(a){this.emit("error",a)}));d.enable()}}else n=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=t(this,function(a){this.inited=!0;this.error=
|
||||
a;a.requireModules=[b];E(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&delete k[a.map.id]});C(a)}),n.fromText=t(this,function(e,c){var d=a.name,u=h(d),v=O;c&&(e=c);v&&(O=!1);q(u);r(m.config,b)&&(m.config[d]=m.config[b]);try{l.exec(e)}catch(k){throw Error("fromText eval for "+d+" failed: "+k);}v&&(O=!0);this.depMaps.push(u);j.completeLoad(d);f([d],n)}),e.load(a.name,f,n,m)}));j.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;x(this.depMaps,t(this,function(a,
|
||||
b){var c,e;if("string"===typeof a){a=h(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=i(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",t(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&s(a,"error",this.errback)}c=a.id;e=k[c];!r(N,c)&&(e&&!e.enabled)&&j.enable(a,this)}));E(this.pluginMaps,t(this,function(a){var b=i(k,a.id);b&&!b.enabled&&j.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=
|
||||
this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){x(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};j={config:m,contextName:b,registry:k,defined:p,urlFetched:S,defQueue:F,Module:W,makeModuleMap:h,nextTick:l.nextTick,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=m.pkgs,c=m.shim,e={paths:!0,config:!0,map:!0};E(a,function(a,b){e[b]?"map"===b?Q(m[b],a,!0,!0):Q(m[b],a,!0):m[b]=a});a.shim&&(E(a.shim,function(a,
|
||||
b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=j.makeShimExports(a);c[b]=a}),m.shim=c);a.packages&&(x(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ga,"").replace(aa,"")}}),m.pkgs=b);E(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=h(b))});if(a.deps||a.callback)j.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Y,arguments));
|
||||
return b||a.exports&&Z(a.exports)}},makeRequire:function(a,d){function f(e,c,u){var i,m;d.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return C(J("requireargs","Invalid require call"),u);if(a&&r(N,e))return N[e](k[a.id]);if(l.get)return l.get(j,e,a);i=h(e,a,!1,!0);i=i.id;return!r(p,i)?C(J("notloaded",'Module name "'+i+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[i]}K();j.nextTick(function(){K();m=q(h(null,a));m.skipMap=d.skipMap;
|
||||
m.init(e,c,u,{enabled:!0});B()});return f}d=d||{};Q(f,{isBrowser:z,toUrl:function(b){var d=b.lastIndexOf("."),g=null;-1!==d&&(g=b.substring(d,b.length),b=b.substring(0,d));return j.nameToUrl(c(b,a&&a.id,!0),g)},defined:function(b){return r(p,h(b,a,!1,!0).id)},specified:function(b){b=h(b,a,!1,!0).id;return r(p,b)||r(k,b)}});a||(f.undef=function(b){w();var c=h(b,a,!0),d=i(k,b);delete p[b];delete S[c.url];delete X[b];d&&(d.events.defined&&(X[b]=d.events),delete k[b])});return f},enable:function(a){i(k,
|
||||
a.id)&&q(a).enable()},completeLoad:function(a){var b,c,d=i(m.shim,a)||{},h=d.exports;for(w();F.length;){c=F.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);D(c)}c=i(k,a);if(!b&&!r(p,a)&&c&&!c.inited){if(m.enforceDefine&&(!h||!Z(h)))return y(a)?void 0:C(J("nodefine","No define call for "+a,null,[a]));D([a,d.deps||[],d.exportsFn])}B()},nameToUrl:function(a,b){var c,d,h,f,j,k;if(l.jsExtRegExp.test(a))f=a+(b||"");else{c=m.paths;d=m.pkgs;f=a.split("/");for(j=f.length;0<j;j-=1)if(k=
|
||||
f.slice(0,j).join("/"),h=i(d,k),k=i(c,k)){I(k)&&(k=k[0]);f.splice(0,j,k);break}else if(h){c=a===h.name?h.location+"/"+h.main:h.location;f.splice(0,j,c);break}f=f.join("/");f+=b||(/\?/.test(f)?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":m.baseUrl)+f}return m.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+m.urlArgs):f},load:function(a,b){l.load(j,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ha.test((a.currentTarget||a.srcElement).readyState))P=
|
||||
null,a=G(a),j.completeLoad(a.id)},onScriptError:function(a){var b=G(a);if(!y(b.id))return C(J("scripterror","Script error",a,[b.id]))}};j.require=j.makeRequire();return j}var l,w,A,D,s,G,P,K,ba,ca,ia=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ja=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,aa=/\.js$/,ga=/^\.\//;w=Object.prototype;var L=w.toString,da=w.hasOwnProperty,fa=Array.prototype.splice,z=!!("undefined"!==typeof window&&navigator&&document),$=!z&&"undefined"!==typeof importScripts,ha=z&&
|
||||
"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,V="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),B={},q={},R=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(H(requirejs))return;q=requirejs;requirejs=void 0}"undefined"!==typeof require&&!H(require)&&(q=require,require=void 0);l=requirejs=function(b,c,d,y){var f,h="_";!I(b)&&"string"!==typeof b&&(f=b,I(c)?(b=c,c=d,d=y):b=[]);f&&f.context&&(h=f.context);(y=i(B,h))||(y=B[h]=l.s.newContext(h));
|
||||
f&&y.configure(f);return y.require(b,c,d)};l.config=function(b){return l(b)};l.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=l);l.version="2.1.2";l.jsExtRegExp=/^\/|:|\?|\.js$/;l.isBrowser=z;w=l.s={contexts:B,newContext:ea};l({});x(["toUrl","undef","defined","specified"],function(b){l[b]=function(){var c=B._;return c.require[b].apply(c,arguments)}});if(z&&(A=w.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))A=
|
||||
w.head=D.parentNode;l.onError=function(b){throw b;};l.load=function(b,c,d){var i=b&&b.config||{},f;if(z)return f=i.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),f.type=i.scriptType||"text/javascript",f.charset="utf-8",f.async=!0,f.setAttribute("data-requirecontext",b.contextName),f.setAttribute("data-requiremodule",c),f.attachEvent&&!(f.attachEvent.toString&&0>f.attachEvent.toString().indexOf("[native code"))&&!V?(O=!0,f.attachEvent("onreadystatechange",
|
||||
b.onScriptLoad)):(f.addEventListener("load",b.onScriptLoad,!1),f.addEventListener("error",b.onScriptError,!1)),f.src=d,K=f,D?A.insertBefore(f,D):A.appendChild(f),K=null,f;$&&(importScripts(d),b.completeLoad(c))};z&&M(document.getElementsByTagName("script"),function(b){A||(A=b.parentNode);if(s=b.getAttribute("data-main"))return q.baseUrl||(G=s.split("/"),ba=G.pop(),ca=G.length?G.join("/")+"/":"./",q.baseUrl=ca,s=ba),s=s.replace(aa,""),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var i,
|
||||
f;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=[]);!c.length&&H(d)&&d.length&&(d.toString().replace(ia,"").replace(ja,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c));if(O){if(!(i=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),i=P;i&&(b||(b=i.getAttribute("data-requiremodule")),f=B[i.getAttribute("data-requirecontext")])}(f?f.defQueue:R).push([b,c,d])};define.amd=
|
||||
{jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this);
|
170
test/unit/api.js
170
test/unit/api.js
@ -68,43 +68,7 @@ $(function () {
|
||||
ok(!('dob' in values), 'date value not present') ;
|
||||
});
|
||||
|
||||
/*
|
||||
//deprecated in 2.0
|
||||
asyncTest("'update' event", function () {
|
||||
expect(2);
|
||||
var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable(),
|
||||
e_nopk = $('<a href="#" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable(),
|
||||
newVal = 'xyt';
|
||||
|
||||
e.on('update', function() {
|
||||
equal($(this).data('editable').value, newVal, 'triggered update after submit');
|
||||
});
|
||||
|
||||
e_nopk.on('update', function() {
|
||||
equal($(this).data('editable').value, newVal, 'triggered update after no-submit');
|
||||
});
|
||||
|
||||
e_nopk.click();
|
||||
var p = e_nopk.data('popover').$tip;
|
||||
p.find('input').val(newVal);
|
||||
p.find('form').submit();
|
||||
|
||||
e.click();
|
||||
p = tip(e);
|
||||
p.find('input').val(newVal);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
e.remove();
|
||||
e_nopk.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
});
|
||||
*/
|
||||
|
||||
/*
|
||||
//deprecated in 2.0
|
||||
test("'init' event", function () {
|
||||
test("'init' event", function () {
|
||||
expect(1);
|
||||
var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo('#qunit-fixture');
|
||||
|
||||
@ -113,74 +77,11 @@ $(function () {
|
||||
});
|
||||
|
||||
e.editable();
|
||||
});
|
||||
*/
|
||||
|
||||
asyncTest("'render' event for text", function () {
|
||||
expect(4);
|
||||
var val = 'afas',
|
||||
e = $('<a href="#" data-pk="1" data-type="text" data-url="post.php" data-name="text1">'+val+'</a>').appendTo(fx),
|
||||
isInit = true;
|
||||
|
||||
e.on('render', function(e, editable) {
|
||||
equal(editable.isInit, isInit, 'isInit flag correct');
|
||||
equal(editable.value, val, 'value correct');
|
||||
});
|
||||
|
||||
e.editable();
|
||||
|
||||
isInit = false;
|
||||
val = '123';
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
p.find('input[type=text]').val(val);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
asyncTest("'render' event for select", function () {
|
||||
expect(4);
|
||||
var val = '1',
|
||||
e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text1" data-value="'+val+'"></a>').appendTo(fx),
|
||||
isInit = true;
|
||||
|
||||
e.on('render', function(e, editable) {
|
||||
equal(editable.isInit, isInit, 'isInit flag correct');
|
||||
equal(editable.value, val, 'init triggered, value correct');
|
||||
});
|
||||
|
||||
e.editable({
|
||||
source: 'groups.php',
|
||||
autotext: 'always'
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
isInit = false;
|
||||
val = '3';
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
p.find('select').val(val);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
|
||||
asyncTest("events: shown / cancel / hidden", function () {
|
||||
expect(3);
|
||||
var val = '1',
|
||||
});
|
||||
|
||||
asyncTest("events: shown / hidden (reason: cancel, onblur, manual)", function () {
|
||||
expect(11);
|
||||
var val = '1', test_reason,
|
||||
e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx);
|
||||
|
||||
e.on('shown', function(event) {
|
||||
@ -188,14 +89,8 @@ $(function () {
|
||||
equal(editable.value, val, 'shown triggered, value correct');
|
||||
});
|
||||
|
||||
e.on('cancel', function(event) {
|
||||
var editable = $(this).data('editable');
|
||||
ok(true, 'cancel triggered');
|
||||
});
|
||||
|
||||
e.on('hidden', function(event) {
|
||||
var editable = $(this).data('editable');
|
||||
ok(true, 'hidden triggered');
|
||||
e.on('hidden', function(event, reason) {
|
||||
ok((reason === test_reason) || (test_reason === 'manual' && reason === undefined), 'hidden triggered, reason ok');
|
||||
});
|
||||
|
||||
e.editable({
|
||||
@ -206,41 +101,54 @@ $(function () {
|
||||
|
||||
setTimeout(function() {
|
||||
var p = tip(e);
|
||||
p.find('button[type=button]').click();
|
||||
setTimeout(function() {
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
test_reason = 'cancel'
|
||||
p.find('button[type=button]').click(); //cancel
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
|
||||
test_reason = 'onblur'
|
||||
e.click();
|
||||
p = tip(e);
|
||||
ok(p.is(':visible'), 'popover shown');
|
||||
e.parent().click();
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
|
||||
test_reason = 'manual'
|
||||
e.click();
|
||||
p = tip(e);
|
||||
ok(p.is(':visible'), 'popover shown');
|
||||
e.editable('hide');
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
asyncTest("event: save / hidden", function () {
|
||||
asyncTest("event: save / hidden (reason: save)", function () {
|
||||
expect(2);
|
||||
var val = '1',
|
||||
e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx);
|
||||
|
||||
e.on('save', function(event, params) {
|
||||
var editable = $(this).data('editable');
|
||||
equal(params.newValue, 2, 'save triggered, value correct');
|
||||
});
|
||||
|
||||
e.on('hidden', function(event) {
|
||||
var editable = $(this).data('editable');
|
||||
ok(true, 'hidden triggered');
|
||||
e.on('hidden', function(event, reason) {
|
||||
equal(reason, 'save', 'hidden triggered, reason ok');
|
||||
});
|
||||
|
||||
e.editable({
|
||||
source: 'groups.php',
|
||||
source: groups,
|
||||
});
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
p.find('select').val(2);
|
||||
p.find('form').submit();
|
||||
|
||||
|
||||
setTimeout(function() {
|
||||
p.find('button[type=button]').click();
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
@ -305,7 +213,6 @@ $(function () {
|
||||
});
|
||||
|
||||
asyncTest("'submit' method: client and server validation", function () {
|
||||
expect(6);
|
||||
var ev1 = 'ev1',
|
||||
ev2 = 'ev2',
|
||||
e1v = 'e1v',
|
||||
@ -322,6 +229,7 @@ $(function () {
|
||||
equal(settings.data.text, ev2, 'first value ok');
|
||||
equal(settings.data.text1, e1v, 'second value ok');
|
||||
equal(settings.data.a, 123, 'custom data ok');
|
||||
equal(settings.type, 'PUT', 'ajaxOptions ok');
|
||||
this.responseText = {errors: {
|
||||
text1: 'server-invalid'
|
||||
}
|
||||
@ -348,11 +256,13 @@ $(function () {
|
||||
data: {a: 123},
|
||||
error: function(data) {
|
||||
equal(data.errors.text1, 'server-invalid', 'server validation error ok');
|
||||
|
||||
e.remove();
|
||||
e1.remove();
|
||||
start();
|
||||
}
|
||||
},
|
||||
ajaxOptions: {
|
||||
type: 'PUT'
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@ -431,4 +341,4 @@ $(function () {
|
||||
equal(e.text(), groups[2], 'new text shown correctly');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -4,21 +4,28 @@ $(function () {
|
||||
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 = '-',
|
||||
var sep = '<br>',
|
||||
newValue,
|
||||
e = $('<a href="#" data-type="checklist" data-url="post.php"></a>').appendTo(fx).editable({
|
||||
e = $('<a href="#" data-type="checklist" data-url="post-checklist.php"></a>').appendTo(fx).editable({
|
||||
pk: 1,
|
||||
source: groupsArr,
|
||||
value: [2, 3],
|
||||
viewseparator: sep
|
||||
value: [2, 3]
|
||||
});
|
||||
|
||||
equal(e.text(), groups[2]+sep+groups[3], 'autotext ok');
|
||||
equal(e.html(), groups[2]+sep+groups[3], 'autotext ok');
|
||||
|
||||
$.mockjax({
|
||||
url: 'post-checklist.php',
|
||||
response: function(settings) {
|
||||
ok($.isArray(settings.data.value), 'value submitted as array');
|
||||
equal(settings.data.value.sort().join(''), [newValue, 3].join(''), 'submitted array correct');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
@ -28,8 +35,8 @@ $(function () {
|
||||
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();
|
||||
p.find('input[type="checkbox"]:checked').eq(0).click(); //uncheck 2
|
||||
p.find('input[type="checkbox"]').first().click(); //check first
|
||||
newValue = p.find('input[type="checkbox"]').first().val();
|
||||
|
||||
//submit
|
||||
@ -39,7 +46,7 @@ $(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');
|
||||
equal(e.html(), groups[newValue]+'<br>'+groups[3], 'new text ok');
|
||||
|
||||
// open container again to see what checked
|
||||
e.click()
|
||||
@ -54,40 +61,5 @@ $(function () {
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
});
|
@ -62,9 +62,9 @@
|
||||
// equal(e3.data('editable').lastSavedValue, v, 'lastSavedValue taken from text correctly (escaped)');
|
||||
});
|
||||
|
||||
test("should take container's title from json options", function () {
|
||||
test("container's title and placement from json options", function () {
|
||||
//do not test inline
|
||||
if(fc.c === 'inline') {
|
||||
if($.fn.editableContainer.Constructor.prototype.containerName === 'editableform') {
|
||||
expect(0);
|
||||
return;
|
||||
}
|
||||
@ -81,7 +81,7 @@
|
||||
ok(p.is(':visible'), 'popover shown');
|
||||
|
||||
//todo: for jqueryui phantomjs calcs wrong position. Need investigation
|
||||
if(!$.browser.webkit && fc.f !== 'jqueryui') {
|
||||
if(!$.browser.webkit && $.fn.editableContainer.Constructor.prototype.containerName !== 'tooltip') {
|
||||
ok(p.offset().top > e.offset().top, 'placement ok');
|
||||
}
|
||||
|
||||
@ -362,36 +362,88 @@
|
||||
ok(!p.find('.editable-buttons').length, '.editable-buttons block not rendered');
|
||||
});
|
||||
|
||||
//unfortunatly, testing this feature does not always work in browsers. Tested manually.
|
||||
/*
|
||||
test("enablefocus option", function () {
|
||||
// focusing not passed in phantomjs
|
||||
if($.browser.webkit) {
|
||||
ok(true, 'skipped in PhantomJS');
|
||||
return;
|
||||
}
|
||||
|
||||
var e = $('<a href="#">abc</a>').appendTo('#qunit-fixture').editable({
|
||||
enablefocus: true
|
||||
}),
|
||||
e1 = $('<a href="#">abcd</a>').appendTo('#qunit-fixture').editable({
|
||||
enablefocus: false
|
||||
});
|
||||
|
||||
e.click()
|
||||
var p = tip(e);
|
||||
ok(p.is(':visible'), 'popover 1 visible');
|
||||
p.find('button[type=button]').click();
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
ok(e.is(':focus'), 'element 1 is focused');
|
||||
|
||||
e1.click()
|
||||
p = tip(e1);
|
||||
ok(p.is(':visible'), 'popover 2 visible');
|
||||
p.find('button[type=button]').click();
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
ok(!e1.is(':focus'), 'element 2 is not focused');
|
||||
});
|
||||
*/
|
||||
asyncTest("composite pk defined as json in data-pk attribute", function () {
|
||||
var e = $('<a href="#" data-pk="{a: 1, b: 2}" data-url="post-pk.php">abc</a>').appendTo(fx).editable({
|
||||
name: 'username'
|
||||
}),
|
||||
newText = 'cd<e>;"'
|
||||
|
||||
$.mockjax({
|
||||
url: 'post-pk.php',
|
||||
response: function(settings) {
|
||||
equal(settings.data.pk.a, 1, 'first part ok');
|
||||
equal(settings.data.pk.b, 2, 'second part ok');
|
||||
}
|
||||
});
|
||||
|
||||
e.click()
|
||||
var p = tip(e);
|
||||
|
||||
ok(p.find('input[type=text]').length, 'input exists')
|
||||
p.find('input').val(newText);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
asyncTest("savenochange: false", function () {
|
||||
var v = 'abc',
|
||||
e = $('<a href="#" data-type="text" data-pk="1" data-url="post-no.php" data-name="text1">'+v+'</a>').appendTo(fx).editable({
|
||||
savenochange: false
|
||||
}),
|
||||
req = 0;
|
||||
|
||||
$.mockjax({
|
||||
url: 'post-no.php',
|
||||
response: function() {
|
||||
req++;
|
||||
}
|
||||
});
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
ok(p.is(':visible'), 'popover visible');
|
||||
p.find('input[type="text"]').val(v);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
equal(req, 0, 'request was not performed');
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
});
|
||||
|
||||
asyncTest("savenochange: true", function () {
|
||||
var v = 'abc',
|
||||
e = $('<a href="#" data-type="text" data-pk="1" data-url="post-yes.php" data-name="text1">'+v+'</a>').appendTo(fx).editable({
|
||||
savenochange: true
|
||||
}),
|
||||
req = 0;
|
||||
|
||||
$.mockjax({
|
||||
url: 'post-yes.php',
|
||||
response: function() {
|
||||
req++;
|
||||
}
|
||||
});
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
ok(p.is(':visible'), 'popover visible');
|
||||
p.find('input[type="text"]').val(v);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
equal(req, 1, 'request was performed');
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
});
|
||||
|
||||
}(jQuery));
|
@ -14,9 +14,7 @@ $(function () {
|
||||
}
|
||||
|
||||
asyncTest("container should contain datepicker with value and save new entered date", function () {
|
||||
expect(9);
|
||||
|
||||
$.fn.editableform.types.date.defaults.datepicker.weekStart = 1;
|
||||
$.fn.editabletypes.date.defaults.datepicker.weekStart = 1;
|
||||
|
||||
var d = '15.05.1984',
|
||||
e = $('<a href="#" data-type="date" data-pk="1" data-url="post-date.php">'+d+'</a>').appendTo(fx).editable({
|
||||
@ -39,8 +37,10 @@ $(function () {
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
ok(p.find('.datepicker').is(':visible'), 'datepicker exists');
|
||||
ok(p.find('.datepicker').find('.datepicker-days').is(':visible'), 'datepicker days visible');
|
||||
|
||||
equal(frmt(e.data('editable').value, f), d, 'day set correct');
|
||||
ok(p.find('td.day.active').is(':visible'), 'active day is visible');
|
||||
equal(p.find('td.day.active').text(), 15, 'day shown correct');
|
||||
equal(p.find('th.dow').eq(0).text(), 'Mo', 'weekStart correct');
|
||||
|
||||
@ -60,7 +60,7 @@ $(function () {
|
||||
|
||||
asyncTest("viewformat, init by text", function () {
|
||||
|
||||
$.fn.editableform.types.date.defaults.datepicker.weekStart = 1;
|
||||
$.fn.editabletypes.date.defaults.datepicker.weekStart = 1;
|
||||
|
||||
var dview = '15/05/1984',
|
||||
d = '1984-05-15',
|
||||
|
@ -345,7 +345,7 @@ $(function () {
|
||||
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-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-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.editabletypes.select.defaults.sourceError;
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
@ -363,6 +363,55 @@ $(function () {
|
||||
});
|
||||
|
||||
|
||||
asyncTest("sourceCache: false", function () {
|
||||
var e = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="2" data-url="post.php" data-source="groups-cache-false.php">customer</a>').appendTo(fx).editable({
|
||||
sourceCache: false
|
||||
}),
|
||||
e1 = $('<a href="#" data-type="select" data-pk="1" id="name1" data-value="2" data-url="post.php" data-source="groups-cache-false.php">customer</a>').appendTo(fx).editable({
|
||||
sourceCache: false
|
||||
}),
|
||||
req = 0;
|
||||
|
||||
$.mockjax({
|
||||
url: 'groups-cache-false.php',
|
||||
response: function() {
|
||||
req++;
|
||||
this.responseText = groups;
|
||||
}
|
||||
});
|
||||
|
||||
//click first
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
|
||||
setTimeout(function() {
|
||||
ok(p.is(':visible'), 'popover visible');
|
||||
equal(p.find('select').find('option').length, size, 'options loaded');
|
||||
equal(req, 1, 'one request performed');
|
||||
|
||||
p.find('button[type=button]').click();
|
||||
ok(!p.is(':visible'), 'popover was removed');
|
||||
|
||||
//click second
|
||||
e1.click();
|
||||
p = tip(e1);
|
||||
|
||||
setTimeout(function() {
|
||||
ok(p.is(':visible'), 'popover2 visible');
|
||||
equal(p.find('select').find('option').length, size, 'options loaded');
|
||||
equal(req, 2, 'second request performed');
|
||||
|
||||
p.find('button[type=button]').click();
|
||||
ok(!p.is(':visible'), 'popover was removed');
|
||||
|
||||
e.remove();
|
||||
e1.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
|
||||
asyncTest("autotext: auto", function () {
|
||||
expect(3);
|
||||
@ -474,6 +523,60 @@ $(function () {
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
asyncTest("'display' callback", function () {
|
||||
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php"></a>').appendTo(fx).editable({
|
||||
pk: 1,
|
||||
source: groups,
|
||||
display: function(value, sourceData) {
|
||||
var els = $.grep(sourceData, function(o) {return o.value == value;});
|
||||
$(this).text('qq' + els[0].text);
|
||||
}
|
||||
}),
|
||||
selected = 3;
|
||||
|
||||
equal(e.text(), 'qq'+groups[2], 'autotext display ok');
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
|
||||
p.find('select').val(selected);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
equal(e.data('editable').value, selected, 'new value saved')
|
||||
equal(e.text(), 'qq'+groups[selected], 'text shown correctly')
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
});
|
||||
|
||||
asyncTest("submit by enter", function () {
|
||||
var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php"></a>').appendTo(fx).editable({
|
||||
pk: 1,
|
||||
source: groups
|
||||
}),
|
||||
selected = 3;
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
p.find('select').val(selected);
|
||||
|
||||
var event = jQuery.Event("keydown");
|
||||
event.which = 13;
|
||||
|
||||
p.find('select').trigger(event);
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
equal(e.data('editable').value, selected, 'new value saved')
|
||||
equal(e.text(), groups[selected], 'text shown correctly')
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
|
@ -43,16 +43,16 @@ $(function () {
|
||||
asyncTest("should load correct value and save new entered text (and value)", function () {
|
||||
var v = 'ab<b>"',
|
||||
esc_v = $('<div>').text(v).html(),
|
||||
e = $('<a href="#" data-pk="1" data-name="text1" data-url="post-text.php" data-params="{\'q\': \'w\'}">'+esc_v+'</a>').appendTo(fx).editable({
|
||||
success: function(data) {
|
||||
return false;
|
||||
e = $('<a href="#" data-pk="1" data-name="text1" data-url="post-text-main.php" data-params="{\'q\': \'w\'}">'+esc_v+'</a>').appendTo(fx).editable({
|
||||
success: function(response, newValue) {
|
||||
equal(newValue, newText, 'new value in success correct');
|
||||
}
|
||||
}),
|
||||
data,
|
||||
newText = 'cd<e>;"';
|
||||
newText = 'cd>e>;"';
|
||||
|
||||
$.mockjax({
|
||||
url: 'post-text.php',
|
||||
url: 'post-text-main.php',
|
||||
response: function(settings) {
|
||||
data = settings.data;
|
||||
}
|
||||
@ -61,13 +61,13 @@ $(function () {
|
||||
|
||||
e.click()
|
||||
var p = tip(e);
|
||||
ok(p.is(':visible'), 'popover visible')
|
||||
ok(p.find('.editableform-loading').length, 'loading class exists')
|
||||
ok(!p.find('.editableform-loading').is(':visible'), 'loading class is hidden')
|
||||
ok(p.find('input[type=text]').length, 'input exists')
|
||||
equal(p.find('input[type=text]').val(), v, 'input contain correct value')
|
||||
ok(p.is(':visible'), 'popover visible');
|
||||
ok(p.find('.editableform-loading').length, 'loading class exists');
|
||||
ok(!p.find('.editableform-loading').is(':visible'), 'loading class is hidden');
|
||||
ok(p.find('input[type=text]').length, 'input exists');
|
||||
equal(p.find('input[type=text]').val(), v, 'input contain correct value');
|
||||
p.find('input').val(newText);
|
||||
p.find('button[type=submit]').click();
|
||||
p.find('form').submit();
|
||||
ok(p.find('.editableform-loading').is(':visible'), 'loading class is visible');
|
||||
|
||||
setTimeout(function() {
|
||||
@ -88,7 +88,10 @@ $(function () {
|
||||
asyncTest("should show error on server validation", function () {
|
||||
var msg = 'required',
|
||||
e = $('<a href="#" data-name="text1">abc</a>').appendTo(fx).editable({
|
||||
validate: function(value) { if(value == '') return msg; }
|
||||
validate: function(value) {
|
||||
ok(this === e[0], 'scope is ok');
|
||||
if(value == '') return msg;
|
||||
}
|
||||
}),
|
||||
newText = '';
|
||||
|
||||
@ -149,34 +152,11 @@ $(function () {
|
||||
});
|
||||
*/
|
||||
|
||||
asyncTest("should not perform request if value not changed", function () {
|
||||
var e = $('<a href="#" data-pk="1" data-url="post-no.php" data-name="text1">abc</a>').appendTo(fx).editable(),
|
||||
req = 0;
|
||||
|
||||
$.mockjax({
|
||||
url: 'post-no.php',
|
||||
response: function() {
|
||||
req++;
|
||||
}
|
||||
});
|
||||
|
||||
e.click();
|
||||
var p = tip(e);
|
||||
ok(p.is(':visible'), 'popover visible');
|
||||
p.find('button[type=submit]').click();
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover closed');
|
||||
equal(req, 0, 'request was not performed');
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
});
|
||||
|
||||
asyncTest("should show error if success callback returns string", function () {
|
||||
var newText = 'cd<e>;"',
|
||||
e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({
|
||||
success: function(response, newValue) {
|
||||
ok(this === e[0], 'scope is ok');
|
||||
equal(newValue, newText, 'value in success passed correctly');
|
||||
return 'error';
|
||||
}
|
||||
@ -266,6 +246,7 @@ $(function () {
|
||||
var e = $('<a href="#" data-pk="1" data-url="post-resp.php">abc</a>').appendTo(fx).editable({
|
||||
name: 'username',
|
||||
params: function(params) {
|
||||
ok(this === e[0], 'scope is ok');
|
||||
equal(params.pk, 1, 'params in func already have values (pk)');
|
||||
return { q: 2, pk: 3 };
|
||||
},
|
||||
@ -328,11 +309,12 @@ $(function () {
|
||||
|
||||
|
||||
asyncTest("submit to url defined as function", function () {
|
||||
expect(3);
|
||||
expect(4);
|
||||
var newText = 'qwe',
|
||||
//should be called even without pk!
|
||||
e = $('<a href="#" data-pk1="1" id="a"></a>').appendTo(fx).editable({
|
||||
url: function(params) {
|
||||
ok(this === e[0], 'scope is ok');
|
||||
ok(params.value, newText, 'new text passed in users function');
|
||||
var d = new $.Deferred;
|
||||
return d.reject('my error');
|
||||
@ -472,6 +454,55 @@ $(function () {
|
||||
delete $.fn.editable.defaults.name;
|
||||
var e = $('<a href="#" id="cde">abc</a>').appendTo('#qunit-fixture').editable();
|
||||
equal(e.data('editable').options.name, 'cde', 'name is taken from id');
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("'display' callback", function () {
|
||||
var newText = 'cd<e>;"',
|
||||
e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({
|
||||
display: function(value) {
|
||||
ok(this === e[0], 'scope is ok');
|
||||
$(this).text('qq'+value);
|
||||
}
|
||||
});
|
||||
|
||||
e.click()
|
||||
var p = tip(e);
|
||||
|
||||
ok(p.find('input[type=text]').length, 'input exists')
|
||||
p.find('input').val(newText);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover was removed');
|
||||
equal(e.text(), 'qq'+newText, 'custom display ok');
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
asyncTest("display: false", function () {
|
||||
var newText = 'cd<e>;"',
|
||||
e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1" data-value="abc"></a>').appendTo(fx).editable({
|
||||
display: false
|
||||
});
|
||||
|
||||
ok(!e.text().length, 'element still empty, autotext did not display value');
|
||||
|
||||
e.click()
|
||||
var p = tip(e);
|
||||
|
||||
p.find('input').val(newText);
|
||||
p.find('form').submit();
|
||||
|
||||
setTimeout(function() {
|
||||
ok(!p.is(':visible'), 'popover was removed');
|
||||
ok(!e.text().length, 'element still empty, new value was not displayed');
|
||||
equal(e.data('editable').value, newText, 'new text saved to value');
|
||||
e.remove();
|
||||
start();
|
||||
}, timeout);
|
||||
|
||||
});
|
||||
|
||||
});
|
@ -34,8 +34,8 @@ $(function () {
|
||||
var e = $('<a href="#" data-pk="1" data-url="post.php">'+v1+'</a>').appendTo(fx).editable({
|
||||
type: 'textarea',
|
||||
send: 'ifpk',
|
||||
success: function(data) {
|
||||
return false;
|
||||
success: function(response, newvalue) {
|
||||
equal(newvalue, v2, 'value in success ok');
|
||||
}
|
||||
});
|
||||
|
||||
@ -93,7 +93,7 @@ $(function () {
|
||||
var p = tip(e);
|
||||
p.find('textarea').val(vnew);
|
||||
|
||||
event = jQuery.Event("keydown");
|
||||
var event = jQuery.Event("keydown");
|
||||
event.ctrlKey = true;
|
||||
event.which = 13;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user