Можно ли объединить элементы для одинаковых атрибутов с querySelectorAll?
Из любопытства, было бы возможно рефакторинг это:
document.querySelectorAll('input[id^=' + tagId + '],select[id^=' + tagId + '],textarea[id^=' + tagId + ']');
к чему-то меньшему, вот так?
document.querySelectorAll('(input|select|textarea)[id^=' + tagId + ']');
Конечно, это не работает, поэтому я спрашиваю. Является ли это возможным?
4 ответа
Использование :any
Псевдо-класс;
document.querySelectorAll('[id^=' + tagId + ']:-webkit-any(input, textarea, select)');
Прямо сейчас вам нужно добавить префикс -webkit-
для Chrome и Safari, или -moz
для Firefox; нет поддержки IE. Это, вероятно, будет стандартизировано в конце концов под названием :matches
, Смотрите документацию MDN здесь.
Однако управление элементами DOM через их идентификаторы, как если бы они назывались переменными в каком-то гигантском глобальном пространстве имен, является анти-паттерном. Весьма вероятно, что есть более эффективные способы поиска и отслеживания элементов, чем назначать связку идентификаторов здесь, в вашем коде, а затем делать getElementById
или эквивалент каждый раз, когда вы оборачиваетесь, чтобы найти его снова, тем более делая эквивалент поиска по шаблону.
Вы могли бы использовать "[id^=" + tagId + "]"
с :not(/* element */):not(/* element */)
var tagId = "abc";
var elems = document.querySelectorAll("[id^=" + tagId + "]:not(div):not(p)");
console.log(elems)
<input id="abc-1">
<select id="abc-2"></select>
<textarea id="abc-3"></textarea>
<div id="abc-4"></div>
<p id="abc-5"></p>
в качестве альтернативы, вы можете добавить className
или data-*
приписывать input
, select
, textarea
элементы; data-*
атрибут не требует имени или значения; используется только для фильтрации выбора; Вы могли бы затем использовать document.querySelectorAll("[id^=" + tagId + "][data-_]");
или короче document.querySelectorAll("[data-_]")
var tagId = "abc";
var elems = document.querySelectorAll("[id^=" + tagId + "][data-_]");
console.log(elems, elems[0].dataset)
<input id="abc-1" data-_>
<select id="abc-2" data-_></select>
<textarea id="abc-3" data-_></textarea>
<div id="abc-4"></div>
<p id="abc-5"></p>
Подход, использующий Array.prototype.filter()
хотя и не так кратко, как использование уникального className
или же data-*
атрибут, аналогичный шаблону, описанному в OP
var tagId = "abc";
var elems = [].filter.call(document.querySelectorAll("[id^=" + tagId + "]")
, function(el) {
return /input|select|textarea/i.test(el.tagName)
});
console.log(elems)
<input id="abc-1">
<select id="abc-2"></select>
<textarea id="abc-3"></textarea>
<div id="abc-4"></div>
<p id="abc-5"></p>
Подход, расширяющий document.querySelcectorAll()
внутренне добавить префикс поставщика в :any
без включения префикса поставщика в строку селектора с помощью функции обнаружения в document.body.style
, Возможно, можно улучшить несколькими способами; дополнительный css
могут быть добавлены селекторы, которые в настоящее время требуют префиксов поставщиков, несколько if
заявления могут быть более тщательными или сокращенными; и другие улучшения
originalQuerySelectorAll = document.querySelectorAll;
console.log(originalQuerySelectorAll);
document.querySelectorAll = function() {
var selector = arguments[0];
if (/\:any/.test(selector)) {
if ("webkitAnimation" in document.body.style) {
selector = selector.replace(/\:(any)/g, ":-webkit-$1");
}
if ("MozAnimation" in document.body.style) {
selector = selector.replace(/\:(any)/g, ":-moz-$1");
}
}
return originalQuerySelectorAll.call(document, selector)
}
var tagId = "abc";
var elems = document.querySelectorAll("[id^=" + tagId + "]:any(input, select, textarea)");
console.log(elems)
<input id="abc-1">
<select id="abc-2"></select>
<textarea id="abc-3"></textarea>
<div id="abc-4"></div>
<p id="abc-5"></p>
jsfiddle https://jsfiddle.net/0xpu1bvw/
До :any
селектор стандартизирован, вы можете использовать вспомогательную функцию, аналогично использованию препроцессора CSS ( пример позаимствования @guest271314):
function makeSelector(tagId, elements) {
return elements.map(function(el) {
return el + '[id^=' + tagId + ']';
}).join(',');
}
var selector = makeSelector('abc', ['input','select','textarea']);
console.log(document.querySelectorAll(selector));
<input id="abc-1">
<select id="abc-2"></select>
<textarea id="abc-3"></textarea>
<div id="abc-4"></div>
<p id="abc-5"></p>
Затем вы можете поменять реализацию помощника на более поздний срок (например, для использования :any
) без ущерба для функциональности.