选择输入焦点上的文本
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 方式”,但是您有什么理由不这样做<input type="text" value="test" onclick="this.select()" />
?
【参考方案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 并存储在那里 true 或 false 我得到 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。
【讨论】:
以上是关于选择输入焦点上的文本的主要内容,如果未能解决你的问题,请参考以下文章