JavaScript обнаруживает событие AJAX

Хорошо, поэтому в основном я хочу иметь немного javascript на странице, которая каким-то образом присоединяет какой-то глобальный прослушиватель событий, который может обнаруживать и делать что-либо, если делается запрос ajax (без прямого вызова от вызова), независимо от того, как выполняется вызов ajax.

Я выяснил, как это сделать с помощью jquery - если запрос ajax выполняется jquery. Вот пример кода для этого:

$.post(
  // requested script
  'someScript.php', 
  // data to send
  {
    'foo' : 'bar',
    'a' : 'b'
  },
  // receive response
  function(response){
    // do something
  }
); // .post

// global event listener    
$(document).ajaxSend(
  function(event,request,settings){
    alert(settings.url); // output: "someScript.php"
    alert(settings.data); // output: "foo=bar&a=b"
  }
);

С помощью этого кода, независимо от того, где/как я вызываю $.post(..), запускается глобальный прослушиватель событий. Он также работает, если я использую $.get или $.ajax(любые jQuery ajax-методы), независимо от того, как/когда я его называю (прикрепляется как onclick, на загрузке страницы, что угодно).

Тем не менее, я хочу, чтобы иметь возможность расширять этот прослушиватель, чтобы запускать независимо от того, что используется js-инфраструктура, или даже если никакая фреймворк не используется. Так, например, если бы я был и, на странице был указан следующий код (общий код ajax из w3schools):

function loadXMLDoc()
{
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","test.txt",true);
xmlhttp.send();
}

И затем у меня есть на какой-то случайной ссылке вызов onclick для этой функции, мой глобальный слушатель событий ajax должен иметь возможность также обнаруживать этот запрос. Ну, я добавил этот код на свою страницу и привязал его к случайной ссылке onclick (да, сам код работает), но код jQuery "global event listener" выше не смог обнаружить этот вызов.

Я сделал еще несколько копаний, и я знаю, что могу в основном сохранить объект в временном объекте и перезаписать текущий объект с помощью объекта "обертка", который вызовет указанную функцию, а затем вызовет временную функцию, но это требует от меня заранее знать оригинальный объект, который создается/используется. Но я не всегда буду знать это раньше времени...

Итак... это возможно? Есть ли способ обнаружить запрос ajax get/post, независимо от того, было ли это сделано с помощью общего объекта или из рамки xyz? Или мне просто нужно сделать дубликат кода для обработки каждой структуры, а также заранее знать, когда создаются/используются объекты ajax?

изменить:

Я забыл упомянуть, что недостаточно обнаружить, что произошел запрос. Мне также необходимо зафиксировать данные, отправляемые в запросе. Ссылка, приведенная в комментариях ниже, поможет выяснить, был ли выполнен запрос "a", но не получить отправленные данные. постскриптум - ответ, указанный в приведенной ниже ссылке, не очень ясен, по крайней мере, мне так или иначе.

Ответ 1

Хорошо, это то, к чему я придумал:

<script type='text/javascript'>
var s_ajaxListener = new Object();
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
  // this.method :the ajax method used
  // this.url    :the url of the requested script (including query string, if any) (urlencoded) 
  // this.data   :the data sent, if any ex: foo=bar&a=b (urlencoded)
}

XMLHttpRequest.prototype.open = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempOpen.apply(this, arguments);
  s_ajaxListener.method = a;  
  s_ajaxListener.url = b;
  if (a.toLowerCase() == 'get') {
    s_ajaxListener.data = b.split('?');
    s_ajaxListener.data = s_ajaxListener.data[1];
  }
}

XMLHttpRequest.prototype.send = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempSend.apply(this, arguments);
  if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
  s_ajaxListener.callback();
}
</script>

НАПРАВЛЕНИЯ:

Просто c/p это на вашей странице или включите его в файл .js или что-то еще. Это создаст объект с именем s_ajaxListener. Всякий раз, когда выполняется запрос AJAX GET или POST, вызывается s_ajaxListener.callback(), и доступны следующие свойства:

s_ajaxListener.method: используется метод ajax. Это должно быть GET или POST. ПРИМЕЧАНИЕ. Значение не всегда может быть заглавным, это зависит от того, как был закодирован конкретный запрос. Я обсуждаю мудрость автоматически верхней части его или оставляя его что-то еще для toLowerCase() для сравнения без учета регистра.

s_ajaxListener.url: URL запрошенного script (включая строку запроса, если есть) (urlencoded). Я заметил, что в зависимости от того, как данные отправляются и из какого браузера/фреймворка, например, это значение может оказаться в виде "или" + "или" %20". Я обсуждаю мудрость его декодирования или оставляю его на что-то еще.

s_ajaxListener.data​​strong > : отправленные данные, если они есть: foo = bar & a = b (то же самое "проблема", что и .url с URL-адресом)

ПРИМЕЧАНИЯ:

Как бы то ни было, это не совместимо с IE6. это решение для меня не совсем хорошо, так как я хочу, чтобы он совместим с IE6. Но так как многие другие люди не заботятся о IE6, я решил опубликовать свое решение в его текущем состоянии, так как оно должно работать для вас, если вас не волнует IE6.

Я тестировал это в (начиная с этой опубликованной даты): текущий Safari, текущий Chrome, текущий FireFox, IE8, IE8 (совместимый с IE7). В настоящее время он не работает с IE6, поскольку IE6 использует объект ActiveX, в то время как практически все остальное использует XMLHttpRequest.

Сейчас у меня нет никакой подсказки, как, в основном, prototype/extend/overload (?) ActiveXObject ( "Microsoft.XMLHTTP" ). Это то, что я сейчас изучаю... кто-нибудь знает небрежно?

В каждом из вышеперечисленных браузеров это работает с запросами AJAX от общего объекта, а также из фреймворков jquery и prototype. Я знаю, что есть другие рамки, но ИМО эти 2 являются основными. Возможно, я мог бы использовать QA MooTools, но кроме этого, я в порядке, только тестируя их.

Если кто-то хочет внести вклад, тестируя и публикуя результаты о других браузерах и/или фреймворках, было бы полезно:)

Ответ 2

Для совместимости с IE 6, как насчет:

<script type='text/javascript'>
  var s_ajaxListener = new Object();

  // Added for IE support
  if (typeof XMLHttpRequest === "undefined") {
    XMLHttpRequest = function () {
      try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
      catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
      catch (e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP"); }
      catch (e) {}
      throw new Error("This browser does not support XMLHttpRequest.");
    };
  }

  s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
  s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
  s_ajaxListener.callback = function () {
    // this.method :the ajax method used
    // this.url    :the url of the requested script (including query string, if any) (urlencoded) 
    // this.data   :the data sent, if any ex: foo=bar&a=b (urlencoded)
  }

  XMLHttpRequest.prototype.open = function(a,b) {
    if (!a) var a='';
    if (!b) var b='';
    s_ajaxListener.tempOpen.apply(this, arguments);
    s_ajaxListener.method = a;  
    s_ajaxListener.url = b;
    if (a.toLowerCase() == 'get') {
      s_ajaxListener.data = b.split('?');
      s_ajaxListener.data = s_ajaxListener.data[1];
    }
  }

  XMLHttpRequest.prototype.send = function(a,b) {
    if (!a) var a='';
    if (!b) var b='';
    s_ajaxListener.tempSend.apply(this, arguments);
    if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
    s_ajaxListener.callback();
  }
</script>