选择输入焦点上的文本

Posted

技术标签:

【中文标题】选择输入焦点上的文本【英文标题】:Select text on input focus 【发布时间】:2013-02-06 09:36:56 【问题描述】:

我有一个文本输入。当输入获得焦点时,我想选择输入内的文本。

使用 jQuery 我会这样做:

<input type="text" value="test" />
$("input[type=text]").click(function() 
    $(this).select();
    // would select "test" in this example
);

我已经四处搜索以尝试找到 Angular 方式,但我发现的大多数示例都是处理一个指令,该指令正在监视模式属性以进行更改。我假设我需要一个指令来监视接收焦点的输入。我该怎么做?

【问题讨论】:

我知道您想找到一种“Angular 方式”,但是您有什么理由不这样做&lt;input type="text" value="test" onclick="this.select()" /&gt; 【参考方案1】:

在 Angular 中执行此操作的方法是创建一个自定义指令,为您执行自动选择。

module.directive('selectOnClick', ['$window', function ($window) 
    return 
        restrict: 'A',
        link: function (scope, element, attrs) 
            element.on('click', function () 
                if (!$window.getSelection().toString()) 
                    // Required for mobile Safari
                    this.setSelectionRange(0, this.value.length)
                
            );
        
    ;
]);

像这样应用指令:

<input type="text" value="test" select-on-click />

View demo

Update1:删除 jQuery 依赖项。

Update2:限制为属性。

Update3:适用于移动版 Safari。允许选择部分文本(需要 IE>8)。

【讨论】:

如果您想在没有 jquery 的情况下执行此操作,请将 element.click 更改为 element.bind('click', function() ... 并将 element.select() 更改为 element[0]。选择() 漂亮优雅。我还将明确限制该指令作为属性应用(通过返回一个对象文字并设置restrict: 'A'),因为该指令旨在扩展现有元素的行为 @Martin 知道如何在页面打开时做到这一点,而无需用户点击?问题是在我的selectOnLoad 指令链接()之前在另一个控制器中设置了默认值。但是在 link() 中,虽然 scope 已经填充,但 element DOM 还没有与 $scope 同步,所以当我调用 select() 时,元素仍然是空的,并且没有选择任何内容。我发现的唯一解决方法是 $timeout,但我觉得可以停止使用一些新的 Angular 版本。 这在桌面/安卓上运行良好,但是当我在 ipad 上尝试时它似乎不起作用。这里有已知的工作吗? @ak85 apparently mobile Safari needs some slightly different javascript【参考方案2】:

这是一个增强的指令,当用户单击以将光标定位在输入框中时,它可以避免重新选择文本。

module.directive('selectOnClick', function () 
    return 
        restrict: 'A',
        link: function (scope, element) 
            var focusedElement;
            element.on('click', function () 
                if (focusedElement != this) 
                    this.select();
                    focusedElement = this;
                
            );
            element.on('blur', function () 
                focusedElement = null;
            );
        
    ;
)

【讨论】:

我认为这个答案比接受的要好,因为它允许将光标设置到输入文本中的某个位置,但是,作为指令有自己的范围 - 我建议重命名 focusedElement 变量到 isElementFocused 并存储在那里 truefalse 我得到 Uncaught TypeError: undefined is not a function on "this" for .select();是的,包括 jQuery 1.9.1。 @RobbieSmith 我迟到了 3 年,但是将 this 的所有实例更改为 element[0],它应该可以工作。我还建议将 click 更改为 focus 以便在用户选择输入而不是单击输入时选择文本。【参考方案3】:

这是 Angular 1.x 的旧答案

更好的方法是使用ng-click 内置指令:

<input type="text" ng-model="content" ng-click="$event.target.select()" />

编辑:

正如JoshMB 所提醒的那样;不再允许在 Angular 1.2+ 中引用 DOM 节点。所以,我已经将$event.target.select() 移到了控制器中:

<input type="text" ng-model="content" ng-click="onTextClick($event)" />

然后在你的控制器中:

$scope.onTextClick = function ($event) 
    $event.target.select();
;

这是example fiddle

【讨论】:

据我所知,这不再受支持。 Angular 抛出错误:“不允许在 Angular 表达式中引用 DOM 节点!”。有关更多信息,请参阅此线程:groups.google.com/forum/#!topic/angular/bsTbZ86WAY4。但是,指令方法效果很好。 你是对的。 Angular 1.2+ 就是这种情况。我会更新答案。 DOM 更改应该在指令中完成,还是不? 由于某种原因,其他解决方案对我不起作用,但确实如此。我认为问题在于我已经对要添加此单击事件的元素有一个指令。 说真的,即使是 onTextClick($event) 现在也在抛出错误。除了这种野兽不直观的性质之外,这种不便对我们的性能造成了多大的影响?【参考方案4】:

所提出的解决方案对我来说都不是很好。经过快速研究,我想出了这个:

module.directive('selectOnFocus', function ($timeout) 
    return 
        restrict: 'A',
        link: function (scope, element, attrs) 
            var focusedElement = null;

            element.on('focus', function () 
                var self = this;
                if (focusedElement != self) 
                    focusedElement = self;
                    $timeout(function () 
                        self.select();
                    , 10);
                
            );

            element.on('blur', function () 
                focusedElement = null;
            );
    

  

);

它混合了几种提出的解决方案,但同时适用于点击和聚焦(想想自动聚焦),并允许手动选择输入中的部分值。

【讨论】:

语法错误已更正:最后一个 );替换为: ; ); 这个适用于 input type="number",太棒了!谢谢 嘿,这适用于 android 中的 Ionic,但不适用于 ios...知道为什么吗?谢谢 好像你在从 onClick 改编它时留下了一些代码......focusedElement 有什么意义?【参考方案5】:

对我来说,ng-click 没有意义,因为如果不再次选择所有文本,您将永远无法重新定位光标,我发现这很烦人。然后最好使用 ng-focus,因为只有在输入没有聚焦时才会选择文本,如果再次单击以重新定位光标,那么文本就会按预期取消选择,并且您可以在两者之间进行书写。

我发现这种方法是预期的用户体验行为。

使用ng-focus

选项1:单独的代码

<input type="text" ng-model="content" ng-focus="onTextFocus($event)" />

在控制器中

$scope.onTextFocus = function ($event) 
  $event.target.select();
;

选项 2: 作为替代方案,您可以将上面的代码加入到这个“单行”中(我没有对此进行测试,但它应该可以工作)

<input type="text" ng-model="content" ng-focus="$event.target.select()" />

【讨论】:

简单而且有效。如上所述,这还允许将光标定位在所选文本中。【参考方案6】:

不需要指令,只需将onfocus="this.select()"原生javascript添加到输入元素或文本区域。

【讨论】:

为什么这么多人想出了所有这些复杂的答案,而最简单的方法就在这里 :D 谢谢亚当 再次强调,简单优于复杂。你跟着KISS,你赢了。 ;)【参考方案7】:

在 Angular 2 中,这对我有用,在 Chrome 和 Firefox 中:

<input type="text" (mouseup)="$event.target.select()">

【讨论】:

在 Angular 2 或您正在使用的更新版本中?当时我没有指定浏览器的版本:这是一个错误,因为浏览器也在发展。因此,您提到的错误可能与 Chrome 和/或 Firefox 的更新版本有关。感谢您在所有情况下都提出问题。 我发现了问题。上面也提供了答案。【参考方案8】:

接受的答案是使用 click 事件,但是如果您使用 focus 事件,则只有第一次点击会触发该事件,并且当使用其他一些方法来关注输入时它也会触发(例如点击选项卡或调用焦点代码)。

这也使得没有必要像 Tamlyn 的回答所建议的那样检查元素是否已经聚焦。

app.directive('selectOnClick', function () 
    return 
        restrict: 'A',
        link: function (scope, element, attrs) 
            element.on('focus', function () 
                this.select();
            );
        
    ;
);

【讨论】:

在 Firefox 38.0.5 中单击文本中间首先会选择全部,但随后会删除选择,因此这不起作用。 如果不延迟this.select,这可能永远无法始终如一地工作。【参考方案9】:

在单击或焦点或选项卡上选择所有文本的最简单方法是!!!:

<input (focus)="inputFocused($event)">

...

inputFocused(event: any)
    event.target.select()

【讨论】:

【参考方案10】:

对我有用的修改版本。 第一次单击选择文本,第二次单击同一元素取消选择文本

module.directive('selectOnClick', function ($timeout) 
return 
    restrict: 'A',
    link: function (scope, element, attrs) 
        var prevClickElem = null; //Last clicked element
        var ignorePrevNullOnBlur = false; //Ignoring the prevClickElem = null in Blur massege function

        element.on('click', function () 
            var self = this;
            if (prevClickElem != self)  //First click on new element
                prevClickElem = self; 
                $timeout(function ()  //Timer
                    if(self.type == "number")
                        self.select();
                    else
                        self.setSelectionRange(0, self.value.length)
                , 10);
            
            else  //Second click on same element
                if (self.type == "number") 
                    ignorePrevNullOnBlur = true;
                    self.blur();
                
                else
                    self.setSelectionRange(self.value.length, self.value.length); //deselect and set cursor on last pos
            
        );

        element.on('blur', function () 
            if (ignorePrevNullOnBlur == true)
                ignorePrevNullOnBlur = false; //blur called from code handeling the second click 
            else
                prevClickElem = null; //We are leaving input box
        );
    

)

【讨论】:

【参考方案11】:

$event.target.select() 未在 Angular 模板中解析

事件目标可以是任何 html 元素,并且应在此处应用对应用程序界面的强制转换(如 HTMLSelectElement),但是,Angular 表达式不允许强制转换。最好的解决方法是将$event.target 包装成$any()

所以,它应该是这样的:(focus) = $any($event.target).select()

更多解释在这里here。

【讨论】:

以上是关于选择输入焦点上的文本的主要内容,如果未能解决你的问题,请参考以下文章

选择焦点上的文本

选择焦点上的所有文本输入内容在 Microsoft Edge 中不起作用

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

html 选择焦点输入内的所有文本

剑道网格选择焦点上的单元格数据

jQuery 屏蔽输入插件。当文本框获得焦点时选择所有内容