11528 sujets

JavaScript, DOM et API Web HTML5

Pages :
(reprise du message précédent)

Menu avec effet tiroir

Du html

<dl class="menu">
  <dt>Rubrique</dt>
    <dd>
      <ul>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	</ul>
  </dd>
</dl>
<dl class="menu">
  <dt>Rubrique</dt>
  <dd>
    <ul>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	  <li><a href="#">Sous-rubrique</a></li>
	</ul>
  </dd>
</dl>


Une càc de css

body
{
	font-family: Arial, Helvetica, sans-serif;
	background: #EEE;
}
dl.menu, dl.menu dt, dl.menu dd, dl.menu dd ul, dl.menu dd ul li
{
	margin: 0px;
	padding: 0px;
}
dl.menu
{
	float: left;
	width: 150px;
	cursor: pointer;
}
dl.menu dt
{
	background: #FFF;
	font-size: 12px;
	font-weight: bold;
	color: #666;
}
dl.menu dd ul
{
	border-right: 1px solid #CCC;
	border-bottom: 1px solid #CCC;
	border-left: 1px solid #CCC;
	width: 140px;
	margin: 0px auto;
	list-style-type: none;
	background: #EEE;
	font-size: 11px;
}
dl.menu dd ul li:hover
{
	background: #CCC;
}
dl.menu dd ul li a
{
	text-decoration: none;
	color: #666;
	padding-left: 5px;
}
dl.menu dd ul li a:hover
{
	color: #FFF;
	padding-left: 10px;
}


Une càs de javascript

var drawerMenu = {
	inc : 5,
	elements : new Array,
	timers : new Array,
	construct : function()
	{
		var dls = document.getElementsByTagName('dl');
		var n = 0;
		for(var i = 0; i < dls.length; i++)
		{
			if(dls[ i].className == 'menu')
			{
				n++;
				drawerMenu.timers[n] = 0;
				dls[ i].onmouseover = drawerMenu.triggerShow;
				dls[ i].onmouseout = drawerMenu.triggerHide;
				dls[ i].targetElement = n;
				for(var j = 0; j < dls[ i].childNodes.length; j++)
				{
					if(dls[ i].childNodes[j].nodeType == 1)
					{
						if(dls[ i].childNodes[j].tagName == 'DD')
						{
							dls[ i].childNodes[j].style.position = 'relative';
							dls[ i].childNodes[j].style.overflow = 'hidden';
							dls[ i].childNodes[j].style.height = '0px';
							for(var k = 0; k < dls[ i].childNodes[j].childNodes.length; k++)
							{
								if(dls[ i].childNodes[j].childNodes[k].nodeType == 1)
								{
									if(dls[ i].childNodes[j].childNodes[k].tagName == 'UL')
									{
										drawerMenu.elements[n] = dls[ i].childNodes[j].childNodes[k];					
										dls[ i].childNodes[j].childNodes[k].style.position = 'absolute';
										dls[ i].childNodes[j].childNodes[k].style.top = '-'+dls[ i].childNodes[j].childNodes[k].offsetHeight+'px';
									}
								}
							}
						}
					}
				}
			}
		}
	},
	triggerShow : function()
	{
		if(drawerMenu.timers[this.targetElement]) clearInterval(drawerMenu.timers[this.targetElement]);
		drawerMenu.timers[this.targetElement] = setInterval('drawerMenu.show('+this.targetElement+')', 20);
	},
	triggerHide : function()
	{
		if(drawerMenu.timers[this.targetElement]) clearInterval(drawerMenu.timers[this.targetElement]);
		drawerMenu.timers[this.targetElement] = setInterval('drawerMenu.hide('+this.targetElement+')', 20);
	},
	show : function(i)
	{
		var ul = drawerMenu.elements[ i];
		var t = parseInt(ul.style.top);
		var inx = Math.ceil(-t/drawerMenu.inc);
		if(t+inx < 0)
		{
			ul.style.top = (t+inx) +'px';
			ul.parentNode.style.height = (ul.offsetHeight+t+inx) + 'px';
		}
		else if(t < 0)
		{
			ul.style.top = '0px';
			ul.parentNode.style.height = ul.offsetHeight + 'px';
		}
		else
		{
			clearInterval(drawerMenu.timers[ i]);
			drawerMenu.timers[ i] = 0;
		}
	},
	hide : function(i)
	{
		var ul = drawerMenu.elements[ i];
		var t = parseInt(ul.style.top);
		var inx = Math.ceil(t/drawerMenu.inc);
		if(inx == 0) inx = -1;
		if(t+inx > -ul.offsetHeight)
		{
			ul.style.top = (t+inx) +'px';
			ul.parentNode.style.height = (ul.offsetHeight+t+inx) + 'px';
		}
		else if(t > -ul.offsetHeight)
		{
			ul.style.top = -ul.offsetHeight + 'px';
			ul.parentNode.style.height = '0px';
		}
		else
		{
			clearInterval(drawerMenu.timers[ i]);
			drawerMenu.timers[ i] = 0;
		}
	}
}

window.onload = drawerMenu.construct;


Exemple en ligne Smiley biggrin

Edit : C'est réglé pour les [ i] j'avais pas lu le post-it Smiley sweatdrop
Modifié par ds-network (15 Jun 2006 - 14:42)
Pour la méthode inArray, petite correction :

a écrit :
* Méthode .inArray pour vérifier qu'un élément est bien présent dans un tableau (Array)


Array.prototype.inArray = function(val) {
	for(var a2 = 0; a2 <= this.length-1;a2++) {
		if(this[ a2] == val)
		               return true;
	}
	return false;
};




Celà devrait fonctionner sous IE.
Modifié par jblecanard (27 Jul 2006 - 12:03)
* Manipulation des classes HTML (avec un équivalent de getElementsByClassName)

// Par Julien Royer :  http://forum.alsacreations.com/topic-5-3716-2.html#p143818
 
var cls = (function() {
	function re(cn) {
		return new RegExp("(^|\\s)" + cn + "(\\s|$)");
	}

	var that = {
		has: function(el, cn) {
			return re(cn).test(el.className);
		},

		add: function(el, cn) {
			if (!el.className) {
				el.className = cn;
			} else if (!that.has(el, cn)) {
				el.className += " " + cn;
			}
		},

		rem: function(el, cn) {
			el.className = el.className.replace(re(cn), function(m, c1, c2) { return c1 && c2; });
		},

		replace: function(el, cn, newCn) {
			el.className = el.className.replace(re(cn), "$1" + newCn + "$2");
		},

		query: function(cn, tn, root) {
			var els = (root || (root = document)).getElementsByTagName(tn || (tn = "*"));
			if (!els.length && root.all && tn === "*") {
				els = root.all;
			}

			var res = [], r = re(cn);
			for (var i = 0, el; (el = els[ i]); ++i) {
				if (r.test(el.className)) {
					res[res.length] = el;
				}
			}

			return res;
		}
	};
	return that;
})();


* Exemples d'utilisation de "query" (getElementsByClassName) :
var els = cls.query("active"); // .active
els = cls.query("active", "span"); // span.active
els = cls.query("active", "span", document.getElementById("root")); // #root span.active
els = cls.query("active", null, document.getElementById("root")); // #root .active

Modifié par Julien Royer (28 Oct 2009 - 14:20)
* Afficher son email en limitant les risques de spam (camion pourriel)

// Par Julien Royer :  http://forum.alsacreations.com/topic-5-3716-2.html#p154887
 
if (document.childNodes && document.getElementById && document.createTextNode && {}.hasOwnProperty) {
(function(cns, doc, win) {
  function createEl(n) {
    var a, i = 0, e = doc.createElementNS ? doc.createElementNS("http://www.w3.org/1999/xhtml", n) : doc.createElement(n);
    while ((a = arguments[++i])) {
      if (typeof a === "string") {
        e.appendChild(doc.createTextNode(a));
      } else {
        for (var p in a) {
          if (a.hasOwnProperty(p)) {
            e[p] = a[p];
          }
        }
      }
    }

    return e;
  }

  function clsRe(c) {
    return new RegExp("(^|\\s)" + c + "(\\s|$)");
  }

  function hasCls(e, c) {
    return clsRe(c).test(e.className);
  }

  function getElsCN(c, t) {
    var els = doc.getElementsByTagName(t), res = [], re = clsRe(c);
    for (var i = 0, e; (e = els[ i]); ++i) {
      if (re.test(e.className)) {
        res[res.length] = e;
      }
    }

    return res;
  }

  function chgEl(el, o) {
    var m = o.user + "@" + o.host + "." + o.domain + (o.subject ? "?subject=" + encodeURIComponent (o.subject) : ""), a = createEl("a", {href: "mailto:" + m, className: cns.email}, o.name || m);
    if (el.title) {
      a.title = el.title;
    }
    el.parentNode.replaceChild(a, el);
  }

  function initEl(el) {
    var o = {}, ss = el.getElementsByTagName("span");
    for (var i = 0, s; (s = ss[ i]); ++i) {
      for (var j in cns) {
        if (cns.hasOwnProperty(j) && hasCls(s, cns[j])) {
          o[j] = s.firstChild && s.firstChild.nodeValue;
        }
      }
    }

    if (o.user && o.host && o.domain) {
      chgEl(el, o);
    }
  }

  function initEls(els) {
    for (var i = 0, e; (e = els[ i]); ++i) {
      initEl(e);
    }
  }

  function init() {
    if (!init.done) {
      init.done = true;
      initEls(getElsCN(cns.email, "span"));
    }
  }

  function addLoadEvt(f) {
    if (doc.addEventListener) {
      doc.addEventListener("DOMContentLoaded", f, false);
    }

    if (win.addEventListener) {
      win.addEventListener("load", f, false);
    } else if (doc.addEventListener) {
      doc.addEventListener("load", f, false);
    } else if (win.attachEvent) {
      win.attachEvent("onload", f);
    }
  }

  addLoadEvt(init);
})({
  email: "email", user: "u", host: "h", domain: "d", name: "n", subject: "s"
}, document, this);
}


* Remplace toutes les occurrences de
<span class="email" title="title">
  [...]
  <span class="n">name</span>
  [...]
  <span class="u">user</span>
  [...]
  <span class="h">host</span>
  [...]
  <span class="d">domain</span>
  [...]
</span>

par
<a href="mailto:user@host.domain" class="email" title="title">name</a>

ou
<a href="mailto:user@host.domain" class="email" title="title">user@host.domain</a>

si name n'est pas présent. title est optionnel.

* Permet de se prévenir du spam tout en proposant une version dégradée aux utilisateurs qui n'ont pas accès à JavaScript. Par exemple :
<span class="email"><span class="n">Gentil kiwiz</span> - <span class="u">kiwiz</span>#arobase#<span class="h">example</span>#point#<span class="d">com</span></span>
// devient
<a href="mailto:kiwiz@example.com" class="email">Gentil kiwiz</a>

<span class="email"><span class="u">kiwiz</span>#arobase#<span class="h">example</span>#point#<span class="d">com</span></span>
// devient
<a href="mailto:kiwiz@example.com" class="email">kiwiz@example.com</a>

<span class="email"><span class="u n">kiwiz</span>#arobase#<span class="h">example</span>#point#<span class="d">com</span></span>
// devient
<a href="kiwiz@example.com" class="email">kiwiz</a>


<edit>Correction d'un bug pour la prise en compte de plusieurs adresses sur la même page. Merci à Benjamin D.C. pour l'avoir signalé.

<edit>Suite à une suggestion de Florent V., une version basée sur une recherche d'expressions régulières a été proposée.
Modifié par Julien Royer (13 Sep 2016 - 14:29)
*Convertir un nombre décimal en hexadécimal

Édit : une solution native à JavaScript a été trouvée, voir le message suivant ...

*Très pratique dès que l'on fait qqch avec des couleurs.
Modifié par Changaco (16 Apr 2008 - 11:17)
CNeo a écrit :
*Convertir un nombre décimal en hexadécimal
Je viens de découvrir que JavaScript permet de faire ça de façon native grâce à la méthode toString :
function toHexStr(nb) {
	return nb.toString(16);
}
Testé avec IE 5+, Opera 9, FF 1.5
Modifié par Julien Royer (11 May 2007 - 23:23)
* Fonction de création d'élément (inspirée d'une fonction créée par koala64)
// Par Julien Royer :  http://forum.alsacreations.com/topic-5-3716-2.html#p174399
 
function createEl(n) {
	var a, i = 0, e = document.createElementNS ? document.createElementNS("http://www.w3.org/1999/xhtml", n) : document.createElement(n);
	while ((a = arguments[++i])) {
		if (typeof a === "string") {
			e.appendChild(document.createTextNode(a));
		} else if (a.nodeName) {
			e.appendChild(a);
		} else {
			for (var p in a) {
				if (a.hasOwnProperty(p)) {
					e[p] = a[p];
				}
			}
		}
	}

	return e;
}

* Permet de créer facilement un élément.

* Le premier paramètre est le nom de l'élément à créer. Les paramètres suivants peuvent être (dans n'importe quel ordre et en n'importe quelle quantité) :
- Un élément à ajouter aux enfants de l'élément créé
- Une chaîne de caractères à ajouter en tant que noeud texte à l'élément créé
- Un tableau associatif nom d'attribut/valeur d'attribut (les attributs sont ajoutés directement en tant que propriétés de l'objet DOM et non en utilisant setAttribute)

* Exemple :
var p = createEl("p", {id: "pouet"},
  "Pouet ",
  createEl("a", {href: "tsoin", title: "tsoin"}, "coin"),
  ".");

génère
<p id="pouet">Pouet <a href="tsoin" title="tsoin">coin</a>.</p>

Modifié par Julien Royer (29 Nov 2007 - 15:01)
* Equivalent pour Javascript de la fonction PHP print_r().

Très pratique pour débugger.


function print_r(theObj){
	if(theObj.constructor == Array ||	theObj.constructor == Object) {
		document.write("<ul>")
		for(var p in theObj){
			if(theObj[p].constructor == Array || theObj[p].constructor == Object) {
				document.write("<li>["+p+"] => "+typeof(theObj)+"</li>");
				document.write("<ul>");
				print_r(theObj[p]);
				document.write("</ul>");
			} else {
				document.write("<li>["+p+"] => "+theObj[p]+"</li>");
			}
		}
		document.write("</ul>")
	}
}


Auteur : brandnewbox.co.uk
Histoire de résumé les discussions sur la manipulation des class d'un node.
Voici l'ensemble des methodes que je recommande vivement d'utiliser.
Un grand merci à tous ceux qui y ont contribués.

MANIPULATION DE CLASS


function addClass(node, className) {if (!node.className) {node.className = className;} else if (!hasClass(node, className)) {node.className += " " + className;}}
function removeClass(node, className) {node.className = node.className.replace(new RegExp("(^| )" + className + "( |$)"), "$1").replace(/ $/, "");if (!node.className) node.removeAttribute("class")}
function setClass(node, className) {node.className = className;}
function replaceClass(node, className, newClassName)	{if (hasClass(node, className)) node.className = node.className.replace(new RegExp("(^| )" + className + "( |$)"), '$1'+newClassName+"$2");}
function hasClass(node, className) {return new RegExp("(^| )" + className + "( |$)").test(node.className);}
function addCSSFile (cssFileSrc,media,id) {
	var cssLinkObj = document.getElementById(id);
	if (cssLinkObj != null) {throw new Error("addStyleNode() - There is already a node with the id '"+id+"'.");}
	else {		
		if (cssFileSrc) {
			if (!existCSSFile(cssFileSrc)) {
				if (!media) media = 'all';
				var cssLinkObj = document.createElement("link");
				cssLinkObj.setAttribute("href",cssFileSrc);
				if (id) {cssLinkObj.setAttribute("id",id);}
				cssLinkObj.setAttribute("rel","stylesheet");
				cssLinkObj.setAttribute("type","text/css");
				cssLinkObj.setAttribute("media",media);
				document.getElementsByTagName('head')[0].appendChild(cssLinkObj);
			}
		}
		else {throw new Error("addCSSFile() - No CSS file is defined. Check the value of 'cssFileSrc'.");}
	}
}
function removeCSSFile (id) {
		var cssLinkObj = document.getElementById(id);
		if (cssLinkObj != null) {
			// This bloody stupid IE is not able to unerstand the css is not there anymore.
			// So let's help him a little bit
			cssLinkObj.removeAttribute("href");
			cssLinkObj.parentNode.removeChild(cssLinkObj);
		}
		else {throw new Error("removeCSSFile() - No <link> with the id '"+id+"' has been bound.");}
}
function updateCSSFile (cssFileSrc,id) {
	var cssLinkObj = document.getElementById(id);
	if (cssLinkObj != null) {
		cssLinkObj.href = cssFileSrc;
	}
	else {
		addCSSFile(cssFileSrc,id);		
	}
}
function existCSSFile (cssFileSrc) {
	var linkNodes = document.getElementsByTagName('link');
	for (var i=0;i <linkNodes.length;i++) {
		if (new RegExp(cssFileSrc + "$").test(linkNodes[i].href)) {return true;}
	}
	return false;
}
[/i]

J'ai aussi ajouté les methodes que j'utilise pour dynamiquement ajouter/supprimer des fichiers CSS à la bonne place dans une page.

Si vous pensez que c'est important je veux bien remplacer tous les nodes par el.

Pour ceux qui cherche une solution simple pour afficher/cacher ou highlight/unhighlight un element je leur recommande vraiment d'utiliser des css class que de manipuler l'attribut style.
Ainsi on tout simplement :


function highlight(node) {addClass(node,'highlight');}
function unhighlight(node) {removeClass(node,'highlight');}
function show(node) {removeClass(node,'hidden');}
function hide(node) {addClass(node,'hidden');}

Modifié par Grumelo (04 Jun 2007 - 10:18)
Ajouter un évènement à un objet avec le modèle DOM2 sans se préoccuper du navigateur. Utilisation du modèle DOM0 en cas de modèle DOM2 indisponible.

a écrit :
Paramètres :
obj - Objet auquel ajouter l'évènement
ev - Type d'évènement, sans le préfixe 'on'. p.ex. : click, load, submit, mouseover, ...
fnc : Fonction à lancer lorsque l'évènement survient


function addEvent(obj, ev, fnc)
{
	if(obj.addEventListener)
		obj.addEventListener(ev, fnc, false);
	else if(obj.attachEvent)
		obj.attachEvent(
			'on'+ev,
			function()
			{
				return fnc.apply(obj, arguments);
			}
		);
	else
	{
		if(!obj['on'+ev])
			obj['on'+ev] = fnc;
		else
		{
			var oldfnc = obj['on'+ev];
			obj['on'+ev] = function()
			{
				oldfnc();
				fnc();
			}
		}
	}
	else
		return false;

	return true;
}



La petite nouveauté par rapport aux fonctions précédentes similaires est l'utilisation ici d'une petite astuce pour pouvoir utiliser le this avec attachEvent sur IE et ainsi utiliser pleinement le modèle DOM2 avec ce navigateur.
Modifié par koala64 (25 Jun 2007 - 14:02)
Les cookies, récupération, création et suppression

Il est ressorti du débat dans ce sujet du forum sur les cookies que l'on peut choisir entre deux façons différentes de gérer les cookies selon le projet.

Note : nous n'avons pas fait de réels tests de comparaison

* Première solution : la mise en cache des cookies. Cette méthode est théoriquement à privilégier si vous devez souvent accéder aux cookies.

Inconvénient : une modification qui ne serait pas faite via cet objet ne serait pas lisible dans cet objet à moins de relancer "cookies.initiate()".

var cookies = {
 number: 0,
 tab: new Array(),

 initiate: function(){
  if(document.cookie!=''){
   var bar = document.cookie.split("; ");
   for(var j=0; j<bar.length; j++){
    var foo = bar[j].split("=");
    this.tab[foo[0]]=unescape(foo[1]);
    this.number++;
   }
  }
 },

 get: function(varName){
  if(this.tab[varName]) return this.tab[varName];
  else return null;
 },

 set: function(varName, varValue, days){
  this.tab[varName]=varValue.toString();
  var expires = '';
  if(days){
   expires='; expires='+new Date(new Date().getTime() + days*24*60*60*1000).toGMTString();
  }
  document.cookie = varName+"="+escape(varValue)+expires+';path=/';
 },

 erase: function(varName){
  this.set(varName,'',-1);
  this.tab[varName]='';
 }
};
cookies.initiate();


* Deuxième méthode qui fonctionne dans tous les cas

// Par Julien Royer :  http://forum.alsacreations.com/topic-5-3716-2.html#p211647
 
var cookieMgr = {
	get: function(name) {
		var o = new RegExp("(?:^|; ?)" + name + "=([^;]+)").exec(document.cookie);
		return o && unescape(o[1]);
	},

	set: function(name, value, days) {
		var expires = "";
		if (days) {
			expires = "; expires=" + new Date(new Date().getTime() + days*24*60*60*1000).toGMTString();
		}
		document.cookie = name + "=" + escape(value) + expires + "; path=/";
	},

	erase: function(name) {
		this.set(name, "", -1);
	}
};

Modifié par Changaco (16 Apr 2008 - 11:15)
Texte changeant avec effet de disparition/apparition

Sujet du forum lié à cette fonction : Créer un "ticker".

var j = -1;
var texts = new Array('Texte 1', 'Texte 2', 'Texte 3', 'Texte par défaut.');
function showNextText(){
 var textColor = document.getElementById('infos').style.color.toLowerCase();
 if(textColor=='#000000' || textColor=='#000' || textColor=='rgb(0, 0, 0)'){
  setTimeout('hideCurrentText()', '3000');
 }
 else{
  if(textColor.substr(0,1)=='#'){
   textHexColor=textColor.substr(1,2);
   eval('nextColor=0x'+textHexColor+'-0x33;');
  }
  else if(textColor.substr(0,3)=='rgb'){
   var colors=RegExp(/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/).exec(textColor);
   nextColor=parseInt(colors[1])-51;
  }
  else return;
  nextColor=nextColor.toString(16);
  document.getElementById('infos').style.color='#'+nextColor+nextColor+nextColor;
  setTimeout('showNextText()', '100');
 }
}
function hideCurrentText(){
 var textColor = document.getElementById('infos').style.color.toLowerCase();
 if(textColor=='#ffffff' || textColor=='#fff' || textColor=='rgb(255, 255, 255)'){
  j++;
  if(j>=texts.length) j=0;
  document.getElementById('infos').firstChild.nodeValue=texts[j];
  showNextText();
 }
 else{
  if(textColor.substr(0,1)=='#'){
   textHexColor=textColor.substr(1,2);
   eval('nextColor=0x'+textHexColor+'+0x33;');
  }
  else if(textColor.substr(0,3)=='rgb'){
   var colors=RegExp(/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/).exec(textColor);
   nextColor=parseInt(colors[1])+51;
  }
  else return;
  nextColor=nextColor.toString(16);
  document.getElementById('infos').style.color='#'+nextColor+nextColor+nextColor;
  setTimeout('hideCurrentText()', '100');
 }
}

window.onload=function (){
 document.getElementById('infos').style.color='#000';
 setTimeout('hideCurrentText()', '3000');
}


À savoir pour paramétrer :
- l'effet de disparition/apparition se fait par changement de couleur du texte c'est pourquoi ce script ne fonctionne que avec du texte noir sur fond blanc
- chaque texte reste affiché 3 secondes pour changer cela il faut changer les deux valeurs '3000' dans les setTimeout
- la vitesse de disparition du texte est liée aux valeurs de temps dans les autres setTimeout c'est-à-dire la valeur '100' qui fait donc disparaître le texte en 0.5 seconde
- le script s'applique sur l'élément possédant l'id "infos", il faut donc modifier les occurrences de "getElementById('infos')"
Gestion de classes CSS (sans RegExp, avec array.split())


//retourne si la valeur demandée est dans le tableau
Array.prototype.find = function(search) {
	var k = this.length;
	while (k--) if (this[k]===search) return true;
	k = null;
	return false;
}

function hasClass(element, className) {
	var tmpClass = element.className.split(" ");
	return tmpClass.find(className);
}

function addClass(element, className) {
	var tmpClass = element.className.split(" ");
	if (!tmpClass.find(className)) {
		tmpClass.push(className);
		element.className = tmpClass.join(" ");
	}
	tmpClass = null;
}

function removeClass(element, className) {
	var tmpClass = element.className.split(" ");
	var newClass = "";
	var k = tmpClass.length;
	while (k--) if (tmpClass[k]!=className) newClass+= tmpClass[k]+" ";
	element.className = newClass;
	tmpClass = newClass = k = null;
}

function replaceClass(element, className, otherClass) {
	var tmpClass = element.className.split(" ");
	var newClass = "";
	var k = tmpClass.length;
	while (k--) {
		if (tmpClass[k]!=className) newClass+= tmpClass[k]+" ";
		else newClass+= otherClass+" ";
	}
	element.className = newClass;
	tmpClass = newClass = k = null;
}


La discussion sur les différentes approches se trouve ici
Modifié par Tymlis (29 Aug 2007 - 11:06)
Réactivation du focus des animations Flash
discution à ce sujet

L'interêt de ce code est parrer le problème avec IE sur les plugins tels que Flash, QuickTime, RealPlayer, Java ou Adobe Acrobat tout en ayant un code HTML valide, un script externe et un script propre.
/!\ Pour l'instant seul Flash Player est géré

flashFocus.js
/* Reactivation du focus des animations Flash _ Rev:1 */
/*@cc_on @*/
/*@if (@_jscript)
// Cette operation doit ce derouler dans un fichier javascript exterieur (see Ref:1)
window.attachEvent("onload", function flashFocus()
{
	// Recherche de tous les elements object de la page
	var objects = document.getElementsByTagName("object");
	var objectSource, object, container;
	for(var j = 0; j < objects.length; j ++)
	{
		object = objects[j];
		// Appliquer si l'object correspond au type animation flash (à voir pour les autres)
		if(object.type == "application/x-shockwave-flash")
		{
			// IE ne supportant pas l'attribut data pour l'ActiveX Flash
			// on doit l'enlever pour que l'on puisse recuperer correctement le code source complet de l'objet (sans doute un bug ?)
			object.removeAttribute("data");
			objectSource = object.outerHTML;
			// Creation temporaire d'un conteneur ou l'on va ecrire le code source de l'objet
			container = document.createElement("div");
			// Insertion du conteneur avant l'objet dans l'arborescence elements HTML
			object.parentNode.insertBefore(container, object);
			// Retirer l'object
			object.parentNode.removeChild(object);
			// Ref:1
			// Ecrire le code source HTML de l'objet dans le conteneur
			// Cette operation doit imperativement etre realise dans fichier Javascript externe. Sinon il n'y aura aucun effet
			container.innerHTML += objectSource
			// Deplacer le clone nouvellement avant le conteneur
			container.parentNode.insertBefore(container.firstChild, container);
			// Suppression du conteneur
			container.parentNode.removeChild(container);
		}
	}
});
/*@end @*/


_page_.html
...
<script type="text/javascript" src="flashFocus.js"></script>
...
<object id="flash1" type="application/x-shockwave-flash" data="flash.swf" style="width: 200px; height: 200px;">
	[#red]<param name="movie" value="flash.swf" />[/#]
	<param name="flashvars" value="text=test" />
	<p>Texte alternatif au flash.</p>
</object>
...

/!\ Attention : Même si le paramètre "movie" n'est pas dans les recommandations du W3C à propos des objets, il est cependant nécessaire pour que IE affiche correctement le Flash (pour les autres il faut voir).
Modifié par heyman85 (20 Oct 2007 - 13:35)
* Capture des événements souris pour un objet Flash

// Par Julien Royer :  http://forum.alsacreations.com/topic-5-3716-2.html#p233049
 
var flashMouseEvtMgr = (function() {
	function createEl(n) {
		return document.createElementNS ? document.createElementNS("http://www.w3.org/1999/xhtml", n) : document.createElement(n);
	}

	function createSpan(obj) {
		var span = createEl("span");

		span.style.position = "absolute";
		span.style.width = obj.width + "px";
		span.style.height = obj.height + "px";
		span.style.background = "url(#)";

		obj.parentNode.insertBefore(span, obj);

		return span;
	}

	return {
		add: function(obj, type, fn) {
			if (fn || (fn = obj["on" + type])) {
				var span = obj.flashMouseEvtEl || (obj.flashMouseEvtEl = createSpan(obj));

				obj["on" + type] = null;
				span["on" + type] = fn;
			}
		}
	};
})();


* Exemple d'utilisation :
<p>
<object id="flashObj" onclick="alert('click');" data="test.swf"
	width="50" height="50" type="application/x-shockwave-flash">
	<param name="movie" value="test.swf" />
	<param name="wmode" value="transparent" />
</object>
</p>

<script type="text/javascript"><!--
	var obj = document.getElementById("flashObj");
	flashMouseEvtMgr.add(obj, "click");
	flashMouseEvtMgr.add(obj, "mousedown", function() { alert("mousedown"); });
//--></script>

* Testé sous IE 5.5+, FF, Opera 9, Safari 3 Win

* Cette technique est à utiliser avec précaution... Pour en savoir plus, voir le sujet à l'origine de ce message.
Modifié par Julien Royer (30 Nov 2007 - 09:53)
Retourne la résolution de l'écran du client

function getScreenSize() {
	var myScreen = new Object();
	myScreen.Height = 0;
	myScreen.Width = 0;
	
	if(window.innerHeight)
	{
		myScreen.Height = window.innerHeight;
		myScreen.Width = window.innerWidth;
	}
	else if(document.body && document.body.clientHeight)
	{
		myScreen.Height = document.body.clientHeight;
		myScreen.Width = document.body.clientWidth;
	}
	else if(document.documentElement && document.documentElement.clientHeight)
	{
		myScreen.Height = document.documentElement.clientHeight;
		myScreen.Width = document.documentElement.clientWidth;
	}
	
	return myScreen;
}
* Tire un ou plusieurs chiffres aléatoires dans un intervalle donné

Topic lié : Nombres aléatoires entre 0 et 50 javascript

function isDouble(aNumbers, randomNumber, floatPrecision){
 if(randomNumber==='0'&&floatPrecision!=0) return true;
 for(var j=0; j<aNumbers.length; j++){
  if(aNumbers[j]==randomNumber){
   return true;
  }
 }
 return false;
}
function randomNumbers(listLength, minNumber, maxNumber, floatPrecision, enableDoubles){

 var aNumbers = new Array(listLength);
 var randomNumber = new Number();
 var i=0;

 if(!floatPrecision) floatPrecision=0;

 if(enableDoubles===false){
  if(floatPrecision==0 && listLength>(maxNumber-minNumber+1) || floatPrecision!=0 && listLength>((Math.pow(10, (floatPrecision)))*(maxNumber-minNumber)+maxNumber-minNumber)){
   alert('Impossible !');
   return false;
  }
 }

 while(i<listLength){
  i++;
  randomNumber=Math.floor(Math.random()*((maxNumber-minNumber)*Math.pow(10, floatPrecision)+1))*Math.pow(10, -floatPrecision)+minNumber;
  if(floatPrecision===0) randomNumber = String(randomNumber).slice(0, String(Math.floor(randomNumber)).length);
  else randomNumber = String(randomNumber).slice(0, String(Math.floor(randomNumber)).length+floatPrecision+1);

  if(enableDoubles===false){
   if(isDouble(aNumbers, String(randomNumber), floatPrecision)===true){
    i--;
    continue;
   }
  }
  aNumbers[i-1] = Number(randomNumber);
 }
 alert('Result : '+aNumbers);
}


* Description des paramètres
listLength : nombre de chiffres à tirer ( entier positif )
minNumber : début de l'intervalle ( ce nombre peut être négatif )
maxNumber : fin de l'intervalle ( ce nombre peut être négatif )
floatPrecision : nombre de chiffres après la virgule ( entier positif )
enableDoubles : autoriser ou non les doublons ( booléen )
Modifié par Changaco (15 Jan 2011 - 15:05)
* Afficher/Masquer les numéros de ligne dans un champ texte

Sujet lié : Afficher/Masquer les numéros de ligne dans un champ texte - Forum Alsacréations

// Le commentaire suivant ne doit pas être effacé.
//  http://forum.alsacreations.com/topic-5-31536-1-AfficherMasquer-les-numeros-de-ligne-dans-un-champ-texte.html
 
function repeatString(str, num){
 var returnStr='';
 for(k=1; k<=num; k++){
  returnStr+=str;
 }
 return returnStr;
}

function lineNumbers(checkbox){
 page=document.getElementById('page');
 // On sauvegarde la position de la scrollbar pour firefox qui ne se replace pas automatiquement contrairement aux autres navigateurs.
 posY=page.scrollTop;
 posX=page.scrollLeft;
 // On découpe le champ texte par ligne et on le stock dans un tableau.
 array=page.value.split("\n");
 // Si c'est la première exécution de la fonction on calcule la taille du numéro correspondant à la dernière ligne.
 if(typeof(maxLength)=='undefined') maxLength=String(array.length).length;
 // On calcule le nombre de caractère à enlever/ajouter par ligne uniquement s'il faut en ajouter de façon à ne pas en supprimer plus qu'il n'y en a.
 if(checkbox.checked==true) maxLength=String(array.length).length;
 // On vérifie si les numéros de ligne sont déjà affichés grâce à un champ texte caché.
 lineNumbersHidden=document.getElementById('lineNumbersHidden');
 if(lineNumbersHidden.value=='true' && checkbox.checked==false) lineNumbersHidden.value='false';
 else if(lineNumbersHidden.value=='false' && checkbox.checked==true) lineNumbersHidden.value='true';
 else if((lineNumbersHidden.value=='true' && checkbox.checked==true) || (lineNumbersHidden.value=='false' && checkbox.checked==false)) return;
 else if(lineNumbersHidden.value==''){
  lineNumbersHidden.value=checkbox.checked;
  return;
 }
 // On rajoute/enlève le numéro pour chaque ligne du champ.
 for(j=0; j<array.length; j++){
  if(checkbox.checked==true) array[j]=String(j+1)+repeatString(' ', maxLength+1-String(j+1).length)+array[j];
  else array[j]=array[j].substring(maxLength+1, array[j].length);
 }
 page.value=array.join("\n");
 // On replace la scrollbar de Firefox.
 page.scrollTop=posY;
 page.scrollLeft=posX;
}
function savePos(){
 document.getElementById('posYHidden').value=document.getElementById('page').scrollTop;
 document.getElementById('posXHidden').value=document.getElementById('page').scrollLeft;
 return true;
}
function setPos(){
 document.getElementById('page').scrollTop=document.getElementById('posYHidden').value;
 document.getElementById('page').scrollLeft=document.getElementById('posXHidden').value;
 return true;
}
window.onload=function (){
 // On affiche la checkbox.
 document.getElementById('controls').style.display='inline';
 // On vérifie si les commentaires sont affichés, si oui on les enlève.
 // Ces balises de commentaires servent à pouvoir afficher du code HTML contenant une balise </textarea> dans Firefox, Opera et IE.
 page=document.getElementById('page');
 if(document.getElementById('comments').value=='yes'){
  page.value=page.value.substring(4, page.value.length-3);
  document.getElementById('comments').value='no';
 }
 c1=document.getElementById('c1');
 lineNumbers(c1);
 // Si l'utilisateur appuie sur entrée dans le champ alors on cache les numéros de lignes car ils ne sont plus bons.
 // On place le retour à la ligne manuellement car sinon il se retrouve à la fin du champ.
 page.onkeypress=function (event){
  var key=window.event?window.event.keyCode:event.keyCode;
  if(key==13 && c1.checked==true){
   var page=document.getElementById('page');
   savePos();
   if(document.selection) document.selection.createRange().text="\n"+repeatString(' ', String(page.value.split("\n").length).length+1);
   else if(page.selectionStart) page.value=page.value.substr(0, page.selectionStart)+"\n"+repeatString(' ', String(page.value.split("\n").length).length+1)+page.value.substr(page.selectionEnd);
   setPos();
   c1.checked=false;
   lineNumbers(c1);
   return false;
  }
 };
 // Si la page est rafraîchie alors on sauvegarde les positions de scroll dans les champs texte car Firefox les conserve.
 window.onunload=savePos;
 // On replace la scrollbar de Firefox si l'on vient de rafraîchir la page.
 setPos();
};

* Améliorations de cette deuxième version
Le problème des doubles numéros de ligne dans Firefox a été réglé grâce à un champ texte caché.
La scrollbar de Firefox est désormais replacée au rafraîchissement de la page et quand on affiche ou cache les lignes.
Les numéros de lignes sont désormais cachés lorsque l'on en insère une nouvelle, logique puisque s'il y en a une de plus ils ne sont plus bons.
Masquage au chargement des commentaires de début et de fin qui servent à "cacher" la balise </textarea> à Firefox, IE et Opera.
* Récupère le contenu XML d'une balise

Sujet lié : Récupérer le contenu _exact_ d'un div

L'équivalent XML de innerHTML. Avec cette dernière, les navigateurs renvoient un code HTML (logique, après tout, c'est ce qu'on demande, innerHTML). Mais certains d'entre eux se donnent un mal fou a le rendre des plus crades (balises et attributs en majuscule, certains attributs ne sont pas entouré de guillemet,...) ce qui rend le code final difficile à travailler en XML.
Donc, plutôt que de corriger les déboires de chacun, autant écrire une fonction qui fait exactement ce qu'on lui demande.

Version universelle :
//root est un objet représentant une balise
var innerXML=function(root){
	var attributes=function(root){
		var str=new String();
		
		for(var t=0; t<root.attributes.length; t++){ //pour chaque attribut de la balise
			//test spécifique à IE permettant d'éliminer les attributs vides (notemment la pluspart des évènements et attributs spécifiques à IE), hérités ainsi que les attributs de type object et function stockés dans la balise
			if(root.attributes[t].nodeValue && root.attributes[t].nodeValue!='inherit' && !root.attributes[t].nodeValue.prototype) str+=' '+root.attributes[t].nodeName.toLowerCase()+'="'+root.attributes[t].nodeValue+'"'; //ecriture du nom et de la valeur de l'attribut
		}
		
		return str;
	}
	
	var str=new String();
	
	if(root.childNodes.length){ //si c'est une balise qui a des balises enfants (div, p, span,...)
		str+='<'+root.tagName.toLowerCase()+attributes(root)+'>';
		
		for(var t=0; t<root.childNodes.length; t++){
			if(root.childNodes[t].tagName) str+=innerXML(root.childNodes[t]); //si c'est une balise enfant, on récupère le contenu XML
			else str+=root.childNodes[t].nodeValue; //sinon, le texte
		}
		
		str+='</'+root.tagName.toLowerCase()+'>'; //puis on ferme la balise
	}else str+='<'+root.tagName.toLowerCase()+attributes(root)+' />'; //si c'est une balise qui n'a pas de balise enfant (br, img,...)
	
	return str;
}


Version DOM :
var innerXML=function(){
	var attributes=function(root){
		var str=new String();
		
		for(var t=0; t<root.attributes.length; t++){ //pour chaque attribut de la balise
			str+=' '+root.attributes[t].nodeName.toLowerString()+'="'+root.attributes[t].nodeValue+'"'; //ecriture du nom et de la valeur de l'attribut
		}
		
		return str;
	}
	
	var str=new String();
	
	if(this.childNodes.length){ //si c'est une balise qui a des balises enfants (div, p, span,...)
		str+='<'+this.tagName.toLowerCase()+attributes(this)+'>';
		
		for(var t=0; t<this.childNodes.length; t++){
			if(this.childNodes[t].innerXML) str+=this.childNodes[t].innerXML(); //si c'est une balise enfant, on récupère son contenu XML
			else str+=this.childNodes[t].nodeValue; //si ce n'est pas une balise, donc du texte
		}
		
		str+='</'+this.tagName.toLowerCase()+'>'; //puis on ferme la balise
	}else str+='<'+this.tagName.toLowerCase()+attributes(this)+' />'; //si c'est une balise qui n'a pas de balise enfant (br, img,...)
	
	return str;
}

if(!Element.prototype.innerXML) Element.prototype.innerXML=innerXML; //Element est l'objet DOM source de toutes les balises


version IE :
var innerXML=function(){
	var attributes=function(root){
		var str=new String();
		
		for(var t=0; t<root.attributes.length; t++){ //pour chaque attribut de la balise
			//permet d'éliminer les attributs vides (notemment la pluspart des évènements et attributs spécifiques à IE), hérités ainsi que les attributs de type object et function stockés dans la balise
			if(root.attributes[t].nodeValue && root.attributes[t].nodeValue!='inherit' && !root.attributes[t].nodeValue.prototype) str+=' '+root.attributes[t].nodeName.toLowerCase()+'="'+root.attributes[t].nodeValue+'"'; //ecriture du nom et de la valeur de l'attribut
		}
		
		return str;
	}
	
	var str=new String();
	
	if(this.childNodes.length){ //si c'est une balise qui a des balises enfants (div, p, span,...)
		str+='<'+this.tagName.toLowerCase()+attributes(this)+'>';
		
		for(var t=0; t<this.childNodes.length; t++){
			if(this.childNodes[t].tagName){ //si c'est une balise enfant
				if(!this.childNodes[t].innerXML) this.childNodes[t].innerXML=this.innerXML; //ajoute la méthode innerXML a l'enfant si celui n'en dispose pas déjà
				str+=this.childNodes[t].innerXML(); //on récupère le contenu XML
			}else str+=this.childNodes[t].nodeValue; //si ce n'est pas une balise, donc du texte
		}
		
		str+='</'+this.tagName.toLowerCase()+'>'; //puis on ferme la balise
	}else str+='<'+this.tagName.toLowerCase()+attributes(this)+' />'; //si c'est une balise qui n'a pas de balise enfant (br, img,...)
	
	return str;
}

if(!node.innerXML) node.innerXML=innerXML; //node est un objet représentant une balise


Avec ce script de heyman85, il est possible d'utiliser la version DOM sous IE en remplaçant l'objet Element par HTMLElement. Néanmoins, les balises ne faisant pas partie de HTML/XHTML ne seront pas pris en charge et il faut, en outre, modifier la fonctions attributes() afin qu'elle vérifie que l'attribut d'une balise ne soit pas vide, une fonction, un objet ou hérité avant de l'ajouté à la balise.
Modifié par MacIntoc (23 Jun 2008 - 12:31)
Pour reprendre la fonction Array.prototype.inArray, je préfère utiliser celle ci

Array.prototype.indexOf = function ( element ) {
	for ( var i = 0; i < this.length; i++ )
		if ( this[ i] === element )
			return i;
	return -1;
}

Qui permet en plus d'indiquer si l'élément est présent dans le tableau ( retour différent de -1 ), d'utiliser des fonctions comme splice pour retirer un élément du tableau.

Et la fonction permettant de supprimer un élément du tableau

Array.prototype.remove = function ( element ) {
	var index = this.indexOf ( element );
	if ( index >= 0 )
		return this.splice ( index, 1 );
	else return null;
}

Modifié par Florent V. (21 Jul 2010 - 09:38)
Pages :