11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour, j'ai fait une carte de france avec rollover sur les régions, mais je trouve mon code javascript un peu, certaine fois, il met beaucoup de temps à ce charger sur le site :

Auriez vous des conseils à me donner pour alléger tout ca, voici mon code HTML :


<div id="carte"><img  src="images/carte/france.jpg" id = "switch1" alt="carte de france" width="190" height="173" border="0" usemap="#carte-france" />

  <map name="carte-france" id="carte-france">
    
    <area   shape="poly" coords="165,158,165,162,168,169,171,174,175,167,177,154,174,144,166,151,164,155"  
                  href="#"
                  onMouseOut = "iljswitch(0)"
                  onMouseOver = "iljswitch(1);"
                  class="tipz"
                  title="Corse" 
                  alt="Corse"
                  style="cursor: pointer" />

ETC pour les autres régions ....


ET mon code javascript
TYPE="text/javascript">
<!--
if(document.images)
{
bild = new Array()
bild[0]= new Image()
bild[1]= new Image()
bild[2]= new Image()
bild[3]= new Image()
bild[4]= new Image()
bild[5]= new Image()
bild[6]= new Image()
bild[7]= new Image()
bild[8]= new Image()
bild[9]= new Image()
bild[10]= new Image()
bild[11]= new Image()
bild[12]= new Image()
bild[13]= new Image()
bild[14]= new Image()
bild[15]= new Image()
bild[16]= new Image()
bild[17]= new Image()
bild[18]= new Image()
bild[19]= new Image()
bild[20]= new Image()
bild[21]= new Image()
bild[22]= new Image()
bild[0].src = "images/carte/france.jpg" 
bild[1].src = "images/carte/corse.jpg" 
bild[2].src = "images/carte/paca.jpg" 
bild[3].src = "images/carte/languedoc-roussillon.jpg" 
bild[4].src = "images/carte/rhone-alpes.jpg" 
bild[5].src = "images/carte/midi-pyrennees.jpg" 
bild[6].src = "images/carte/aquitaine.jpg" 
bild[7].src = "images/carte/poitou-charente.jpg" 
bild[8].src = "images/carte/auvergne.jpg" 
bild[9].src = "images/carte/limousin.jpg" 
bild[10].src = "images/carte/pays-de-la-loire.jpg" 
bild[11].src = "images/carte/bretagne.jpg"
bild[12].src = "images/carte/basse-normandie.jpg" 
bild[13].src = "images/carte/haute-normandie.jpg" 
bild[14].src = "images/carte/franche-comte.jpg" 
bild[15].src = "images/carte/alsace.jpg" 
bild[16].src = "images/carte/lorraine.jpg" 
bild[17].src = "images/carte/bourgogne.jpg" 
bild[18].src = "images/carte/centre.jpg" 
bild[19].src = "images/carte/ile-de-france.jpg"  
bild[20].src = "images/carte/champagne-ardenne.jpg" 
bild[21].src = "images/carte/picardie.jpg" 
bild[22].src = "images/carte/nord-pas-de-calais.jpg" 


}

function iljswitch(nummer)
{
if(document.images && document.getElementById)
{
document.getElementById('switch1').src=bild[nummer].src
}
}
//-->
</SCRIPT>



Merci pour votre précieuse aide !
Hello,

Pour commencer, tu pourrais rendre ton code un peu plus élégant et succinct en:
- laissant tomber les tests de fonctionnalités comme document.images (que tu n'utilises pas?) et document.getElementById (supporté partout...);
- construisant ton tableau d'images avec une boucle.

En encapsulant le tout dans un module, ça peut donner:
var myMap = function(){
  var regions = [
    'france', 'corse', 'paca', 'languedoc-roussillon', 'rhone-alpes',
    'midi-pyrennees', 'aquitaine', 'poitou-charente', 'auvergne', 'limousin',
    'pays-de-la-loire', 'bretagne', 'basse-normandie', 'haute-normandie',
    'franche-comte', 'alsace', 'lorraine', 'bourgogne', 'centre', 'ile-de-france',
    'champagne-ardenne', 'picardie', 'nord-pas-de-calais'
  ]
  for (var r in regions) {
    var img = new Image();
    img.src = 'images/carte/'+regions[r]+'.jpg';
    regions[r] = img;
  }
  function swap(n) {
    document.getElementById('switch1').src = regions[n].src;
  }
  return {regions: regions, swap: swap}
}();

Et tu peux alors appeler myMap.regions pour obtenir le tableau des éléments image, myMap.regions Smiley indice pour récupérer un élément donné, myMap.swap(0) pour afficher la carte de France, etc.

Cela dit:
- Je ne vois pas trop pourquoi tu crées des éléments IMG, si c'est juste pour récupérer leur attribut src et l'appliquer à une image différente.
- Tu devrais pouvoir gérer le tout en JS non intrusif et exploiter une information placée dans un attribut de l'élément AREA, soit en créant un attribut exprès (en HTML5, tu peux l'appeler data-region par exemple: <area ... data-region="corse">), soit en utilisant le href (<area ... href="#corse">).
pour compléter ce qu'a dit Florent qui me paraît excellent, il y a 2 choses qui te font ramer à mon avis :


machin = New Image();
machin.src = 'url';

cela lance le téléchargement de l'image, c'est peut être ce que tu veux, mais vu le nombre d'images, cela prend de la bande passante et de la place en RAM, ça doit surement contribuer à ton impression de lenteur



<area
onMouseOut = "iljswitch(0)"
onMouseOver = "iljswitch(1);"
>

tu as autant de listeners que de régions de France (ce qui fait beaucoup) et en plus il faut savoir que les onmouseover et onmouseout sont les pires car ils se déclenchent aussi vite que possible pour chaque pixel au dessus duquel arrive la souris. Donc là c'est ton CPU qui en prend un coup, et si ta fonction n'est pas "protégée", elle se déclenche des dizaines de fois par seconde.
Selon ce que tu fais dedans, forcément ça rame.

il faut donc utiliser la technique dite de "l'event delegation", en voici un bon exemple avec la librairie YUI : http://developer.yahoo.com/yui/examples/event/event-delegation.html

la solution en complément du code de Florent :
- poser 2 seul listener pour onmouseover et onmouseout sur ta map
- dans le callback pour mouseout : un code qui ferme tout région "ouverte", car l'utilisateur a quitté ta map
- dans le callback mouseover : faire un this.getAttribute('data-region') pour savoir si tu as changé de région ou pas, et donc ouvrir ta nouvelle région et fermer une éventuelle ancienne
- si ça ne suffit pas, dans les 2 cas : avec un timer vérifier que ta fonction n'est pas appellée trop souvent. Moi j'utilise ce bout de code en début de fonction de callback :

if(	dateLastMovement &&
	(new Date().getTime() - dateLastMovement.getTime()) < 100) {
		return;
}
dateLastMovement = new Date();

dateLastMovement étant une variable définie en dehors du scope de la fonction, ici on interdit d'appeller la fonction en dessous de toutes les 100 millisecondes.
Je remonte le post avec un peu de retard, car j'ai été obligé de mettre en standby le projet. Mais me voici de retour. Merci en tout cas à vous pour votre feedbacK.

J'ai encapsulé comme me la conseillé florent, je suis content, car c'est beaucoup plus propre. Par contre je ne sais pas comment tester pour voir si le script est plus rapide ou pas.

voici ce que j'ai fait :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  <title>Test Javascript </title>
  
<link rel="stylesheet" href="css/template.css" type="text/css" media="screen" /> 

</head>


<SCRIPT LANGUAGE="JavaScript"
TYPE="text/javascript">
<!--
var myMap = function(){ 
  var regions = [ 
    'france', 'corse', 'paca', 'languedoc-roussillon', 'rhone-alpes', 
    'midi-pyrennees', 'aquitaine', 'poitou-charente', 'auvergne', 'limousin', 
    'pays-de-la-loire', 'bretagne', 'basse-normandie', 'haute-normandie', 
    'franche-comte', 'alsace', 'lorraine', 'bourgogne', 'centre', 'ile-de-france', 
    'champagne-ardenne', 'picardie', 'nord-pas-de-calais' 
  ] 
  for (var r in regions) { 
    var img = new Image(); 
    img.src = 'images/carte'+regions[r]+'.jpg'; 
    regions[r] = img; 
  } 
  function swap(n) { 
    document.getElementById('switch1').src = regions[n].src; 
  } 
  return {regions: regions, swap: swap} 
}();
//-->
</SCRIPT>



<div id="nsink-carte"><img  src="images/france.jpg" id = "switch1" alt="carte de france" width="190" height="173" border="0" usemap="#carte-france" />

  <map name="carte-france" id="carte-france">
    
    <area   shape="poly" coords="165,158,165,162,168,169,171,174,175,167,177,154,174,144,166,151,164,155"  
                  href="regions/corse"
                  onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(1);"
                  class="tipz"
                  title="Corse" 
                  alt="Corse"
                  style="cursor: pointer" />
             
    
  
    <area shape="poly" coords="145,134,141,141,133,143,114,138,121,127,126,122,134,124,140,120,144,118,144,124,147,127,156,128,148,135" 
                href="regions/provence-alpes-cote-d-azur"
                onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(2);"
                title="Paca" 
                alt="Paca"
                class="tipz"
                style="cursor: pointer"
                       />
    
    <area shape="poly" coords="121,124,112,118,107,111,98,113,101,125,92,139,83,141,80,149,83,153,89,155,98,155,97,146,102,138,112,137,117,138" 
              href="regions/languedoc-roussillon"
              onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(3);"
              class="tipz"
              title="Languedoc Roussillon"
              alt="languedoc-roussillon"
              style="cursor: pointer" />
                   
    
    <area shape="poly" coords="106,112,112,108,104,101,104,94,112,88,118,87,125,90,132,93,139,89,141,90,141,94,144,99,141,99,143,103,144,107,140,110,142,113,143,117,137,121,120,123" 
                href="regions/rhone-alpes" 
                onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(4);"
                class="tipz"
                title="Rhone-alpes" 
                alt="rhone-alpes" 
                style="cursor: pointer"/>
                
    
    <area shape="poly" coords="98,114,90,116,83,113,75,113,74,124,70,132,62,136,64,141,66,148,68,150,72,149,77,152,85,142,94,138,97,131,99,120" 
                href="regions/midi-pyrennees" 
                onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(5);"
                class="tipz"
                title="Midi-Pyennees"
                alt="midi-pyrennees" 
                style="cursor: pointer"/>
    
    
        <area shape="poly" coords="75,115,74,106,65,106,60,114,56,111,47,104,47,125,43,138,38,140,56,149,66,150,63,137,72,130,75,122" 
        href="regions/aquitaine"
       onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(6);"
        class="tipz"
        title="Aquitaine" 
        alt="aquitaine" />
    
        <area shape="poly" coords="69,107,78,100,81,91,74,82,64,83,60,78,51,87,53,94,49,97,46,98,50,106,59,115" 
        href="regions/poitou-charente" 
        onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(7);"
        class="tipz"
        title="Poitou Charente"
        alt="poitou-charente" />
        
        <area shape="poly" coords="108,90,115,82,110,75,95,80,91,89,95,102,89,111,96,115,106,114,111,110,105,98" 
        href="regions/auvergne" 
        onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(8);"
        class="tipz"
        title="Auvergne"
        alt="auvergne" />
        
        
        <area shape="poly" coords="80,88,89,87,93,93,94,102,90,109,92,116,80,116,75,107,80,99" 
        href="regions/limousin" 
        onMouseOut = "myMap.swap(0)"
                  onMouseOver = "myMap.swap(9);"
        class="tipz"
        title="Limousin"
        alt="limousin" />
        
        
        <area shape="poly" coords="63,82,69,76,76,67,76,58,63,55,52,54,50,63,48,76,43,73,37,79,41,89,48,97,50,100,52,94,52,87,58,82,63,82" 
        href="regions/pays-de-la-loire" 
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(10);"
        class="tipz"
        title="Pays de la Loire"
        alt="pays-de-la-loire" />
        
        
        <area shape="poly" coords="40,47,47,52,52,56,51,61,49,75,43,77,39,79,34,70,28,67,18,63,9,61,4,61,6,58,8,56,4,55,4,53,10,50,14,48,19,46,24,48,29,50,32,51,40,52" 
        href="regions/bretagne" 
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(11);"
        class="tipz"
        title="Bretagne"
        alt="bretagne" />
        
        
        
        <area shape="poly" coords="76,57,78,50,72,44,69,35,63,33,56,37,49,33,46,32,43,29,41,36,41,42,40,49,52,54" 
        href="regions/basse-normandie" 
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(12);"
        class="tipz"
        title="Basse Normandie"
        alt="basse-normandie" />
        
        <area shape="poly" coords="76,48,84,44,86,35,84,24,78,19,71,27,62,30,71,38" 
        href="regions/haute-normandie" 
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(13);"
        class="tipz"
        title="Haute Normandie"
        alt="haute-normandie" />
        
        
        <area shape="poly" coords="120,89,118,80,126,71,133,64,142,62,146,68,141,75,137,82,133,91,130,92,120,89" 
        href="regions/franche-comte" 
       onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(14);"
        class="tipz"
        title="Franche Comte"
        alt="franche-comte" />
        
        
        <area shape="poly" coords="142,63,142,59,146,49,143,42,150,40,157,43,153,52,154,61,149,69,145,66" 
        href="regions/alsace" 
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(15);"
        class="tipz"
        title="Alsace"
        alt="alsace" />
        
        
        <area shape="poly" coords="123,30,119,43,118,53,125,58,133,64,141,63,144,55,147,49,145,41,144,37,138,34,129,32" 
        href="regions/lorraine" 
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(16);"
        class="tipz"
        title="Lorraine"
        alt="lorraine" />
        
        
        <area shape="poly" coords="100,78,97,74,98,64,100,57,106,53,113,52,119,55,129,61,135,65,128,71,120,79,115,81,110,77" 
        href="regions/bourgogne" 
         onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(17);"
        class="tipz"
        title="Bourgogne"
        alt="bourgogne" />
        
        
        <area shape="poly" coords="85,46,95,51,102,56,99,62,98,72,99,79,92,86,84,91,77,89,72,83,68,85,68,80,77,68,77,59,77,49" 
        href="regions/centre" 
         onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(18);"
        class="tipz"
        title="Centre"
        alt="centre" />
        
        
        
        <area shape="poly" coords="85,42,88,49,94,52,104,50,106,45,100,42,93,40,89,42" 
        href="regions/ile-de-france" 
         onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(19);"
        class="tipz"
        title="Ile-de-France"
        alt="ile-de-france" />
    
    
    
    
        <area shape="poly" coords="108,21,103,29,103,43,106,51,113,53,116,53,119,45,121,37,124,31,121,29,118,22,113,26" 
        href="regions/champagne-ardenne"
         onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(20);"
        class="tipz" 
        title="Champagne-Ardenne" 
        alt="champagne-ardenne" />
        
        <area shape="poly" coords="81,19,90,19,98,19,103,22,108,21,105,27,104,41,94,42,87,44,88,35,84,25" 
        href="regions/picardie" 
       onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(21);"
        class="tipz" 
        title="Picardie"
        alt="picardie" />
    
    
    
        <area shape="poly" coords="79,18,89,18,98,19,104,22,110,22,110,19,104,16,99,11,93,8,91,5,86,5,81,8,82,14" 
        href="regions/nord-pas-de-calais"
        onMouseOut = "myMap.swap(0)"
        onMouseOver = "myMap.swap(22);"
        class="tipz" 
        title="Nord-Pas-De-Calais"
        alt="nord-pas-de-calais" />
  </map>

</div>

</html>


Je vous avoue que j'opterais bien pour la solution javascript non intrusif, mais j'ai peur que mes connaissances faibles de ce language ne m'empêche de le faire. Pensez vous qu'il soit nécessaire que je me penche sur cette solution ? Quel est le rapport gain de vitesse du script / temps d'apprentissage pour mettre en place cette solution ?


Par ailleurs, j'ai placé la fonction datelastmovement ici : est bon ?

<SCRIPT LANGUAGE="JavaScript"
TYPE="text/javascript">
<!--
var myMap = function(){ 
  var regions = [ 
    'france', 'corse', 'paca', 'languedoc-roussillon', 'rhone-alpes', 
    'midi-pyrennees', 'aquitaine', 'poitou-charente', 'auvergne', 'limousin', 
    'pays-de-la-loire', 'bretagne', 'basse-normandie', 'haute-normandie', 
    'franche-comte', 'alsace', 'lorraine', 'bourgogne', 'centre', 'ile-de-france', 
    'champagne-ardenne', 'picardie', 'nord-pas-de-calais' 
  ] 
  for (var r in regions) { 
    var img = new Image(); 
    img.src = 'images/'+regions[r]+'.jpg'; 
    regions[r] = img; 
  } 
  function swap(n) { 
    document.getElementById('switch1').src = regions[n].src; 
  } 
  
  return {regions: regions, swap: swap} 
  
  if(    dateLastMovement && 
    (new Date().getTime() - dateLastMovement.getTime()) < 100) { 
        return; 
} 
dateLastMovement = new Date(); 
  
}();


//-->
</SCRIPT>
merci !
dreadstock a écrit :
Je vous avoue que j'opterais bien pour la solution javascript non intrusif, mais j'ai peur que mes connaissances faibles de ce language ne m'empêche de le faire. Pensez vous qu'il soit nécessaire que je me penche sur cette solution ? Quel est le rapport gain de vitesse du script / temps d'apprentissage pour mettre en place cette solution ?

Utiliser du JS non intrusif te permet d'épurer ton code HTML et de ne pas mélanger autant ton contenu HTML et la logique JavaScript. Ça ne te fait rien gagner en temps de chargement ou réactivité de la page.

dreadstock a écrit :
Par ailleurs, j'ai placé la fonction datelastmovement ici : est bon ?

Non, le code ne sera même pas analysé vu qu'on est dans une fonction et qu'il est placé après l'instruction return. Par ailleurs ce n'est pas un code à utiliser seul, mais qui peut faire partie d'une fonction de callback comme suggéré par jpvincent.

Il se peut que ça soit utilisable comme test au début de la méthode myMap.swap(). Ce qui pourrait donner:

var myMap = function(){ 
  var regions = [ 
    'france', 'corse', 'paca', 'languedoc-roussillon', 'rhone-alpes', 
    'midi-pyrennees', 'aquitaine', 'poitou-charente', 'auvergne', 'limousin', 
    'pays-de-la-loire', 'bretagne', 'basse-normandie', 'haute-normandie', 
    'franche-comte', 'alsace', 'lorraine', 'bourgogne', 'centre', 'ile-de-france', 
    'champagne-ardenne', 'picardie', 'nord-pas-de-calais' 
  ] 
  for (var r in regions) { 
    var img = new Image(); 
    img.src = 'images/carte/'+regions[r]+'.jpg'; 
    regions[r] = img; 
  } 
  var dateLastMovement = new Date();
  function swap(n) {
    if (dateLastMovement && (new Date().getTime() - dateLastMovement.getTime()) < 100) { 
        return;
    } 
    document.getElementById('switch1').src = regions[n].src; 
  } 
  return {regions: regions, swap: swap} 
}();

Mais j'ai pas testé et ce n'est peut-être pas pertinent utilisé comme ça...

En passant, écrire <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"> dans du code XHTML, tss tss...
Modifié par Florent V. (14 Sep 2010 - 13:54)
super, merci pour ton aide, par contre quand tu dis tss tss tss ... je comprends pas trop. Cette syntaxe n'est pas très catholique dans le milieu du XHTML ?? merci encore pour ton aide !
dreadstock a écrit :
Cette syntaxe n'est pas très catholique dans le milieu du XHTML ?? merci encore pour ton aide !

<boutade>Je vois que tu débutes en HTML aussi, pas juste en JavaScript. Smiley smile </boutade>
Cette syntaxe n'est ni catholique, ni pastafari, ni valide. (C'est ce dernier point qui pose problème, vu que la religion d'un bout de code HTML nous importe peu.)
Pour rappel: http://validator.w3.org/

Concrètement, écrire <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"> ne causera pas de problème particulier. Mais il est de bon ton de suivre la règles syntaxiques de la version de HTML choisie.
<!-- HTML 4.01: -->
<SCRIPT TYPE="text/javascript">...</SCRIPT>
<script type="text/javascript">...</script>
<!-- ... autres écritures possibles,
     mais dans tous les cas l'attribut "language" n'existe pas -->

<!-- XHTML 1.0 -->
<script type="text/javascript">...</script>

<!-- HTML5 -->
<SCRIPT TYPE="text/javascript">...</SCRIPT>
<script type="text/javascript">...</script>
<script>...</script>

Pour info, les commentaires HTML à l'intérieur de l'élément SCRIPT n'ont pas un grand intérêt. C'est une ancienne pratique désormais obsolète.

À lire aussi: Comment intégrer du code JavaScript dans une page de manière valide ?
Modifié par Florent V. (15 Sep 2010 - 13:19)
<eureka> Mais bien sur ! que m'est il passé pas la tête !!! </eureka>merci pour cette petite piqure de rappel sur la synthase du html. En effet, j'ai tendance à délaisser un peu mon code html. La validation n'est pas toujours l'une de mes priorités. Je ferai plus attention dorénavant !