2010-03-30 5 views
3

Я пытаюсь написать плагин с встроенной функцией, чтобы дождаться загрузки всех изображений, которые находятся на странице, прежде чем он выполнит сам. $(window).load() работает только в том случае, если это начальная загрузка страницы, но если кто-то хочет вытащить некоторый HTML через AJAX, содержащий изображения, он не работает.jQuery: динамическая обработка изображений (ожидание загрузки)

Есть ли хороший способ сделать это И реализовать его, чтобы он мог быть автономным в подключаемом модуле? Я пробовал цикл за $('img').complete, и я знаю, что это не работает (изображения никогда не загружаются, а браузер падает из-за ошибки «скрипт занимает слишком много времени»). В качестве примера того, что я пытаюсь сделать, посетите страницу Я ищу дом плагин на:

http://www.simplesli.de

Если вы идете в раздел «больше сфер применения» (щелкните по нему на нав bar), вы увидите, что слайд-шоу изображения не будет загружаться должным образом. Я знаю, что текущий код не работает, но он просто держится, пока я не получу что-то.

Edit: Попытка это решение, но это просто не работает:

if($('.simpleSlide-slide img').size() > 0) { 
    var loaded_materials = $('.simpleSlide-slide img').get(); 
} else { 
    var loaded_materials = $('.simpleSlide-slide').get(); 
} 

$(loaded_materials).live('load', function() { 
     /* Image processing and loading code */ 
    }); 

ответ

1

После попытки выполнить эту задачу почти всех мыслимых образом, это один был один, который, наконец, работал, и большое спасибо Naugtur за указание мне в правильном направлении:

var no_of_images = $('img').size(); 

$.extend(no_of_images); 

if(no_of_images > 0) { 

    var images = new Array(); 
    var i = 0; 
    $('img').each(function() { 
     images[i] = $(this).attr('src'); 
     i++; 
    }); 

    i = 0; 

    $(images).each(function(){ 
     var imageObj = new Image(); 
     imageObj.src = images[i]; 
     $(imageObj).load(function() { 
      no_of_images--; 
      i++; 
      if(no_of_images == 0){ 
       functionToPerform(); 
      } 
     }); 
    }); 
} else { 
    functionToPerform(); 
} 

Для быстрого объясняя, что происходит, я буду использовать аналогию. Представьте, что каждое изображение является гостем на вашей вечеринке. Свет погас. Вы включаете огни, затем гоните к каждому гостю и даете им лист бумаги, ручку и сотовый телефон, все время подсчитывая, сколько людей вы передавали материалы. Они все начинают рисовать яростно, а затем, как только они заканчивают свои рисунки, они зовут вас и расскажут вам. Для каждого, кто звонит, вы пересекаете счет с вашего доски.Когда последний называет вас (когда у вас заканчиваются отметки на вашей доске), вы говорите им, чтобы они повесили трубку и позвонили парню пиццы. Время пиццы. Если бы не было гостей, чтобы начать разговор, вы сами вызываете парня-пиццу.

Если вы думаете, «Почему он создает Image() объект для каждого $.load(), ну, я пытался идти традиционный JQuery маршрут с использованием прямой селектор JQuery стиля вместо объекта изображения. Он был, казалось бы, полностью игнорируется (который разбился на страницу). Я попытался с помощью Image() в сочетании с .onLoad, и работал, поскольку не врезаться страницу, но она не выполняет функцию, для которой я написал.

Этот бит кода является само- поэтому я предполагаю, что это может быть copypasta'd в любое приложение для загрузки изображений. Это кажется мне достаточно маленьким, чтобы не быть навязчивым. functionToPerform() в основном действует как любая функция, которую вы хотели бы ждать, пока l загружаются изображения (в моем случае это был весь плагин). Toodles.

+0

Почему вы называете '$ .extend (no_of_images);'? –

1

Задумывались ли вы с помощью live() для связывания всех текущих и будущих img элементов?

$('img').live('load', function() 
{ 
    alert("image loaded: "+this.src); 
}); 

После вашего обновления я вижу проблему, с которой вы сталкиваетесь. live() работает лучше всего на селекторе, тогда как вы используете его в массиве элементов, обернутых jQuery. Использование live(), как это ничем не отличается от использования bind(). Вы должны попробовать что-то вроде этого, вместо:

if($('.simpleSlide-slide img').size() > 0) { 
    var loaded_materials = '.simpleSlide-slide img'; 
} else { 
    var loaded_materials = '.simpleSlide-slide'; 
} 

$(loaded_materials).live('load', function() { 
     /* Image processing and loading code */ 
}); 
+0

Я пробовал эту последнюю ночь, и она не работала, если только я просто не пропустил синтаксис, но жить не кажется мне сложным. Я считаю, что это не по своей сути поддерживает «load» как событие, хотя ... – dclowd9901

+1

Ты машина! Я был в середине своего ответа: P Это несправедливо;) – naugtur

+0

@ dclowd9901: в документации не упоминается о неподдерживаемых событиях. Просто 'Строка, содержащая тип события JavaScript, такой как« щелчок »или« сбой ». Он даже утверждает, что поддерживает пользовательские события, поэтому я уверен, что он может поддерживать стандартные :-) –

3

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

$.ajaxSuccess(function(){ 
$('img').load(function(){ 
    //Your code here 
}); 
}); 

или когда Вы ожидаете много изображений:

$.ajaxSuccess(function(){ 
$('img:not(.loaded)').addClass('.loaded').bind('load',function(){ 
    //Your code here 
}); 
}); 

Если какой-либо из приведенного выше кода не работает должным образом Tou могли бы хотеть поместить код в функции обратного вызова, который добавляет HTML на сайте после того, как добавив его. использование setTimeout в приведенной выше функции также может помочь.

[править]

Вы можете создавать изображения <img src="something" onload="$.imgHello()" /> в серверном коде и увеличиваете некоторый счетчик в каждом вызове функции $.imgHello(), если Вы знаете, сколько изображений там будет загружено. Но это не решение, которое я бы рекомендовал кому угодно.

+1

В чем смысл добавления класса .loaded? – dclowd9901

+0

Если у вас есть сотни изображений на странице, нужно быстрее выбирать только новые, а не связывать новую функцию загрузки со всеми из них. – naugtur

+0

Но я бы выполнял ту же функцию для такого количества изображений, сколько у меня на странице? Разве это не так сильно замедлит все? Я продолжаю возвращаться к этой идее, что если бы был какой-то способ, я мог бы узнать, сколько изображений было на странице (что может), и каждое изображение могло каким-то образом уведомить скрипт о его завершении, тогда сценарий может, в свою очередь, выполнить функцию после этого уведомления о завершении, тогда мне было бы хорошо идти. Является ли javascript даже такой способной? – dclowd9901

3

Проблема с петлей над изображениями и вызовом $('img').complete заключается в том, что пользовательский интерфейс браузера является однопоточным, поэтому вы никогда не даете ему возможности загружать изображения, потому что он всегда находится в вашем цикле. Вы можете использовать setTimeout, чтобы браузер работал. например,

$.get("whatever",function(html) { 
    $('#foo').html(html); 
    var images = getTheImages(); 
    function checkImages() { 
     var done = true; 
     $.each(images,function() { 
     done = done && this.complete; 
     return done; 
     }); 
     if(done) { 
     fireEvent(); 
     } else { 
     setTimeout(checkImages,100); // wait at least 100 ms and check again 
     } 
    } 
}); 
+0

Я тоже пробовал это. вернусь в нужное время. Возможно, мой метод был неправильным, но он выглядел очень похоже на то, что вы написали здесь. – dclowd9901

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