[英]Can I select multiple tags using getElementsByTagName?
I'm using a javascript snippet in order for visitors to my site to increase the font size on all paragraphs using the following javascript:我正在使用 javascript 代码段,以便我网站的访问者使用以下 javascript 增加所有段落的字体大小:
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"
}
}
How can I also include "li" to this code so that "p" and "li" are the selected elements that are affected?我怎样才能在此代码中包含“li”,以便“p”和“li”是受影响的选定元素?
I would also like to avoid adding a class or an id to my "li" or "ul".我还想避免在我的“li”或“ul”中添加一个类或一个 id。 Is there a way to select two tags at once?
有没有办法一次选择两个标签?
No, you can't select multiple tags with a single call to getElementsByTagName
.不,您不能通过一次调用
getElementsByTagName
来选择多个标签。 You can either do two queries using getElementsByTagName
or use querySelectorAll
.您可以使用
getElementsByTagName
或使用querySelectorAll
执行两个查询。
var elems = document.querySelectorAll('p,li')
A year late, but if you intend on using the desired functionality multiple times in your project, and you don't have access to querySelector() , it might be worth extending the Node
object with a simple function:晚了一年,但如果您打算在项目中多次使用所需的功能,并且您无权访问querySelector() ,则可能值得使用一个简单的函数扩展
Node
对象:
JavaScript 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;
};
Working demo on JSFiddle. JSFiddle 上的工作演示。
All it does is iterating over an array of tag names, then getting the corresponding elements using getElementsByTagName()
for each iteration.它所做的只是迭代一个标签名称数组,然后每次迭代都使用
getElementsByTagName()
获取相应的元素。
This can then of course be used on any element the same exact way you use similar functions - for example, getElementById()
- on any Node
object, you are not limited to document
.这当然可以用在任何元素上,就像您在任何
Node
对象上使用类似函数一样——例如getElementById()
,您不仅限于document
。
Can I select multiple tags using getElementsByTagName?我可以使用 getElementsByTagName 选择多个标签吗?
Yes, but you will have to use getElementsByTagName multiple times.是的,但您必须多次使用 getElementsByTagName。
Although your example only specifies Document.getElementsByTagName() I have assumed you would like this to work with element.getElementsByTagName() as well.尽管您的示例仅指定Document.getElementsByTagName()我假设您也希望它与 element.getElementsByTagName() 一起使用。
getElementsByTagName returns a HTMLCollection object so the ideal outcome would be a method which returns a HTMLCollection object of elements for all tag names provided. getElementsByTagName 返回一个HTMLCollection对象,因此理想的结果是一个方法,该方法为提供的所有标签名称返回元素的HTMLCollection对象。
Things to note about HTMLCollection's HTMLCollection 的注意事项
getElementsByTagName
, getElementsByClassName
and getElementsByTagNameNS
getElementsByTagName
、 getElementsByClassName
和getElementsByTagNameNS
nodeList.children
nodeList.children
As HTMLCollection's cannot be modified the best we can do is either return an object which resembled a HTMLCollection's as much as possible, see Create a HTMLCollection or to create an nodeList
and return the children
property.由于HTMLCollection无法修改,我们能做的最好的事情是返回一个尽可能类似于HTMLCollection 的对象,请参阅创建 HTMLCollection或创建
nodeList
并返回children
属性。
Firstly we need to collect all the matching elements for our HTMLCollection首先,我们需要为HTMLCollection收集所有匹配的元素
The simplest way would be to use the querySelectorAll function which returns a nodeList
.最简单的方法是使用返回
nodeList
的querySelectorAll函数。
var nodeList = document.querySelectorAll(selector);
An alternative would be to use the getElementsByTagName
method for each tag, convert the returned HTMLCollection object to an array so they can be merged together.另一种方法是对每个标签使用
getElementsByTagName
方法,将返回的 HTMLCollection 对象转换为数组,以便将它们合并在一起。
Like so .像这样。
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])));
}
The nodeList can also be converted to an array using the same method.也可以使用相同的方法将 nodeList 转换为数组。
HTMLCollectionArray = Array.prototype.slice.call(nodeList);
We can now either return all the elements as an array or try to return a HTMLCollection.我们现在可以将所有元素作为数组返回,也可以尝试返回 HTMLCollection。
If we were to return a HTMLCollection it would have to be either move or copy the elements to a single parentNode so we can access parentNode.children
.如果我们要返回一个 HTMLCollection,它必须将元素移动或复制到单个 parentNode 以便我们可以访问
parentNode.children
。
I found using document.createDocumentFragment
works best.我发现使用
document.createDocumentFragment
效果最好。
var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children;
return HTMLCollection;
Although this would return the correct type(HTMLCollection) it does not return the actual state of the elements when the method was called.尽管这会返回正确的类型(HTMLCollection),但它不会在调用该方法时返回元素的实际状态。 The DOM has been modified to achieve this.
DOM 已被修改以实现此目的。 Not a good idea.
不是个好主意。
So this leaves us with making a Fake HTMLCollection所以这让我们需要制作一个 Fake 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);
Now to piece it all together.现在把它们拼凑起来。
Ive also implemented a 'getElementsByClassNames' method and well as 'getElementsByTagNames' which both use the same core method getElementsBySelector
.我还实现了一个“getElementsByClassNames”方法和“getElementsByTagNames”,它们都使用相同的核心方法
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');
}
We ONLY want the Document and Element interfaces to inherit our new methods because they call prototype methods which do not exist in all Node interfaces.我们只希望Document和Element接口继承我们的新方法,因为它们调用的原型方法并不存在于所有Node接口中。 eg
getElementsByClassName
, querySelectorAll
, etc.例如
getElementsByClassName
、 querySelectorAll
等。
If you want to minify your code then you could use Node.prototype instead of stating Element.prototype.
如果你想缩小你的代码,那么你可以使用 Node.prototype 而不是声明
Element.prototype.
and Document.prototype.
和
Document.prototype.
Node.prototype.getElementsByTagNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Node.prototype.getElementsByClassNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByClassName');
}
Just make sure you don't try to use it on any node which isn't Document or Element .只要确保您不要尝试在任何不是Document或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');
You can select multiple tags using getElementsByTagName for the purpose of having one iterable array, where results for multiple tags eg P and LI could be processed together.您可以使用 getElementsByTagName 选择多个标签以获得一个可迭代数组,其中多个标签(例如 P 和 LI)的结果可以一起处理。
It can't be done by one call to getElementsByTagName(), but it's possible to chain two getElementsByTagName() and avoid more complicated code or the use of the querySelectorAll().它不能通过一次调用 getElementsByTagName() 来完成,但可以链接两个 getElementsByTagName() 并避免更复杂的代码或使用 querySelectorAll()。
This is your whole example.这是你的整个例子。
function increaseFontSize() {
Array.from(document.getElementsByTagName('p'))
.concat(Array.from(document.getElementsByTagName('li'))).forEach(el => {
if(el.style.fontSize) {
var s = parseInt(el.style.fontSize.replace("px",""));
} else {
var s = 14;
}
if(s != max) {
s += 1;
}
el.style.fontSize = s+"px"
});
}
Explanation:解释:
Array.from()
this is the official way how to make real array from a collection.这是如何从集合中制作真实数组的官方方法。
Some browsers might support forEach()
on HTMLCollection
, but it's not in specs.一些浏览器可能支持
HTMLCollection
上的forEach()
,但它不在规范中。
Even so, they probably don't support concat()
method.尽管如此,他们可能不支持
concat()
方法。
Using from()
will create a shallow copy of the collection.使用
from()
将创建集合的浅拷贝。
That's an advantage on HTMLCollection
because items could be modified during iteration and modification to elements inside the array will still be a modification on original objects.这是
HTMLCollection
的一个优势,因为项目可以在迭代期间修改,对数组内元素的修改仍然是对原始对象的修改。
Now we have two standard arrays and can use concat()
to join them and forEach()
to iterate the joined result.现在我们有两个标准数组,可以使用
concat()
连接它们并forEach()
迭代连接的结果。
This only works in Chrome , and is not mean as the solution but found as remarkable javascript behaviour:这仅适用于 Chrome ,并不意味着作为解决方案,而是发现了非凡的 javascript 行为:
document.getElementsByTagName('p' || 'li') //-> selects both P and LI elements.
It even works with html collections where you might only want to ONLY select elements that contain multiple types of tags at the same time.它甚至适用于您可能只想同时选择包含多种类型标签的元素的 html 集合。 That can be done like this eg:
可以这样做,例如:
var table = document.getElementByID('myTable');
var rows = table.getElementsByTagName('tr');
rows[1].getElementsByTagName('input' && 'select') //-> select only when both input and select are present
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.