Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 12.10.2014, 17:56
Аватар для giv13
Интересующийся
Отправить личное сообщение для giv13 Посмотреть профиль Найти все сообщения от giv13
 
Регистрация: 06.10.2014
Сообщений: 11

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 раз в секунду.

Надеюсь, объяснил доходчиво. Помогите, пожалуйста, в этой нелегкой для меня ситуации...
Ответить с цитированием
  #2 (permalink)  
Старый 13.10.2014, 19:45
Аватар для giv13
Интересующийся
Отправить личное сообщение для giv13 Посмотреть профиль Найти все сообщения от giv13
 
Регистрация: 06.10.2014
Сообщений: 11

Ну помогите хоть чем-нибудь. Очень давно борюсь с проблемой. Есть ли решение? Или лучше обойти как-то с другой стороны?
Ответить с цитированием
  #3 (permalink)  
Старый 13.10.2014, 19:51
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

giv13,
интервал делайте свойством элемента а не через var
Ответить с цитированием
  #4 (permalink)  
Старый 13.10.2014, 19:54
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Вроде в data элемента обычно закидывают.
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #5 (permalink)  
Старый 13.10.2014, 19:56
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

danik.js,
можно в дата -- основное индивидуальный таймер с возможностью его обнулить
Ответить с цитированием
  #6 (permalink)  
Старый 13.10.2014, 19:56
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

giv13, ты не предусмотрел вызов на коллекции из более 1 элемента. Нужно обернуть все в return this.each()
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #7 (permalink)  
Старый 13.10.2014, 19:57
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Сообщение от рони
можно
Ну писать в свойства DOM объекта - не лучшая идея (да, знаю, jQuery пишет, но там без вариантов)
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #8 (permalink)  
Старый 13.10.2014, 21:28
Аватар для giv13
Интересующийся
Отправить личное сообщение для giv13 Посмотреть профиль Найти все сообщения от giv13
 
Регистрация: 06.10.2014
Сообщений: 11

рони, 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);
Ответить с цитированием
  #9 (permalink)  
Старый 13.10.2014, 21:58
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

У тебя this ссылается на коллекцию. Когда в коллекции 1 элемент - все ок. А что будет при $('div').ex() ? Тогда в коллекции будет два (допустим) элемента, а this.text() вернет конкатенацию строк. Интервал будет запущен для всей коллекции, но если затем вызвать $('.ex1'), то интервал будет отменен как для ex1 так и для всех div.
Ну а return нужен чтобы можно было писать $(x).ex().blabla()
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #10 (permalink)  
Старый 14.10.2014, 21:05
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

giv13, а за что минус то поставил?
__________________
В личку только с интересными предложениями
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
setInterval внутри обьекта Jekel Javascript под браузер 3 29.06.2014 15:14
Как можно упростить доступ к функциям внутри плагина Sanu0074 Events/DOM/Window 1 17.01.2014 13:56
Не работает setInterval внутри jQuery ready в Chrome Universe jQuery 6 14.08.2013 18:03
Вызов метода внутри метода при инициализации плагина SergXP jQuery 0 01.07.2013 22:27
один setInterval внутри другого setInterval-а dadli Общие вопросы Javascript 5 20.03.2012 18:16