Skip to content

prevent the cursor in Chrome's textarea from jumping to the top when the user inserts a newline #72

Closed

Description

@andrelsm

hi, WebCoder,

It's a Chromium(Blink)-based browsers misbehavior (bug?). But take a look at this:

https://www.debugcn.com/en/article/41179722.html

[ ] andrelsm

Activity

  1. KaiWilke commented on Dec 15, 2023

    @KaiWilke

    Solution is simple.

    1.) Intercept Enter onKey event
    2.) Save scrollTop value before calling execCommand to send Enter on behalf.
    3.) Calculate scrollTop after execCommand has been run.
    a.) Check if the current carrot position is above or below current scrollTop and adjust scrollTop to move the cursor back to the currently visible area.
    b.) If the current carrot position is still inside the visible area, then always restore the saved scrollTop position. This will have no effect at all, unless the jump bug occurs causing the annoying scrollTop change...

    Cheers, Kai

  2. andrelsm commented on Dec 15, 2023

    @andrelsm
    ContributorAuthor

    @KaiWilke I've added your code for indentation and brackets completion as a plugin and it fixed this browser misbehavior. Thanks a lot. (Please check my comment on the topic).

    my best regards, andrelsm

  3. KaiWilke commented on Dec 16, 2023

    @KaiWilke

    You mean your "enter on last line not working" comment?

    Cheers, Kai

  4. andrelsm commented on Dec 16, 2023

    @andrelsm
    ContributorAuthor
  5. KaiWilke commented on Dec 17, 2023

    @KaiWilke

    @andrelsm : I pointed out in my post, that the use of "Padding-Top" makes it hard to calculate the exact position the scrollTop has to move at the end of the visible area. My own solution does not use any paddings on the textarea window, so it does not add any offsets to account paddings.

    The relevant lines to handle the scrollTop at the end of the window are.

    		else if(cp>=st+ch)st=cp-ch+0.25;
    		EE.scrollTop=st;
    

    Which means if the calculated carrot position (aka. #lines*lineHeight) is greater than current scrollTop + clientHeight, than set new scrollTop to carrot position - clientHeight includings an hardcoded offset of 0.25 to get on an overage the same results as you would get when you hit the cursor-down key.

    If a Padding-Top of 10px is used, you may change the lines to become a...

       	else if(cp>=st+ch)st=cp-ch+0.25+10;
       	EE.scrollTop=st;
    

    ... you may want to tweak the +10 to give the same results as hitting cursor down.

    Note: I've tested it with different Padding-Top settings and never found a stable formular that will work with any given Padding-Top settings. At some point the calculated scrollTop started to not match the hitting cursor down position anymore. :-(

    BTW: I've attached my Prism/Textarea solution to show how the 'Enter' code works out with 0px Padding-Top. My Editor box is not based on code-input at all. Its purely based on the css-tricks.com posting made by @WebCoder49 back in the days, but then radically customized until i was happy with it. My 'Enter' intercepts are very different to the latest version of code-input. Play with both and you will notice the differences. Hold enter till 100 lines are created, move cursor at the very top again or somewhere in the middle and hold enter again, move cursor outside of the currently visible scrollTop (upper and lower) and hit enter again. Compare enter on last visible line with cursor down scolling. Try out enter between braces on last line or even outside of the currently visible scrollTop. Now change the size of the Textarea by either clicking on those +/- buttons or via drag'n'drop and try again. Working everything as expected? You may also want to try out my TAB'ing sequences. Compare the behavior with Notepad++ You miss anything? What would you change?

    Original Posting: https://css-tricks.com/creating-an-editable-textarea-that-supports-syntax-highlighted-code/

    Code-Input Auto-Intent: https://codepen.io/WebCoder49/pen/WNgdzar

    My F5 iRule Debug Page Solution: Debug Page.zip

    Cheers, Kai

  6. andrelsm commented on Dec 19, 2023

    @andrelsm
    ContributorAuthor
  7. WebCoder49 commented on Dec 19, 2023

    @WebCoder49
    Owner

    Thank you for this! I will look at it and implement it in the CSS-powered more lightweight scrolling that the library is using now once I return from holidays and hopefully release it in January 2024.

  8. andrelsm commented on Dec 19, 2023

    @andrelsm
    ContributorAuthor

    Happy holidays and happy new year!

  9. KaiWilke commented on Dec 19, 2023

    @KaiWilke

    @andrelsm

    I did a quick test with .blur() and .focus(). I changed my code to become this...

    	//let ch=EE.clientHeight,l=getComputedStyle(EE).lineHeight.slice(0,-2)*1,cp=(c.slice(0,s).split('\n').length+1+bb)*l;
    	//if(cp<st+l)st=cp-l*2-bb*l;
    	//else if(cp>=st+ch)st=cp-ch+0.25
    	//EE.scrollTop=st;
    	//EE.scrollLeft=0;
    	EE.blur();
    	EE.focus();
    

    It solves a lot of problems with as little as possible code. But it does not solve the Chrome bug and also causes additional unexpected carrot jumps to the center of the textarea (e.g. hitting enter between pair of baces on last line, if carrot is outside of the screen and somehow also sometimes in the middle of the screen which may be related to the chrome again).

    In the end, I prefer a stable editor and carrot position more than having as little as possible code footprint. So I'm gonna keep my rather complex scrollTop calculations to get a smooth scrolling behavior.

    Cheers, Kai

  10. KaiWilke commented on Dec 19, 2023

    @KaiWilke

    Happy holidays and happy new year too!

  11. andrelsm commented on Dec 19, 2023

    @andrelsm
    ContributorAuthor

    @KaiWilke

    try this

    st = ta.scrollTop;
    ...
    document.execCommand('insertText', false, r);
    ta.scrollTop = st;
    ta.blur(); ta.focus();
    

    (ta is your ele)

    it fixes chrome bug with no complex calculations. (Be aware that computed style lineHeight may be "normal" or etc.).

  12. KaiWilke commented on Dec 19, 2023

    @KaiWilke

    @andrelsm

    Works much better and also fixes the Chrome Bug. But it still causes some jumps to the center of the textarea, if you do:

    1.) Create empty lines until scrollbar kicks in, move carrot up a couple lines and then press enter again until you are back to last line. Then hit enter between two braces.

    2.) Hit enter on a line which is somewhere above/below currently visible textarea.

    Its up to you which behavior you like more, or if you are willing to add more code to handle those edge cases.

    Be aware that computed style lineHeight may be "normal" or etc.).

    My code is not a generic solution. Its pretty much tailored for my specific needs and I'm the only one who is changing any CSS. My productive code even skips getComputedStyle() and uses a fixed '15' for lineHeight calculations. But for Code-Input this should be definitely a thing to consider.

    Cheers, Kai

  13. WebCoder49 commented on Jan 20, 2024

    @WebCoder49
    Owner

    Another thing that seems to fix it (that I found by accident!):

    • Make the code-input element scrollable rather than the textarea.
    • This will be released in the next version of the library.
  14. andrelsm commented on Jan 22, 2024

    @andrelsm
    ContributorAuthor
  15. WebCoder49 commented on Feb 12, 2024

    @WebCoder49
    Owner

    Another thing that seems to fix it (that I found by accident!):

    • Make the code-input element scrollable rather than the textarea.
    • This will be released in the next version of the library.

    This has been implemented in pull request #76

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions