Skip to content

Commit

Permalink
fix(textarea): fix textarea grow
Browse files Browse the repository at this point in the history
  • Loading branch information
devversion committed Jan 5, 2016
1 parent 8ef798f commit 101b1bc
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 11 deletions.
28 changes: 28 additions & 0 deletions src/components/input/demoTextarea/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<div layout="column" ng-cloak class="md-inline-form" ng-init="textBind = 'Input is binded to a Model'">

<md-content layout-padding>

<div class="demoTextarea">
<md-input-container class="md-block">
<label>Fixed Rows</label>
<textarea rows="5" ng-model="textBind">This is an example Content</textarea>
</md-input-container>
</div>

<div class="demoTextarea">
<md-input-container class="md-block">
<label>Minimum Rows</label>
<textarea min-rows="5" ng-model="textBind"></textarea>
</md-input-container>
</div>

<div class="demoTextarea">
<md-input-container class="md-block">
<label>Dynamic Rows</label>
<textarea>This is an example Content</textarea>
</md-input-container>
</div>

</md-content>

</div>
2 changes: 2 additions & 0 deletions src/components/input/demoTextarea/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
angular
.module('inputTextareaDemo', ['ngMaterial', 'ngMessages']);
4 changes: 4 additions & 0 deletions src/components/input/demoTextarea/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.demoTextarea {
margin: 14px;
background-color: #f7f7f7;
}
42 changes: 31 additions & 11 deletions src/components/input/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,31 +323,36 @@ function inputTextareaDirective($mdUtil, $window, $mdAria) {
var node = element[0];
var container = containerCtrl.element[0];

var min_rows = NaN;
var rows = NaN;
var minRows = NaN;
var lineHeight = null;
// can't check if height was or not explicity set,
// so rows attribute will take precedence if present
if (node.hasAttribute('rows')) {
min_rows = parseInt(node.getAttribute('rows'));
rows = parseInt(node.getAttribute('rows'));
} else if (node.hasAttribute('min-rows')) {
minRows = parseInt(node.getAttribute('min-rows'));
}

var onChangeTextarea = $mdUtil.debounce(growTextarea, 1);
var onChangeTextarea = $mdUtil.debounce(function() {
$mdUtil.nextTick(growTextarea);
}, 1);

function pipelineListener(value) {
onChangeTextarea();
return value;
}

if (ngModelCtrl) {
if (hasNgModel) {
ngModelCtrl.$formatters.push(pipelineListener);
ngModelCtrl.$viewChangeListeners.push(pipelineListener);
} else {
onChangeTextarea();
}
element.on('keydown input', onChangeTextarea);

if (isNaN(min_rows)) {
element.attr('rows', '1');
if (isNaN(rows)) {
element.attr('rows', isNaN(minRows) ? '1' : minRows);

element.on('scroll', onScroll);
}
Expand All @@ -365,12 +370,13 @@ function inputTextareaDirective($mdUtil, $window, $mdAria) {
// temporarily disables element's flex so its height 'runs free'
element.addClass('md-no-flex');

if (isNaN(min_rows)) {
var contentHeight;
if (isNaN(rows) || !isNaN(minRows)) {
node.style.height = "auto";
node.scrollTop = 0;
var height = getHeight();
if (height) node.style.height = height + 'px';
} else {
contentHeight = getHeight();
}
if (!isNaN(rows) || !isNaN(minRows)) {
node.setAttribute("rows", 1);

if (!lineHeight) {
Expand All @@ -381,8 +387,22 @@ function inputTextareaDirective($mdUtil, $window, $mdAria) {
node.style.minHeight = null;
}

var rows = Math.min(min_rows, Math.round(node.scrollHeight / lineHeight));
node.setAttribute("rows", rows);
}

if (isNaN(rows)) {
if (!isNaN(minRows) && contentHeight) {
var calcHeight;
var minHeight = lineHeight * minRows;

if (contentHeight <= minHeight) calcHeight = minHeight;
else calcHeight = minHeight + (contentHeight - minHeight);

node.style.height = calcHeight + "px";
} else if (contentHeight) {
node.style.height = contentHeight + 'px';
}
} else {
node.style.height = lineHeight * rows + "px";
}

Expand Down
84 changes: 84 additions & 0 deletions src/components/input/input.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,5 +418,89 @@ describe('md-input-container directive', function() {
var newHeight = textarea.offsetHeight;
expect(textarea.offsetHeight).toBeGreaterThan(oldHeight);
});

it('should not grow or shrink the textarea with rows attribute', function() {
var rows = 5;
createAndAppendElement('rows="' + rows +'"');

textarea.style.minHeight = '0';
var lineHeight = ngTextarea.prop('clientHeight');
textarea.style.minHeight = null;

ngTextarea.val('Multiple\nlines\nof\ntext');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

expect(textarea.style.height).toBe(rows * lineHeight + "px");
});

it('should grow and shrink the textarea without any attribute', function() {
createAndAppendElement();
var lastHeight;

ngTextarea.val('Multiple\nlines\nof\ntext\nwhich\ncontains\neight\nlines');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

lastHeight = textarea.scrollHeight;
expect(textarea.style.height).toBe(lastHeight + "px");

ngTextarea.val('Multiple\nlines\nof\ntext');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

expect(textarea.style.height).toBeLessThan(lastHeight + "px");
lastHeight = textarea.scrollHeight;

ngTextarea.val('Multiple\nlines\nof\ntext\nwhich\ncontains\neight\nlines\nplus\nmore');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

expect(textarea.style.height).toBeGreaterThan(lastHeight + "px");
});

it("should grow the textarea with min-rows attribute", function() {
var rows = 3;
var lastHeight;
createAndAppendElement('min-rows="' + rows +'"');

textarea.style.minHeight = '0';
var lineHeight = ngTextarea.prop('clientHeight');
textarea.style.minHeight = null;

ngTextarea.val('Multiple\nlines');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

var minHeight = lastHeight = rows * lineHeight;
expect(textarea.style.height).toBe(lastHeight + "px");

ngTextarea.val('Multiple\nlines\nof\ntext\nwhich\ngot\nincreased');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

expect(parseInt(textarea.style.height)).toBeGreaterThan(lastHeight);

ngTextarea.val('Multiple\nlines');
ngTextarea.triggerHandler('input');

scope.$apply();
$timeout.flush();

expect(textarea.style.height).not.toBeLessThan(minHeight);
});

});
});

0 comments on commit 101b1bc

Please sign in to comment.