// 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, 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;
}
}
}
* 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"),
".");
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.href)) {return true;}
}
return false;
}
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');}
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.
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
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++;
}
}
},
À 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)
You can cut our wings, but we will always remember what it was like to fly.
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 @*/
/!\ 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)
* 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)
* 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 (16 Apr 2008 - 11:20)
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.