Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
feat(textarea): make textarea autogrow with size of content
Browse files Browse the repository at this point in the history
Closes #565. Closes #212.
  • Loading branch information
ajoslin committed Jan 8, 2015
1 parent 3ee83a6 commit 1c65369
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 12 deletions.
8 changes: 4 additions & 4 deletions src/components/input/demoBasicUsage/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<input ng-model="user.company" disabled>
</md-input-container>

<div layout layout-padding layout-sm="column">
<div layout layout-sm="column">
<md-input-container flex>
<label>First Name</label>
<input ng-model="user.firstName">
Expand All @@ -34,7 +34,7 @@
<input ng-model="user.address">
</md-input-container>

<div layout layout-padding layout-sm="column">
<div layout layout-sm="column">
<md-input-container flex>
<label>City</label>
<input ng-model="user.city">
Expand All @@ -50,8 +50,8 @@
</div>

<md-input-container flex>
<label>Country</label>
<input ng-model="user.country">
<label>Biography</label>
<textarea ng-model="user.biography" columns="1"></textarea>
</md-input-container>

</md-content>
Expand Down
2 changes: 1 addition & 1 deletion src/components/input/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ angular.module('inputBasicDemo', ['ngMaterial'])
address: '1600 Amphitheatre Pkwy' ,
city: 'Mountain View' ,
state: 'CA' ,
country: 'USA' ,
biography: 'Loves kittens, snowboarding, and can type at 130 WPM. And rumour has it she\'s bouldered up Castle Craig!',
postalCode : '94043'
};
});
49 changes: 42 additions & 7 deletions src/components/input/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ angular.module('material.components.input', [
])
.directive('mdInputContainer', mdInputContainerDirective)
.directive('label', labelDirective)
.directive('input', inputDirective)
.directive('textarea', inputDirective);
.directive('input', inputTextareaDirective)
.directive('textarea', inputTextareaDirective);

/**
* @ngdoc directive
Expand Down Expand Up @@ -86,7 +86,7 @@ function labelDirective() {
};
}

function inputDirective($mdUtil) {
function inputTextareaDirective($mdUtil, $window) {
return {
restrict: 'E',
require: ['^?mdInputContainer', '?ngModel'],
Expand All @@ -104,6 +104,10 @@ function inputDirective($mdUtil) {

if ( !containerCtrl ) return;

if (element[0].tagName.toLowerCase() === 'textarea') {
setupTextarea();
}

if (containerCtrl.input) {
throw new Error("<md-input-container> can only have *one* <input> or <textarea> child element!");
}
Expand Down Expand Up @@ -143,10 +147,41 @@ function inputDirective($mdUtil) {
containerCtrl.input = null;
});

function isNotEmpty(value) {
value = angular.isUndefined(value) ? element.val() : value;
return (angular.isDefined(value) && (value!==null) &&
(value.toString().trim() !== ""));
function setupTextarea() {
var node = element[0];

if (ngModelCtrl) {
ngModelCtrl.$formatters.push(growTextarea);
ngModelCtrl.$parsers.push(growTextarea);
} else {
element.on('input', growTextarea);
growTextarea();
}
element.on('keydown', growTextarea);

This comment has been minimized.

Copy link
@gkalpak

gkalpak Jan 9, 2015

Member

@ajoslin: Why is this needed ?

element.on('scroll', onScroll);
angular.element($window).on('resize', growTextarea);

scope.$on('$destroy', function() {
angular.element($window).off('resize', growTextarea);
});

function growTextarea(value) {
node.style.height = "auto";
var line = node.scrollHeight - node.offsetHeight;
node.scrollTop = 0;
height = node.offsetHeight + (line > 0 ? line : 0);

This comment has been minimized.

Copy link
@gkalpak

gkalpak Jan 9, 2015

Member

@ajoslin: Or simply height = Math.max(node.offsetHeight, node.scrollHeight);...

node.style.height = height + 'px';

return value; // for $formatter/$parser
}

function onScroll(e) {
node.scrollTop = 0;
// for smooth new line adding
var line = node.scrollHeight - node.offsetHeight;
height = node.offsetHeight + line;

This comment has been minimized.

Copy link
@gkalpak

gkalpak Jan 9, 2015

Member

@ajoslin: Or simply height = node.scrollHeight; 😃
Is height needed as a global var ?

node.style.height = height + 'px';
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/components/input/input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ md-input-container {
-moz-appearance: none;
-webkit-appearance: none;
}
textarea {
resize: none;
overflow: hidden;
}

label {
order: 1;
Expand Down

1 comment on commit 1c65369

@yarl
Copy link
Contributor

@yarl yarl commented on 1c65369 Jan 9, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need additional CSS code for IE10, otherwise autoresize is not working.

md-input-container textarea.md-input {
    -ms-flex-preferred-size: auto;
}

Please sign in to comment.