Статьи

jQuery: кратко: выбор jQuery

Нет необходимости указывать фактический элемент вместе с фильтром, например, $('div:hidden') . Можно просто пропустить фильтр в любом месте, где ожидается выражение селектора.

Несколько примеров:

1
2
3
4
// Selects all hidden elements
$(‘:hidden’);
// Selects all div elements, then selects only even elements
$(‘div’).filter(‘:even’);

Пользовательские фильтры селектора jQuery :hidden и :visible не учитывают свойство видимости CSS, как можно было бы ожидать. Способ jQuery определяет, является ли элемент скрытым или видимым, заключается в том, занимает ли элемент какое-либо место в документе. offsetWidth offsetHeight , элемент виден, если его сообщенные браузером offsetWidth или offsetHeight больше 0. Таким образом, элемент, который может иметь display значение CSS для block содержащегося в элементе с display значением none , точно сообщит, что он не видно

Внимательно изучите код и убедитесь, что вы понимаете, почему возвращаемое значение имеет значение true хотя выбранный <div> имеет встроенный стиль display:block .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div id=»parentDiv» style=»display: none;»>
        <div id=»childDiv» style=»display: block;»></div>
    </div>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function($){
          // Returns true because the parent div is hidden, so the
          // encapsulated div reports zero offsetWidth and offsetHeight
      alert($(‘#childDiv’).is(‘:hidden’));
  })(jQuery);
</body>
</html>

Часто необходимо определить, действительно ли выбранный набор элементов содержит конкретный элемент. Используя метод is() , мы можем проверить текущий набор по выражению / фильтру. Проверка вернет true если набор содержит хотя бы один элемент, выбранный данным выражением / фильтром. Если он не содержит элемент, возвращается false значение. Изучите следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div id=»i0″>jQuery</div>
    <div id=»i1″>jQuery</div>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function($){
      // Returns true
      alert($(‘div’).is(‘#i1’));
      // Returns false.
      alert($(‘div’).is(‘#i2’));
      // Returns false.
      alert($(‘div’).is(‘:hidden’));
  })(jQuery);
</body>
</html>

Должно быть очевидно, что второе alert() вернет значение false, потому что наш набор оболочек не содержал <div> со значением атрибута id i2 . Метод is() очень удобен для определения, содержит ли набор обертки определенный элемент.

Примечания: Начиная с jQuery 1.3, метод is() поддерживает все выражения. Ранее сложные выражения, например, содержащие селекторы иерархии (например, + , ~ и > ), всегда возвращали значение true .

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

Некоторые разработчики используют is('.class') чтобы определить, есть ли у элемента определенный класс. Не забывайте, что в jQuery уже есть метод для этого, называемый hasClass('class') , который можно использовать с элементами, содержащими более одного значения класса. Но, по правде говоря, hasClass() — это просто удобная оболочка для метода is() .


В качестве первого параметра функции jQuery можно указать несколько выражений, разделенных запятой: $('expression, expression, expression') . Другими словами, вы не ограничены выбором элементов, используя только одно выражение. Например, в приведенном ниже примере я передаю функции jQuery три выражения, разделенные запятой.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div>jQuery </div>
    <p>is the </p>
    <ul>
        <li>best!</li>
    </ul>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
      // Alerts jQuery is the best!
      alert($(‘div, p, ul li’).text());
      // Inefficient way.
      alert($(‘div’).text() + $(‘p’).text() + $(‘ul li’).text());
  })(jQuery);
</body>
</html>

Каждое из этих выражений выбирает элементы DOM, которые все добавляются в набор оболочек. Затем мы можем работать с этими элементами, используя методы jQuery. Имейте в виду, что все выбранные элементы будут помещены в один и тот же набор оболочек. Неэффективный способ сделать это — вызвать функцию jQuery три раза, по одному разу для каждого выражения.


Можно определить, выбрало ли ваше выражение что-либо, проверив, имеет ли длина обертки набор. Вы можете сделать это, используя length свойства массива. Если свойство length не возвращает 0, то вы знаете, что хотя бы один элемент соответствует выражению, которое вы передали функции jQuery. Например, в приведенном ниже коде мы проверяем страницу на наличие элемента с id «notHere». Угадай, что? Его там нет!

01
02
03
04
05
06
07
08
09
10
<!DOCTYPE html>
<html lang=»en»>
<body>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function($){
      // Alerts «0»
      alert($(‘#notHere’).length);
  })(jQuery);
</body>
</html>

Примечания: Если это не очевидно, свойство length может также сообщать о количестве элементов в наборе обёрток — иначе говоря, сколько элементов было выбрано выражением, переданным функции jQuery.


Возможности механизма выбора jQuery можно расширить, создав собственные пользовательские фильтры. Теоретически, все, что вы здесь делаете, — это создание пользовательских селекторов, которые уже являются частью jQuery. Например, скажем, мы хотели бы выбрать все элементы на веб-странице, которые абсолютно позиционированы. Поскольку у jQuery еще нет специального фильтра :positionAbsolute , мы можем создать свой собственный.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div style=»position: absolute»>absolute</div>
    <span style=»position: absolute»>absolute
    <div>static</div>
    <div style=»position: absolute»>absolute</div>
    <div>static</div>
    <span style=»position: absolute»>absolute
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
     // Define custom filter by extending $.expr[‘:’]
     $.expr[‘:’].positionAbsolute = function (element)
     { return $(element).css(‘position’) === ‘absolute’;
     // How many elements in the page are absolutely positioned?
     alert($(‘:positionAbsolute’).length);
     // How many div elements are absolutely positioned?
     alert($(‘div:positionAbsolute’).length);
 })(jQuery);
</body>
</html>

Здесь важно понять, что вы не ограничены селекторами по умолчанию, предоставляемыми jQuery. Вы можете создать свой собственный. Однако, прежде чем тратить время на создание собственной версии селектора, вы можете просто попробовать метод filter() с указанной функцией фильтрации. Например, я мог бы избежать написания селектора :positionAbsolute , просто отфильтровав элементы <div> в моем предыдущем примере с помощью функции, которую я передал методу filter() .

1
2
3
4
5
6
7
// Remove <div> elements from the wrapper
// set that are not absolutely positioned
$(‘div’).filter(function () { return $(this).css(‘position’) === ‘absolute’; });
// or
// Remove all elements from the wrapper
// set that are not absolutely positioned
$(‘*’).filter(function () { return $(this).css(‘position’) === ‘absolute’; });

Примечания: Для получения дополнительной информации о создании ваших собственных селекторов я предлагаю следующее: http://www.bennadel.com/blog/1457-How-To-Build-A-Custom-jQuery-Selector.htm


jQuery предоставляет фильтры для фильтрации обертки, заданной числовым контекстом элемента в наборе.

Эти фильтры:

  • :first
  • :last
  • :even
  • :odd
  • :eq(index)
  • :gt(index)
  • :lt(index)

Примечания: Фильтры, которые фильтруют сам набор оболочек, делают это путем фильтрации элементов в наборе в начальной точке 0 или индекса 0. Например :eq(0) и :first доступ к первому элементу в наборе — $('div:eq(0)') — с индексом 0. Это противоречит фильтру :nth-child который индексируется одним индексом. Это означает, например, что :nth-child(1) вернет первый дочерний элемент, но попытка использовать :nth-child(0) не будет работать. Использование :nth-child(0) всегда ничего не выберет.

Использование :first выберет первый элемент в наборе, в то время как :last выберет последний элемент в наборе. Помните, что они фильтруют набор на основе отношений (числовая иерархия, начинающаяся с 0) внутри набора, но не отношений элементов в контексте DOM. Учитывая эти знания, должно быть очевидно, почему фильтры :first :last и :eq(index) всегда будут возвращать один элемент.

Если это не очевидно, позвольте мне объяснить дальше. Причина, по которой :first может вернуть только один элемент, заключается в том, что в наборе может быть только один элемент, который считается первым, когда существует только один набор. Это должно быть довольно логично. Изучите приведенный ниже код, чтобы увидеть эту концепцию в действии.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang=»en»>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <ul>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
    </ul>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
     // Remember that text() combines the contents of all
     // elements in the wrapper set into a single string.
     alert(‘there are ‘ + $(‘li’).length + ‘ elements in the set’);
     // Get me the first element in the set
     alert($(‘li:first’).text());
     // Get me the last element in the set
     alert($(‘li:last’).text());
     // Get me the 6th element in the set, 0 based index
     alert($(‘li:eq(5)’).text());
 })(jQuery);
</body>
</html>

Имея четкое понимание управления самим набором, мы можем расширить наше понимание выбора элементов, используя фильтры, которые выбирают элементы, которые имеют уникальные отношения с другими элементами в реальном DOM. JQuery предоставляет несколько селекторов для этого. Некоторые из этих селекторов являются пользовательскими, а некоторые являются хорошо известными CSS-выражениями для выбора элементов DOM.

  • ancestor descendant
  • parent > child
  • prev + next
  • prev ~ siblings
  • :nth-child(selector)
  • :first-child
  • :last-child
  • :only-child
  • :empty
  • :has(selector)
  • :parent

Использование этих селекторных фильтров будет выбирать элементы на основе их взаимосвязи в DOM как относящихся к другим элементам в DOM. Чтобы продемонстрировать эту концепцию, давайте посмотрим на некоторый код.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang=»en»>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
     // Remember that text() combines the contents of all
     // elements in the wrapper set into a single string.
     alert($(‘li:nth-child(2)’).text());
     alert($(‘li:nth-child(odd)’).text());
     alert($(‘li:nth-child(even)’).text());
     alert($(‘li:nth-child(2n)’).text());
 })(jQuery);
</body>
</html>

Если вас удивляет тот факт, что $('li:nth-child(odd)').text() возвращает значение 135135, вы еще не используете фильтры отношений. Выражение $('li:nth-child(odd)') устной форме гласит: «найдите все элементы <li> на веб-странице, которые являются дочерними, и затем отфильтруйте их по нечетным $('li:nth-child(odd)') элементам». Ну, просто так получилось, что на странице есть две структуры, в которых есть группа братьев и сестер, составленная из <li> s. Моя точка зрения такова: набор обёрток состоит из элементов на основе фильтра, который учитывает отношение элемента к другим элементам в DOM. Эти отношения могут быть найдены в нескольких местах.

Концепция, которую нужно убрать, состоит в том, что не все фильтры созданы одинаково. Убедитесь, что вы понимаете, какие из них фильтруются на основе отношений DOM, например, :only-child а какие фильтруются по позиции элементов, например :eq() в упакованном наборе.


Селекторы jQuery используют набор метасимволов (например, # ~ [] = > ), которые при использовании в качестве литеральной части имени (например, id="#foo[bar]" ) должны быть экранированы. Можно убежать от персонажа, поместив две обратные косые черты перед персонажем. Изучите приведенный ниже код, чтобы увидеть, как использование двух обратных косых черт в выражении выбора позволяет нам выбрать элемент со значением атрибута id #foo[bar] .

01
02
03
04
05
06
07
08
09
10
11
12
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div id=»#foo[bar]»>jQuery</div>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
      // Alerts «jQuery»
      alert($(‘#\\#foo\\[bar\\]’).text());
  })(jQuery);
    </script>
</body>
</html>

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

  • #
  • ;
  • &
  • ,
  • .
  • +
  • *
  • ~
  • '
  • :
  • "
  • !
  • ^
  • $
  • [
  • ]
  • (
  • )
  • =
  • >
  • |
  • /

Можно сложить фильтры селектора, например, a[title="jQuery"][href^="http://"] . Очевидным примером этого является выбор элемента, который имеет определенные атрибуты с определенными значениями атрибутов. Например, приведенный ниже код jQuery будет выбирать только те элементы <a> на странице HTML, которые:

  • Содержат атрибут href со начальным значением «http: //»
  • Иметь атрибут title со значением «jQuery»

Только один <a> выбирается.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang=»en»>
<body>
    <a title=»jQuery»>jQuery.com</a>
 
    <a href=»http://www.jquery.com» title=»jQuery» class=»foo»>jQuery.com 1</a>
 
    <a href=»»>jQuery.com</a>
 
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script>
        (function ($) {
            // Alerts «1»
            alert($(‘a[title=»jQuery»][href^=»http://»]’).length);
        })(jQuery);
    </script>
</body>
</html>

Обратите внимание, что в коде мы собрали два фильтра для выполнения этого выбора.

Другие фильтры селектора могут быть сложены помимо только атрибутных фильтров. Например:

1
2
3
4
5
// Select the last <div> contained in the
// wrapper set that contains the text «jQuery»
$(‘div:last:contains(«jQuery»)’)
// Get all check boxes that are both visible and selected
$(‘:checkbox:visible:checked’)

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

Примечания: Вы также можете вкладывать и составлять фильтры — например, $('p').filter(':not(:first):not(:last)')


Фильтры селектора могут быть вложенными. Это позволяет вам использовать фильтры очень кратко и эффективно. Ниже я приведу пример того, как вы можете вкладывать фильтры для выполнения сложной фильтрации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div>javascript</div>
    <div><span class=»jQuery»>jQuery
    <div>javascript</div>
    <div><span class=»jQuery»>jQuery
    <div>javascript</div>
    <div><span class=»jQuery»>jQuery
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
     // Select all div’s, remove all div’s that have a child element with class=»jQuery»
     alert($(‘div:not(:has(.jQuery))’).text());
     // Select all div’s, remove all div’s that are odd in the set (count starts at 0)
     alert($(‘div:not(:odd)’).text());
 })(jQuery);
</body>
</html>

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

Примечания: Вы также можете вкладывать и составлять фильтры — например, $('p').filter(':not(:first):not(:last)')


Фильтр :nth-child() имеет много применений. Например, скажем, вы хотите выбрать только каждый третий элемент <li> содержащийся в элементе <ul> . Это возможно с помощью фильтра :nth-child() . Изучите следующий код, чтобы лучше понять, как использовать фильтр :nth-child() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang=»en»>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
    </ul>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
     // Remember that text() combines the contents of all
     // elements in the wrapper set into a single string.
     // By index
     alert($(‘li:nth-child(1)’).text());
     // By even
     alert($(‘li:nth-child(even)’).text());
     // By odd
     alert($(‘li:nth-child(odd)’).text());
     // By equation
     alert($(‘li:nth-child(3n)’).text());
     // Remember this filter uses a 1 index
     alert($(‘li:nth-child(0)’).text());
 })(jQuery);
</body>
</html>

Если фильтры атрибутов jQuery, используемые для выбора элементов, недостаточно надежны, попробуйте использовать регулярные выражения. Джеймс Падолси написал приятное расширение для селекторов фильтров, которое позволит нам создавать собственные регулярные выражения для фильтрации. Я привел здесь пример кода, но обязательно ознакомьтесь со статьей на http://james.padolsey.com, чтобы узнать все подробности.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div id=»123″></div>
    <div id=»oneTwoThree»></div>
    <div id=»0″></div>
    <div id=»zero»><div>
 
<script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
<script> (function ($) {
      //James Padolsey filter extension
      jQuery.expr[‘:’].regex = function (elem, index, match) {
          var matchParams = match[3].split(‘,’), validLabels = /^(data|css):/, attr = { method: matchParams[0].match(validLabels) ?
          return regex.test(jQuery(elem)[attr.method](attr.property));
      }
      // Select div’s where the id attribute contains numbers
      alert($(‘div:regex(id,[0-9])’).length);
      // Select div’s where the id attribute contains the string «Two»
      alert($(‘div:regex(id, Two)’).length);
  })(jQuery);
</div></div></body>
</html>

Только прямые дочерние элементы могут быть выбраны с помощью combiner > или с помощью метода обхода children() . Все потомки могут быть выбраны с помощью выражения * CSS. Убедитесь, что вы четко понимаете разницу между ними. Пример ниже демонстрирует различия.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang=»en»>
<body>
    <div>
        <p><strong><span>text
        <p><strong><span>text
    </div>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
      // Each statement alerts «2» because there are
      // two direct child <p> elements inside of <div>
      alert($(‘div’).children().length);
      // or
      alert($(‘>*’, ‘div’).length);
      alert($(‘div’).find(‘>*’).length);
 
      // Each statement alerts 6 because the <div> contains
      // 6 descendants, not including the text node.
      alert($(‘div’).find(‘*’).length);
      // or
      alert($(‘*’, ‘div’).length);
  })(jQuery);
</body>
</html>

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang=»en»>
<body>
    <ul id=»firstUL»>
        <li>text</li>
        <li>
            <ul id=»secondUL»>
                <li>text</li>
                <li>text</li>
            </ul>
        </li>
        <li>text</li>
    </ul>
    <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js»></script>
    <script> (function ($) {
      // Select only the direct <li> children.
      alert($(‘ul:first’).find(‘> li’).length);
      alert($(‘> li’, ‘ul:first’).length);
  }
      )(jQuery);
</body>
</html>

По сути, '> element' может использоваться как выражение, когда контекст уже определен.