2013-12-20 9 views
2

У меня есть следующие функции яваскрипта, который я использую для создания базового обработчика событий для изображений которые загружаются в любой контейнер ...Пользовательские события без триггера

function onImagesLoaded($container, callback) { 
    var $images = $container.find("img"); 
    var imgCount = $images.length; 
    if (!imgCount) { 
     callback(); 
    } else { 
     $images.each(function() { 
      $(this).one("load error", function() { 
       imgCount--; 
       if (imgCount == 0) { 
        callback(); 
       } 
      }); 
      if (this.complete) $(this).load(); 
     }); 
    } 
} 

В настоящее время я называю это что-то вроде этого .. .

onImagesLoaded($("div.image-container"), function() { 
    console.log("Images loaded"); 
}); 

Это нормально, и это работает, но я хочу, чтобы иметь возможность прикрепить его к элементам, как это ...

$("div.image-container").on("imagesloaded", function() { 
    console.log("Images loaded"); 
}); 

Это не «мой код не работает - исправьте его» Тип вопроса, потому что он действительно работает и выполняет именно то, что я хочу, функционально. Я задаю этот вопрос, потому что не могу найти никакой помощи в том, как это сделать, как я хочу это сделать, и я пытаюсь узнать что-то новое. Все, что я читал о пользовательских событиях jQuery, требует, чтобы вы вручную запускали их, и это не то, что я пытаюсь сделать здесь.

Я говорю, что хочу привязать обработчик события к элементу, а затем назначить свою функцию этому элементу , потому что этого обработчика событий. Возможно, мне нужно разобрать элементы в DOM вручную, чтобы это сделать - я не знаю.

Может ли кто-нибудь хотя бы указать мне, как это можно сделать (если это возможно)?

Редактировать

Я начал работать над отменяя существующую on() функцию аналогично тому, как KevinB предлагаемых ниже. Код он снабжал охватывает несколько вопросов, которые я имел с моей версией, так что я объединил два вместе и пришел с рабочей версией ....

var $_on = $.fn.on 

$.fn.on = function() { 
    switch (arguments[0]) { 
     case "imagesloaded": 
      onImagesLoaded(this, arguments[1]); 
      break; 
     default: 
      return $_on.apply(this, arguments); 
      break; 
    } 
}; 

Используя, что теперь я могу приложить собственные обработчик событий с помощью .on(), точно так же, как я сказал, я хотел в вопросе выше.

Оглядываясь назад, заголовок вопроса был сформулирован плохо. Это должно было быть именно так: переопределение on().

Другой Редактировать

После дальнейших размышлений по этому вопросу, я решил создать метод createEvent(), так что я мог бы добавить пользовательские события в JQuery-х on() без хлопот. Если кто-то приходит на эту страницу, и ищет того, вы можете найти здесь ...

http://johncmolyneux.blogspot.co.uk/2013/12/how-to-override-jquery-on-and-add.html

Там также ссылку на эту страницу в библиотеку jQuery.extend на GitHub, что я буду добавлять к всякий раз, когда я делаю то, что, я думаю, должен быть добавлен.

+0

Простое присоединение события к элементу ничего не делает, пока вы не активируете указанное событие. Вы должны вызвать метод onImagesLoaded для запуска и инициировать событие. Вы можете превратить свою функцию в плагин и использовать его так: '$ (« someselector »). On (« imagesloaded », обработчик) .loadImages()' –

+0

Это моя точка, @KevinB. В приведенном выше примере глупо попытаться создать триггер для настраиваемого события, поскольку он может быть привязан к каждому элементу страницы, на котором могут быть дочерние элементы. – Archer

+0

Извините, да, мы оба печатаем в одно и то же время :) – Archer

ответ

3

я бы превратить его в плагин и использовать его таким образом:

$.loadImages = function($images, callback) {   
    var imgCount = $images.length; 
    if (!imgCount) { 
     callback(); 
    } else { 
     $images.each(function() { 
      /*$(this).one("load error", function() { 
       imgCount--; 
       if (imgCount == 0) { 
        callback(); 
       } 
      }); 
      if (this.complete) $(this).load();*/ 
      var img = new Image(); 
      $(img).on("load error", function(){ 
       imgCount--; 
       if (imgCount == 0) { 
        callback(); 
       } 
      }); 
      img.src = this.src; 
     }); 
    } 
}; 
$.fn.loadImages = function (callback) { 
    var $images = this.find("img").addBack().filter("img"); 
    var self = this; 
    $.loadImages($images,function(){ 
     if ($.isFunction(callback)) { 
      callback(); 
     } 
     self.trigger("imagesLoaded"); 
    }); 
}; 

Теперь вы можете использовать его как это:

$.loadImages($("div.image-container").find("img"), function() { 
    console.log("Images loaded"); 
}); 

или вы можете использовать его как это:

$("div.image-container").on("imagesLoaded",function(){ 
    console.log("Images loaded"); 
}).loadImages(); 

или даже вот так:

$("div.image-container").loadImages(function(){ 
    console.log("Images loaded"); 
}); 

это тоже работает:

$("div.image-container img").loadImages(function(){ 
    console.log("Images loaded"); 
}); 

Там нет никакого способа сделать .он автоматически вызвать плагин для запуска без monkeypatching .На, которая, как правило, плохая идея. Это может выглядеть примерно так:

var oldOn = $.fn.on 

$.fn.on = function() { 
    var ret = oldOn.apply(this,arguments); 
    if (arguments[0] == "imagesloaded") { 
     var self = this; 
     onImagesLoaded(this,function(){ 
      self.trigger("imagesloaded"); 
     }); 
    } 
    return ret; 
}; 
+0

, вам также может потребоваться принять во внимание тот факт, что изображение может быть загружено до того, как событие, подготовленное dom, будет запущено ... поэтому событие «load error» не будет вызвано. –

+0

Я бы решил, создавая новые изображения и предварительно загружая Кстати, я просто не хотел переписывать все, что он сделал –

+0

Спасибо, Кевин. Я думаю, что это тот маршрут, в который я собираюсь закончиться, и это то, чего я ожидал. Я в идеале хотел узнать, что есть способ использовать 'on', без« monkeypatching it »: p – Archer

Смежные вопросы