Имеется такая задача - на странице расположен блок. Страница скроллится, то есть наличествует событие scroll.

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

Вариантов решения этой задачи может быть несколько. В этой статье будут показаны два из них. Все они будут выполнены на JavaScript + jQuery.

Вариант первый - метод off()

Этот способ основан на методе jQuery - .off(). Как говорится в описании, метод

1
.off()
удаляет событие, вызванное с помощью метода
1
.on()
. То есть, выполняет обратную операцию.

Рассмотрим пример ниже:

var blockScrolled = $('.scrolled');
var spins = $('.spin');

spins.text('0');

$(window).on('scroll', function () {
    if ( $(window).scrollTop() > blockScrolled.offset().top - $(window).height() / 2 ) {
        spins.each( function () {
            var current = $(this);
            $( { Spin: 0 }).animate( { Spin: current.attr('data-stop') }, {
                duration: 2000,
                easing: 'swing',
                step: function ( now ) {
                    current.text( Math.ceil( now ) );
                }
            });
        });
        $(window).off('scroll');
    }
});

Что мы имеем в этом коде? Видим, что на окно

1
window
повешен обработчик ( метод
1
.on()
`) события scroll.

При возникновении этого события выполняется проверка условия. Если условие true, то для каждого из элементов коллекции spins выполнить функцию.

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

1
$(window).off('scroll')
. Эта строка “говорит” - на объекте
1
window
остановить событие scroll.

Мы получили нужный результат - при событии scroll и выполнении условия функция выполнится только один раз.

Один важный момент - после выполнения строки

1
$(window).off('scroll')
событие scroll будет “прибито” и дальнейшие попытки повесить handler на него не увенчаются успехом.

Другими словами, если дальше на странице есть еще элементы, на которых нужно обработать событие scroll, то ничего не получится.

Вариант второй - маркер

Второй способ не использует метод

1
.off()
, но применяет специальный маркер. Код простой, но эффективный. И в этом случае событие scroll не “убивается”, а функция исполняется один раз:

var marker = true;

function count() {
    // function code here ...
    marker = false;
}

$( window ).on('scroll', function () {
    if ( $( window ).scrollTop() > overview.offset().top - $( window ).height() * 0.5 ) {
        if ( marker ) {
            count();
        }
    }
});

Что есть в этом коде? Есть глобальная переменная

1
marker
, у которой изначально значение
1
true
.

При выполнении условия функция

1
count()
запускается и по ходу дела меняет значение
1
marker
на противоположный. Таким образом функция
1
count()
сработает только один раз.

Но событие scroll останется “невредимым”.

Заключение

За бортом остался еще один jQuery-метод - .one(). Его задача - также запустить на исполнение функцию только один раз.

Например, в коде ниже клик мыши на каждом из элементов коллекции likeLinks сработает только один раз:

var likeLinks = $('.overlay__link-heart');
likeLinks.one('click', function () {

// увеличить значение счетчика на единицу при клике
// -----------------------------------------------------------
var currentCount = $(this).find('.overlay__link-count');
currentCount.html( currentCount.html() * 1 + 1 );

Однако, применить метод

1
.one()
для обработки события scroll и вызова на исполнение функции только один раз у меня не получилось. Событие scroll вообще не срабатывало.

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


P.S. Сразу на ум пришло одно у самого себя - заменить

1
$( window )
на переменную. Но уже лень менять. )

MongoDB - создание документа

![MongoDB]({{site.url}}/images/uploads/2017/05/mongodb-logo.jpg "MongoDB")Приступили к самому основному - операциям создания, чтения, изм...… Continue reading

MongoDB - документы

Published on May 23, 2017