jQuery输入框获得焦点时全选

360

当用户集中焦点于某个文本框时,我使用以下代码来尝试选择该文本框中的所有文本。问题是,它会在一秒钟内全选所有文本,然后取消选择并将光标留在我点击的位置...

$("input[type=text]").focus(function() {
   $(this).select();
});

我希望所有的选项都保持被选择。


什么浏览器?在我的火狐浏览器中似乎工作正常? - Roman
8
Chrome对于这个不行。 - wowo_999
1
我之前在使用Chrome,但是.click()解决了这个问题 :) - Tim
4
注意:此处接受的答案只解决了问题的一半。它使选择工作正常,但难以通过后续点击来取消选择。更好的解决方案可以在这里找到:https://dev59.com/VnA75IYBdhLWcg3wSm64 - SDC
17个回答

518

试着使用click替代focus。它似乎对鼠标和键盘事件都有效(至少在Chrome/Mac上):

jQuery版本< 1.7:

$("input[type='text']").click(function () {
   $(this).select();
});

jQuery 版本 1.7+:

$("input[type='text']").on("click", function () {
   $(this).select();
});

这里有一个演示


65
问题在于你现在无法通过鼠标选择文本的部分,一旦点击发生,就会选择整个文本。 - Helin Wang
8
不适合我的可行方案,这会造成王所描述的问题。 - Marquez
4
$.fn.on('click',..) 可以使用较少的内存,并适用于动态添加的子元素。 - Ricky Boyce
1
user2072367的focus/mouseup解决方案比Nianpeng的更好。 - George
7
在使用Tab键聚焦一个字段时,这种方法无效。 - Colin Breame
显示剩余5条评论

69

我认为发生的情况是这样的:

focus()
   UI tasks related to pre-focus
   callbacks
       select()
   UI tasks related to focus (which unselect again)
一个解决方法可能是异步调用select(),这样它将在focus()之后完全运行:
$("input[type=text]").focus(function() { 
    var save_this = $(this);
    window.setTimeout (function(){ 
       save_this.select(); 
    },100);
});

4
$("input[type=text]").focus(function() { var save_this = $(this);window.setTimeout(function(){ save_this.select(); },100); });这段代码的作用是:当文本输入框被聚焦时,选择其中所有文本。 - etienne
通常不喜欢超时,但在这里非常适合,简单而有效。+1 - t.mikael.d
3
一个超时值为0似乎也可以,而且“focusin()”函数也可以与这种方法一起使用。 - Tanguy
4
没问题,即使不设置句号,写0也可以,因为超时函数在当前调用栈的末尾运行。这意味着焦点和点击事件都会触发,然后才会运行你的函数。 - Joshua Bambrick
1
超时0似乎存在问题,即“click”事件可能会在后续帧中触发,导致取消选择框。我发现超时10似乎效果很好 - 没有明显的延迟,但比超时0更可靠。 - philh
显示剩余2条评论

60

我认为这是更好的解决方案。与仅在点击事件中选择不同,它不会阻止使用鼠标选择/编辑文本。 它适用于包括IE8在内的主要渲染引擎。

$('input').on('focus', function (e) {
    $(this)
        .one('mouseup', function () {
            $(this).select();
            return false;
        })
        .select();
});

http://jsfiddle.net/25Mab/9/


4
仅适用于现有字段,这里是将其绑定到新输入字段的更新:jsfiddle.net - adriaan
有时候可以在没有点击的情况下给予焦点,而这个方法可以很好地处理。因此,对我来说,这是最干净的答案——尽管每次输入框获得焦点时可能会有一些悬挂的事件监听器,但比使用setTimeout要好得多。 - ilovett
这不允许在数字输入框内进行第二次点击以使用鼠标选择文本的其他部分。然而,移除第二个 select() 似乎可以解决这个问题。 - dperish
更好的是,加上一个 $('input[autofocus]').select(); - Daniel Bleisteiner

40

这里有一些不错的答案,其中@user2072367的是我最喜欢的,但是当您通过标签而不是单击进行聚焦时会有一个意外结果。(意外的结果是:在通过标签聚焦后正常选择文本,您必须再点击一次)

这个 Fiddle 修复了这个小 bug,并额外将 $(this) 存储在变量中,以避免冗余的 DOM 选择。看看吧!(:

在 IE > 8 中测试过。

$('input').on('focus', function() {
    var $this = $(this)
        .one('mouseup.mouseupSelect', function() {
            $this.select();
            return false;
        })
        .one('mousedown', function() {
            // compensate for untriggered 'mouseup' caused by focus via tab
            $this.off('mouseup.mouseupSelect');
        })
        .select();
});

2
+1 你和 @user2072367 的解决方案在整个串中最干净了,我希望有一种方法可以更快地让它们排到顶部。 - KyleMit
1
即使用户试图自己选择所有文本,也能正常工作,太棒了。 - Vitani
对我来说,在Windows 8.1上的ie11上无法运行。但在Windows 7和Windows 10上的ie11上可以正常工作。 - Lars Thomas Bredland
1
@LarsThomasBredland 我刚在Win 8.1 + IE11上尝试了一下,它按预期工作。你遇到了什么“不起作用”的问题? - animatedgif
它就是不选择任何东西。(我在另一个win8上进行了测试,那里可以正常工作-相同的操作系统级别和ie版本) - Lars Thomas Bredland
这种方法适用于桌面浏览器,但似乎在iOS 8.4上的Google Chrome上无法正常工作。 - theGreenCabbage

26

经过仔细审核,我提议这是该主题中更为简洁的解决方案:

$("input").focus(function(){
    $(this).on("click.a keyup.a", function(e){      
        $(this).off("click.a keyup.a").select();
    });
});

在 jsFiddle 中的演示

问题:

这里有一点解释:

首先,让我们看一下当您鼠标或按 Tab 键进入字段时事件的顺序。
我们可以像这样记录所有相关事件:

$("input").on("mousedown focus mouseup click blur keydown keypress keyup change",
              function(e) { console.log(e.type); });

focus events

注意:我已经更改了此解决方案,使用click而不是mouseup,因为它在事件管道中稍后发生,并且根据@Jocie的评论在firefox中似乎会引起一些问题。
某些浏览器尝试在mouseup或click事件期间定位光标。这很有意义,因为您可能想从一个位置开始插入符号并拖动以突出显示某些文本。在您实际抬起鼠标之前,它无法确定插入符号位置。因此,处理焦点的函数注定会太早响应,使浏览器覆盖您的定位。
但问题在于我们确实希望处理焦点事件。它让我们知道第一次有人进入该领域。在那之后,我们不希望继续覆盖用户选择行为。
解决方法:
相反,在焦点事件处理程序中,我们可以快速附加即将触发的click(单击)和keyup(制表符)事件的侦听器。

注意:按下Tab键后的keyup事件实际上会在新的输入框中触发,而不是之前的那个

我们只希望事件触发一次。我们可以使用.one("click keyup"),但这将为每个事件类型调用事件处理程序一次。相反,一旦鼠标抬起或按键松开,我们就会调用函数。首先,我们将删除两个处理程序。这样,无论我们是通过Tab键还是鼠标进入,都不会有影响。该函数应该只执行一次。

注意:大多数浏览器在按下Tab键时自然选择所有文本,但正如animatedgif指出的那样,我们仍然要处理keyup事件,否则mouseup事件仍然会在任何时候闲置。我们监听两个事件,以便在处理完选择后立即关闭监听器。

现在,我们可以在浏览器进行选择后调用select(),以确保覆盖默认行为。
最后,为了额外的保护,我们可以将事件命名空间添加到mouseupkeyup函数中,这样.off()方法就不会删除任何其他正在运行的监听器。

已在IE 10+,FF 28+和Chrome 35+中测试


如果您想使用一个名为once的函数来扩展jQuery,使其可以在任意数量的事件中仅触发一次,请参考function called once

$.fn.once = function (events, callback) {
    return this.each(function () {
        var myCallback = function (e) {
            callback.call(this, e);
            $(this).off(events, myCallback);
        };
        $(this).on(events, myCallback);
    });
};

然后,您可以进一步简化代码,如下所示:
$("input").focus(function(){
    $(this).once("click keyup", function(e){      
        $(this).select();
    });
});

在fiddle中的演示


1
@Jocie,我不确定为什么会交替出现,但看起来FF在click事件中处理文本选择,这个事件比mouseup更靠后。因为我们希望尽可能晚地处理选择的结束,以便最大限度地覆盖浏览器,所以使用click而不是mouseup应该可以解决问题。已在FF、Chrome和IE中测试。 - KyleMit
1
谢谢!终于有一个真正能在所有浏览器中运行的解决方案了! - Vincent
2
是的!这对我也起作用了!谢谢你。这应该是官方答案。 - Fandango68
也许在回答撰写时它还没有出现,但是现在已经有类似“once”的东西了:http://api.jquery.com/one/ - RiZKiT
1
@RiZKiT,one 作为“处理程序每个事件类型对元素只执行一次”的选项是不够的。它会自动关闭触发它的事件,但其他事件仍然存在,而 off 无论如何都会处理它们。请参见我的问题:function that will fire exactly once for any number of events - KyleMit
显示剩余2条评论

12

这样做可以完成工作,并避免您无法使用鼠标选择文本的问题。

$("input[type=text]").click(function() {
    if(!$(this).hasClass("selected")) {
        $(this).select();
        $(this).addClass("selected");
    }
});
$("input[type=text]").blur(function() {
    if($(this).hasClass("selected")) {
        $(this).removeClass("selected");
    }
});

1
重要的是保持能够用鼠标选择文本的能力。我正在使用它,它非常棒。 - Philibert Perusse
2
这里有太多的内容,使用user2072367的focus/mouseup解决方案 - George
@George user2072367的方案还不错,但是它有一些严重的缺陷。看看我的解决方案吧 (: - animatedgif

6

这个版本可以在iOS设备上使用,并且修复了Windows Chrome上的标准拖拽选择问题。

var srcEvent = null;

$("input[type=text],input[type=number]")

    .mousedown(function (event) {
        srcEvent = event;
    })

    .mouseup(function (event) {
        var delta = Math.abs(event.clientX - srcEvent.clientX) 
                  + Math.abs(event.clientY - srcEvent.clientY);

        var threshold = 2;
        if (delta <= threshold) {
                   try {
                        // ios likes this but windows-chrome does not on number fields
                        $(this)[0].selectionStart = 0;
                        $(this)[0].selectionEnd = 1000;
                    } catch (e) {
                        // windows-chrome likes this
                        $(this).select();
                    }
        }
    });

http://jsfiddle.net/Zx2sc/2/


添加了丑陋的try/catch以平息浏览器。 - anihilnine

6
大多数这样的解决方案存在一个问题,即当更改输入字段中的光标位置时,它们无法正常工作。
事件onmouseup在字段内更改光标位置,并在onfocus之后触发(至少在Chrome和FF中是如此)。如果您无条件地放弃mouseup,则用户无法使用鼠标更改光标位置。
function selectOnFocus(input) {
    input.each(function (index, elem) {
        var jelem = $(elem);
        var ignoreNextMouseUp = false;

        jelem.mousedown(function () {
            if (document.activeElement !== elem) {
                ignoreNextMouseUp = true;
            }
        });
        jelem.mouseup(function (ev) {
            if (ignoreNextMouseUp) {
                ev.preventDefault();
                ignoreNextMouseUp = false;
            }
        });
        jelem.focus(function () {
            jelem.select();
        });
    });
}
selectOnFocus($("#myInputElement"));

如果字段当前没有焦点,该代码将有条件地阻止mouseup的默认行为。 它适用于以下情况:

  • 在字段没有焦点时单击
  • 在字段具有焦点时单击
  • 切换到该字段

我已在Chrome 31、FF 26和IE 11中进行了测试。


这对于点击事件非常有效,但是如果我使用Tab键移动到下一个输入字段,我会看到内容稍后被选择和取消选择。 - ToX 82

4

在阅读这个帖子时,我找到了一个很棒的解决方案。

$(function(){

    jQuery.selectText('input:text');
    jQuery.selectText('input:password');

});

jQuery.extend( {
    selectText: function(s) { 
        $(s).live('focus',function() {
            var self = $(this);
            setTimeout(function() {self.select();}, 0);
        });
    }
});

这本质上与Piskvor的答案相同。 - Oliver
不要忘记其他HTML5文本类型,例如“input[type=email]”。 - jamiebarrow

3

我来自2016年晚期,这段代码只适用于最新版本的jquery(在本例中为jquery-2.1.3.js)。

if ($(element).is("input")) {
    $(element).focus(function () {
        $(element).select();
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接