Page 1 sur 1

Modification du DOM

MessagePosté: 22 Jan 2007, 20:32
par MacIntoc
J'aimerais savoir s'il y a un moyen de modifier les objets DOM, notamment les HTMLElements.

C'est en particulier la méthode addEventListener que je voudrais modifier (afin de lui faire gérer l'attachement de méthode avec argument) et ajouter une méthode getElementByClassName.

MessagePosté: 22 Jan 2007, 23:39
par Olivier
Je ne comprends pas trop ce que tu veux faire avec le addEventListener(), mais pour rechercher des éléments par leur classe, tu as des exemples ici :

http://www.glazman.org/weblog/newarchive/2003_06_01_glazblogarc.html#s95320189

MessagePosté: 23 Jan 2007, 09:21
par MacIntoc
Et bien, concernant le addEventListener, j'ai besoin de passer un index a la fonction que j'attache à l'évènement :
  Code:
for(var index=0;index<6;index++){
    tabs.add(document.getElementById('tab'+index)).addEventListener('click', tabs.select(index), false);
}


Cette écriture ne fonctionne évidemment pas. Habituellement, je passe par une fermeture lexicale :
  Code:
for(var index=0;index<6;index++){
    tabs.add(document.getElementById('tab'+index)).addEventListener('click', evtFct=function(){tabs.select(index).bind(tabs)}, false);
}


Le bind(tabs) est là pour rappeller a JavaScript le contexte dans lequel il doit éxécuter tabs.select
Seulement, dans ce cas, il y a un piège, c'est que l'index étant une fermeture lexicale, il continue d'évoluer a l'intérieur de evtFct en même temps qu'il évolue a l'intérieur de la fonction parent. Résultat logique, je me retrouve toujours avec la valeur 6 pour index (donné par la boucle for) a l'intérieur de tabs.select

Donc, je voudrais modifier la fonction addEventListener afin de lui faire accepter un tableau servant a lister les arguments a passer a la fonction au moment de son appel :
  Code:
addEventListener('event', function, bool, array){
    ...
    function(array) //au lieu de function()
    ...
}


Pour le getElementByClassName, je regarde ça. A vu de nez, y a certains trucs que je comprends pas.

[edit]En faite, c'est pas que je ne les comprenaient pas, c'est que ça n'allait pas ^^
Les versions données récupèrent les class sur l'ensemble de l'arbre Hors, dans mon cas, je veux récupérer les class sur une une branche donnée, idéalement sans avoir a précisé la branche. D'où l'intérêt de rajouter cette méthode sur chaque branche de l'arbre.[/edit]

MessagePosté: 23 Jan 2007, 14:59
par MacIntoc
En fait, ça y est, j'ai réussis a implémenter mon getElementByClassName comme je le voulais ^^

Aprés un load, avant d'utiliser cette méthode :
  Code:
//ajout d'une fonction de validation de présence de contenu pour la class Array
Array.prototype.inArray=function(value){
    var inNotInArray=true;
    for(var index=0;index<this.length && inNotInArray;index++) {
        if(this[index]==value) inNotInArray=false;
    }
    return inNotInArray;
}

//Pour le DOM, il ne faut pas passer par prototype...
var tags=document.getElementsByTagName('*')
for(var index=0;index<tags.length;index++){
    tags[index].getElementsByClassName=function(className){
    var elements=this.getElementsByTagName('*');
    var class=new Array();
    for (var index=0;index<elements.length;index++){
        if(elements[index].hasAttribute('class') && elements[index].getAttribute('class').split(' ').inArray(className)){
            class.push(elements[index]);
        }
    }
    return class;
}


Ca doit être possible de faire mieux, mais c'est déjà satisfaisant comme ceci.

MessagePosté: 23 Sep 2008, 17:27
par MacIntoc
Tiens, un peu d'archéologie. Si ça intéresse du monde, y a effectivement mieux :

  Code:
var getElementsByAttribute=function(srcElement, attribute, value){
   var elements=srcElement.getElementsByTagName('*');
   var selected=new Array();
               
   value=value.split(' ');
   if(!value.inArray) value=new Array(value);
   var maxValue=value.length;
               
   for(var index=0;index<elements.length;index++){
      if(elements[index].hasAttribute(attribute)){
         var list=elements[index].getAttribute(attribute).split(' ');
                     
         if(list.inArray){
            for(var i=0; i<maxValue && list.inArray(value[i]); i++){}
            if(i==maxValue) selected.push(elements[index]);
         }
      }
   }
               
   return selected;
}

if(!Element.getElementsByAttribute) Element.getElementsByAttribute=getElementsByAttribute;


Cette technique permet d'obtenir la méthode getElementsByAttibutes sur toutes les balises de la pages sans autre manipulation. Bien sur, elle fonctionne sur tous les navigateurs sauf... IE. Ce dernier ne gère pas la méthode hasAttribute (il faut donc faire une fonction spécifique en remplaçant hasAttribute par getAttribute) et ne donne pas accès à l'objet Element (il faut donc ajouter manuellement la méthode à chaque balise qui doit l'utiliser). De plus, l'attribut class est nommé className (sauf IE8 qui nomme bien l'attribut class "class", comme tous les autre navigateurs).
Cette technique peut-être étendu a tous les objets XML/HTML pour divers besoin. Par exemple, pour obtenir l'option actif d'un select :
  Code:
var selectedOption=function(){
   return this.options[this.selectedIndex];
}
if(!HTMLSelectElement.selectedOption) HTMLSelectElement.selectedOption=selectedOption;


En ce qui concerne addEventListener, la solution est également facile à défaut d'être simple :
  Code:
var temp=function(fonction, param){
   return fonction(param);
}

for(var i=0; i<10; i++){
   balise.addEventListener('event', temp(mafonction, monparametre), false);
}