使用jQuery在焦点上选择所有文本

23

我有一个小的jQuery函数,旨在在焦点进入时自动选择ASP.NET文本框中的文本。但是,在文本框中的文本被选择后立即取消选择。

如果使用.focus(function())绑定到焦点事件,则代码有效,但是我正在动态向页面添加文本框,这就是我认为需要使用.live事件的原因。

是否有人看到问题?所涉及的文本框位于Multiview内的两个GridView的Item模板中,是否会有影响?

代码:

<script type="text/javascript">

    //Select all text in Cost Rate Text Boxes when they have focus
    $(document).ready(function () {
        $(".CostRateTextBox").live('focus', function () {
            $(this).select();
        });

    });

</script>

在此输入图片描述

编辑:

<script type="text/javascript">

    //Select all text in Cost Rate Text Boxes when they have focus
    $(document).ready(function () {
        $(".CostRateTextBox").live('focus', function () {
            $(this).select();
            preventDefault();
        });

    });

</script>

1
你需要使用 preventDefault(); 吗? - Lazarus
1
@WraithNath - 在你的“focus”函数中的任何位置。下面的答案类似,只需用preventDefault();替换return false;,因为这可以涵盖许多return false;无法涵盖的错误。 - Lazarus
@WraithNath 抱歉 - 我的意思是想看一些原始的HTML代码,以便从标记的角度了解那些文本框的外观。 - Fourth
@所有人 - 感谢大家的评论,我最终通过下面的解决方案找到了答案。我已经点赞了。 - WraithNath
1
@Lazarus:如果你查看jQuery的live文档,你会看到一些注意事项。其中之一是event.stopPropagation()不起作用,必须使用return false;代替。 - Andy E
显示剩余8条评论
3个回答

25

看起来是 mouseup 事件的干扰。如果你在表单字段内单击并按住,然后移动到外面进行 "mouseup" 操作,你会发现选择会保留。使用 mouseup 而不是 focus 触发 select() 方法似乎效果更好:

<script type="text/javascript">

    //Select all text in Cost Rate Text Boxes when they have focus
    jQuery(function($){
        $("table.demo").on("mouseup", ".CostRateTextBox", function () {
            $(this).select();
        });
    });

</script>

示例: jsfiddle.net/gableroux/jvJzX/12

请参考原始示例以获取与jQuery 1.3-1.8兼容的代码。


嗨,Marcel - 谢谢,你的解决方案很有效,一开始我有点担心,因为这是一个时间表输入页面,用户会使用 Tab 键。幸运的是,Tab 键的行为已经选择了字段中的文本,所以我只需要处理点击事件 :) - WraithNath
@WraithNath:没错,Tab键本来就会选中,所以你不需要在焦点上触发。 - Marcel
刚刚查看了你的 jsfiddle,非常不错 :) - WraithNath
@AndyE:由于他的截图中有很多行和列,如果表单字段在相反的角落,点击它可能会更容易些。 - Marcel
2
更新了演示,使其与最新的jQuery兼容,并在文本区域上进行了测试。 http://jsfiddle.net/gableroux/jvJzX/12/ - GabLeRoux

3

我曾遇到一个与产品搜索表单有关的类似问题。虽然已经有了答案,但我认为提交我的代码也不会有什么坏处,对吧?

$('#product-search').focus(function(){
    $('#product-search').mouseup(function(){
        $(this).select(function(){
            $(this).off('mouseup');
        });

        $(this).select();
    });
});

优点是它只在表单第一次获得焦点时选择文本,而不是每次表单被点击时都选择文本,例如当用户想要选择文本的一部分时。我重写了Marcel的示例来演示这种区别。 http://jsfiddle.net/7tDYq/2/

1
你太棒了!这正是我在寻找的。 - Tech Savant
嗯,这并不是一个好的解决方案,因为您无法选择文本框的部分区域进行删除或编辑。 - Fandango68

2
这是我在问题jquery input select all on focus中想出的解决方案:
$("input").focus(function(){
    $(this).on("click.a keyup.a", function(e){      
        $(this).off("click.a keyup.a").select();
    });
});

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

// event logger
$("input").on("mousedown focus mouseup click blur " + 
              "keydown keypress keyup change",
              function(e) {
     console.log(e.type);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" value="potato" />
<input type="text" value="tomato" />

问题:
这里有一点解释:
首先,让我们看一下当您将鼠标或制表符移到字段中时事件的顺序。 我们可以像这样记录所有相关事件:
$("input").on("mousedown focus mouseup click blur keydown keypress keyup change",
              function(e) { console.log(e.type); });

focus events

一些浏览器在 mouseup 事件期间尝试定位光标。这是有道理的,因为您可能想要从一个位置开始拖动以突出显示一些文本。直到您实际抬起鼠标,它才能确定光标位置。因此,处理 focus 的函数注定会太早响应,使浏览器覆盖您的定位。
但问题在于我们确实希望处理焦点事件。它让我们知道第一次有人进入该字段。在那之后,我们不想继续覆盖用户选择行为。
解决方案:
相反,在 focus 事件处理程序内,我们可以快速附加即将触发的 click(单击)和 keyup(切换)事件的侦听器。
注意:Tab 事件的 keyup 实际上会在新输入字段中触发,而不是在先前的字段中。
我们只想触发一次事件。我们可以使用.one("click keyup),但这会对每个事件类型调用事件处理程序一次。相反,只要按下单击或键盘弹起键,我们就会调用函数。首先,我们将删除两者的处理程序。这样,无论我们是通过制表符还是鼠标进入,都不会有影响。该函数应该只执行一次。

注意:大多数浏览器在选项卡事件期间自然选择所有文本,但正如动画GIF所指出的, 我们仍然希望处理keyup事件,否则click事件仍会在我们制表符后悬而未决。我们同时监听两个事件,以便我们在处理选择后立即关闭监听器。

现在,我们可以在浏览器进行其选择后调用select(),以确保覆盖默认行为。
最后,为了额外保护,我们可以在clickkeyup函数中添加事件命名空间,这样.off()方法就不会删除其他可能在使用的监听器。
此外,如果您想使用一个名为once的函数扩展jQuery,以便它可以在任意数量的事件中仅触发一次:
//The handler is executed at most once per element for all event types.
$.fn.once = function (events, callback) {
    return this.each(function () {
        $(this).on(events, myCallback);
        function myCallback(e) {
            $(this).off(events, myCallback);
            callback.call(this, e);
        }
    });
};

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

//The handler is executed at most once per element for all event types.
$.fn.once = function (events, callback) {
    return this.each(function () {
        $(this).on(events, myCallback);
        function myCallback(e) {
            $(this).off(events, myCallback);
            callback.call(this, e);
        }
    });
};

$("input").focus(function(){
    $(this).once("click keyup", function(e){      
        $(this).select();
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" value="potato" />
<input type="text" value="tomato" />


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

1
这是一个优秀的答案! - jessegavin
你为什么不能只是这样做呢?$(sel).on('focus', function() { $(this).select(); }).mouseup(function(e) { e.preventDefault(); }); - Tech Savant
@NotoriousPet0,这是一个相当不错的解决方案(jsFiddle)。我只想指出的是,在第一次选择之后,你不能点击并拖动来选择文本的一部分。这并��是一个很大的问题,但它确实是一个奇怪的用户界面体验。 - KyleMit
谢谢您指出这一点。然而,我在Chrome中,有些文本区域和输入框重新选择文本时没有问题。但是,我的页面上使用完全相同的代码的一些输入框在尝试选择文本时会将光标推到框中的任何内容的末尾(并且不选择文本)。我想知道在这些特定情况下导致它们表现不良的变量是什么。您在哪个浏览器中看到这些问题?我现在会去检查fiddle。 - Tech Savant
抱歉,我有一段新的代码正在使用中... 我会尝试添加到 fiddle 中。 - Tech Savant

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