setInterval внутри плагина
Задаю вопрос в первый раз тут. Так что если что не так, не судите строго. Возникла проблема. Постараюсь объяснить более внятней на более простом примере. Есть такой код на странице:
<script type="text/javascript"> function go() { $(".ex1").ex(); }; </script> <div class="ex1">tick1</div> <input type="button" value="GO" onclick="go()" /> То есть по нажатию на кнопку GO для элемента ex1 вызывается плагин ex. Вот код плагина: (function($) { $.fn.ex = function() { var text = this.text(); interval = setInterval(function() { console.log(text); }, 1000) return this; }; })(jQuery); То есть каждую секунду в консоль прописывается слово tick1. И все бы ничего, но если нажать на кнопку GO несколько раз, например, 3 раза, то в консоли видно, что слово tick1 начинает выводится 3 раза в секунду. То есть плагин ex с таймером вызывается заново, но старый таймер не удаляется. Дальше я пришел к такому коду, который решил мою проблему (сколько бы раз я не нажимал кнопку GO, в консоль пишется слово tick1 раз в секунду): (function($) { var interval; $.fn.ex = function() { var text = this.text(); clearInterval(interval); interval = setInterval(function() { console.log(text); }, 1000) return this; }; })(jQuery); Но теперь возникла новая необходимость, по нажатию кнопки GO вызывать плагин ex для нескольких элементов одновременно: function go() { $(".ex1").ex(); $(".ex2").ex(); }; <div class="ex1">tick1</div> <div class="ex2">tick2</div> <input type="button" value="GO" onclick="go()" /> И тут, так как стоит clearInterval, то он очищает вызов плагина для элемента ex1 и выводит в консоль только слово tick2. А если закомментировать clearInterval, то выводится оба слова - tick1 и tick2, но стоит нажать на кнопку GO несколько раз и возвращается первая проблема - старые таймеры не удаляются и слова tick1 и tick2 начинают выводится более чем 1 раз в секунду. Надеюсь, объяснил доходчиво. Помогите, пожалуйста, в этой нелегкой для меня ситуации... |
Ну помогите хоть чем-нибудь. Очень давно борюсь с проблемой. Есть ли решение? Или лучше обойти как-то с другой стороны?
|
giv13,
интервал делайте свойством элемента а не через var |
Вроде в data элемента обычно закидывают.
|
danik.js,
можно в дата -- основное индивидуальный таймер с возможностью его обнулить |
giv13, ты не предусмотрел вызов на коллекции из более 1 элемента. Нужно обернуть все в return this.each()
|
Цитата:
|
рони, danik.js, спасибо большое за ответы. Про первое не понял, если честно, а вот про data почитал и пришел к такому решению:
(function($) { $.fn.ex = function() { return this.each(function() { var text = $(this).text(); clearInterval($(this).data('interval')); $(this).data('interval', setInterval(function() { console.log(text); }, 1000)); }); }; })(jQuery); Теперь это именно то, что мне нужно!) Но возникло еще пару вопросов. Ответьте, очень прошу. Вопрос 1: Нормальное ли это решение? Или корявое? Вопрос 2 (больше к данику): Правильно ли я сделал обвертку в return this.each()? Объясни мне, пожалуйста, для чего нужна эта обвертка? При написании плагина пользовался многими мануалами, и во всех пишут, что надо обворачивать в нее. Но для чего именно, я так и не понял. И в итоге написал без нее. Что я теряю, не обвернув плагин? какой-то особый вызов не сработает? Или что? Можно хотя бы пример вызова, который не сработает в этом коде: (function($) { $.fn.ex = function() { var text = this.text(); clearInterval(this.data('interval')); this.data('interval', setInterval(function() { console.log(text); }, 1000)); return this; }; })(jQuery); |
У тебя this ссылается на коллекцию. Когда в коллекции 1 элемент - все ок. А что будет при $('div').ex() ? Тогда в коллекции будет два (допустим) элемента, а this.text() вернет конкатенацию строк. Интервал будет запущен для всей коллекции, но если затем вызвать $('.ex1'), то интервал будет отменен как для ex1 так и для всех div.
Ну а return нужен чтобы можно было писать $(x).ex().blabla() |
giv13, а за что минус то поставил? :-/
|
danik.js, эй это не я. Я вам обоим плюсы поставил. Вы мне очень помогли. Я реально с этой проблемой очень долго сидел. А вы навели на решение.
|
Цитата:
![]() |
Ладно, не парься. Ну промахнулся, бывает )
|
danik.js, пхаха, блин, как можно плюс с минусом перепутать)) ща реабилитируюсь :agree:
UPD: Вы должны добавить отзыв кому-то еще, прежде чем сможете снова добавить его danik.js...Ну ладно, как-нибудь реабилитируюсь) |
Ну что ж, придется в ответку минус ставить ..
|
danik.js, эх..:)
Не буду уж новой темы создавать. Подскажите еще кто-нибудь, какая разница между объявлениями переменных до fn и после? Где лучше объявлять? И вообще стоит ли заморачиваться по этому поводу? Вот наглядный пример: (function($) { //Какая разница между объявлениями? var x = 2, //Вот тут? y = 3; $.fn.ex = function() { var x = 2, //Или тут? y = 3; alert(x * y); //Выводит ответ в обоих случаях, но какой вариант лучше? }; })(jQuery); |
В первом случае они будут созданы единожды и расшарены. А во втором - создаваться при каждом вызове ex()
Если x y - константы, то используй первый вариант. Если не константы - то первый вариант не подходит, конечно же. |
Часовой пояс GMT +3, время: 13:26. |