0

So I have a problem with this auto-resize function I grabbed off the internet (By Adam Beres-Deak). Everything works perfectly except one small problem; say the textarea has 100 lines (or more than the page can fit) and say you go and edit something in the middle, the screen will jump all the way up to make the text RIGHT at the bottom of your browser/screen.

Example: Example of the probme.

(function(){
    function adjustHeight(el, minHeight){
        var outerHeight = parseInt(window.getComputedStyle(el).height, 10);
        var diff = outerHeight - el.clientHeight;
        el.style.height = 0;
        el.style.height = Math.max(minHeight, el.scrollHeight + diff) + 'px';
    }
        
    var textAreas = [].slice.call(document.querySelectorAll('textarea[data-adaptheight]'));
    textAreas.forEach(function(el){
        el.style.boxSizing = el.style.mozBoxSizing = 'border-box';
        el.style.overflow = 'hidden';
        var minHeight = el.scrollHeight;
        el.addEventListener('input', function(){
            adjustHeight(el, minHeight);
        });
        window.addEventListener('resize', function(){
            adjustHeight(el, minHeight);
        });
        adjustHeight(el, minHeight);
    });
}());
<textarea data-adaptheight rows="2" cols="40" placeholder="Your input" style="padding: 7px; line-height: 1.5;width: 100%;display: block;"></textarea>

Does anybody have any idea what can be causing this? Im not the greatest at javascript, but I did try to look it over and see what could be causing it but I had no success.

Would greatly appreciate the help guys, Thank you!


Answer:

After reviewing the answer on question: https://stackoverflow.com/a/18262927/13231904

I was able to merge the code from this question with the code from that answer for a very effective function:

if(window.attachEvent){
    observe = function(element, event, handler){ element.attachEvent('on'+event, handler); };
}else{
    observe = function(element, event, handler){ element.addEventListener(event, handler, false); };
}
function init(){
    var textAreas = [].slice.call(document.querySelectorAll('textarea[data-adaptheight]'));
    textAreas.forEach(function(el){
        function resize(){
            var scrollLeft = window.pageXOffset ||
                (document.documentElement || document.body.parentNode || document.body).scrollLeft;
            var scrollTop = window.pageYOffset ||
                (document.documentElement || document.body.parentNode || document.body).scrollTop;
            el.style.resize = "none";
            el.style.overflow = 'hidden';
            el.style.boxSizing = el.style.mozBoxSizing = 'border-box';
            el.style.height = "auto";
            el.style.height = el.scrollHeight + 'px';
            window.scrollTo(scrollLeft, scrollTop);
        }
        observe(el, 'input', resize);
        resize();
    });
}
init();
<textarea data-adaptheight style="padding: 7px;width: 100%;display: block;" rows="1" cols="40" placeholder="Your input">
</textarea>
Crimin4L
  • 610
  • 2
  • 8
  • 23
  • This is the normal behavior of the browser. It has nothing to do with the script. – BOZ Feb 05 '21 at 18:29
  • @BOZ But It doesn't seem to happen on other websites when In a textarea? Even on the website I got the code from, it has an example and it doesn't do it. – Crimin4L Feb 05 '21 at 18:32
  • 1
    You should have made a new answer and accepted it, that way others see the question has an answer. This is definitely a better and more feature rich solution than my hacky one. Happy coding. – sxkx Feb 05 '21 at 21:08
  • I cant; I already associated this question with another so it rendered it as duplicate. Hopefully the edit does just as good, I also threw the code in the linked question as an answer aswell: https://stackoverflow.com/a/66070525/13231904 Happy coding bud :) – Crimin4L Feb 05 '21 at 21:12

2 Answers2

2

The problem is this line of code:

el.style.height = 0;

It sets the height of the textarea to zero, the browser then renders the textarea to that size which reduces the height of the browser window back to the screen size making the scroll position 0, or the very top.

The code:

el.style.height = Math.max(minHeight, el.scrollHeight + diff) + 'px';

then resizes the textarea back to the size necessary to fit all text and scrolls the browser windows so far down to just show the current cursor position, which is why you will always be as far down as possible in the browser screen.

You can fix the problem by restoring the window scroll position to the value before the textarea's height was set to 0. See this answer for how to do that.

John Caprez
  • 393
  • 2
  • 10
  • the crazy part is, when I was typing the question I was looking at that the code and more importantly the line of code itself & wondering if it could be that line because that is really the only line I wondered why it was it there. haha THANKS! <3 <3 <3 – Crimin4L Feb 05 '21 at 18:37
  • True. The right solution seems to be to restore the scroll position of the window as mentioned in a comment above. – John Caprez Feb 05 '21 at 18:41
  • Actually, that line is there to reset it for when a newline is deleted. (https://i.imgur.com/R6r2cw1.gif) So what I did was instead of taking out `el.style.height = 0;` i did `el.style.height = 50;` (https://i.imgur.com/xZns4OP.gif | https://i.imgur.com/IvGM3Hd.gif). And now it works like a charm! I can delete the new line and when I add new lines or characters it does NOT jump anymore! Thank you still because you're the one who confirmed my suspicions about that piece of code! Cheers11 – Crimin4L Feb 05 '21 at 18:52
  • Actually, the above fix i included didn't work either. Back to square one! haha :P – Crimin4L Feb 05 '21 at 19:05
0

I came to the same conclusion as John Caprez, tried setting el.style.height to el.clientHeight like so:

el.style.height = el.clientHeight + 'px';

This would grow the text area but wouldn't shrink it when you removed the text.

Did some web searches and found this; ccs-tricks.com - Auto-Growing Inputs & Textareas.

It grows, shrinks and doesn't jump all over the place when you want to make edits somewhere else but the end of your text.

// Dealing with Textarea Height
function calcHeight(value, minHeight, lineHeight, padding, border) {
  let numberOfLineBreaks = (value.match(/\n/g) || []).length;
  // min-height + lines x line-height + padding + border
  let newHeight = minHeight + numberOfLineBreaks * lineHeight + padding + border;
  return newHeight;
}

let textarea = document.querySelector(".resize-ta");
textarea.addEventListener("keyup", () => {
  let style = window.getComputedStyle(textarea);
  let lineHeight = parseFloat(style.getPropertyValue('line-height'));
  let paddingTop = parseFloat(style.getPropertyValue('padding-top'));
  let paddingBottom = parseFloat(style.getPropertyValue('padding-bottom'));
  let minHeight = parseFloat(style.getPropertyValue('min-height'));
  let borderTopWidth = parseFloat(style.getPropertyValue('border-top-width'));
  let borderBottomWidth = parseFloat(style.getPropertyValue('border-top-width'));
  textarea.style.height = calcHeight(textarea.value, minHeight, lineHeight, paddingTop + paddingBottom, borderTopWidth + borderBottomWidth) + "px";
});
.resize-ta{
  font-size:16px;
  line-height:1.5; /* MUST BE EXPLICITLY SET, decimal or float */
  overflow-y:hidden;
  min-height:60px;
  padding:0;
}
<textarea class="resize-ta" placeholder="Your input"></textarea>
sxkx
  • 512
  • 5
  • 13
  • that code doesn't really work well. Calculations are off causing textarea change to different sizes when entering in new or deleting lines – Crimin4L Feb 05 '21 at 19:07
  • 1
    Crimin4L, well spotted. Redid the code to take into account the CSS variables. – sxkx Feb 05 '21 at 19:44
  • I ended up using the code from another linked question (https://stackoverflow.com/a/18262927/13231904) and editing the code for my purposes. I will be posting my code as the answer shortly, as it works flawlessly now! – Crimin4L Feb 05 '21 at 20:34
  • 1
    Took a look at the link and fiddle, looks good indeed. – sxkx Feb 05 '21 at 20:44
  • Nah that code was too much useless crap, and had a delay for whatever reason so I edited a lot out for efficiency. You can see the new code in the OP, I just updated it. – Crimin4L Feb 05 '21 at 20:58