我的页面上有2个使用Ajax的元素。一个是简单的复选框(设置默认值),另一个是由链接触发的弹出窗口。弹出窗口必须加载一堆元素,所以我有一个'loading ...'叠加div,由ajaxStart()触发并隐藏在ajaxStop()。
除了为复选框和弹出窗口触发ajaxStart()加载叠加层外,一切正常。它对于复选框很烦人,因为它是我不想要的div的快速“闪现”。
我的问题:我如何仅针对页面上的特定元素触发AjaxStart而不是页面上的每个Ajax-able元素?
HTML
<input type="checkbox" id="defaultproject" />
<a class="openDialog" data-dialog-id="subscriberDialog" data-dialog-title="Project Subscriber" href="/Project/CreateSubscriber/1020" id="newsubscriber">Add Subscriber</a>
的Javascript
//POPUP
$(document).ready(function () {
$(".openDialog").live("click", function (e) {
e.preventDefault();
$("<div></div>")
.addClass("dialog")
.attr("id", $(this).attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this).attr("data-dialog-title"),
close: function () { location.reload() },
modal: true,
draggable: false,
resizable: false,
width: 500
})
.load(this.href);
});
$(".close").live("click", function (e) {
e.preventDefault();
$(this).closest(".dialog").dialog("close");
});
//CHECKBOX
$("#defaultproject").change(function ()
{
var isitchecked = document.getElementById("defaultproject").checked
$.ajax({
url: '@Url.Action("SetDefaultProject")',
data: {"id": ProjectId, "isitchecked": isitchecked },
type: 'POST',
cache: 'false',
success: function (response) {
document.getElementById("defaultproject").disabled = "disabled";
},
error: function (xhr) {
alert('There was an error. Please try again');
document.getElementById("defaultproject").checked = ""
}
});
});
//SHOW LOADING DIV
//*** THIS IS WHERE I'M HAVING PROBLEMS
$('.openDialog').ajaxStart(function () {
$('#loadingdiv').show();
}).ajaxStop(function () {
$('#loadingdiv').hide();
});
答案 0 :(得分:3)
为什么要使用活动?如果它仅特定于pop使用回调函数:
$(".openDialog").live("click", function (e) {
e.preventDefault();
$('#loadingdiv').show();
$("<div></div>")
.addClass("dialog")
.attr("id", $(this).attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this).attr("data-dialog-title"),
close: function () { location.reload() },
modal: true,
draggable: false,
resizable: false,
width: 500
})
.load(this.href,function(){
$('#loadingdiv').hide();
});
});
答案 1 :(得分:1)
jQuery似乎没有将任何内容传递给ajaxStart,让您知道启动了什么ajax请求。
因此,最好只处理ajax调用源中的区别,而不是尝试在ajaxStart处理程序中处理它。
您可以通过全局变量实现此目的。 声明一个像
这样的全局变量 var checkBoxAjax = false;
然后在将复选框ajax调用放置为
之前将其设为true $("#defaultproject").change(function ()
{
checkBoxAjax = true;
var isitchecked = document.getElementById("defaultproject").checked
$.ajax({
url: '@Url.Action("SetDefaultProject")',
data: {"id": ProjectId, "isitchecked": isitchecked },
type: 'POST',
cache: 'false',
success: function (response) {
document.getElementById("defaultproject").disabled = "disabled";
},
error: function (xhr) {
alert('There was an error. Please try again');
document.getElementById("defaultproject").checked = ""
}
});
});
并在你的ajaxStart中添加一个像
这样的支票$('.openDialog').ajaxStart(function () {
if(!checkBoxAjax)
$('#loadingdiv').show();
else
checkBoxAjax = false;
}).ajaxStop(function () {
$('#loadingdiv').hide();
});
答案 2 :(得分:1)
这里的问题是将ajax调用绑定到特定的dom对象只是特定于加载函数或者设置了上下文。
因此,整个任务不是确定性的。请考虑以下示例:
$.ajax({
url: "example.com",
success: function(response) {
$('.openDialog').html(response);
}
});
由于对$.ajax
的调用没有在其options参数中的任何地方明确提及.openDialog
,因此无法判断成功函数是否将html加载到其中。
但是,无论何时设置上下文对象,您都可以触发事件。这不是很可靠,但有些目的可能没问题。
(function(ajax) {
$.fn.ajax = function(options) {
if (options.context) {
$(options.context).trigger("ajaxLoadStart");
return ajax.apply(this, arguments).then(function() {
$(options.context).trigger("ajaxLoadEnd");
});
}
return ajax.apply(this, arguments);
};
})($.fn.ajax);
现在您可以绑定到ajaxLoadStart
和ajaxLoadEnd
:
$(document).on("ajaxLoadStart", ".dialog", function () {
$('#loadingdiv').show();
}).on("ajaxLoadEnd", ".dialog", function () {
$('#loadingdiv').hide();
});
(请注意,$(document).on(event, selector, callback)
与已弃用 $(selector).live(event, callback);
相同
现在只要将dialog
类的div作为上下文包含在$.ajax
的选项对象中,它就会触发ajaxLoadStart
然后ajaxLoadEnd
。据我所知,jQuery的.load()
在内部调用$.ajax
,并在相应的对象上设置了上下文。
不幸的是.load
不会在上下文中使用$.ajax
。因此,您还需要将触发器附加到.load
:
(function(load) {
$.fn.load = function(url, params, callback) {
if ( typeof url !== "string")
return load.apply(this, arguments);
this.trigger("ajaxLoadStart");
var done = (function(callback) {
return function() {
$(this).trigger("ajaxLoadEnd");
if ($.isFunction(callback))
callback.apply(this, arguments);
};
})($.isFunction(params) ? params : callback);
return load.call(this, url, $.isFunction(params) ? done : params, $.isFunction(callback) ? done : callback);
};
})($.fn.load);
这两个适配器现在应该可以正常工作。但是,如果你需要在每次升级jquery时修改它们,因为如果jquery的内部工作发生变化,这很容易破坏(事件的双重触发)。