Добавление нескольких обработчиков загрузки - PullRequest
3 голосов
/ 30 декабря 2010

У меня есть два js-файла, каждый со своим обработчиком window.onload. В зависимости от того, как я присоединяю два обработчика загрузки к объекту окна, я получаю другое поведение на втором обработчике.

Более конкретно, вот мой HTML-файл:

<html>
<head>
 <title>Welcome to our site</title>
 <script type="text/javascript" src="script1.js"> </script>
 <script type="text/javascript" src="script2.js"> </script>
</head>
<body id="pageBody">
 <h2 align="center"> 
  <a href="http://www.whatever.com" id="redirect"> Wellcome to our site... c'mon in! </a> 
 </h2>
</body>
</html>

Загружает два js-файла, script1.js и script2.js.

Вот версия этих двух сценариев, которая приводит к (по крайней мере, мне) неожиданному поведению.

Script1.js:

window.onload = initAll1(); // attach first onload handler

function initAll1() {
 alert("initAll1");
 document.getElementById("redirect").onclick = foo; // attach an onclick handler
}

function foo() {
 alert("we are in foo"); 
 return false;
}

Script2.js:

addOnloadHandler(initAll2); // with this we should attach a second onload handler

function initAll2() {
 alert("initAll2");
 if (linkHasOnclickHandler(document.getElementById("redirect"))) {
  alert("correct!"); 
 }
 else {
  alert("wrong!");
 }
}

function addOnloadHandler (newFunction) {
 var oldevent = window.onload;
 if (typeof oldevent == "function") {
  window.onload = function() {
      if (oldevent) {
          oldevent();
      }
   newFunction();
  };
 }
 else {
      window.onload = newFunction;
 }
}

function linkHasOnclickHandler() {
 var oldevent = document.getElementById("redirect").onclick;
 if (typeof oldevent == "function") {
  return true;
 }
 else {
  return false;
 }
}

В Script2.js я попытался добавить второй обработчик загрузки приятным неинвазивным способом, используя функцию addOnloadHandler (). Эта функция не делает никаких предположений относительно того, есть ли уже какой-либо обработчик загрузки, присоединенный к объекту окна. Он неинвазивен, поскольку должен добавлять новый обработчик, не удаляя предыдущие.

Дело в том, что при загрузке с помощью addOnloadHandler () initAll2 () не может обнаружить тот факт, что document.getElementById («redirect») уже имеет функцию foo (), присоединенную в качестве обработчика события onclick (см. InitAll1 ()) , Предупреждение "неправильно!" срабатывает, что мне кажется неправильным поведением.

Когда я забываю о addOnloadHandler () и присоединяю оба обработчика загрузки в Script1.js, используя:

window.onload = function () {initAll1(); initAll2();};

тогда все работает как положено, и initAll2 () запускает «правильно!» предупреждающее сообщение.

Что-то не так с addOnloadHandler ()? Кто-нибудь может заставить это работать? Я бы очень хотел использовать его вместо второго метода.

Спасибо!

Ответы [ 4 ]

5 голосов
/ 12 ноября 2012

На всякий случай, если будущие люди обнаружат это и ищут способ использовать несколько обработчиков событий, когда сам объект не поддерживает addEventListener, attachEvent или какую-либо другую форму стекирования слушателя - т.е. это сделанный на заказобъект, плохо реализованный.Затем вы можете сделать следующее:

object.onload = (function(pre){
  return function(){
    pre && pre.apply(this,arguments);
    /// do what you need for your listener here
  }
})(object.onload);

Каждый раз, когда вы используете вышеупомянутый код, предыдущий onload слушатель передается в качестве аргумента, и когда ваш новый слушатель запускается, он сначала запускает старый слушатель -это означает, что вы можете составить множество слушателей следующим образом: , если хотите, .Однако это будет работать только до тех пор, пока приведенный выше код всегда используется для добавления слушателей к вашему объекту.Вся ваша тяжелая работа будет отменена, если где-то еще она будет переопределена простым:

object.onload = function(){}

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

2 голосов
/ 30 декабря 2010

Вам нужно взглянуть на addEventListener и attachEvent, которые являются собственными реализациями вашего addOnloadHandler.

1 голос
/ 30 декабря 2010

Спасибо за ответы!

Я переписал свой script2.js, используя addEventListener и attachEvent, вот так:

//addOnloadHandler(initAll1); // it works only when uncommenting this
addOnloadHandler(initAll2);

function initAll2() {
    alert("initAll2");
    if (linkHasOnclickHandler(document.getElementById("redirect"))) {
        alert("correct!"); 
    }
    else {
        alert("wrong!");
    }
}

function addOnloadHandler(newFunction) {    
    if (window.addEventListener) { // W3C standard
        window.addEventListener('load', newFunction, false); // NB **not** 'onload'
    }    
    else if (window.attachEvent) { // Microsoft
        window.attachEvent('onload', newFunction);
    }
}

function linkHasOnclickHandler(element) {
    var oldevent = document.getElementById("redirect").onclick;
    if (typeof oldevent == "function") {
        return true;
    }
    else {
        return false;
    }
}

Как видите, addOnloadHandler () был переписан с использованием нативногоРеализации, которые вы, ребята, упомянули.Я оставил script1.js нетронутым.

Полученный код по-прежнему не работает (т. Е. Отображается предупреждение «Неправильно!»).Он работает только тогда, когда я дважды регистрирую обработчик onload initAll1 (), раскомментируя первую строку кода в script2.js.

По-видимому, смешивая

window.onload = handler1;

и

window.addEventListener('load', handler2, false);

или

window.attachEvent('onload', handler2);

не работает нормально.

Есть ли способ обойти эту проблему, которая не подразумевает прикосновения к script1.js?

На тот случай, если вам интересно, почему я не хочу касаться script1.js, причина в том, что я хочу, чтобы мой код (script2.js) можно было повторно использовать и в других проектах, независимо от того, какие другие jsфайлы, которые использует каждый проект.Таким образом, он должен работать со всеми возможными методами регистрации обработки событий, используемыми в script1.js.

еще раз спасибо за вашу помощь!

1 голос
/ 30 декабря 2010

Ссылка PPK на addEventListener объясняет, как это сделать довольно хорошо:

http://www.quirksmode.org/js/events_advanced.html

...