Как узнать, какой элемент в теле вызвал запрос AJAX в jQuery
Я работаю над приложением и пытаюсь использовать поведение Facebook для запроса AJAX. В Facebook вы получаете хорошее загрузочное изображение рядом с пиктограммой, которая запускает запрос AJAX. Ну, это довольно просто реализовать, если на странице есть 1-2 элемента.
Я хочу сделать его общим и хотел бы, чтобы всякий раз, когда какой-либо элемент запускает запрос AJAX, я хочу показать небольшой GIF рядом с ним. Для этого я думал, что событие AjaxSend jQuery будет достаточно хорошим, но, увы, это не дает мне дескриптора объекта, который вызвал вызов AJAX. Я хотел бы знать, возможно ли с помощью некоторого метода jQuery узнать, какой элемент вызвал вызов AJAX, а также получить тот же самый дескриптор, когда вызов AJAX завершен.
Если вы чувствуете, что мой подход к проблеме неверен, я хотел бы услышать ваши предложения.
Ответы
Ответ 1
Если вы хотите использовать обработчики запросов ajax, идентификатор должен быть назначен (вручную или автоматически) для элемента, вызвавшего событие. Затем вы можете отправить этот идентификатор в качестве дополнительной пары ключ-значение в запросе (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
Другим общим способом, который требует наименьшей настройки, является использование свойства 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
сообщит вам об исключении, если оно есть, и вы сможете исправить его позже.
Ответ 3
Я также пытался поймать событие 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 может преуспеть.
Ответ 4
Я столкнулся с той же проблемой, прежде чем... ну, это не даст ручку u, посмотрите, полезен ли код ниже или нет.
вот мое решение
$(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...");
}
}
});
просто отслеживать все события кликов на теле и получать его источник
Ответ 5
У меня была такая же проблема,
я установил глобальный параметр и установил для него кнопку клика:
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.
<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>
Ответ 6
Довольно много подходов к решению этой проблемы.
У меня было несколько элементов, которые могут запускать событие 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))
Вы можете полностью обобщить его, чтобы он мог запускать любой обратный вызов, который вы автоматически добавляете + ошибки журналов. Я написал учебник, как это сделать + вы можете найти код на GitHub.
Ответ 7
$(document).ajaxStart( function(e) {
var el = e.target.activeElement.id;
alert('event triggerd by : ' + el);
});
Основное решение: e.target.activeElement.id