Ответ 1
Нет, вы не можете выбрать несколько тегов с одним вызовом getElementsByTagName
. Вы можете выполнить два запроса с помощью getElementsByTagName
или использовать querySelectorAll
.
var elems = document.querySelectorAll('p,li')
Я использую фрагмент 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"
}
}
Как я могу также включить "li" в этот код, чтобы "p" и "li" были выбранными элементами, которые были затронуты?
Я также хотел бы избежать добавления класса или идентификатора к моим "li" или "ul". Есть ли способ сразу выбрать два тега?
Нет, вы не можете выбрать несколько тегов с одним вызовом getElementsByTagName
. Вы можете выполнить два запроса с помощью getElementsByTagName
или использовать querySelectorAll
.
var elems = document.querySelectorAll('p,li')
Через год, но если вы намерены использовать требуемую функциональность несколько раз в своем проекте, и у вас нет доступа к querySelector(), возможно, стоит расширить объект Node
с помощью функции 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;
};
Рабочая демонстрация на JSFiddle.
Все, что он делает, это итерация по массиву имен тегов, а затем получение соответствующих элементов с помощью getElementsByTagName()
для каждой итерации.
Это, конечно, можно использовать для любого элемента точно так же, как вы используете аналогичные функции - например, getElementById()
- на любом объекте Node
, вы не ограничены document
.
Можно ли выбрать несколько тегов с помощью getElementsByTagName?
Да, но вам придется использовать getElementsByTagName несколько раз.
Хотя ваш пример указывает только Document.getElementsByTagName() Я предположил, что вы хотели бы, чтобы это работало с элементом element.getElementsByTagName(),
getElementsByTagName возвращает объект HTMLCollection, поэтому идеальным результатом будет метод, который возвращает HTMLCollection объект элементов для всех предоставленных имен тегов.
Заметки о HTMLCollection
getElementsByTagName
, getElementsByClassName
и getElementsByTagNameNS
nodeList.children
Как HTMLCollection не может быть изменено, мы можем только вернуть объект, похожий на HTMLCollection как можно больше, см. Создать HTMLCollection или создать nodeList
и вернуть свойство children
.
Во-первых, нам нужно собрать все соответствующие элементы для нашего HTMLCollection
Самый простой способ - использовать функцию querySelectorAll, которая возвращает nodeList
.
var nodeList = document.querySelectorAll(selector);
Альтернативой было бы использовать метод getElementsByTagName
для каждого тега, преобразовать возвращенный объект HTMLCollection в массив, чтобы они могли быть объединены вместе.
Так же.
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])));
}
nodeList также может быть преобразован в массив с использованием того же метода.
HTMLCollectionArray = Array.prototype.slice.call(nodeList);
Теперь мы можем либо вернуть все элементы в виде массива, либо попытаться вернуть HTMLCollection.
Если бы мы вернули HTMLCollection, он должен был бы либо переместить, либо скопировать элементы в один родительскийNode, чтобы мы могли получить доступ к parentNode.children
.
Я нашел, что использование document.createDocumentFragment
работает лучше всего.
var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children;
return HTMLCollection;
Хотя это вернет правильный тип (HTMLCollection), он не возвращает фактическое состояние элементов при вызове метода. Для этого DOM был изменен. Не хорошая идея.
Итак, это оставляет нас с созданием 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;
}
Использование
var HTMLCollection = new MyHTMLCollection(elementsArray);
Теперь, чтобы собрать все это вместе.
Ive также реализовал метод 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');
}
Мы ТОЛЬКО хотим Document и Element, чтобы наследовать наши новые методы, потому что они называют прототипы, которые не существуют во всех Node интерфейсах. например getElementsByClassName
, querySelectorAll
и т.д.
Если вы хотите уменьшить свой код, вы можете использовать Node.prototype вместо того, чтобы указывать Element.prototype.
и Document.prototype.
Node.prototype.getElementsByTagNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Node.prototype.getElementsByClassNames = function(selector){
return this.getElementsBySelector(selector, 'getElementsByClassName');
}
Просто убедитесь, что вы не пытаетесь использовать его на любом node, который не является 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;
*/
}
Использование
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');