Possible to scroll caret into view inside a single

2020-05-22 20:03发布

问题:

Knowing the jQuery Caret plugin, I'm still seeing no way to do the following on a single line text box in HTML (i.e. the input:type=text control) with JavaScript:

  1. Programmatically inserting text into a text box
  2. Setting the caret to the end.
  3. Making the caret visible (i.e. scroll the text box content)

I know how to do 1. and 2., just for 3. I have found no way of doing it.

To illustrate it:

My question is:

Is there any way to reliable put the caret at the end of the text and scroll it into the view?

(I can think of simulating pressing the END key or something like that, but I'm unsure whether this would be the best option).

回答1:

//hack to get cursor at end:

$(textboxselector).val($(textboxselector).val());

edit: should note focus first:

$(textboxselector).val(newtext);
$(textboxselector).focus();
$(textboxselector).val($(textboxselector).val());


回答2:

You could try triggering a right key press after focus.

$('#textbox').focus();
var e = jQuery.Event("keydown");
e.which = 39; // aka right arrow.
$("input").trigger(e);


回答3:

try to set the scrollLeft property of the input, as:

input.scrollLeft = 10000;

You can use scrollWidth to get a better guess on the final value, but using a high one can ensure correctness on most cases.



回答4:

It's not possible to implement this behavior cross-browser. FireFox supports the KeyboardEvent.initKeyPress method, which allows key events to be simulated.

See the comments at the function below for an explanation. I've successfully tested this function in FireFox 3.6.22, 7.0.1 and Chrome 14.

The function itself is plugin-independent. Fiddle: http://jsfiddle.net/Jskbb/1/

/* @name caretAtEnd
 * @description Places caret at the end
 * @param elem  DOM element
 * @param focus boolean, optional. If true, the element will be focused.
 */
function caretAtEnd(elem, focus){
    var value = elem.value;

    //Add an extra character to the input field (necessary for this method)
    // An additional advantage is that the caret automatically moves to the end
    elem.value = elem.value + ".";

    try {
        // Create and simulate/trigger a [Backspace] keypress event.
        var evt = document.createEvent("KeyboardEvent");
        evt.initKeyEvent("keypress", 1, 1, null, 0, 0, 0, 0, 8, 0);
        elem.dispatchEvent(evt);
    } catch(e){
        //The current key event is not supported yet. Change back the value
        // In some browsers, the caret is at the end after executing this code.
        elem.value = value;
    }

    //Optionally, Focus on the element
    if(focus) elem.focus();
}

var element = $("#yourInputElement")[0]; //Important: Get the DOM element!
caretAtEnd(element);


回答5:

So with the help of Mark and Rob W, I finally managed to solve it.

My additional challenge was that the text box already has the focus, which came out is an issue (I'm using the whole stuff in the OnClientItemSelected of the Ajax Toolkit's AutoCompleteExtender).

So my solution is:

<ajaxToolkit:AutoCompleteExtender 
    runat="server" 
    ID="EMailTextBoxControlAutoCompleteExtender" 

    ...

    OnClientItemSelected="function() { 
        // Read current text and append some string.
        var tbSel = '#EMailTextBoxControl';
        var newText = $(tbSel).val() + ', ';

        // Since we already have the focus, 
        // remove it and set it to another control.
        $('#AdditionalRemarksControl').focus();

        // https://stackoverflow.com/questions/7892902/7903519#7903519
        $(tbSel).val(newText);
        $(tbSel).focus();
        $(tbSel).val($(tbSel).val());
    }">

It's working for me successfully in Google Chrome, Firefox and Internet Explorer 9. Hopefully it works in other browsers, too.

I'm marking Mark's comment as the answer.



回答6:

If you want to put the caret at the end and scroll to the bottom of a textarea, this works perfectly :

function moveCaretToEnd(el) {
    if (typeof el.selectionStart == "number") {
        el.selectionStart = el.selectionEnd = el.value.length;
    } else if (typeof el.createTextRange != "undefined") {
        el.focus();
        var range = el.createTextRange();
        range.collapse(false);
        range.select();
    }
   setTimeout(function(){
        var pos = $(el).offset().top + $(el).height();
        $('html, body').animate({
            scrollTop: pos
        }, 1000);
    },100);
}

moveCaretToEnd(document.getElementById("replyBox"));

It will place the caret at the end, and then smoothly scroll the window to the bottom.