Из всех JavaScript-библиотек, jQuery вероятно имеет синтаксис селекторов, наиболее близкий к спецификации CSS. Это делает её простой для изучения верстальщиками и веб-дизайнерам, разбирающихся в CSS, хотя в jQuery существует целых 52 селектора. Если вам нравятся CSS-селекторы :first-child
, :hover
или :only-child
, то в арсенале jQuery вы сможете воспользоваться 34 подобными селекторами псевдоклассов.
Если вам будет недостаточно стандартных селекторов jQuery — таких как :animated
, :even
, :not()
или :visible
— то существует множество других селекторов, созданных сообществом разработчиков jQuery, которые вы можете смело использовать (например, :exactIgnoreCase()
, :nothidden
или :loaded()
).
А все это значит, что вам нет нужды беспокоиться об изучении того, как создавать собственные селекторы — ведь так? А вот и нет!
Чем проще задача, тем больше шанс того, что она будет выполнена без ошибок. Попробуем выполнить следующий код:
if ($(el).offset().top > $(window).scrollTop() - $(el).outerHeight(true) && $(el).offset().top < $(window).scrollTop() + $(el).outerHeight(true) + $(window).height()) { // выполнить что-нибудь }
А теперь взглянем на этот код:
if ($(el).is(":inview")) { // выполнить что-нибудь }
Нетрудно догадаться, что оба куска кода выполняют одни и те же действия, и второй из них более понятный и короткий. И в первом, и во втором случае проверяется, находится ли элемент в области видимости в окне браузера.
Если вы понимаете, что условие получается слишком длинное и запутанное, и оно повторяется в коде скрипта не один раз, вы можете упростить скрипт, сделать его более понятным и удобным для доработки, создав собственный селектор. А сделать это очень легко:
jQuery.extend(jQuery.expr[':'], { // $.extend($.expr[':'], если покороче expression: function () { // функция должна возвращать булевское значение return false; } });
В этом примере expression
— это название вашего нового селектора… он может называться, например, inview
, loaded
или nothidden
. В функции нужно отобрать элементы, которые должны быть отфильтрованы вашим селектором.
Теперь посмотрим на функционал функции фильтрации нашего селектора inview
:
jQuery.extend(jQuery.expr[':'], { inview: function (el) { if ($(el).offset().top > $(window).scrollTop() - $(el).outerHeight(true) && $(el).offset().top < $(window).scrollTop() + $(el).outerHeight(true) + $(window).height()) { return true; } return false; } });
Условие не самое оптимальное, но оно выполняет возложенную на него задачу. Код по созданию селекторов нужно добавить перед их использованием — можно вынести этот код в отдельный файл и оформить в виде плагина. Использовать созданный селектор можно любым доступным способом:
$("p:inview").css("color","orange");
или
$("p").filter(":inview").each(function(){ // выполнить что-нибудь });
или
if ($("p#desc").is(":inview")) { // выполнить что-нибудь }
Теперь попробуем немного оптимизировать созданный селектор. В созданном условии некоторые объекты вызываются несколько раз. Поэтому после их однократного использования нужно записать результат в переменную, и затем использовать только эту переменную. Теперь код выглядит следующим образом:
jQuery.extend(jQuery.expr[':'], { inview: function (el) { var $e = $(el), $w = $(window), top = $e.offset().top, height = $e.outerHeight(true), windowTop = $w.scrollTop(), windowScroll = windowTop - height, windowHeight = windowTop + height + $w.height(); return (top > windowScroll && top < windowHeight); } });
Мы создали свой собственный jQuery-селектор, который отбирает все элементы, видимые в окне браузера. Кроме того наш код оптимизирован и понятен.
Селектор "in view" уже достаточно давно был создан и используется многими разработчиками jQuery. Но только что созданный нами селектор кроме всего прочего учитывает и высоту элемента, так что селектор отберет и элементы, которые только частично видимы в окне браузера.
Статья основана на публикации "Make Your Own Custom jQuery Selector".
Опросы, близкие по теме