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

textarea: long textarea causes scroll jumping issues #3070

Open
asans opened this issue Jun 1, 2015 · 42 comments
Open

textarea: long textarea causes scroll jumping issues #3070

asans opened this issue Jun 1, 2015 · 42 comments
Assignees
Labels
- Lots of Comments needs: investigation The cause of this issue is not well understood and needs to be investigated by the team or community os: Windows This issue is specific to Windows P3: important Important issues that really should be fixed when possible. severity: inconvenient type: bug ux: polish
Milestone

Comments

@asans
Copy link

asans commented Jun 1, 2015

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.

@mckenzielong
Copy link
Contributor

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.

@mckenzielong
Copy link
Contributor

Also, this is a dupe of #3024

@orange-buffalo
Copy link

@mckenzielong, I applied the fix you proposed for my application and textarea behaves fine now. Thank you!

@WhiteAbeLincoln
Copy link

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.

plunker

@WhiteAbeLincoln
Copy link

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

@kamarouski
Copy link

👍 have the same issue in my project as well. Looking forward to the official fix.

@DevinHolland
Copy link

Same problem here. @mckenzielong This fix worked, thank you! Hope this fix makes it into the repo soon.

@mckenzielong
Copy link
Contributor

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, '&amp;').replace(/"/gm, '&quot;')
    .replace(/'/gm, '&#39;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;').split('\n');
  while (rows > tokens.length) {
    tokens.push('');
  }

  mirror.html(tokens.join('<br>') + '&nbsp;');
}

@asans
Copy link
Author

asans commented Jul 4, 2015

This issue didn't get closed, but I assume this should be addressed and fixed by commit:

5fdcf90

Whether new bugs appear is likely a separate story.

@asans asans closed this as completed Jul 4, 2015
@mckenzielong
Copy link
Contributor

Please reopen. The issue still present in demo, same root cause:

node.style.height = "auto";

@asans asans reopened this Jul 4, 2015
@asans
Copy link
Author

asans commented Jul 4, 2015

Reopened.

@sagidayan
Copy link

sagidayan commented Jul 19, 2015

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

@ThomasBurleson ThomasBurleson modified the milestones: 1.0-rc1, 1.0-rc2, 1.0-rc3 Oct 27, 2015
@ThomasBurleson ThomasBurleson modified the milestones: 1.0-rc3, 1.0-rc4 Nov 7, 2015
@jonBennevall
Copy link

@ricardosaracino Your IE11 hack unfortunately doesn't work for me. :/ We also tried event.stopPropagation() on keydown and keyup whithout success. We had the same issue with scroll jumping in long textareas when clicking inside the textarea in IE11. We solved that problem with event.stopPropagation() on the click event.

@Splaktar Splaktar modified the milestones: 1.1.13, 1.1.14 Feb 10, 2019
@riyajk
Copy link

riyajk commented Feb 13, 2019

Reopened.

The issue still exists

@Splaktar Splaktar removed their assignment Feb 23, 2019
@Splaktar Splaktar modified the milestones: 1.1.14, - Backlog Feb 23, 2019
@Splaktar
Copy link
Member

Splaktar commented Apr 1, 2019

Just FYI, this likely won't be fixed unless someone from the community comes up with a fix and opens a PR for it. I will be happy to help support, verify the fix, and work to get it merged, but I will be focused on P1-P2 issues for the next few months.

@saurabhsingh1003

This comment has been minimized.

@Splaktar

This comment has been minimized.

@Splaktar Splaktar self-assigned this Sep 20, 2020
@Splaktar Splaktar added the P3: important Important issues that really should be fixed when possible. label Sep 20, 2020
@Splaktar Splaktar modified the milestones: - Backlog, 1.2.2 Sep 20, 2020
@Splaktar Splaktar removed the P4: minor Minor issues. May not be fixed without community contributions. label Sep 20, 2020
@Splaktar
Copy link
Member

I just tried to reproduce this on iOS (iPad OS 14.0) using Safari 14, but I was not able to do so on https://material.angularjs.org/1.2.0/demo/input#basic-usage.

If anyone can provide a reproduction demo and steps for iOS, please let me know.

I'll try to take a look on Windows soon.

@Splaktar
Copy link
Member

Here the codepen, http://codepen.io/kiro64/pen/gPOmxp
on my codepen safari is work fine, but still have an issue on firefox

I tried to reproduce this on macOS using Firefox 80.0.1 with an updated CodePen but I was not able to reproduce it. I had to fix up the CodePen a bit to get it to render properly since the way that md-input-container was being used wasn't correct. But auto growing was working fine w/o any jumping on Firefox and Chrome.

@justusromijn
Copy link

justusromijn commented Dec 1, 2021

Just want to chip in here, not related to angular material, but a native solution to this scrolling issue with auto-height trigger to do a calculation. What I've done, is before setting the height to auto for the textarea, have another element next to it take over the current height, and when the new height is calculated, apply this also to that other element. This way, the space stays reserved and the page won't notice a height-drop when setting the textarea to auto. You could see this as some sort of memoization pattern for the height :)

Pseudo code below:

<textarea id="my-textarea" />
<div id="my-textarea-stub" />
calculateTextareaHeight() {
const textarea = document.querySelector('#my-textarea');
const textareaStub = document.querySelector('#my-textarea-stub');
// store the reserved height in our stub element before setting "auto"
textareaStub.style.height = textarea.style.height;
textarea.style.height = 'auto';

// some real calculations here...
let someCalculatedHeight = 2000;

// reset the textarea height, and after that, reset the stub height
textarea.style.height = `${someCalculatedHeight}px`;
textareaStub.style.height = textarea.style.height;

@codeunifier
Copy link

Seeing this issue as well in Catalina / Safari 14 using an angular directive to manually change the textarea height.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
- Lots of Comments needs: investigation The cause of this issue is not well understood and needs to be investigated by the team or community os: Windows This issue is specific to Windows P3: important Important issues that really should be fixed when possible. severity: inconvenient type: bug ux: polish
Projects
None yet
Development

No branches or pull requests