diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 3996703..fdef278 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -5,6 +5,7 @@ X-editable changelog
Version 1.4.2 wip
----------------------------
+[enh] source defined as function now has scope of element and can return string used as url (vitalets)
[bug #99] select2 with Hierarchical Data (kev360)
[bug #81] wysihtml5: fix inserting image (vitalets)
[bug] remove $.browser from wysihtml5 input to support jQuery 1.9 (vitalets)
diff --git a/src/element/editable-element.js b/src/element/editable-element.js
index 10a4366..9836455 100644
--- a/src/element/editable-element.js
+++ b/src/element/editable-element.js
@@ -26,7 +26,9 @@ Makes editable any HTML element on the page. Applied as jQuery method.
//name
this.options.name = this.options.name || this.$element.attr('id');
- //create input of specified type. Input need already here to convert value for initial display (e.g. show text by id for select)
+ //create input of specified type. Input needed already here to convert value for initial display (e.g. show text by id for select)
+ //also we set scope option to have access to element inside input specific callbacks (e. g. source as function)
+ this.options.scope = this.$element[0];
this.input = $.fn.editableutils.createInput(this.options);
if(!this.input) {
return;
diff --git a/src/inputs/abstract.js b/src/inputs/abstract.js
index e32c844..c1ad480 100644
--- a/src/inputs/abstract.js
+++ b/src/inputs/abstract.js
@@ -186,7 +186,10 @@ To create your own input you can inherit from this class.
@type string
@default input-medium
**/
- inputclass: 'input-medium'
+ inputclass: 'input-medium',
+ //scope for external methods (e.g. source defined as function)
+ //for internal use only
+ scope: null
};
$.extend($.fn.editabletypes, {abstractinput: AbstractInput});
diff --git a/src/inputs/list.js b/src/inputs/list.js
index e5fcb00..d01de0b 100644
--- a/src/inputs/list.js
+++ b/src/inputs/list.js
@@ -70,12 +70,19 @@ List - abstract class for inputs that have source option loaded from js array or
error.call(this);
return;
}
+
+ var source = this.options.source;
+
+ //run source if it function
+ if ($.isFunction(source)) {
+ source = source.call(this.options.scope);
+ }
//loading from url
- if (typeof this.options.source === 'string') {
+ if (typeof source === 'string') {
//try to get from cache
if(this.options.sourceCache) {
- var cacheID = this.options.source,
+ var cacheID = source,
cache;
if (!$(document).data(cacheID)) {
@@ -108,7 +115,7 @@ List - abstract class for inputs that have source option loaded from js array or
//loading sourceData from server
$.ajax({
- url: this.options.source,
+ url: source,
type: 'get',
cache: false,
dataType: 'json',
@@ -143,12 +150,8 @@ List - abstract class for inputs that have source option loaded from js array or
}
}, this)
});
- } else { //options as json/array/function
- if ($.isFunction(this.options.source)) {
- this.sourceData = this.makeArray(this.options.source());
- } else {
- this.sourceData = this.makeArray(this.options.source);
- }
+ } else { //options as json/array
+ this.sourceData = this.makeArray(source);
if($.isArray(this.sourceData)) {
this.doPrepend();
@@ -165,16 +168,20 @@ List - abstract class for inputs that have source option loaded from js array or
}
if(!$.isArray(this.prependData)) {
+ //run prepend if it is function (once)
+ if ($.isFunction(this.options.prepend)) {
+ this.options.prepend = this.options.prepend.call(this.options.scope);
+ }
+
//try parse json in single quotes
this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true);
+
+ //convert prepend from string to object
if (typeof this.options.prepend === 'string') {
this.options.prepend = {'': this.options.prepend};
- }
- if (typeof this.options.prepend === 'function') {
- this.prependData = this.makeArray(this.options.prepend());
- } else {
- this.prependData = this.makeArray(this.options.prepend);
}
+
+ this.prependData = this.makeArray(this.options.prepend);
}
if($.isArray(this.prependData) && $.isArray(this.sourceData)) {
diff --git a/test/unit/select.js b/test/unit/select.js
index 93a0321..e4a34e3 100644
--- a/test/unit/select.js
+++ b/test/unit/select.js
@@ -105,11 +105,15 @@ $(function () {
ok(!p.is(':visible'), 'popover was removed');
});
- test("load options from function", function () {
+ test("load options from function returning array", function () {
var e = $('customer').appendTo('#qunit-fixture').editable({
pk: 1,
- prepend: 'prepend',
+ prepend: function() {
+ equal(this, e[0], 'prepend scope is element');
+ return 'prepend';
+ },
source: function() {
+ equal(this, e[0], 'source scope is element');
return groups;
}
});
@@ -124,6 +128,40 @@ $(function () {
ok(!p.is(':visible'), 'popover was removed');
});
+ asyncTest("load options from function returning URL", function () {
+ var e = $('customer').appendTo('#qunit-fixture').editable({
+ pk: 1,
+ //need to disable cache to force request
+ sourceCache: false,
+ source: function() {
+ equal(this, e[0], 'source scope is element');
+ return 'groups.php';
+ }
+ });
+
+ e.click();
+ var p = tip(e);
+
+ setTimeout(function() {
+ ok(p.is(':visible'), 'popover visible');
+ ok(p.find('select').length, 'select exists');
+ equal(p.find('select').find('option').length, size, 'options loaded');
+ equal(p.find('select').val(), e.data('editable').value, 'selected value correct') ;
+ p.find('.editable-cancel').click();
+ ok(!p.is(':visible'), 'popover was removed');
+
+ //open second time: items should not dublicate
+ e.click();
+
+ ok(p.find('select').length, 'select exists');
+ equal(p.find('select').find('option').length, size, 'options loaded');
+ equal(p.find('select').val(), e.data('editable').value, 'selected value correct') ;
+
+ e.remove();
+ start();
+ }, timeout);
+ });
+
test("load options from html (single quotes)", function () {
var e = $('customer').appendTo('#qunit-fixture').editable({
pk: 1