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 = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').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 = $('<a href="#" data-type="select" data-value="2" data-url="post.php">customer</a>').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 = $('<a href="#" data-type="select" data-value="M" data-source=\'{"L":"Low", "": "None", "M": "Medium", "H": "High"}\'>customer</a>').appendTo('#qunit-fixture').editable({
              pk: 1