2016-01-11 26 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