JQuery AjaxStart用于特定元素

时间:2012-06-02 16:48:16

标签: jquery ajax

我的页面上有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();
    });

3 个答案:

答案 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);

现在您可以绑定到ajaxLoadStartajaxLoadEnd

$(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的内部工作发生变化,这很容易破坏(事件的双重触发)。