Самый простой способ получить узлы из DOM с указанными значениями атрибутов - PullRequest
0 голосов
/ 04 января 2012

Это не проблема, я просто прошу самый простой способ реализовать это.

Что у меня есть.

В HTML: список флажков.

<input type="checkbox" value="1" />
<input type="checkbox" value="2" />
<input type="checkbox" value="3" />
<input type="checkbox" value="4" />

В JavaScript - массив из нескольких значений: var aValues = [1, 3]; И мне нужно извлечь все флажки из DOM со значениями, указанными в aValues.

Как я это сделал:

var aoNodes = document.querySelectorAll('input[value="1"], input[value="3"]');

Но, возможно, кто-нибудь знает более простой (более короткий) способ построения запроса, например: input[value="1"|"3"] или input[value="1", "3"].

Оба приведенных выше примера неверны, но я дал их просто для того, чтобы вам было понятнее.

UPDATE

Еще несколько вещей, чтобы уточнить мой вопрос:

  • jQuery не может быть использован в моем случае
  • Мы используем ExtJS в нашем проекте.

Ответы [ 3 ]

1 голос
/ 04 января 2012

Как насчет ...

var checkboxes = form.querySelectorAll( 'input[type="checkbox"]' );

checkboxes = [].filter.call( checkboxes, function ( checkbox ) {
    return aValues.indexOf( +checkbox.value ) > -1;
});

, где form - это элемент, содержащий все ваши флажки.(Вы не хотите делать ненужный запрос на уровне документа.)

Обратите внимание, что здесь используется Array.filter(), который может быть недоступен во всех браузерах .

Демонстрационная версия: http://jsfiddle.net/zF3mu/

1 голос
/ 04 января 2012

Ваш querySelectorAll('input[value="1"], input[value="3"]'), вероятно, самый короткий, даже в CSS3 нет селектора атрибута *1003* для "любого из этих значений". (Так же как и jQuery.) Вы можете довольно просто создать большой селектор из aValues, используя Array#join:

var selector = 'input[type="checkbox"][value="' +
               aValues.join('"], input[type="checkbox"][value="') +
               '"]');
var matches = querySelectorAll(selector);

Довольно лаконично, хотя, к сожалению, повторяет кусочки. Вы можете использовать функцию многократного использования:

function niftyJoin(array, prefix, delim, suffix) {
  return prefix + array.join(suffix + delim + prefix) + suffix;
}

Тогда:

var matches = querySelectorAll(niftyJoin(aValues, 'input[type="checkbox"][value="', ',', '"]'));

Если вам не нравится подход join, вы можете получить все соответствующие элементы input, а затем отфильтровать те, чьи значения отсутствуют в массиве:

var matches, inputs, index, input;
matches = [];
inputs = querySelectorAll('input[type="checkbox"]'); // Or perhaps more targeted
for (index = 0; index < inputs.length; ++index) {
    input = inputs[index];
    if (aValues.indexOf(parseInt(input.value, 10)) !== -1) {
        matches.push(input);
    }
}

Это может быть медленнее, чем создание большого селектора для querySelectorAll, поскольку вы фильтруете в слое JavaScript, а не в селекторном движке браузера, но если вы не делаете это многократно в узком цикле, это вряд ли будет иметь значение , Также обратите внимание, что я полагался на Array#indexOf, который не поддерживается таким количеством браузеров, как querySelectorAll (например, в IE8 есть последний, но не первый).

Кстати, я думаю, вы знаете, что еще не все браузеры поддерживают querySelectorAll, хотя вау приближается , похоже почти на все, кроме IE6 и IE7. Я предполагаю, что если вы используете его, вы знаете, что ваша целевая среда будет иметь его.


Для людей jQuery: эта фильтрация становится (намного) более краткой, используя jQuery:

var matches = $('input[type="checkbox"]').filter(function() {
    return $.inArray(parseInt(this.value, 10), aValues);
});

Красиво и лаконично. Опять же, возможно, немного медленнее, чем делать все это в querySelectorAll, и снова вряд ли будет иметь значение.


Обновление : Вы сказали, что используете ExtJS в этом проекте. Согласно DomQuery документам , он также не предлагает селектор, который делает то, что вы хотите. Он предлагает filter, который может быть полезен, если вы хотите применить подход «фильтр после факта», но я откровенно думаю, что подход join, указанный в самом верху, будет самый лаконичный и эффективный.

0 голосов
/ 04 января 2012
var boxes = [].slice.call(form.elements).filter(function ( element ) {
    return element.type === 'checkbox' && [1,3].indexOf(+element.value) > -1;
});

Используйте form.elements, чтобы получить входные данные формы. Затем отфильтруйте по типу и значению.

...