我创建了一个指令,以便在键入时自动调整宽度的输入(如 Google 联系人)。但是好像不行,因为每个字符的宽度都不一样。你能帮我提供一个更优化的方法吗?谢了。
5 回答
根据@notme 的回答,我为我自己的自动调整大小输入角度指令版本创建了以下要点:
https://gist.github.com/Zmaster/6923413
这是代码:
模板:
<span>
<input type="text" ng-model="value">
<span style="visibility:hidden; position:absolute; left:-1000; top:-1000;">{{value}}</span>
</span>
指示:
angular.module('autoSizeInput', [])
.directive('autoSizeInput', function() {
return {
replace: true,
scope: {
value: '=inputValue'
},
templateUrl: 'templates/directives/autoSizeInput.html',
link: function(scope, element, attrs) {
var elInput = element.find('input');
var elSpan = element.find('span');
elSpan.html(elInput.val());
scope.$watch('value', function(value) {
if(value) {
elSpan.html(elInput.val());
elInput.css('width', (elSpan[0].offsetWidth + 10) + 'px');
}
});
}
};
});
您可以创建一个虚拟跨度来存储您在输入文本字段中拥有的相同字符串。
在 keyup 上,您刷新 span 内容并获得新的长度。
最好为跨度和输入文本创建一个带有文本样式定义的 CSS 规则,这样您就可以确保它们具有相同的字体样式。
您的指令如下所示:
.html
<div edit-inline>
<input type="text" value="hello world">
<span class="dummy">blbla</span>
</div>
.js
app.directive("editInline", function(){
return function(scope, element, attr){
var elInput = element.find('input');
var elDummy = element.find('span');
var inputText = elInput.val();
elDummy.html(inputText);
elInput.bind("keyup", function(){
var inputText = elInput.val();
elDummy.html(inputText);
elInput.css('width', elDummy[0].offsetWidth + 'px');
});
}
});
.css
input, .dummy {
font-size: 12px;
font-family: Arial;
white-space:pre;
}
.dummy {
visibility:hidden; // this would prevent the dummy text to be shown without losing its size
}
在这里你可以看到plunker
所以问题是你必须测量输入中的文本。你不能只是猜测你是否想要它合适。
所以这个比听起来更复杂,但我想我在这里有一个 Plunk 可以帮你解决问题。
基本流程:
- 创建一个临时跨度。
- 将相同的字体样式应用于跨度。
- 将值作为文本放入范围中。
- 测量跨度。
- 删除跨度。
代码:和 Plunk
app.directive("editInline", function($window){
return function(scope, element, attr){
// a method to update the width of an input
// based on it's value.
var updateWidth = function () {
// create a dummy span, we'll use this to measure text.
var tester = angular.element('<span>'),
// get the computed style of the input
elemStyle = $window.document.defaultView
.getComputedStyle(element[0], '');
// apply any styling that affects the font to the tester span.
tester.css({
'font-family': elemStyle.fontFamily,
'line-height': elemStyle.lineHeight,
'font-size': elemStyle.fontSize,
'font-weight': elemStyle.fontWeight
});
// update the text of the tester span
tester.text(element.val());
// put the tester next to the input temporarily.
element.parent().append(tester);
// measure!
var r = tester[0].getBoundingClientRect();
var w = r.width;
// apply the new width!
element.css('width', w + 'px');
// remove the tester.
tester.remove();
};
// initalize the input
updateWidth();
// do it on keydown so it updates "real time"
element.bind("keydown", function(){
// set an immediate timeout, so the value in
// the input has updated by the time this executes.
$window.setTimeout(updateWidth, 0);
});
}
});
编辑:另外,我已将其更改为在keydown事件后异步更新输入大小。当您执行诸如按住某个键之类的操作时,这将导致它更流畅地更新。
我以前做过。我使用的解决方案是使用屏幕外的 SPAN,其中包含相同的文本,与您的文本框具有相同的字体,并询问其宽度。
我可能有这样的事情:
<span class="textbox-copy"></span>
.textbox-copy {
position: absolute;
left: -9999px;
top: -9999px;
font: -webkit-small-control;
font: -moz-field;
font-size: 13px;
}
然后在 keydown 上设置该innerHTML
SPAN 的,并检查其当前宽度。请注意,至少在 Chrome 和 Firefox 中,无样式的文本框有自己的特殊字体。它不只是继承 Arial 之类的。
我知道这是一个古老的讨论,但我想分享我的解决方案,我认为它比所有给出的答案都要好。我刚刚完成了一个角度指令的编写:angular-autogrow:
- 没有 jQuery 依赖。
- 简单且高性能(无需 $watchers / 昂贵的 DOM 操作)。
- 适用于任何 CSS 定义(填充/框大小)。