Достаточно интересный (для меня) метод выборки элементов из коллекции - метод .slice(). Хотя чего-то эдакого в этом методе нет совсем.

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

Синтаксис метода .slice() таков:

.slice(start,[end])

Возвращает элементы с индексами от start до end, если последний задан или до конца, если параметр end опущен.

Элементы с индексом start включаются в результат, а end - нет (т.е. .slice(3,5) вернет элементы, идущие под индексом 3 и 4, элемент с индексом 5 включен не будет).

Кроме этого, параметры могут быть заданы в форме отрицательных чисел, в таком случае, отсчет элементов идет с конца набора: -1 – последний элемент, -2 – предпоследний элемент и т. д.

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

$("div").slice(3) - вернет все div-элементы, начиная с четвертого (с индексами 3, 4, …) $("div").slice(3, 5) - вернет div-элементы с индексами 3 и 4 $("div").slice(-4, -2) - вернет div-элементы, идущие четвертым и третьим с конца $("div").slice(-2) - вернет предпоследний и последний div-элементы на странице

Приведу пример 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>

Такой javascript-код:

$(function(){
  var list = $('.test');
  list.find('li').slice(2,10).addClass('test__link--sliced');
});

… выполнит следующее:

  • создаст переменную list и поместит в нее результат выборки - $('.test')
  • найдет в переменной list все элементы li - .find('li')
  • в найденной коллекции определит диапазон элементов li с индексами с 2-го по 10-й - .slice(2,10)
  • добавит к элементам li этого диапазона класс - .addClass('test__link--sliced')
  • но не добавит класс .test__link--sliced к элементу li с индексом 10!

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

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

Обратите внимание, что нумерация элементов начинается с 0 - это индекс элемента! Элемент с последним индексом не включен в выборку!

Еще один пример, более краткий и наглядный.

Начальный HTML-код:

<ul class="bad">
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
</ul>

JavaScript-код:

$(function(){
  var bad = $('.bad');
  bad.find('li').slice(2,4).addClass('bad__item--sliced');
});

Результат:

<ul class="bad">
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item bad__item--sliced"></li>
  <li class="bad__item bad__item--sliced"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
  <li class="bad__item"></li>
</ul>

На этом все. Материал частично основан на ресурсе jquery.page2page и не претендует на оригинальность.


Этот метод очень похож на то, как это дело обстоит в CSS. С помощью него можно выбрать любой элемент в коллекции ему подобных, если они имеют одного общего родителя.

Приведу пример 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>

И начну учиться выбирать элементы из такого списка с помощью метода .nth-child().

nth-child(even) и nth-child(odd)

Такой пример javascript-кода:

$(function(){
  var list = $('.test');
  list.find('li:nth-child(even)').addClass('test__item--right');
  list.find('li:nth-child(odd)').addClass('test__item--left');
});

… этот javascript-код читается так:

  • создать переменную list и поместить в нее результат выборки $('.test')
  • в переменной list найти все четные (even) элементы li - .find('li:nth-child(even)')
  • и присвоить этим элементам li класс - .addClass('test__item--right')
<ul class="test">
  <li class="test__item"></li>
  <li class="test__item test__item--right"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--right"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--right"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--right"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--right"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--right"></li>
</ul>

… затем:

  • в переменной list найти все нечетные (odd) элементы li - .find('li:nth-child(odd)')
  • и присвоить этим элементам li класс - .addClass('test__item--left')
<ul class="test">
  <li class="test__item test__item--left"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--left"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--left"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--left"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--left"></li>
  <li class="test__item"></li>
  <li class="test__item test__item--left"></li>
  <li class="test__item"></li>
</ul>

Как видим, все просто и в точности также, как это обстоит в CSS с его селектором nth-child.

nth-child(pattern)

Такой пример javascript-кода:

$(function(){
  var list = $('.test');
  list.find('li:nth-child(2)').addClass('test__link--capitalize');
  list.find('li:nth-child(11)').addClass('test__link--uppercase');
});
  • найдет второй элемент li из коллекции - .find('li:nth-child(2)')
  • и присвоить ему класс - .addClass('test__link--capitalize')
  • найдет 11-й элемент li из коллекции - .find('li:nth-child(11)')
  • и присвоить ему класс - .addClass('test__link--uppercase')
<ul class="test">
  <li class="test__item"></li>
  <li class="test__item test__link--capitalize"></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 test__link--uppercase"></li>
  <li class="test__item"></li>
</ul>

Заключение

Вот и все, что можно сказать о методе nth-child библиотеки jQuery.

Но чуть не забыл упомянуть такой важный момент! Как уже можно было заметить, нумерация при использовании метода nth-child начинается не с 0, а с 1!

Впрочем, точно также обстоят дела и с селектором nth-child в CSS.

На этом все.


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

Метод first

Метод 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>

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

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

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

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

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

Код несложный и вроде бы все понятно. Но вот вопрос - а какой элемент 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>

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

Это объяснимо, если слегка подумать. В переменной wrapper хранится коллекция элементов; и элементов li - в том числе.

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

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

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

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

Метод first-child()

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

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

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

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

Все просто и вроде бы точно также, как и в случае с методом .first(). Вроде бы да, но возникает вопрос - а какой элемент 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>

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

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

На этом думаю закончить сравнительный обзор двух методов - .first() и .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>

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

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

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

Метод next()

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

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

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

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

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

В результате выполнения этого кода класс .test__link--nexted будет присвоен элементу 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()

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

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

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

Результатом выполнения этого кода класс .test__link--preved будет присвоен элементу 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>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

На этом все.


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

Метод .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');

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

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

Краткие примеры использования метода .siblings(), взятые с ресурса jQuery Page2Page:

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

Важный момент - в этом случае класс .selected не будет добавлен к элементу .proba. Другими словами, в методе .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>

Метод .siblings() прост и понятен. Единственным “подводным камнем” при работе с ним является такой момент - нужно быть внимательным с уровнями вложения элементов. Другими словами, в дереве DOM элементы не расположены на одном уровне (не являются sibling), однако разработчик упрямо пытается применить к этим элементам метод .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-код работать не будет, так как элементы a (а код был сделан в расчете на эти элементы) соседними (siblings) не являются. Это хорошо заметно, если внимательно рассмотреть HTML-код примера.

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

На этом все.