mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 06:23:38 +00:00
typeahead: Ignore mouse position for selection until it's moved.
Added a property `mouse_moved_since_typeahead` to the typeahead class which tracks whether the mouse has been moved since the typeahead menu appeared. The hovered over menu item is highlighted on `mouseenter` only if `mouseMoved` is true. Otherwise, the cursor is hidden temporarily. Code substantially reorganized by tabbott. Fixes: #21018.
This commit is contained in:
@@ -491,6 +491,11 @@ class CommonUtils {
|
|||||||
`//*[@class="typeahead dropdown-menu" and contains(@style, "display: block")]//li[contains(normalize-space(), "${item}")]//a`,
|
`//*[@class="typeahead dropdown-menu" and contains(@style, "display: block")]//li[contains(normalize-space(), "${item}")]//a`,
|
||||||
{visible: true},
|
{visible: true},
|
||||||
);
|
);
|
||||||
|
const entry_x = (await entry?.boundingBox())?.x;
|
||||||
|
const entry_y = (await entry?.boundingBox())?.y;
|
||||||
|
if (entry_x && entry_y) {
|
||||||
|
await page.mouse.move(entry_x, entry_y);
|
||||||
|
}
|
||||||
await page.evaluate((entry) => {
|
await page.evaluate((entry) => {
|
||||||
entry.click();
|
entry.click();
|
||||||
}, entry);
|
}, entry);
|
||||||
|
|||||||
@@ -229,6 +229,9 @@ async function get_suggestions(page: Page, str: string): Promise<void> {
|
|||||||
async function select_from_suggestions(page: Page, item: string): Promise<void> {
|
async function select_from_suggestions(page: Page, item: string): Promise<void> {
|
||||||
await page.evaluate((item: string) => {
|
await page.evaluate((item: string) => {
|
||||||
const tah = $(".create_default_stream").data().typeahead;
|
const tah = $(".create_default_stream").data().typeahead;
|
||||||
|
tah.mousemove({
|
||||||
|
currentTarget: $(`.typeahead:visible li:contains("${CSS.escape(item)}")`)[0],
|
||||||
|
});
|
||||||
tah.mouseenter({
|
tah.mouseenter({
|
||||||
currentTarget: $(`.typeahead:visible li:contains("${CSS.escape(item)}")`)[0],
|
currentTarget: $(`.typeahead:visible li:contains("${CSS.escape(item)}")`)[0],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
this.$header = $(this.options.header_html).appendTo(this.$container)
|
this.$header = $(this.options.header_html).appendTo(this.$container)
|
||||||
this.source = this.options.source
|
this.source = this.options.source
|
||||||
this.shown = false
|
this.shown = false
|
||||||
|
this.mouse_moved_since_typeahead = false
|
||||||
this.dropup = this.options.dropup
|
this.dropup = this.options.dropup
|
||||||
this.fixed = this.options.fixed || false;
|
this.fixed = this.options.fixed || false;
|
||||||
this.automated = this.options.automated || this.automated;
|
this.automated = this.options.automated || this.automated;
|
||||||
@@ -199,6 +200,7 @@
|
|||||||
|
|
||||||
this.$container.show()
|
this.$container.show()
|
||||||
this.shown = true
|
this.shown = true
|
||||||
|
this.mouse_moved_since_typeahead = false
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,11 +330,12 @@
|
|||||||
this.$menu
|
this.$menu
|
||||||
.on('click', 'li', this.click.bind(this))
|
.on('click', 'li', this.click.bind(this))
|
||||||
.on('mouseenter', 'li', this.mouseenter.bind(this))
|
.on('mouseenter', 'li', this.mouseenter.bind(this))
|
||||||
|
.on('mousemove', 'li', this.mousemove.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
, unlisten: function () {
|
, unlisten: function () {
|
||||||
this.$container.remove();
|
this.$container.remove();
|
||||||
var events = ["blur", "keydown", "keyup", "keypress"];
|
var events = ["blur", "keydown", "keyup", "keypress", "mousemove"];
|
||||||
for (var i=0; i<events.length; i++) {
|
for (var i=0; i<events.length; i++) {
|
||||||
this.$element.off(events[i]);
|
this.$element.off(events[i]);
|
||||||
}
|
}
|
||||||
@@ -375,6 +378,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
, mousemove: function(e) {
|
||||||
|
if (!this.mouse_moved_since_typeahead) {
|
||||||
|
/* Undo cursor disabling in mouseenter handler. */
|
||||||
|
$(e.currentTarget).find('a').css('cursor', '');
|
||||||
|
this.mouse_moved_since_typeahead = true;
|
||||||
|
this.mouseenter(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
, keydown: function (e) {
|
, keydown: function (e) {
|
||||||
if (this.trigger_selection(e)) {
|
if (this.trigger_selection(e)) {
|
||||||
if (!this.shown) return;
|
if (!this.shown) return;
|
||||||
@@ -450,6 +462,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
, mouseenter: function (e) {
|
, mouseenter: function (e) {
|
||||||
|
if (!this.mouse_moved_since_typeahead) {
|
||||||
|
// Prevent the annoying interaction where your mouse happens
|
||||||
|
// to be in the space where typeahead will open. (This would
|
||||||
|
// result in the mouse taking priority over the keyboard for
|
||||||
|
// what you selected). If the mouse has not been moved since
|
||||||
|
// the appearance of the typeahead menu, we disable the
|
||||||
|
// cursor, which in turn prevents the currently hovered
|
||||||
|
// element from being selected. The mousemove handler
|
||||||
|
// overrides this logic.
|
||||||
|
$(e.currentTarget).find('a').css('cursor', 'none')
|
||||||
|
return
|
||||||
|
}
|
||||||
this.$menu.find('.active').removeClass('active')
|
this.$menu.find('.active').removeClass('active')
|
||||||
$(e.currentTarget).addClass('active')
|
$(e.currentTarget).addClass('active')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user