【问题标题】:Iteratively write words in a textbox when not in focus and stop when in focus不聚焦时在文本框中迭代地写单词,聚焦时停止
【发布时间】:2016-01-11 15:53:04
【问题描述】:

我有一个简单的任务是根据普通文本框是否在焦点上与它进行交互,但我对如何使用 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('');
    });

正如我在 cmets 中所写的那样,这实现了所需的迭代效果(尽管我不确定为什么仅使用 1000*words.length 的递归调用会永远工作而没有任何其他增量,因为所有 setTimeout 调用几乎都会立即发生,但它确实有效:当我移开焦点时,它会在所有单词之间循环一秒钟,永远相隔一秒)。

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

我怎样才能让我的永远循环在文本框进入焦点时立即停止,然后在失去焦点时重新开始?

编辑:我曾想过使用clearTimeout(),但它需要您想要停止的setTimeout var,我无法弄清楚如何使用的逻辑跟踪我递归创建的所有不同的setTimeout() 调用。

谢谢!

【问题讨论】:

    标签: javascript jquery textbox


    【解决方案1】:

    你可以写一个小插件,让它更可重用

    $.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>

    【讨论】:

    • 感谢您的快速响应,效果很好。但是,为什么需要bind()?再次感谢。
    • bind 只是在区间内设置this-value,所以this 是元素,而不是window,仅此而已
    • 这里的变量start不是多余的吗?它总是在开头设置为true,仅在else 中检查,因此this.value = words[i] 将始终在else 命中时命中。在setInterval 中设置为false,但再次调用该函数时不总是设置为true 吗?
    • 是的,函数第一次运行时它总是设置为 true,它只是让它立即启动,并且在第一次设置值之前不会等待一秒钟
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    相关资源
    最近更新 更多