2

我的页面上有 2 个使用 Ajax 的元素。一个是简单的复选框(设置默认值),另一个是由链接触发的弹出窗口。弹出窗口必须加载一堆元素,所以我有一个由 ajaxStart() 触发并隐藏在 ajaxStop() 处的“正在加载...”覆盖 div。

一切正常,除了复选框和弹出窗口都触发了 ajaxStart() 加载覆盖。它对复选框来说很烦人,因为它是我不想要的 div 的快速“闪烁”。

我的问题:我如何只为页面上的特定元素而不是页面上的每个 Ajax-able 元素触发 AjaxStart?


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();
    });
4

3 回答 3

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();
        });
});
于 2012-06-02T17:27:30.667 回答
1

jQuery 似乎没有向 ajaxStart 传递任何东西,让您知道启动了什么 ajax 请求。

因此,最好只处理 ajax 调用源中的区别,而不是尝试在 ajaxStart 处理程序中处理它。

你可以通过一个全局变量来实现这一点。声明一个全局变量,如

 var checkBoxAjax = false;

然后在放置复选框ajax调用之前使其成为真的

 $("#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();
});
于 2012-06-02T17:05:20.600 回答
1

这里的问题是,将 ajax 调用绑定到特定的 dom 对象仅特定于加载函数或设置上下文时。

因此,整个任务不是确定性的。考虑以下示例:

$.ajax({
   url: "example.com",
   success: function(response) {
       $('.openDialog').html(response);
   }
});

由于调用$.ajax没有.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);

现在您可以绑定到ajaxLoadStartand ajaxLoadEnd

$(document).on("ajaxLoadStart", ".dialog", function () {
    $('#loadingdiv').show();
}).on("ajaxLoadEnd", ".dialog", function () {
    $('#loadingdiv').hide();
});

(注意与弃用$(document).on(event, selector, callback)的相同) $(selector).live(event, callback);

现在,只要带有类的 divdialog作为上下文包含在 的选项对象中$.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 的内部工作发生变化,这很容易中断(事件的双重触发)。

于 2012-06-02T17:09:31.300 回答