J'utilise un extrait de code javascript pour que les visiteurs de mon site augmentent la taille de la police sur tous les paragraphes en utilisant le javascript suivant:
function increaseFontSize() {
var paragraphs = document.getElementsByTagName('p');
for(i=0;i<paragraphs.length;i++) {
if(paragraphs[i].style.fontSize) {
var s = parseInt(paragraphs[i].style.fontSize.replace("px",""));
} else {
var s = 14;
}
if(s != max) {
s += 1;
}
paragraphs[i].style.fontSize = s+"px"
}
}
Comment puis-je également inclure "li" dans ce code afin que "p" et "li" soient les éléments sélectionnés qui sont affectés?
Je voudrais également éviter d'ajouter une classe ou un identifiant à mon "li" ou "ul". Existe-t-il un moyen de sélectionner deux balises à la fois?
Non, vous ne pouvez pas sélectionner plusieurs balises en un seul appel à getElementsByTagName
. Vous pouvez effectuer deux requêtes à l'aide de getElementsByTagName
ou utiliser querySelectorAll
.
var elems = document.querySelectorAll('p,li')
Puis-je sélectionner plusieurs balises à l'aide de getElementsByTagName?
Oui, mais vous devrez utiliser getElementsByTagName plusieurs fois.
Bien que votre exemple spécifie uniquement Document.getElementsByTagName () J'ai supposé que vous souhaitiez que cela fonctionne également avec element.getElementsByTagName ().
getElementsByTagName renvoie un objet HTMLCollection donc le résultat idéal serait une méthode qui renvoie un objet HTMLCollection des éléments pour tous les noms de balise fournis.
Choses à noter sur HTMLCollection's
getElementsByTagName
, getElementsByClassName
et getElementsByTagNameNS
nodeList.children
Comme HTMLCollection's ne peut pas être modifié, le mieux que nous puissions faire est de renvoyer autant que possible un objet qui ressemblait à HTMLCollection , voir Créer une HTMLCollection ou pour créer un nodeList
et renvoyer la propriété children
.
Premièrement, nous devons collecter tous les éléments correspondants pour notre HTMLCollection
La manière la plus simple serait d'utiliser la fonction querySelectorAll qui renvoie un nodeList
.
var nodeList = document.querySelectorAll(selector);
Une alternative serait d'utiliser la méthode getElementsByTagName
pour chaque balise, de convertir l'objet HTMLCollection retourné en un tableau afin qu'ils puissent être fusionnés ensemble.
Ainsi .
var HTMLCollectionArray = [];
var names = selector.split(",");
for (var i = 0, n = names.length; i < n; i++){
HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(document.getElementsByTagName(names[i])));
}
La nodeList peut également être convertie en un tableau en utilisant la même méthode.
HTMLCollectionArray = Array.prototype.slice.call(nodeList);
Nous pouvons maintenant soit renvoyer tous les éléments sous forme de tableau, soit essayer de renvoyer une HTMLCollection.
Si nous devions renvoyer une HTMLCollection, il faudrait soit déplacer, soit copier les éléments dans un seul parentNode afin que nous puissions accéder à parentNode.children
.
J'ai trouvé en utilisant document.createDocumentFragment
fonctionne mieux.
var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children;
return HTMLCollection;
Bien que cela renvoie le type correct (HTMLCollection), il ne renvoie pas l'état réel des éléments lors de l'appel de la méthode. Le DOM a été modifié pour y parvenir. Pas une bonne idée.
Donc, cela nous laisse avec faire un faux HTMLCollection
window.MyNodeList = function(elements) {
for ( var i = 0; i < elements.length; i += 1 ) {
this[i] = elements[i];
}
Object.defineProperty( this, 'length', {
get: function () {
return elements.length;
}
});
Object.freeze( this );
};
window.MyNodeList.prototype.item function ( i ) {
return this[i] != null ? this[i] : null;
}
window.MyHTMLCollection = function(elements) {
MyNodeList.call(this, elements);
}
MyHTMLCollection.prototype = Object.create(MyNodeList.prototype);
MyHTMLCollection.prototype.constructor = MyHTMLCollection;
window.MyHTMLCollection.prototype.namedItem = function ( name ) {
for ( var i = 0; i < this.length; i += 1 ) {
if ( this[i].id === name || this[i].name === name ) {
return this[i];
}
}
return null;
}
Usage
var HTMLCollection = new MyHTMLCollection(elementsArray);
Maintenant, pour tout assembler.
Ive a également implémenté une méthode "getElementsByClassNames" ainsi que "getElementsByTagNames" qui utilisent toutes les deux la même méthode principale getElementsBySelector
.
Element.prototype.getElementsByTagNames = Document.prototype.getElementsByTagNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Element.prototype.getElementsByClassNames = Document.prototype.getElementsByClassNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByClassName');
}
Nous voulons UNIQUEMENT que les interfaces Document et Element héritent de nos nouvelles méthodes car elles appellent des méthodes prototypes qui n'existent pas dans toutes les interfaces Node . par exemple. getElementsByClassName
, querySelectorAll
, etc.
Si vous souhaitez réduire votre code, vous pouvez utiliser Node.prototype au lieu d'indiquer Element.prototype.
et Document.prototype.
Node.prototype.getElementsByTagNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Node.prototype.getElementsByClassNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByClassName');
}
Assurez-vous simplement de ne pas l'utiliser sur un nœud qui n'est pas Document ou Element .
Element.prototype.getElementsBySelector = Document.prototype.getElementsBySelector = function (selector, HTMLCollectionType) {
var HTMLCollectionArray = [];
if(typeof this.querySelectorAll !== 'undefined'){
var nodeList = this.querySelectorAll(selector);
HTMLCollectionArray = Array.prototype.slice.call(nodeList);
} else {
if(typeof HTMLCollectionType !=='undefined' && typeof this[HTMLCollectionType] !== 'undefined'){
var names = selector.split(",");
for (var i = 0, n = names.length; i < n; i++){
HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(this[HTMLCollectionType](names[i])));
}
}
}
return new MyHTMLCollection(HTMLCollectionArray);
/*
var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children;
return HTMLCollection;
*/
}
Usage
var element = document.getElementById('id');
element.getElementsbyClassNames('class1,class2,class2');
element.getElementsbyTagNames('li,div,p');
document.getElementsbyClassNames('class1,class2,class2');
document.getElementsbyTagNames('li,div,p');
Un an de retard, mais si vous avez l'intention d'utiliser plusieurs fois la fonctionnalité souhaitée dans votre projet et que vous n'avez pas accès à querySelector () , il peut être utile d'étendre le Node
objet avec une fonction simple :
JavaScript
/**
* @param {Array} tags - The array of tagNames to search for.
* @return {Array} - The elements with matching tagNames.
*/
Node.prototype.getElementsByTagNames = function (tags) {
var elements = [];
for (var i = 0, n = tags.length; i < n; i++) {
// Concatenate the array created from a HTMLCollection object
elements = elements.concat(Array.prototype.slice.call(this.getElementsByTagName(tags[i])));
}
return elements;
};
Tout ce qu'il fait est d'itérer sur un tableau de noms de balises, puis d'obtenir les éléments correspondants en utilisant getElementsByTagName()
pour chaque itération.
Ceci peut alors bien sûr être utilisé sur l'élément any de la même manière que vous utilisez des fonctions similaires - par exemple, getElementById()
- sur n'importe quel objet Node
, vous ne sont pas limités à document
.