2016-01-11 30 views
1

我有一個簡單的任務來與普通文本框進行交互,這是基於焦點還是不焦點,而是掛起如何啓動和停止迭代過程使用jQuery。當焦點不對焦時在文本框中迭代地寫文字並在焦點時停止

目標

我有一個包含用於在data-*屬性幾個空格分隔單詞的數據的HTML文本框:<input type="text" data-queries="The big brown fox jumped" ...>

無論何時文本框不在焦點(以及頁面加載時),我希望文本框的值每秒更改一次,不斷反覆更改data-queries屬性中的不同單詞。

只要文本框處於焦點狀態,我想迭代停止並將值設置爲空白(所以佔位符文本顯示)。

到目前爲止我的代碼

HTML

<form class="form-horizontal" action="" autocomplete="on"> 
    <label for="search"><h3 class="text-default">My Label</h3></label> 
    <input class="landing-search ml-15" data-queries="The big brown fox jumped" id="search" name="search" type="text" placeholder="Search..."> 
</form> 

JS

//Function that writes each string in @words one second apart 
//then calls itself recursively to repeat 
//Tries to "stop" by checking if selector is in focus 
//but stops only after last word is reached, not immediately when in focus 
    function write_to_textbox_loop(selector, words) { 
      if(selector.is(":focus")) { 
       return; 
      } 
      for(var i = 0; i < words.length; i++){ 
       (function(i){ 
        setTimeout(function(){ 
         selector.val(words[i]); 
        }, 1000*i); 
       })(i); 
      } 

      setTimeout(function(){ 
       write_to_textbox_loop(selector, words); 
      }, 1000*(words.length)); 
    } 

    if($('.landing-search').length > 0) { 

      data_queries = $('.landing-search').attr('data-queries').split(' ') 

      //Write data-query attribute values into search textbox when not in focus 
      $('.landing-search').focusout(function(){ 
       write_to_textbox_loop($(this), data_queries); 
      }); 

      $('.landing-search').focus(function(){ 
       $(this).val(''); 
    }); 

正如我在評論中寫道,這達到了預期的反覆影響(雖然我我不確定爲什麼只用遞歸調用1000*words.length永遠沒有任何其他增量作品,因爲所有的setTimeout調用很快就會發生,但它確實有效:當我移除焦點時,它會永久循環遍歷所有單詞。

但是,當我點擊文本框並將其引入焦點時,只有在完成了該循環中的最後一個單詞的寫入後,它纔會停止。這是有道理的,因爲我在一系列遞歸調用中停止返回,但我需要它立即停止

當文本框進入焦點時,我怎樣才能讓詞語瞬間停止,然後在失去焦點時再次啓動?

編輯:我想用clearTimeout()的,但它需要你想停止setTimeout var和我無法弄清楚如何跟蹤所有不同setTimeout()調用創建遞歸的邏輯。

謝謝!

回答

1

你可以只寫一個小插件,使得它更可重複使用的快速反應

$.fn.inputShow = function(opts) { 
 
    var start = true; 
 
    
 
    return this.each(function() { 
 
    \t if (opts === false) { 
 
      clearInterval($(this).data('timer')); 
 
      this.value = ''; 
 
     } else { 
 
      var words = $(this).data('queries').split(/\b/).filter(function(x) { return x.trim().length }); 
 
      var i = $(this).data('i') || 0; 
 
      
 
      if (start) this.value = words[i]; 
 
      
 
      $(this).data('timer', setInterval(function() { 
 
       start = false; 
 
       this.value = words[i+1] ? words[++i] : words[i=0]; 
 
       $(this).data('i', i); 
 
      }.bind(this), opts || 1000)); 
 
     } 
 
    }); 
 
} 
 

 
$('.landing-search').on({ 
 
\t focus : function() { 
 
    \t $(this).inputShow(false); // stops it 
 
    }, 
 
    blur: function() { 
 
    \t $(this).inputShow(1000); // starts it, delay of 1000 milliseconds 
 
    } 
 
}).trigger('blur'); // start on pageload
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<form class="form-horizontal" action="" autocomplete="on"> 
 
    <label for="search"><h3 class="text-default">My Label</h3></label> 
 
    <input class="landing-search ml-15" data-queries="The big brown fox jumped" id="search" name="search" type="text" placeholder="Search..."> 
 
</form>

+0

感謝,它的偉大工程。但是,爲什麼需要bind()?再次感謝。 – ministry

+1

'bind'只是在這個時間間隔內設置這個值,所以'this'是元素,而不是'window',這就是所有 – adeneo

+0

不是變量'start'在這裏是多餘的嗎?它始終設置爲「true」,只在「else」中進行檢查,因此,當「else」命中時,this.value = words [i]'將始終打開。它在'setInterval'中被設置爲false,但是當函數被再次調用時它不會總是被設置爲'true'? – ministry