jQuery имеет множество встроенных селекторов для выборки элементов по id, классу, тегу, атрибуту. Если данного списка селекторов jQuery вам недостаточно , вы можете создать собственные селекторы.

Первое, на что я обратил внимание, когда начал знакомиться с возможностями jQuery – это легкость, с которой можно обратиться к нужному элементу. Использование селекторов css - отличная идея! Имеющихся селекторов вполне достаточно для решения большинства задач, однако при помощи $.extend список селекторов/фильтров jQuery можно дополнить еще несколькими отличными селекторами/фильтрами (смотрите примеры полезных селекторов).

Теория

Шаблон для собственного селектора jQuery

1
2
3
4
5
6
7
8
9
10
$.expr[':'].test = function(obj, index, meta, stack){
   // obj - текущий элемент DOM
   // index - текущий индекс при обходе массива элементов
   // meta - метаданные селектора
   // stack - массив всех просматриваемых элементов
   // Return true если элемент соответствует селектору
   // Return false если элемент не соответствует селектору
};
// Использование:
$('.someClasses:test').doSomething();

Если вы хотите использовать параметр при вызове селектора (например :contains(некий_текст) ), то в селекторе вам необходимо смотреть значение параметра meta.

meta - это массив из четырех элементов:

[полное написание селектора, имя селектора, тип используемых в параметре кавычек, значение параметра].

Обратившись к meta[3] вы получите список переданных параметров, пример:

#1

1
2
3
4
5
6
7
8
$('a:test');
//meta будет содержать следующие данные:
[
':test(argument)', // полный селектор
'test',            // имя селектора
undefined,         // тип кавычек
undefined          // параметр
]

#2

1
2
3
4
5
6
7
8
$('a:test(argument)');
//meta будет содержать следующие данные:
[
':test(argument)', // полный селектор
'test',            // имя селектора
'',                // кавычки не используются (пустая строка)
'argument'         // параметр
]

#3

1
2
3
4
5
6
7
8
$('a:test("arg1, arg2")');
//meta будет содержать следующие данные:
[
':test('arg1, arg2')', // полный селектор
'test',                // имя селектора
'"',                   // используемые в параметре кавычки
'arg1, arg2'           // параметр
]

Примеры

Эти примеры, в основном, только для демонстрации возможностей собственных селекторов. Примеры полезных селекторов ниже.

:inline jQuery селектор

Возвращает все элементы с display:inline.

1
2
3
4
5
6
7
$.extend($.expr[':'],{
   inline: function(a) {
      return $(a).css('display') === 'inline';
   }
});
$(':inline'); // Выбирает все inline элементы
$('a:inline'); // Выбирает все inline ссылки

:red jQuery селектор

Проверяет цвет элемента.

1
2
3
4
5
6
7
$.extend($.expr[':'],{
   red: function(a) {
      return $(a).css('color') === 'red';
   }
});
// Вызов:
$('p:red'); // Выбирает красные параграфы

:childOfDiv jQuery селектор

Выбирает элементы, родитель у которых div.

1
2
3
4
5
6
7
8
$.extend($.expr[':'],{
   childOfDiv: function(a) {
      return $(a).parents('div').size();
   }
});
// Это только демонстрация. В скриптах следует использовать селектор $('div p') 
// вызов:
$('p:childOfDiv'); // Выбирает параграфы, у которых родительский элемент DIV

:biggerThan() jQuery селектор

Выбирает элементы больше чем указанные (сравнивает площадь).

1
2
3
4
5
6
7
8
$.extend($.expr[':'],{
   biggerThan: function(a,i,m) {
      if(!m[3]) {return false;}
      return $(a).width() * $(a).height() > $(m[3]).width() * $(m[3]).height();
   }
});
// вызов:
$('div:biggerThan(div#banner))'); // Все DIVs размер которых больше чем у #banner

:external jQuery селектор

Выбирает внешние ссылки.

1
2
3
4
5
6
7
8
9
// (Только для ссылок с заданным атрибутом href):
$.extend($.expr[':'],{
   external: function(a,i,m) {
      if(!a.href) {return false;}
      return a.hostname && a.hostname !== window.location.hostname;
   }
});
// вызов:
$('a:external'); // Выбирает все внешние ссылки

Примеры полезных селекторов

:width() jQuery селектор

Сравнивает ширину (больше/меньше).

1
2
3
4
5
6
7
8
9
10
.extend($.expr[':'],{
   width: function(a,i,m) {
      if(!m[3]||!(/^(<|>)\d+$/).test(m[3])) {return false;}
      return m[3].substr(0,1) === '>' ?
         $(a).width() > m[3].substr(1) : $(a).width() < m[3].substr(1);
   }
});
// вызов:
$('div:width(>200)'); // Все DIVs с шириной более 200px
$('div:width(>200):width(<300)'); // Все DIVs с шириной в интервале от 200 до 300 px

:inview jQuery селектор

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$.extend($.expr[':'],{
   inView: function(a) {
      var st = (document.documentElement.scrollTop || document.body.scrollTop),
          ot = $(a).offset().top,
          wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
      return ot > st && ($(a).height() + ot) < (st + wh);
   }
});
// Вызов:
$('div:inView'); // Все DIV которые сейчас видны
// Альтернативный вызов:
if ( $('div#footer').is(':inView') ) {
   // Do stuff...
}

:loaded jQuery селектор

Возвращает список загруженных изображений.

1
2
3
4
5
6
7
8
9
10
11
12
// Флаг завершения загрузки:
$('img').load(function(){
   $(this).data('loaded',true);
});
// Расширяем список селекторов:
$.extend($.expr[':'],{
   loaded: function(a) {
      return $(a).data('loaded');
   }
});
// пример использования:
alert( 'Images loaded so far: ' + $('img:loaded').size() );

:data jQuery селектор

Выбирает элементы, по хранимым данным .data()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Обертка из анонимной функции:
(function($){
   // расширяем jQuery ':'
   $.extend($.expr[':'],{
      // Новый метод "data"
      data: function(a,i,m) {
         var e = $(a).get(0), keyVal;
         // m[3] ссылается на значения внутри скобок вызываемого селектора
         // (передаваемые параметр) например :data(___)
         if(!m[3]) {
            // Цикл по свойствам объекта, находим ссылки на jquery:
            for (var x in e) { if((/jQuery\d+/).test(x)) { return true; } } 
         } else {
            // создаем массив (name,value):
            keyVal = m[3].split('=');
            // если value задано:
            if (keyVal[1]) {
               // Test for regex syntax and test against it:
               if((/^\/.+\/([mig]+)?$/).test(keyVal[1])) {
                  return
                  (new RegExp(
                     keyVal[1].substr(1,keyVal[1].lastIndexOf('/')-1),
                     keyVal[1].substr(keyVal[1].lastIndexOf('/')+1))
                  ).test($(a).data(keyVal[0]));
               } else {
                  // Test key against value:
                  return $(a).data(keyVal[0]) == keyVal[1];
               }
            } else {
               // Проверяем имеет ли элемент свойство data:
               if($(a).data(keyVal[0])) {
                  return true;
               } else {
                  // If it doesn't remove data (this is to account for what seems
                  // to be a bug in jQuery):
                  $(a).removeData(keyVal[0]);
                  return false;
               }
            }
         }
         return false;
      } 
   });
})(jQuery);

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

1. наличие данных

1
2
3
4
5
6
7
// новый элемент:
$('<img/>')
.data('dom', true) // флаг
.appendTo('body'); // добавляем в DOM
$(':data(dom)'); // Все элементы у которых задан 'dom' флаг
$('div:data(dom)'); // Все DIV с флагом 'dom'
$(':not(:data(dom))'); // Все элементы БЕЗ флага 'dom'

2. данные и значения

1
$(':data(ABC=123)'); // Все элементы у которых ключ 'ABC' имеет значение 123

3. регулярные выражения

1
2
3
4
5
6
7
8
// Предположим, у нас заданы разные данные для ряда элементов:
$('div').each(function(i){
   $(this).data('divInfo','index:' + i);
   // В результате имеем данные типа 'index:0', 'index:1', 'index:2' ...
});
// Мы можем выбрать все эти DIV так:
$('div:data(divInfo=/index:\\d+/)');
// Не забывайте экранировать слеши

4. выбрать все элементы которые используют/не используют .data()

1
2
$(':data');       // Все элементы использующие данные
$(':not(:data)'); // Все элементы не использующие данные

Другой селектор на основе .data()

:regex() jQuery селектор

Позволяет использовать регулярные выражения при поиске по атрибутам, css-стилям и данным .data()

1
2
3
4
5
6
7
8
9
10
11
jQuery.expr[':'].regex = function(elem, index, match) {
   var matchParams = match[3].split(','),
   validLabels = /^(data|css):/,
   attr = {
      method: matchParams[0].match(validLabels) ? matchParams[0].split(':')[0] : 'attr',
      property: matchParams.shift().replace(validLabels,'')
   },
   regexFlags = 'ig',
   regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
   return regex.test(jQuery(elem)[attr.method](attr.property));
}

Примеры:

#1

1
2
3
4
5
6
// Выбрать все элементы, ID которых начинается с гласной:
$(':regex(id,^[aeiou])');
// Выбрать все DIV атрибут class которых содержит цифры:
$('div:regex(class,[0-9])');
// выбрать все теги SCRIPT, SRC которых содержат jQuery:
$('script:regex(src,jQuery)');

#2

1
2
3
4
// Выбрать все элементы, ширина которых в диапазоне от 100 до 300px:
$(':regex(css:width, ^[1-3]\\d{2}px$)');
// Выбрать все DIV, отображаемые не как блочные элементы:
$('div:not(:regex(css:display, ^block$))');

#3

1
2
3
4
5
6
// добавляем data для всех картинок (просто пример);
$('img').each(function(){
$(this).data('extension', $(this)[0].src.match(/\.(.{1,4})$/)[1]);
});
// Выбираем все картинки формата PNG и JPG:
$('img:regex(data:extension, png|jpg)');

В статье использованы материалы следующих сайтов

  1. smertnik77 :

    Спасибо – насчёт data реально круто!

    [Ответить]

Оставьте свой комментарий