mirror of https://github.com/zulip/zulip.git
compose: Ensure cursor is scrolled into view after content is inserted.
This fixes the bug where on pressing enter after the last line in a textarea, the cursor would go to the new line but the textarea would not scroll it into view unless more was typed. This was observed on chromium browsers. A new function `insert_and_scroll_into_view` is added to `compose_ui.js` which blurs and refocuses the textarea after inserting the content, then autosizes the textarea.
This commit is contained in:
parent
acdae9eae2
commit
0cdb54cf65
|
@ -35,6 +35,14 @@ export function autosize_textarea($textarea) {
|
|||
}
|
||||
}
|
||||
|
||||
export function insert_and_scroll_into_view(content, $textarea) {
|
||||
insert($textarea[0], content);
|
||||
// Blurring and refocusing ensures the cursor / selection is in view.
|
||||
$textarea.trigger("blur");
|
||||
$textarea.trigger("focus");
|
||||
autosize_textarea($textarea);
|
||||
}
|
||||
|
||||
function get_focus_area(msg_type, opts) {
|
||||
// Set focus to "Topic" when narrowed to a stream+topic and "New topic" button clicked.
|
||||
if (msg_type === "stream" && opts.stream_id && !opts.topic) {
|
||||
|
@ -99,8 +107,7 @@ export function smart_insert_inline($textarea, syntax) {
|
|||
syntax += " ";
|
||||
}
|
||||
|
||||
insert($textarea[0], syntax);
|
||||
autosize_textarea($textarea);
|
||||
insert_and_scroll_into_view(syntax, $textarea);
|
||||
}
|
||||
|
||||
export function smart_insert_block($textarea, syntax, padding_newlines = 2) {
|
||||
|
@ -146,8 +153,7 @@ export function smart_insert_block($textarea, syntax, padding_newlines = 2) {
|
|||
const new_lines_needed_after_count = padding_newlines - new_lines_after_count;
|
||||
syntax = syntax + "\n".repeat(new_lines_needed_after_count);
|
||||
|
||||
insert($textarea[0], syntax);
|
||||
autosize_textarea($textarea);
|
||||
insert_and_scroll_into_view(syntax, $textarea);
|
||||
}
|
||||
|
||||
export function insert_syntax_and_focus(
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import $ from "jquery";
|
||||
import _ from "lodash";
|
||||
import {insert} from "text-field-edit";
|
||||
|
||||
import * as typeahead from "../shared/src/typeahead";
|
||||
import render_topic_typeahead_hint from "../templates/topic_typeahead_hint.hbs";
|
||||
|
@ -165,8 +164,7 @@ function handle_bulleting_or_numbering($textarea, e) {
|
|||
// below we select and replace the last 2 characters in the textarea before
|
||||
// the cursor - the bullet syntax - with an empty string
|
||||
$textarea[0].setSelectionRange($textarea.caret() - 2, $textarea.caret());
|
||||
insert($textarea[0], "");
|
||||
compose_ui.autosize_textarea($textarea);
|
||||
compose_ui.insert_and_scroll_into_view("", $textarea);
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
@ -183,8 +181,7 @@ function handle_bulleting_or_numbering($textarea, e) {
|
|||
$textarea.caret() - previous_number_string.length - 2,
|
||||
$textarea.caret(),
|
||||
);
|
||||
insert($textarea[0], "");
|
||||
compose_ui.autosize_textarea($textarea);
|
||||
compose_ui.insert_and_scroll_into_view("", $textarea);
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
@ -194,8 +191,7 @@ function handle_bulleting_or_numbering($textarea, e) {
|
|||
// if previous line was neither numbered nor bulleted, only add
|
||||
// a new line to emulate default behaviour (to_append is blank)
|
||||
// else we add the bulleting / numbering syntax to the new line
|
||||
insert($textarea[0], "\n" + to_append);
|
||||
compose_ui.autosize_textarea($textarea);
|
||||
compose_ui.insert_and_scroll_into_view("\n" + to_append, $textarea);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
|
@ -217,8 +213,7 @@ export function handle_enter($textarea, e) {
|
|||
if ($textarea[0].selectionStart !== $textarea[0].selectionEnd) {
|
||||
// Replace it with the newline, remembering to resize the
|
||||
// textarea if needed.
|
||||
insert($textarea[0], "\n");
|
||||
compose_ui.autosize_textarea($textarea);
|
||||
compose_ui.insert_and_scroll_into_view("\n", $textarea);
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// if nothing had been selected in the texarea we
|
||||
|
|
|
@ -80,6 +80,8 @@ function make_textbox(s) {
|
|||
return $widget.s;
|
||||
};
|
||||
|
||||
$widget.trigger = noop;
|
||||
|
||||
return $widget;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ const noop = () => {};
|
|||
|
||||
let autosize_called;
|
||||
|
||||
mock_esm("../src/compose_ui", {
|
||||
const compose_ui = mock_esm("../src/compose_ui", {
|
||||
autosize_textarea() {
|
||||
autosize_called = true;
|
||||
},
|
||||
|
@ -52,7 +52,6 @@ const compose_pm_pill = zrequire("compose_pm_pill");
|
|||
const compose_recipient = zrequire("compose_recipient");
|
||||
const composebox_typeahead = zrequire("composebox_typeahead");
|
||||
const settings_config = zrequire("settings_config");
|
||||
const text_field_edit = mock_esm("text-field-edit");
|
||||
const pygments_data = zrequire("../generated/pygments_data.json");
|
||||
|
||||
const ct = composebox_typeahead;
|
||||
|
@ -1161,8 +1160,8 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
|||
selectionStart: 0,
|
||||
selectionEnd: 0,
|
||||
};
|
||||
override(text_field_edit, "insert", (_textarea, syntax) => {
|
||||
assert.equal(syntax, "\n");
|
||||
override(compose_ui, "insert_and_scroll_into_view", (content, _textarea) => {
|
||||
assert.equal(content, "\n");
|
||||
});
|
||||
$("#compose-textarea").caret = () => $("#compose-textarea")[0].selectionStart;
|
||||
|
||||
|
@ -1189,8 +1188,8 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
|||
$("#compose-textarea").val("- List item 1\n- List item 2");
|
||||
$("#compose-textarea")[0].selectionStart = 27;
|
||||
$("#compose-textarea")[0].selectionEnd = 27;
|
||||
override(text_field_edit, "insert", (_textarea, syntax) => {
|
||||
assert.equal(syntax, "\n- ");
|
||||
override(compose_ui, "insert_and_scroll_into_view", (content, _textarea) => {
|
||||
assert.equal(content, "\n- ");
|
||||
});
|
||||
$("form#send_message_form").trigger(event);
|
||||
|
||||
|
@ -1202,8 +1201,8 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
|||
assert.equal(start, 28);
|
||||
assert.equal(end, 30);
|
||||
};
|
||||
override(text_field_edit, "insert", (_textarea, syntax) => {
|
||||
assert.equal(syntax, "");
|
||||
override(compose_ui, "insert_and_scroll_into_view", (content, _textarea) => {
|
||||
assert.equal(content, "");
|
||||
});
|
||||
$("form#send_message_form").trigger(event);
|
||||
|
||||
|
@ -1211,8 +1210,8 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
|||
$("#compose-textarea").val("1. List item 1\n2. List item 2");
|
||||
$("#compose-textarea")[0].selectionStart = 29;
|
||||
$("#compose-textarea")[0].selectionEnd = 29;
|
||||
override(text_field_edit, "insert", (_textarea, syntax) => {
|
||||
assert.equal(syntax, "\n3. ");
|
||||
override(compose_ui, "insert_and_scroll_into_view", (content, _textarea) => {
|
||||
assert.equal(content, "\n3. ");
|
||||
});
|
||||
$("form#send_message_form").trigger(event);
|
||||
|
||||
|
@ -1224,16 +1223,16 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
|||
assert.equal(start, 30);
|
||||
assert.equal(end, 33);
|
||||
};
|
||||
override(text_field_edit, "insert", (_textarea, syntax) => {
|
||||
assert.equal(syntax, "");
|
||||
override(compose_ui, "insert_and_scroll_into_view", (content, _textarea) => {
|
||||
assert.equal(content, "");
|
||||
});
|
||||
$("form#send_message_form").trigger(event);
|
||||
|
||||
$("#compose-textarea").val("A");
|
||||
$("#compose-textarea")[0].selectionStart = 4;
|
||||
$("#compose-textarea")[0].selectionEnd = 4;
|
||||
override(text_field_edit, "insert", (_textarea, syntax) => {
|
||||
assert.equal(syntax, "\n");
|
||||
override(compose_ui, "insert_and_scroll_into_view", (content, _textarea) => {
|
||||
assert.equal(content, "\n");
|
||||
});
|
||||
event.altKey = false;
|
||||
event.metaKey = true;
|
||||
|
|
|
@ -199,6 +199,9 @@ import {get_string_diff} from "../../src/util";
|
|||
// select / highlight the minimal text to be replaced
|
||||
this.$element[0].setSelectionRange(from, to_before);
|
||||
insert(this.$element[0], replacement);
|
||||
// Blurring and refocusing ensures the cursor is in view.
|
||||
this.$element.trigger("blur");
|
||||
this.$element.trigger("focus");
|
||||
}
|
||||
|
||||
return this.hide()
|
||||
|
|
Loading…
Reference in New Issue