如何知道正文中的哪个元素在jQuery中触发了AJAX请求

时间:2011-02-19 14:24:10

标签: jquery

我正在开发一款应用并试图将Facebook行为用于AJAX请求。在Facebook中,您可以在触发AJAX请求的图标旁边获得一个很好的加载图像。好吧,如果页面中有1-2个元素,那么实现起来非常简单。

我想让它变得通用,并希望每当任何元素触发AJAX请求时,我想在它旁边显示一个小GIF。为此,我认为jQuery的AjaxSend事件已经足够好了,但是它没有给我一个触发AJAX调用的对象的句柄。我想知道是否可以通过jQuery的某些方法知道哪个元素触发了AJAX调用,并且在AJAX调用完成时获得相同的句柄。

如果您认为我对问题的处理方法不正确,我很乐意听取您的建议。

8 个答案:

答案 0 :(得分:11)

另一种需要最少设置的通用方法是使用事件目标的activeElement属性:

$(document).ajaxStart(function (e) {
    try {
        var $el = $(e.target.activeElement);
        var isButton = $el.hasClass('btn');

        // just a precautionary check
        if (!isButton) {
            return;
        }

        $el.button('loading'); // or whatever else you want to do

    } catch (ex) {
        console.log(ex);
    }
});

$(document).ajaxStop(function (e) {
    try {
        var $el = $(e.target.activeElement);
        var isButton = $el.hasClass('btn');

        if (!isButton) {
            return;
        }

        $el.button('reset');

    } catch (ex) {
        console.log(ex);
    }
});

这样做的原因是因为当点击一个按钮时,它会获得焦点。 e.target(此时为document通过activeElement属性告诉我们当前关注的元素。

请注意,try...catch是完全可选的。在try...catch中包装任何全局处理程序通常是个好主意,只是为了确保此处的任何异常都不会导致任何副作用。 console.log会告诉您有关异常的信息(如果有),以便您以后可以修复。

答案 1 :(得分:5)

如果要使用ajax请求处理程序,则需要(手动或自动)将id分配给触发事件的元素。然后,您可以将此id作为请求中的附加键值对(element_id:THEID)发送,并使用ajax请求处理程序中的各种子字符串方法获取它。

示例:

<script type="text/javascript">

    $(document).ready(function(){

        $("input").click(function(){

            var newid = (create a custom id with date and time);

            $(this).attr("id", newid);
            $.post("handler.php", {element_id : $(this).attr("id")});
        });

   }).ajaxSend(function(e, xhr, settings){

        var start_position = settings.data.indexOf("element_id");
        var equalsign_position = settings.data.indexOf("=", start_position);
        var ampersand_position = settings.data.indexOf("&", start_position);

        var element_id;
        if(ampersand_position == -1){
            element_id = settings.data.substr(equalsign_position+1);
        } else {
            element_id = settings.data.substr(equalsign_position+1, ampersand_position-equalsign_position-1);
        }

        $("#"+element_id).after("<div id='div"+element_id+"'><img src='loading_start.png' /></div>");

    }).ajaxComplete(function(e, xhr, settings) {

        var start_position = settings.data.indexOf("element_id");
        var equalsign_position = settings.data.indexOf("=", start_position);
        var ampersand_position = settings.data.indexOf("&", start_position);

        var element_id;
        if(ampersand_position == -1){
            element_id = settings.data.substr(equalsign_position+1);
        } else {
            element_id = settings.data.substr(equalsign_position+1, ampersand_position-equalsign_position-1);
        }

        $("#div"+element_id).remove();


    });

    </script>

    <input type="button" value="Save" />

另一种方法是处理每个事件处理程序中加载图像的出现和消失(但我似乎理解你有太多它们?),如下所示:

<script type="text/javascript">

    $(document).ready(function(){

        $("input").click(function(){


            var element_id = (generate custom id);

            $(this).after("<div id='div"+element_id+"'><img src='loading_start.png' /></div>");

            $.post("handler.php", {var:"hello"}, function(){
                $("#div"+element_id).remove();
            });

        });
    })
</script>

答案 2 :(得分:2)

我还试图抓住ajax事件来动画一些按钮,我想出了:

        $j('.btn').bind('click',function(){
            triggerElement = $j(this);
        });
        $j(document).ajaxSend(function(event,xhr,options){
            var userAgent = $j.browser;
            if (userAgent.mozilla)
                triggerElement = $j(event.target.activeElement);
            if (triggerElement && triggerElement.is('.btn')){
                var triggerOffset = triggerElement.offset();
                genericDisabler = $j('<div></div>');
                genericDisabler.addClass('generic-disabler');
                $j('body').append(genericDisabler);
                genericDisabler.width(triggerElement.outerWidth());
                genericDisabler.height(triggerElement.outerHeight());
                genericDisabler.offset({
                    left:triggerOffset.left,
                    top:triggerOffset.top
                });
                triggerElement.switchClass('orange','gray-ajax-gradient',25).animate({
                    opacity: 0.6
                });         
            }
        });
        $j(document).ajaxComplete(function(event,xhr,options){
            if (triggerElement && triggerElement.is('.btn')){
                triggerElement.switchClass('gray-ajax-gradient','orange',25,function(){
                    if (genericDisabler)
                        genericDisabler.remove()
                }).animate({
                    opacity: 1
                });
            }
            triggerElement = null;
        });

所以我确保获得完成点击的元素,但我保留了FF可以做得好的参考。

答案 3 :(得分:0)

我之前遇到过同样的问题......好吧它不会给你处理,看看下面的代码是否对你有用。 这是我的解决方案

$(document).click(function(event){
        if(event.target.id != "comment" && event.target.id != "fb-button"){
            $("#submit-button").css("display","none");
            if($("#comment").val() == ""){
                $("#comment").addClass("lightText").val("write a comment...");
            }
        }
    });

只需跟踪正文上的所有点击事件并获取其来源

答案 4 :(得分:0)

我有同样的问题, 我做的是设置一个全局参数并将单击的按钮设置为它:

var btn = null;

$(document).ajaxSend(function(event, xhr, settings) {
    btn.find(".ui-button-text:first").append('<div class="loading"></div>');
}).ajaxComplete(function(event,request, settings) {
    $(".loading").remove();
});

只需为加载添加样式,它将为Jquery UI按钮添加一个加载指示器。

<style type="text/css">
.btn {
    margin: 5px 10px 0 0;
}

.loading {
    display: inline;
    background: url(../images/loading.gif) center no-repeat;
    margin: 0 0 0 5px;
    padding: 0 0 0 16px;
}
</style>

答案 5 :(得分:0)

如何解决这个问题有很多方法。

我有多个元素可以触发AJAX事件,并希望每次发送和完成AJAX请求时都执行一些自动回调。但仅限于触发它的元素。

我最终将$ .get()方法包装到我自己的对象中

var AJAX = {
  fetch: function (url, data, targetObj) {
    var oldText = ''
    targetObj = (this.isDefined(targetObj) ? targetObj : null)
    if (targetObj) {
      oldText = targetObj.text()
      targetObj.text('Loading...')
    }

    return $
      .get(url, data)
      .always(function () {
        // if target object is provided, run end callbacks on it
        if (targetObj) {
          targetObj.text(oldText)
        }
      })
  }
}

然后这样称呼它:

AJAX.fetch('my_script.php', {somedata: 'blabla'}, $(this))

您可以完全概括它,以便它可以运行您添加的任何回调+自动记录错误。我写了tutorial how to achieve that +你可以找到代码on GitHub

答案 6 :(得分:0)

$(document).ajaxStart( function(e) {
    var el = e.target.activeElement.id;
    alert('event triggerd by : ' + el);     
});

主要解决方案:e.target.activeElement.id

答案 7 :(得分:0)

这对我有用:

$(document).ajaxSend(function (e, jqXHR, ajaxOptions) {
    try {
        if (e.target.activeElement) {

            var $el = $(e.target.activeElement);
            var isButton = $el.hasClass('btn');

            if (!isButton) return;

            $el.prop('disabled', true);

            jqXHR.complete(function () {
                $el.prop('disabled', false);
            });
        }
    } catch (ex) {
        console.log(ex);
    }
});