不集中时在文本框中反复写单词,集中时停止

Iteratively write words in a textbox when not in focus and stop when in focus

本文关键字:集中 单词 文本      更新时间:2023-09-26

我有一个简单的任务,根据普通文本框是否处于焦点来与它交互,但我对如何使用jQuery启动和停止迭代过程感到困惑。

目标

我有一个HTML文本框,其中包含data-*属性中几个空格分隔单词的数据:<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调用几乎都是立即发生的,但它确实有效:当我移除焦点时,它会在所有单词之间永远间隔一秒循环)。

但是,当我点击文本框并将其聚焦时,它只有在完成循环中的最后一个单词后才会停止。这是有道理的,因为我在一系列递归调用中以返回停止,但我需要它立即停止

当文本框聚焦时,我如何让我的单词循环瞬间停止,然后在失去焦点时重新开始?

EDIT:我曾想过使用clearTimeout(),但它需要您想要停止的setTimeout变量,而且我不知道如何跟踪我递归创建的所有不同setTimeout()调用的逻辑。

谢谢!

您只需编写一个小插件,使其更易于重用

$.fn.inputShow = function(opts) {
    var start = true;
    
    return this.each(function() {
    	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({
	focus : function() {
    	$(this).inputShow(false); // stops it
    },
    blur: function() {
    	$(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>