以下脚本允许jQueryUI的自动完成功能与xeditable一起使用,并且可以按照需要运行:
$(function(){
dialog.find('a.car').xEdit('autocomplete',{name:'carName', title:'Car Name', url: '/1.0/cars/', pk: carId, autocomplete: {
url: "/1.0/cars/",
params: {term:null, fields:['id','name']}
}});
});
$.fn.xEdit = function(type, options) {
var common={
placement: 'right',
ajaxOptions: {type: "PUT"},
send: 'always'
// pk: null, title: null, params: {name: null}, url: null, //Must be passed
}
// Not shown, but different actions will be performed based on "type"
options.params={name: options.name};
delete(options.name);
options.type='text';
//autocomplete is not used by xeditable but by jQueryUI autocomplete, but doesn't seem to hurt anything
this.editable($.extend({}, common, {value: null}, options))
.on('shown', function(e, editable) {
//console.log('on.show','this',this,'e',e,'editable',editable)
var elem=this;
var $input=editable.input.$input.val('');
var $button=$input.parent().next().find('button.editable-submit').css('opacity', 0.3)
.bind('click.prevent', function() {return false;});
var autocomplete={
source: function( request, response ) {
options.autocomplete.params.term=request.term;
$.getJSON( options.autocomplete.url, options.autocomplete.params, function(json) {
var data=[];
for (var j = 0; j < json.length; j++) {
data.push({id:json[j].id,label:json[j].name});
}
response(data);
} );
},
minLength: 2,
position: { my : "left top+20", at: "left bottom" },
select: function(e, ui) {
$input.blur();
$button.css('opacity', 1).unbind('click.prevent');
editable.option('params', {
value: ui.item.id,
name: options.params.name
});
}
};
if (typeof options.autocomplete.select != "undefined") autocomplete.select=options.autocomplete.select;
$input.focus(function() {
$button.css('opacity', 0.3).bind('click.prevent', function() {return false;});
})
.autocomplete(autocomplete)
.autocomplete('widget').click(function() {return false;});
});
break;
};
我现在希望能够使用select: function(e, ui) {...}
中定义的新函数覆盖xedit中的options
(以及后来的其他方法),并尝试以下方法:
$(function(){
dialog.find('a.car').xEdit('autocomplete',{name:'carName', title:'Car Name', url: '/1.0/cars/', pk: carId, autocomplete: {
url: "/1.0/cars/",
params: {term:null, fields:['id','name']},
select: function(e, ui) {
//Be able to do something different
$input.blur();
$button.css('opacity', 1).unbind('click.prevent');
editable.option('params', {
value: ui.item.id,
name: options.params.name,
model: 123
}
);
}
}});
});
但它会导致错误,指出e
,ui
,$input
,$button
,editable
,options
都未定义。我认为这是由于在不同的变量范围内定义新函数。
如何在一个变量范围内定义一个对象,然后对其应用另一个范围?
PS。我希望我这样做是非常难看的,如果有更漂亮的方式,请随时发表评论。
答案 0 :(得分:1)
好吧,我之前从未使用过这个xEdit插件,但你的问题与JavaScript有关,所以我可以给我两分钱。
在第一个示例中,select
处理程序可以访问这些变量,因为它在词法上绑定到外部函数的范围(shown
事件的处理程序)。在另一个函数中声明函数时,此构造称为闭包。内部函数,即使在其容器函数之外调用,也将始终记住其原始上下文。 这个链接是牢不可破的。
function a() {
const favoriteSport = 'Football';
const team = 'Packers';
return function(){
console.log(`My favorite sport and team are "${favoriteSport}" and "${team}" respectively`);
};
}
const b = a();
const c = b;
const d = c;
const e = d;
const anObject = { e };
// One does not simply forget its origins... =)
anObject.e(); //=> My favorite sport and team are "Football" and "Packers" respectively
// This is what you're doing...
anObject.e = function(){
console.log(`I really do love "${favoriteSport}" and the "${team}".`);
};
// BOOOM!
anObject.e(); //=> Uncaught ReferenceError: favoriteSport is not defined
当您在词汇上声明函数a
的函数b
时,a
无法访问b
内声明的任何变量}。 这就是你要做的事情。
因此,在声明函数后,无法更改函数的范围。
Here's a fabulous SO question有很多关于闭包如何工作的好答案。