Конспект JS-course

jQuery: поиск элементов

Источник: http://learn.javascript.ru/jquery-search

Поиск в jQuery

«Сердцем» jQuery является функция $(). Все вызовы делаются через $. Это самая обычная функция, которая объявлена библиотекой. Как мы помним, символ "$" является допустимым символом для имён в JavaScript.

Простейший поиск элементов выглядит так:

var result = $('...CSS-селектор...');

Например, $("div a") — ссылки a внутри div.

Возможны и более сложные запросы, например:

var list = $('li > a:odd:not([href^="http://"])');
// расшифровка: нечётные (:odd) ссылки внутри li,
// кроме тех (:not), у которых атрибут href начинается c http://

Вызов $(селектор) аналогичен document.querySelectorAll(селектор), но:

  • Во-первых, поддерживается всеми браузерами, включая старые IE. Список CSS3-селекторов можно найти в главе Знаете ли вы селекторы?.
  • Во-вторых, jQuery предоставляет свои поисковые расширения, например псевдофильтр :checked — выбранные элементы input и option, :header — заголовок h1..6, и другие, более полный список которых доступен в документации.

Перебор результатов

Результатом поиска является jQuery-объект. Он похож на массив: в нём есть нумерованные элементы и length, но методы у него совсем другие.

jQuery-объект также называют «jQuery-коллекцией», «элементами, обёрнутыми в jQuery» и десятком других жаргонных терминов.

Используем jQuery, чтобы выбрать все элементы по селектору li > a и перебрать их:

<!-- подключить библиотеку -->
<script src="http://code.jquery.com/jquery.js"></script>

<ul>
  <li><a href="http://jquery.com">jQuery</a></li>
  <li><a href="http://jqueryui.com">jQuery UI</a></li>
  <li><a href="http://blog.jquery.com">jQuery Blog</a></li>
</ul>

<script>
var links = $('li > a');

// перебор результатов
for(var i=0; i<links.length; i++) {
  alert( links[i].href );
}
</script>

Контекст поиска

Для поиска внутри какого-либо элемента — можно передать его вторым аргументом $.

Например, найдём все a внутри #menu:

var menu = document.getElementById('menu');
$('a', menu); // поиск аналогичен menu.querySelectorAll('a')

Второй аргумент в этом случае называются «контекстом поиска».

В качестве контекста можно передать не только DOM-элемент, но и селектор:

$('a', '#menu' );

Также можно передать результат другого поиска:

var menu = $('#menu');
$('a', menu);

Не важно, в каком виде мы хотим указать контекст: DOM-элемент, строка или результат поиска — jQuery понимает всё.

А что, если контекст поиска содержит много элементов? Например, как будет работать запрос $(&#39;a&#39;, &#39;li&#39;), если &lt;li&gt; в документе много?

Здесь все немного сложнее, но, тем не менее, интуитивно понятно.

Если в контексте много элементов, то поиск будет произведён в каждом из них. А затем результаты будут объединены.

Повторы элементов при этом отфильтровываются, то есть два раза один и тот же элемент в результате не появится.

Например, найдём $(&#39;a&#39;, &#39;li&#39;) в многоуровневом списке:

<script src="http://code.jquery.com/jquery.js"></script>

<ul>
  <li>
    <a href="http://jquery.com">jQuery</a>
    <ul>
      <li><a href="http://blog.jquery.com">jQuery Blog</a></li>
    </ul>
  </li>
  <li><a href="http://sizzlejs.com">Sizzle</a></li>
</ul>

<script>
var links = $('a', 'li');

for(var i=0; i<links.length; i++) {
  alert( i + ": " +  links[i].href ); // 3 ссылки по очереди
}
</script>

Метод each

Для более удобного перебора у jQuery-коллекции есть метод each. Его синтаксис похож на forEach массива:

.each( function(index, item) ) Он выполняет для каждого элемента коллекции перед точкой функцию-аргумент, и передаёт ей номер index и очередной элемент item.

Используем его вместо for, чтобы перебрать коллекцию найденных ссылок:

$('li a').each(function(i, a) {
  alert( i + ": " + a.href);
});

У .each есть важная возможность, которой нет в forEach: возврат false из функции прекращает перебор.

Например:

<script src="http://code.jquery.com/jquery.js"></script>

<a href="http://wikipedia.ru">Википедия</a>

<ul>
  <li><a href="http://jquery.com">jQuery</a></li>
  <li><a href="http://sizzlejs.com">Sizzle</a></li>
  <li><a href="http://blog.jquery.com">jQuery Blog</a></li>
</ul>

<script>
var links = $('li a'); // найти все ссылки на странице внутри LI

links.each(function(i, a) {
  alert(i + ': ' + a.innerHTML);

  if (i == 1) return false; // стоп на элементе коллекции с индексом 1
});
</script>

При переборе each, текущий элемент передаётся как this.

Можно было бы использовать это, чтобы сделать код короче:

$('li a').each(function(i) {
  alert(i + ': ' + this.innerHTML);

  if (i == 1) return false;
});

Получение конкретного элемента

Даже если элемент найден только один, всё равно результатом поиска будет jQuery-коллекция. Но нам же нужен один элемент, так что посмотрим, как его получить.

Для получения одного элемента из jQuery-коллекции есть три способа:

  1. Прямой доступ по номеру:

     alert( $('body')[0] ); // BODY
    

    Это — самый быстрый и прямой доступ, он использует внутреннюю структуру jQuery-коллекции: элементы там хранятся по индексам. Но этим он нарушает принцип инкапсуляции.

    Вообще-то, в jQuery есть специальные методы для получения элемента по номеру, и сейчас мы будем говорить о них.

  2. Метод get(индекс), работает так же, как прямой доступ:

     alert( $('body').get(0) ); // BODY
    

    Если элемента с таким номером нет — вызов get возвратит undefined.

  3. Метод eq(индекс) возвращает коллекцию из одного элемента — с данным номером. Он отличается от метода get(индекс) и прямого обращения по индексу тем, что возвращает именно jQuery-коллекцию с одним элементом, а не сам элемент.

    Например:

    // DOM-элемент для первой ссылки
     $('a').get(0);
    
     // jQuery-объект из одного элемента: первой ссылки
     $('a').eq(0);
    

    Во втором случае вызов eq создаёт новую jQuery-коллекцию, добавляет в нее нулевой элемент и возвращает. Это удобно, если мы хотим дальше работать с этим элементом, используя методы jQuery.

    Если элемента с таким номером нет — eq возвратит пустую коллекцию.

«Сцепление» вызовов

Почти все методы jQuery-объекта возвращают jQuery-объект — либо новый, либо тот на котором вызваны.

Поэтому можно вызывать методы один за другим.

Это называют «сцепление» вызовов, или «чейнинг» (от англ. «chaining»):

$('li a[href$=".pdf"]') // ссылки, оканчивающиеся на pdf
  .each(function() {
    this.className = "pdf"; // дать им класс
  })
  .each(function() {    
    alert(this.href); // вывести
  });

Для удобства чтения каждый новый вызов в чейнинге идёт с отступом и с новой строки.

Итого

Для поиска элементов можно вызвать $(CSS-селектор[, контекст]). Результатом будет jQuery-объект, который можно:

  • Перебирать как массив.
  • Перебирать методом each.
  • Получить один элемент прямым доступом по индексу, либо вызовом get или eq.

Для поиска используется, по возможности, querySelectorAll, либо если он не может обработать запрос — встроенный движок Sizzle.