Рассмотрю два метода, которые похожи внешне и внутренне, как может показаться с первого взгляда. Однако, между ними есть тонкая разница.

Метод first

Метод

1
first()
призван возращать первый элемент из коллекции (выборки) этих элементов. Как всегда, чтобы не быть голословным и иметь наглядный пример перед глазами, приведу ниже HTML-разметку, на которой буду тренироваться:

<div class="wrapper">
  <ul id="primo" class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
</div>

Вот такая большая разметка

1
div class="wrapper"
с четырьмя блоками
1
ul class="block"
, у каждого из которых есть элементы-потомки
1
li class="block__item"
.

И создам небольшой скрипт на JS/jQuery такого плана:

$(function(){
  var wrapper = $('.wrapper');
  wrapper.find('li:first').addClass('block__item--firstSimple');
});

Работа вышеприведенного js-кода будет сводиться к следующему:

  • создается переменная
    1
    
    wrapper
    , в которую помещается результат выборки
    1
    
    $('.wrapper')
  • в переменной
    1
    
    wrapper
    находим элемент
    1
    
    li
    , который является первым в коллекции -
    1
    
    .find('li:first')
  • этому элементу добавляется класс -
    1
    
    .addClass('block__item--firstSimple')

Код несложный и вроде бы все понятно. Но вот вопрос - а какой элемент

1
li
с точки зрения данного кода является первым в коллекции?

Чтобы не ломать понапрасну голову, приведу сразу ответ:

<div class="wrapper">
  <ul id="primo" class="block">
    <li class="block__item block__item--firstSimple"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
</div>

Вот так - только он один и только этот элемент является первым в коллекции элементов

1
li
.

Это объяснимо, если слегка подумать. В переменной

1
wrapper
хранится коллекция элементов; и элементов
1
li
- в том числе.

Коллекция элементов - это не что иное, как массив. А в массиве только один элемент может быть первым. То есть, иметь индекс 0.

Именно поэтому метод

1
.first()
- это всего лишь синоним (alias) другого, более универсального метода
1
.eq()
и может быть записан таким способом -
1
.eq(0)
- вернуть элемент с нулевым индексом, то есть - первый элемент массива.

Антагонистом метода

1
.first()
является метод
1
last()
, который возвращает последний элемент массива. И метод
1
.last()
также можно записать по другому -
1
.eq(-1)
; это также вернет последний элемент массива.

Ок, с методом

1
.first()
вроде разобрались. Двигаемся дальше и рассмотрим метод
1
.first-child()
.

Метод first-child()

Казалось бы, в чем разница? Трудно догадаться, поэтому сразу приведу js-код с описанием работы. В качестве подопытной HTML-разметки будет выступать все та же, приведенная в самом начале статьи.

$(function(){
  var wrapper = $('.wrapper');
  wrapper.find('li:first-child').addClass('block__item--firstChild');
});

Что делает приведенный выше код? А вот что:

  • создает переменную
    1
    
    wrapper
    и присваивает ей значение выборки - $(‘.wrapper’)
  • в переменной
    1
    
    wrapper
    находим первый элемент
    1
    
    li
    -
    1
    
    .find('li:first-child')
  • этому элементу присваивается класс -
    1
    
    .addClass('block__item--firstChild')

Все просто и вроде бы точно также, как и в случае с методом

1
.first()
. Вроде бы да, но возникает вопрос - а какой элемент
1
li
данный код считает первым в данном случае?

Чтобы не гадать, снова приведу готовый ответ:

<div class="wrapper">
  <ul id="primo" class="block">
    <li class="block__item block__item--firstChild"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item block__item--firstChild"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item block__item--firstChild"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
  <ul class="block">
    <li class="block__item block__item--firstChild"></li>
    <li class="block__item"></li>
    <li class="block__item"></li>
  </ul>
</div>

Вот она - разница в подходе отбора первого элемента. Другими словами, метод

1
.first-child()
находит все элементы, которые являются первыми потомками у своих непосредственных родителей. А в данном случае таких потомков насчиталось аж 4 штуки.

Конечно, можно провести аналогию и рассмотреть метод

1
.last-child()
. Но мне кажется, смысла в этом особого нет - все и так понятно. Выборка будет производиться с точностью до наоборот и будут отбираться последние потомки своих неспосредственных родителей.

На этом думаю закончить сравнительный обзор двух методов -

1
.first()
и
1
.first-child()
.


Рассмотрю методы для нахождения следующих и предыдущих элементов из выборки. Предполагается, что имеется группа элементов, у которых один родитель.

Чтобы не ходить вокруг да около, приведу пример HTML-разметки:

<ul class="test">
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
</ul>

Видно, что у элемента-родителя

1
ul class="test"
имеется двенадцать элементов-потомков
1
li class="test__item"
.

Так вот, в библиотеке jQuery имеются несколько методов, с помощью которых можно “погулять” по этому DOM-дереву. Расссмотрю каждый из них в отдельности.

Но стоит сразу сказать - как всегда, эти методы очень краткие и предельно понятные. Вся “прелесть” начинается, когда методы объединяют в jQuery-цепочку.

Метод next()

С помощью этого метода возвращается элемент, находящий следующим по отношению к текущему элементу.

Приведу такой JS-код:

$(function(){
  var list = $('.test');
  list.find('li').eq(6).next().addClass('test__link--nexted');
});

… который выполняет следующее:

  • создать переменную
    1
    
    list
    и поместить в нее результат выборки
    1
    
    $('.test')
  • в переменной
    1
    
    list
    найти все элементы
    1
    
    li
  • вернуть элемент
    1
    
    li
    с индексом 6 -
    1
    
    .eq(6)
  • найти следующий за ним элемент
    1
    
    li
  • присвоить ему класс
    1
    
    .test__link--nexted

В результате выполнения этого кода класс

1
.test__link--nexted
будет присвоен элементу
1
li
с индексом 7 (или восьмому - по счету):

<ul class="test">
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item test__link--nexted"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
</ul>

Метод prev()

Этот метод абсолютно аналогичен методу

1
next()
за тем исключением, что его действие направлено в противоположную сторону. Метод
1
prev()
возвращает элемент, который предшествует текущему элементу.

То есть, такой JS-код:

$(function(){
  var list = $('.test');
  list.find('li').eq(6).prev().addClass('test__link--preved');
});
  • создаст переменную
    1
    
    list
    и поместит в нее результат выборки
    1
    
    $('.test')
  • в переменной
    1
    
    list
    найдет все элементы
    1
    
    li
  • вернет элемент
    1
    
    li
    с индексом 6 -
    1
    
    .eq(6)
  • найдет предшествующий ему элемент
    1
    
    li
  • присвоит ему класс
    1
    
    .test__link--preved

Результатом выполнения этого кода класс

1
.test__link--preved
будет присвоен элементу
1
li
с индексом 5 (или шестому - по счету):

<ul class="test">
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item test__link--preved"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
</ul>

Краткое заключение

Обобщением вышесказанного является такое предложение. Методы

1
next()
и
1
prev()
возвращают один элемент, который является следующим или предшествует текущему элементу. Все элементы имеют одного общего родителя и поиск осуществляется только в этих рамках (другими словами - это sibling-элементы).

Методы nextAll() и prevAll()

Производными от рассмотренных мною выше методов

1
next()
и
1
prev()
являются методы
1
nextAll()
и
1
prevAll()
. Фактически, это те же самые методы
1
next()
и
1
prev()
, но в этих методах возвращается не один элемент, а все оставшиеся элементы, которые являются sibling по отношению к текущему элементу.

То есть, такой JS-код:

$(function(){
  var list = $('.test');
  list.find('li').eq(3).nextAll().addClass('block__item--squared');
});
  • создаст переменную
    1
    
    list
    и поместит в нее результат выборки
    1
    
    $('.test')
  • в переменной
    1
    
    list
    найдет все элементы
    1
    
    li
  • вернет элемент
    1
    
    li
    с индексом 3 -
    1
    
    .eq(3)
  • найдет все следующие за ним элементы
    1
    
    li
    -
    1
    
    .nextAll()
  • присвоит всем найденным элементам
    1
    
    li
    класс
    1
    
    .block__item--squared

Результатом будет такой HTML-код:

<ul class="test">
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
  <li class="test__item block__item--squared"></li>
</ul>

Метод

1
prevAll()
работает аналогично, но “в другую сторону”. Этот метод возвращает все элементы, которые предшествуют текущему элементу.

То есть, такой JS-код:

$(function(){
  var list = $('.test');
  list.find('li').eq(3).prevAll().addClass('block__item--circled');
});
  • создаст переменную
    1
    
    list
    и поместит в нее результат выборки
    1
    
    $('.test')
  • в переменной
    1
    
    list
    найдет все элементы
    1
    
    li
  • вернет элемент
    1
    
    li
    с индексом 3 -
    1
    
    .eq(3)
  • найдет все элементы
    1
    
    li
    , которые предшествуют ему -
    1
    
    .prevAll()
  • присвоит всем найденным элементам
    1
    
    li
    класс
    1
    
    .block__item--circled

Результатом работы этого js-скрипта будет такой HTML-код:

<ul class="test">
  <li class="test__item block__item--circled"></li>
  <li class="test__item block__item--circled"></li>
  <li class="test__item block__item--circled"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
  <li class="test__item"></li>
</ul>

Общее заключение

Вывод по методам

1
nextAll()
и
1
prevAll()
. Эти методы работают с sibling-элементами, то есть - имеющими одного родителя. Эти методы возвращают все найденные элементы, которые предшествуют или расположены после текущего элемента.

Методы

1
nextAll()
и
1
prevAll()
очень похожи также на рассмотренный мною в предыдущей статье метод
1
siblings
. Вот только действие метода
1
siblings
более “тупое” (если позволительно так сказать) - этот метод “фигачит” свое действие сразу в обе стороны от текущего элемента, по принципу - “от забора и до обеда”.

Методы

1
nextAll()
и
1
prevAll()
более “интеллектуальные” - они “фигачат” свое действие только в одну сторону - указанную.

Ну, а методы

1
next()
и
1
prev()
самые “умные” - “только один элемент, который ближайший и слева”; “только один элемент, который ближайший и справа”.

На этом все.


Небольшое отступление - в одних постах я говорю о функциях jQuery, в других - о методах jQuery. Где же правильно? В принципе, и то и то правильно. И функция jQuery, и метод jQuery. Но последний вариант более правильный, поэтому в дальнейшем буду “обзывать” подобные вещи методами.

Метод

1
.siblings()
предназначен для выборки соседних элементов. С помощью этого метода выбираются все элементы, находящиеся на одном уровне DOM с элементом, служащим в качестве критерия отбора.

Метод имеет один вариант использования (синтаксис):

.parent([selector])

Все очень похоже на то, как эти дела обстоят в CSS, но приведу простой пример для иллюстрации:

<nav class="test">
  <a href="#" class="test__link">test link item</a>
  <a href="#" class="test__link">test link item</a>
  <a href="#" class="test__link proba">test link item</a>
  <a href="#" class="test__link">test link item</a>
  <a href="#" class="test__link">test link item</a>
</nav>
$('.proba').siblings().addClass('selected');

читается это так - добавить класс

1
.selected
для всех элементов, соседних (sibling) с элементом, имеющим класс
1
.proba
. То есть, класс
1
.selected
будет добавлен всем элементам
1
a
, так как они находятся на одном уровне DOM с элементом
1
.proba
и являются соседними по отношению к нему.

По умолчанию можно не передавать методу

1
.siblings()
аргумент в виде селектора -
1
.siblings('a')
, так как подразумеваются элементы, которые являются соседними в текущей HTML-разметке. Но можно передавать методу в качестве аргумента имя класса -
1
.siblings('.test__link')
; или элемент с именем класса (идентификатора) -
1
.siblings('a.test__link')
.

Краткие примеры использования метода

1
.siblings()
, взятые с ресурса jQuery Page2Page:

  • 1
    
    $("#block").siblings()
    - найдет элементы, которые имеют общего родителя с элементом, обладающим идентификатором
    1
    
    #block
  • 1
    
    $(".lBlock").siblings()
    - найдет элементы, которые имеют общих родителей с элементами класса
    1
    
    .lBlock
  • 1
    
    $(".lBlock").siblings(".cont")
    - найдет элементы класса
    1
    
    .cont
    , которые имеют общих родителей с элементами класса
    1
    
    .lBlock

Важный момент - в этом случае класс

1
.selected
не будет добавлен к элементу
1
.proba
. Другими словами, в методе
1
.siblings()
к элементу, служащему в качестве критерия, не применяются действия этого метода.

Чтобы было еще понятнее, о чем идет речь, представлю ниже результат работы описанного выше javascript-кода:

<nav class="test">
  <a href="#" class="test__link selected">test link item</a>
  <a href="#" class="test__link selected">test link item</a>
  <a href="#" class="test__link proba">test link item</a>
  <a href="#" class="test__link selected">test link item</a>
  <a href="#" class="test__link selected">test link item</a>
</nav>

Метод

1
.siblings()
прост и понятен. Единственным “подводным камнем” при работе с ним является такой момент - нужно быть внимательным с уровнями вложения элементов. Другими словами, в дереве DOM элементы не расположены на одном уровне (не являются sibling), однако разработчик упрямо пытается применить к этим элементам метод
1
.sibling()
. И потом сильно недоумевает, почему ничего не работает, хотя код то правильный!

Приведу простой пример такой ошибки, с которой один раз сам столкнулся. Здесь пример кристально ясный и понятный, однако на деле все было не так прозрачно (в совокупности с другим кодом):

<ul class="test">
  <li class="test__item">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item">
    <a href="#" class="test__link proba">test item link</a>
  </li>
  <li class="test__item">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item">
    <a href="#" class="test__link">test item link</a>
  </li>
</ul>
$('.proba').siblings().addClass('selected');

Представленный выше javascript-код работать не будет, так как элементы

1
a
(а код был сделан в расчете на эти элементы) соседними (siblings) не являются. Это хорошо заметно, если внимательно рассмотреть HTML-код примера.

Вот, в принципе, и все, что можно сказать о методе

1
.siblings()
.

На этом все.


Два метода-антагониста, принцип работы которых ясен из имени самих методов.

Метод children

Метод

1
.children()
возвращает все элементы, которые являются дочерними по отношению к элементу, указанному в качестве аргумента метода.

Примеры использования:

  • 1
    
    $('div').children()
    - вернет элементы, которые лежат непосредственно внутри div-элементов
  • 1
    
    $('div').children('.block')
    - вернет элементы класса
    1
    
    .block
    , которые лежат непосредственно внутри div-элементов
  • 1
    
    $('#area').children('.block') - вернет элементы класса .
    block
    1
    
    , которые лежат непосредственно внутри элемента с идентификатором 
    #area`

Метод

1
.children()
в чем-то похож на метод
1
.find()
, рассмотренный мною ранее. Но между двумя этими методами существует одно большая разница.

Метод

1
.children()
возвращает (другими словами - ищет) все элементы, расположенные на DOM-уровне ниже указанного элемента; и только на этом уровне. Другими словами - возвращаются все непосредственные children-элементы.

Метод

1
.find()
производит поиск указанных элементов на всех уровнях DOM-дерева. Другими словами, будет производиться поиск элементов на всех уровнях, вне зависимости от глубины вложенности этих уровней.

Метод parent

Метод

1
.parent()
возвращает все элементы, являющиеся непосредственными родителями элемента(ов), указанных в качестве аргументов данного метода.

Примеры использования:

  • 1
    
    $('#block').parent()
    - вернет родителя элемента с идентификатором
    1
    
    #block
  • 1
    
    $('div').parent()
    - вернет родительские элементы всех div-ов
  • 1
    
    $('div').parent('.block')
    - вернет элементы класса
    1
    
    .block
    , которые являются родительскими для div-элементов на странице

На этом все.


Достаточно интересные методы -

1
.eq()
и
1
.index()
, особенно в сочетании друг с другом. Поэтому и решил объединить рассмотрение этих методов. Каждый по отдельности - методы просты и мало показательны.

Но для начала вкратце (по другому и не получиться) опищу каждый из методов, по возможности своими словами.

Метод index

Работа метода

1
.index()
проста - он возвращает индекс (порядковый номер) указанного элемента среди группы ему подобных.

Синтаксис метода

1
.index()
также простой:

index([element])

или

.index(selector)

И пример для иллюстрации:

<ul class="test">
  <li class="primo">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="secondo">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="tetro">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="quattro">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="cinque">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="sei">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="sedici">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="ten">
    <a href="#" class="test__link">test item link</a>
  </li>
</ul>

Сделать выборку всех элементов

1
li
и вернуть индекс элемента
1
li
с классом
1
.cinque
:

var listIndex = $('.cinque');
console.log('Index of ' + $('li').index(listIndex));

Найти элемент с классом

1
.sei
среди соседних элементов и вернуть его индекс:

console.log('Index of ' + $('.sei').index());

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

Метод eq

Метод

1
.eq()
прямопротивоположен методу
1
.index()
. Этот метод возвращает элемент (как объект) по его индексу (порядковому номеру).

Если взять предыдущую HTML-разметку, то такой javascript-код:

$('li').eq(1).html("Secondo");

… изменит содержимое второго по счету элемента

1
li
на “Secondo”. Почему второго? Как можно догадаться, результатом выборки
1
$('li')
является массив элементов; а в массиве индексирование элементов начинается с нуля (0).

Методы eq и index

Рассмотренные выше примеры использования методов

1
.eq()
и
1
.index()
просты и понятны. И неинтересны.

Гораздо более интеерсным примером является случай объединения обоих методов в jQuery-цепочке.

Приведу такой гипотетический пример:

<ul class="test">
  <li class="test__item primo">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item secondo">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item tetro">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item quattro">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item cinque">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item sei">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item sedici">
    <a href="#" class="test__link">test item link</a>
  </li>
  <li class="test__item">
    <a href="#" class="test__link">test item link</a>
  </li>
</ul>
$('.test__item').click(function(){
  $('li').eq($(this).index()).html($(this).index()).siblings().html("test item link");
});

Javascript-код, написанный выше, читается таким образом:

  • сделать выборку всех элементов с классом
    1
    
    .test__item
  • при клике мыши на любом из этих элементов выполнить функцию:
    • сделать выборку всех элементов
      1
      
      li
    • вернуть индекс активного элемента из выборки -
      1
      
      $(this).index()
    • вернуть активный элемент по его индексу -
      1
      
      .eq($(this).index())
    • для возвращенного элемента
      1
      
      .eq($(this).index())
      изменить его содержимое на значение его индекса -
      1
      
      html($(this).index())
    • всем соседним (sibling) элементам установить значение в -
      1
      
      .siblings().html("test item link")

Пример рабочий, поэтому его можно свободно попробовать.

В принципе, на этом все.