Substr() с отрицательным значением, не работающим в IE
EDIT: я изменил название, потому что проблема не имела никакого отношения к IE image.load() firing - мой substr() не работал (см. принятый ответ).
Там много сообщений о том, что вы определяете свой обработчик onload перед назначением img.src, чтобы гарантировать, что обработчик onload находится на месте, если сначала загружается изображение из кеша.
Это не кажется проблемой в моем коде, так как это именно то, что я сделал.
Обратите внимание, что этот script работает во всех других браузерах, но IE 8 и ниже не запускают встроенную функцию onload.
var i = lastSlideIndex || 1;
while(imagesQueued < MAX_IMAGES){
var preloadImage = new Image();
preloadImage.arrayIndex = i;
preloadImage.onload = function(eventObj){
debug('Image ' + this.src + ' loaded.');
slideshowImages[this.arrayIndex] = this;
if (this.arrayIndex > lastImageIndex) lastImageIndex = this.arrayIndex;
triggerSlideshow(this.arrayIndex);
}
// add leading zeros
var leadingZeros = "0000000".substr(-(String(MAX_IMAGES).length));
imageNumber = leadingZeros.substr(String(i).length) + i;
debug('preloading Image #' + imageNumber);
preloadImage.src = fullImagePrefix + imageNumber + "." + IMAGES_TLA;
if (++i > MAX_IMAGES) i = 1;
imagesQueued++;
}
Любые другие предложения будут глубоко оценены!
Ответы
Ответ 1
Обновление: Как отмечают комментаторы (и пока не могу доказать их иначе), я удалил первое предложение.
Еще несколько вещей, чтобы отметить:
onload
Событие не срабатывает, если изображение загружается из кеша. Попробуйте очистить кеш и повторить попытку.
Другая проблема заключается в том, что IE не любит отрицание в substr
. Вместо этого используйте slice
:
"0000000".slice(-(String(MAX_IMAGES).length));
Ответ 2
Теперь, когда этот вопрос имеет название substr()
в IE 8, здесь быстро исправить проблему с отрицательным индексом. Вставьте следующий код из Mozilla Developer Network:
// only run when the substr() function is broken
if ('ab'.substr(-1) != 'b') {
/**
* Get the substring of a string
* @param {integer} start where to start the substring
* @param {integer} length how many characters to return
* @return {string}
*/
String.prototype.substr = function(substr) {
return function(start, length) {
// call the original method
return substr.call(this,
// did we get a negative start, calculate how much it is from the beginning of the string
// adjust the start parameter for negative value
start < 0 ? this.length + start : start,
length);
}
}(String.prototype.substr);
};
Этот код обнаруживает сломанную реализацию substr и заменяет его на совместимый.
Ответ 3
Два способа борьбы с этим:
-
Добавьте к URL-адресу изображения параметр nonce.
var nonce = new Date().getTime();
// ...
preloadImage.src = fullImagePrefix + imageNumber + "." + IMAGES_TLA + ('?_=' + nonce++);
-
Задайте свойство "src" в другом цикле событий.
setTimeout(function(img, src) {
img.src = src;
}(preloadImage, fullImagePrefix + imageNumber + "." + IMAGES_TLA), 1);
Используя параметр nonce каждый раз, когда вы извлекаете изображение, вы обходите кеш. Теперь это, вероятно, не такая замечательная идея, поэтому второй вариант касается проблемы, убедившись, что свойство "src" задано в отдельном цикле событий. Тогда "load" будет срабатывать.
Здесь показан пример. Код использует nonces на некоторых изображениях, но устанавливает "src" для всех из них в обработчике тайм-аута. Как вы можете видеть, все они загружаются (краснеют).
Я не знаю, почему IE не запускает обработчик "load", когда изображение находится в кеше, но это происходит, когда "src" устанавливается в другом цикле событий, из которого находится объект изображения (в противном случае) инициализированы.
edit — Здесь та же самая скрипка, но изменена, чтобы пропустить таймаут. В IE8 вы должны заметить, что четные изображения часто не получают вызов обработчикам нагрузки.