Changing AngularJS width pointer width with keyup

I created a directive to make an input that has a width that automatically changes when the keys are pressed (e.g. Google Contacts). However, this does not seem to be normal, because the width of each character is different. Could you help me more optimally? Tks.

http://plnkr.co/edit/DSn0JDDShOXvuXXF9PP2?p=preview

+4
source share
5 answers

Based on @notme's answer, I created the following entity for my own version of the angular auto-size directive:

https://gist.github.com/Zmaster/6923413

Here is the code:

Template:

<span> <input type="text" ng-model="value"> <span style="visibility:hidden; position:absolute; left:-1000; top:-1000;">{{value}}</span> </span> 

Directive

 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'); } }); } }; }); 
+6
source

You can create a dummy range to keep the same line as in the input text box.
On the keyboard, you update the content of the range and get a new length.
You better create a css rule with a text style definition for both text and text input, so you are sure that they have the same font style.

Your directive will look like this:

.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 } 

Here you can see plunker

+5
source

So the problem is that you need to measure the text in the input file. You can't just guess if you want it to fit.

So this is harder than it might seem, but I think I have Plunk here for you that will do the trick.

The main process:

  • Create a time interval.
  • Apply the same font style to the range.
  • Put the value in the range as text.
  • Measure the range.
  • Delete range.

Code: and Plunk

 app.directive("editInline", function($window){ return function(scope, element, attr){ // a method to update the width of an input // based on it 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); }); } }); 

EDIT : I also changed it to update the input size asynchronously after the keydown event. This will make it update more smoothly when you do something like keystroke.

+4
source

I have done this before. The solution I used was an off-screen SPAN with the same text in it, with the same font as the text box, and polling its width.

I might have something like this:

 <span class="textbox-copy"></span> .textbox-copy { position: absolute; left: -9999px; top: -9999px; font: -webkit-small-control; font: -moz-field; font-size: 13px; } 

Then, in keydown mode, set the innerHTML this SPAN and check its current width. Please note that, at least in Chrome and Firefox, there is a special font in the unencrypted text box. It does not just inherit Arial or something else.

+2
source

I know this is an old discussion, but I wanted to share my decision, which, in my opinion, is better than all the answers. I just finished writing the angular: angular-autogrow directive :

  • No jQuery dependency.
  • Simple and high-performance (without $ watchers / expensive DOM manipulation).
  • Works well with any CSS definition (paddings / box-size).
0
source

Source: https://habr.com/ru/post/1489140/


All Articles