11548 sujets

JavaScript, DOM et API Web HTML5

salut à tous,
je viens de terminer une version d'un plugin de pré-chargement des images dans une page web.

J'ai implémenté une fonction de redimensionnement durant le pré-chargement pour que l'image qui est affichée soit déjà redimensionnée.

L'intérêt d'un tel plugin est d'afficher une image d'attente durant le pré-chargement et le redimensionnement de l'image...

J'arrive à tout faire fonctionner sans problème, mais pas sous Internet Explorer 6 et 7 confondus : les variables qui sont sensées récupérer les dimensions des images récupèrent 0 à chaque fois !

Donc l'image n'est pas redimensionnée... la ou c'est vraiment perturbant c'est que sur tous les autres navigateurs il n'y a aucun problème !!

je post le code du plugin


;(function( $ ){

	var $preload = $.preload = function( original, settings ){
		if( original.split )//selector
			original = $(original);

		settings = $.extend( {}, $preload.defaults, settings );
		var sources = $.map( original, function( source ){
			if( !source ) 
				return;//skip
			if( source.split )//URL Mode
				return settings.base + source + settings.ext;
			var url = source.src || source.href;//save the original source
			if( typeof settings.placeholder == 'string' && source.src )//Placeholder Mode, if it's an image, set it.
				source.src = settings.placeholder;
			if( url && settings.find )//Rollover mode
				url = url.replace( settings.find, settings.replace );
			return url || null;//skip if empty string
		});

		var data = {
			loaded:0, //how many were loaded successfully
			failed:0, //how many urls failed
			next:0, //which one's the next image to load (index)
			done:0, //how many urls were tried
			total:sources.length //how many images are being preloaded overall
		};
		
		function resizeImg(resizeMod,hThis,wThis,hMax,wMax,hMin,wMin) {
			var newW,newH;
			var tab = new Array; 

			if (resizeMod == 1) { // Rétrécissement
				if ((hThis >= hMax) || (wThis >= wMax)) {
					if ((hThis >= hMax) && (wThis >= wMax)) {
						if (hThis > wThis) {
							newH = hMax;
							newW = parseInt((wThis * newH) / hThis, 10);
						} else {
							newW = wMax;
							newH = parseInt((hThis * newW) / wThis, 10);
						}
					} else if ((hThis >= hMax) && (wThis <= wMax)) {
						newH = hMax;
						newW = parseInt((wThis * newH) / hThis, 10);
					} else if ((hThis <= hMax) && (wThis >= wMax)) {
						newW = wMax;
						newH = parseInt((hThis * newW) / wThis, 10);
					}
					tab[0] = newH;
					tab[1] = newW;
					return tab;
				} else {
					tab[0] = hThis;
					tab[1] = wThis;
					return tab;
				}
			} else if (resizeMod == 2) { // Aggrandissement
				if ((hThis <= hMin) || (wThis <= wMin)) {
					if ((hThis <= hMin) && (wThis <= wMin)) {
						if (hThis < wThis) {
							newH = hMin;
							newW = parseInt((wThis * newH) / hThis, 10);
						} else {
							newW = wMin;
							newH = parseInt((hThis * newW) / wThis, 10);
						}
					} else if ((hThis <= hMin) && (wThis >= wMin)) {
						newH = hMin;
						newW = parseInt((wThis * newH) / hThis, 10);
					} else if ((hThis >= hMin) && (wThis <= wMin)) {
						newW = wMin;
						newH = parseInt((hThis * newW) / wThis, 10);
					}
					tab[0] = newH;
					tab[1] = newW;
					return tab;
				} else {
					tab[0] = hThis;
					tab[1] = wThis;
					return tab;	
				}
			} else if (resizeMod == 3) { // Rétrecissement et Aggrandissement
				if ((hThis >= hMax) || (wThis >= wMax)) {
					if ((hThis >= hMax) && (wThis >= wMax)) {
						if (hThis > wThis) {
							newH = hMax;
							newW = parseInt((wThis * newH) / hThis, 10);
						} else {
							newW = wMax;
							newH = parseInt((hThis * newW) / wThis, 10);
						}
					} else if ((hThis >= hMax) && (wThis <= wMax)) {
						newH = hMax;
						newW = parseInt((wThis * newH) / hThis, 10);
					} else if ((hThis <= hMax) && (wThis >= wMax)) {
						newW = wMax;
						newH = parseInt((hThis * newW) / wThis, 10);
					}
					tab[0] = newH;
					tab[1] = newW;
					return tab;
				} else if ((hThis <= hMin) || (wThis <= wMin)) {
					if ((hThis <= hMin) && (wThis <= wMin)) {
						if (hThis < wThis) {
							newH = hMin;
							newW = parseInt((wThis * newH) / hThis, 10);
						} else {
							newW = wMin;
							newH = parseInt((hThis * newW) / wThis, 10);
						}
					} else if ((hThis <= hMin) && (wThis >= wMin)) {
						newH = hMin;
						newW = parseInt((wThis * newH) / hThis, 10);
					} else if ((hThis >= hMin) && (wThis <= wMin)) {
						newW = wMin;
						newH = parseInt((hThis * newW) / wThis, 10);
					}
					tab[0] = newH;
					tab[1] = newW;
					return tab;
				}	
			}			
		}
		
		if( !data.total ) // Pas de pre-chargement
			return finish();
		
		var imgs = '<img/>',//ensure one
			thres = settings.threshold;//save a copy
		
		
		while( --thres > 0 )//it could be oddly negative
			imgs += '<img/>';
		
		imgs = $(imgs).load(handler).error(handler).bind('abort',handler).each(fetch);
        

            
		function handler(e){
		    //var test = $(e).height();//$(imgs).height(); 
            //alert(test);
			data.found = e.type == 'load';
			data.image = this.src;
		    
			var wThis = this.width;
			var hThis = this.height;
			
			// Appel de la fonction de redimmensionnement en lui passant les parametres
			var resizeMod = settings.resizeMode;
			var hMax = settings.heightMax;
			var wMax = settings.widthMax;
			var hMin = settings.heightMin;
			var wMin = settings.widthMin;
			var recupSize = resizeImg(resizeMod,hThis,wThis,hMax,wMax,hMin,wMin);
			var orig = data.original = original[this.index];
			data[data.found?'loaded':'failed']++;
			data.done++;
			
			// on retaille les images avant l'affichage
			orig.height = recupSize[0];
			orig.width = recupSize[1];
			
			if(settings.placeholder && orig.src ) // On interverti le placeHolder et l'image réelle // Début du pré-chargement
				orig.src = data.found ? data.image : settings.notFound || orig.src;
			if( settings.onComplete ) // Après le pré-chargement
				settings.onComplete( data );
			if( data.done < data.total )//Durant le pré-chargement
				fetch(0,this);
			else{//we are finished
				if( imgs.unbind )//sometimes IE gets here before finishing line 84
					imgs.unbind('load').unbind('error').unbind('abort');//cleanup
				imgs = null;
				finish();
			}
		};
		function fetch( i, img, retry ){
			if( $.browser.msie && data.next && data.next % $preload.gap == 0 && !retry ){//IE problem, can't preload more than 15
				setTimeout(function(){ fetch( i, img, true ); }, 0);
				return false;
			}
			
			if( data.next == data.total ) return false; // On se place à la fin du pré-chargement
			img.index = data.next; //save it, we'll need it.
			img.src = sources[data.next++];
	
			if( settings.onRequest ){
				data.image = img.src;
				data.original = original[data.next-1];
				settings.onRequest( data );
				
			}
		};
		function finish(){
			if( settings.onFinish )
				settings.onFinish( data );
		};
	};

	// each time we load this amount and it's IE, we must rest for a while, make it lower if you get stack overflow.
	$preload.gap = 14; 

	$preload.defaults = {
		threshold:2,//how many images to load simultaneously
		base:'',// URL mode: a base url can be specified, it is prepended to all string urls
		ext:'',// URL mode:same as base, but it's appended after the original url.
		replace:'',// Rollover mode: replacement (can be left empty)
		resizeMode:1, // Mode de redimentionnement
		widthMax:110, // Largeur Maximale
		heightMax:110, // Hauteur Maximale
		widthMin:110, // Largeur Minimale
		heightMin:110 // Hauteur Minimale		
		/*
		find:null,//Rollover mode: a string or regex for the replacement
		notFound:''//Placeholder Mode: Optional url of an image to use when the original wasn't found
		placeholder:'',//Placeholder Mode: url of an image to set while loading
		onRequest:function( data ){ ... },//callback called every time a new url is requested
		onComplete:function( data ){ ... },//callback called every time a response is received(successful or not)
		onFinish:function( data ){ ... }//callback called after all the images were loaded(or failed)
		*/
	};

	$.fn.preload = function( settings ){
		$preload( $(this), settings );
		return this;
	};

})( jQuery );


Pour son utilisation c'est très simple Smiley cligne


$(function() {
		        $.preload('ul.topList li dl dt img', {
		            placeholder:'chargement.gif'
		        });
 });


Si quelqu'un à une idée... je pense que ça viens de la méthode de récupération des attributs qui ne plait pas à Internet explorer mais bon monsieur est tellement exigeant que la je ne vois pas
Smiley ohwell
Modifié par dvilston (04 Nov 2008 - 11:34)
personne a une idée ?

en fait la ou ca va pas c'est ici

        var wThis = this.width;
        var hThis = this.height;


les variables wThis et hThis renvoient 0 sous ie et la bonne valeur sous les autres navigateurs... je ne comprends pas pourquoi.

Un hack peut etre ???
Le renvoi de tailles reelles est pas très bien géré sous IE avec jQuery.

Bien que ce que tu proposes à pas mal de différence avec la lib jQuery que je connaisse, essai de contourner en utilisant this.get(0).offsetWidth des trucs du genre.
get() retourne les noeuds en élément javascript.

Ca m'a très souvent aidé, par contre les valeurs risques d'êtres différentes selon les navigateurs.
Modifié par McDudu (03 Nov 2008 - 15:00)
IE est clairement un navigateur de merde, il a été codé avec les pieds (même le 7). Smiley murf

Vu que c'est un peu mon cauchemar journalier je pousse mon coup de gueule même si c'est un coup dans l'eau et que je ne suis pas le premier ni le dernier.

Pour en revenir au script (c'est quand même çà l'essentiel) :
La méthode postée ci-dessus fonctionne très bien avec tous les autres navigateurs, mais pas sur ie.

Avec l'ancienne méthode, le plugin récupère [0x0] sous ie, avec l'utilisation des callBacks i.e récupère les bonnes dimensions.
La solution réside dans le fait d'utiliser les différentes fonction de callBack du plugin.

Plusieurs fonction de call back sont natives au plugin.


Il faut donc récupérer les valeurs au moment ou les fonctions callback sont appelées, ca permet à Internet explorer d'être [DEL]aware et de pouvoir récupérer les bonnes dimensions des images à récupérer.

La méthode de récupération doit donc se faire dans la fonction onComplete...

Suite à ca le plugin pré-charge les éléments image et les redimensionne.
La contrainte de cette technique c'est qu'on remarque le redimensionnement partiel des images (pour les connexions lentes).

Si vous avez besoin que je reposte le code.. y'a plus qu'a demander!

Dv!L$ToN
++

Smiley lol