material
material copied to clipboard
textarea: long textarea causes scroll jumping issues
Place a textarea
inside a content pane (ie. md-content
or md-dialog-content
). As one starts to create a very long message that span many rows and causes overflow to occur and scrollbars to show, one will notice that when you type anything, the scrollbar will jump to the top of the overflow content pane. If one tries to type text, the screen will jump down to the text (which is what the browser does automatically) but then the screen is immediately jumped back up to the top of the scrolling content.
The result is that you cannot see what you're typing once you get to a very long text message. Additionally, the scroll jumping causes headaches. Somewhere along the line, I think someone is doing some sort of scroll reset or setting the scrollTop.
You can duplicate this using the Demo on ngmaterial website.
https://material.angularjs.org/latest/#/demo/material.components.input
Simply keep creating new rows and making the overflown content type expand until it begins to jump.
This is happening because of this line in growTextarea():
node.style.height = "auto";
This handles the shrinking (and also expanding, but as far as I can see it is really here for shrinking) of the textarea by setting the height back to auto.
I took a stab at a fix for this today as it was interfering with a part of my project, and perhaps this will work for anyone looking for a temp fix... I have only tested this on webkit. In src/components/input/input.js:
Add the variable minTextAreaHeight to setupTextarea(), we will use this for saving the initial height to limit shrinking.
function setupTextarea() {
var node = element[0];
var onChangeTextarea = $mdUtil.debounce(growTextarea, 1);
var minTextareaHeight;
...
Adjust the scroll event listener to call the same textarea change function. Remove onScroll as it will no longer be needed.
element.on('scroll', onChangeTextarea);
growTextarea becomes:
function growTextarea() {
node.scrollTop = 0;
var height = getHeight();
if (height) node.style.height = height + 'px';
}
getHeight becomes:
function getHeight() {
var line = node.scrollHeight - node.offsetHeight;
var height = Number(window.getComputedStyle(node)["height"].replace("px", ""));
var lineHeight = Number(window.getComputedStyle(node)["line-height"].replace("px", ""));
var newHeight = height + (line >= 0 ? line : lineHeight*-1);
//cache the initial height that can be adjusted using 'rows'
if (!minTextareaHeight) {
minTextareaHeight = height
}
if (newHeight <= minTextareaHeight) {
return minTextareaHeight;
} else {
return newHeight;
}
}
As I mentioned, I am sure this is a better way of doing this.
Also, this is a dupe of #3024
@mckenzielong, I applied the fix you proposed for my application and textarea behaves fine now. Thank you!
This also happens when the textarea is in a tab container. When you don't have md-dynamic-height on, the jumping starts much sooner. When you do have md-dynamic-height applied to the tabs, then the scrollbar doesn't jump until it reaches the bottom of the mdcontent area.
I havent tried @mckenzielong's fix yet, but I'll update if it works for me.
@mckenzielong Your fixed worked for me, even in a tab container. There is still a slight jump when a newline is added (press enter key), but as soon as you start typing, the textarea focuses on the correct line, without jumps. I think that is reasonable, and isn't that annoying.
Another thing is if you select the content of the textarea and press the backspace, the content is deleted, including the newlines, but the textarea stays the same size. When you start typing again the content area shrinks everytime you hit a key, but there wasn't actually anything in the content area... This didn't happen with the old text area, but I don't find it to be too much of an issue.
here is a screenrecording of the issue
This isn't too much of an issue, and the textarea is a ton better after this fix, so I think this fix outweighs the minor new issues.
If this works in all of the use cases you can think of, and hasn't broken anything else, then I suggest you submit a pull request. I'm sure the developers would appreciate it, since they have 700+ open issues right now.
:+1: have the same issue in my project as well. Looking forward to the official fix.
Same problem here. @mckenzielong This fix worked, thank you! Hope this fix makes it into the repo soon.
Here is a different (better?) fix based on how iron-autogrow-textarea works. This gets rid of the case when the textarea doesn't collapse based on a large delete (as @WhiteAbeLincoln demonstrated above.) Again, I have only tested this on webkit.
First add the following css:
md-input-container .md-textarea-container {
display: inline-block;
position: relative;
padding:0;
border-bottom: none;
}
md-input-container .md-textarea-container textarea {
height: 100%;
position: absolute;
width: 100%;
padding:0;
}
md-input-container .md-textarea-container .md-textarea-mirror {
padding-top: 2px;
padding-left: 2px;
padding-right: 2px;
width: 100%;
min-height: 56px;
visibility: hidden;
word-wrap: break-word;
}
Next, in input.js, make the following changes: Change the scroll listener and remove onScroll
element.on('scroll', onChangeTextarea);
Adjust setupTextarea()
function setupTextarea() {
var mirror = angular.element('<div class="md-textarea-mirror"></div>');
var onChangeTextarea = $mdUtil.debounce(growTextarea, 1);
var minTextareaHeight;
element.wrap('<div class="md-textarea-container md-input"></div>');
element.after(mirror);
...
Adjust growTextarea()
function growTextarea() {
var rows = element.prop('rows');
//see https://github.com/PolymerElements/iron-autogrow-textarea/blob/master/iron-autogrow-textarea.html
var tokens = element.val().replace(/&/gm, '&').replace(/"/gm, '"')
.replace(/'/gm, ''').replace(/</gm, '<').replace(/>/gm, '>').split('\n');
while (rows > tokens.length) {
tokens.push('');
}
mirror.html(tokens.join('<br>') + ' ');
}
This issue didn't get closed, but I assume this should be addressed and fixed by commit:
https://github.com/angular/material/commit/5fdcf905b4355c0385a02f59d2875b93e7a18ce4
Whether new bugs appear is likely a separate story.
Please reopen. The issue still present in demo, same root cause:
node.style.height = "auto";
Reopened.
Just a small fix to @mckenzielong getHeight function. so that the text area will collapse to the right size after a massive deletion:
function getHeight() {
var line = node.scrollHeight - node.offsetHeight;
var height = Number(window.getComputedStyle(node)["height"].replace("px", ""));
var lineHeight = Number(window.getComputedStyle(node)["line-height"].replace("px", ""));
var newHeight = node.value.split('\n').length * lineHeight; //This Will set the new height to the number of lines in the Value of node
//cache the initial height that can be adjusted using 'rows'
if (!minTextareaHeight) {
minTextareaHeight = height;
}
if (newHeight <= minTextareaHeight) {
return minTextareaHeight;
} else {
return newHeight;
}
}
Hope this helps
@asans it seems to be fixed in HEAD, closing for now. if it's still happening please write here and i will reopen this issue.
Rel #3024 #2902
@EladBezalel i still have an issue when <md-input-contaner>
contain more than textarea
tag, such as md-icon
, auto grow and auto collapse don't work with firefox and safari. i'm using v1.0.0-rc6.
Please post a codepen so I can investigate further
@EladBezalel Here the codepen , http://codepen.io/kiro64/pen/gPOmxp on my codepen safari is work fine, but still have an issue on firefox i can't find v1.0.0-rc6 on cdn. so, i use 1.0.0-rc5 instead,
@robertmesserle can you take a look at this with Firefox?
Faced the same issue.Found the below solution which is working for me in IE 10 and chrome.
$(".Autoresizetextarea").on("input",function(){
//set the height
$("#textarea").focus();
})
This issue is closed as part of our ‘Surge Focus on Material 2' efforts. For details, see our forum posting @ http://bit.ly/1UhZyWs.
Is there any official suggestion on how to fix this bug? I didn't try the suggested fixes in this thread, are they still working on the version 1.1.1?
This behavior is really annoying for IE users...
I'm having a problem with this. Is there a reasonable hack to fix this problem available?
This issue still exists in ios mobile devices and we can see this problem in angular material demo with the version 1.1.1. Looking forward to official fix in the main repo!
I am still facing the same issue in IE in 1.1.3. Is the bug closed really and if so what is the version of material is it fixed?
Reopened as there are many reports of this still being a problem. Need to investigate.
Has this bug even been addressed. Or is there a clean way to solve it?
@shannahutch no, it hasn't been fixed yet. There are some workarounds mentioned above but no one has submitted a PR to fix this yet.
Based on the discussion here, it appears that this was caused by the auto grow enhancements in https://github.com/angular/material/commit/5fdcf905b4355c0385a02f59d2875b93e7a18ce4.
Can anyone provide some updated reproduction steps for this issue in 1.1.10
or HEAD
?
I just tested on various browsers and did not see any scroll jumping in the Input demo when adding lots of text to a textarea
. I had to resize the text area on Firefox and Safari as they appear to keep growing as more text is added unless you resize it to force a scrollbar. Either way, with or without the scrollbar, adding more text isn't causing me any scroll issues on these browsers on macOS:
- Chrome Version 71.0.3578.80 (Official Build) (64-bit)
- Safari Version 12.0.2 (14606.3.4)
- Firefox 63.0.3 (64-bit)
Is this only an issue now with iOS and/or IE11? Please confirm.
@Splaktar We see this a lot less now, but I am guessing that is because we made the move from BB10 devices to Android. The way chrome seems to handle this is a bit better.
That being said, you can still trigger a jump by pumping a bunch of newlines into the demo field (Chrome 71, Windows 10):
Edit: specify windows.
We have an elastic textarea. It works as long as the maxLength is small. In a few places maxLength="32000" this is when the issue happens. You can put 32000 in. However, if you save and come back you can delete but when you try to add the characters it jumps and won't add. This only takes place on ios devices.