Commit 324ffd5e authored by JC Brand's avatar JC Brand

Let `@` trigger autocomplete with all possible options shown

parent cc3a158b
...@@ -15,6 +15,50 @@ ...@@ -15,6 +15,50 @@
return describe("A groupchat textarea", function () { return describe("A groupchat textarea", function () {
it("shows all autocompletion options when the user presses @",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'tom')
.then(() => {
const view = _converse.chatboxviews.get('lounge@localhost');
['dick', 'harry'].forEach((nick) => {
_converse.connection._dataRecv(test_utils.createRequest(
$pres({
'to': 'tom@localhost/resource',
'from': `lounge@localhost/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': `${nick}@localhost/resource`,
'role': 'participant'
})));
});
// Test that pressing @ brings up all options
const textarea = view.el.querySelector('textarea.chat-textarea');
const at_event = {
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 50
};
view.keyPressed(at_event);
textarea.value = '@';
view.keyUp(at_event);
expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(3);
expect(view.el.querySelector('.suggestion-box__results li[aria-selected="true"]').textContent).toBe('tom');
expect(view.el.querySelector('.suggestion-box__results li:first-child').textContent).toBe('tom');
expect(view.el.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('dick');
expect(view.el.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('harry');
done();
}).catch(_.partial(console.error, _));
}));
it("autocompletes when the user presses tab", it("autocompletes when the user presses tab",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
...@@ -102,7 +146,7 @@ ...@@ -102,7 +146,7 @@
'stopPropagation': _.noop, 'stopPropagation': _.noop,
'keyCode': 13 // Enter 'keyCode': 13 // Enter
}); });
expect(textarea.value).toBe('hello s some2'); expect(textarea.value).toBe('hello s some2 ');
// Test that pressing tab twice selects // Test that pressing tab twice selects
presence = $pres({ presence = $pres({
...@@ -122,18 +166,7 @@ ...@@ -122,18 +166,7 @@
view.keyPressed(tab_event); view.keyPressed(tab_event);
view.keyUp(tab_event); view.keyUp(tab_event);
expect(textarea.value).toBe('hello z3r0'); expect(textarea.value).toBe('hello z3r0 ');
// Test that pressing @ brings up all options
const at_event = {
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 50
};
view.keyPressed(at_event);
view.keyUp(at_event);
textarea.value = 'hello z3r0 and @';
done(); done();
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
......
...@@ -193,8 +193,7 @@ ...@@ -193,8 +193,7 @@
if (this.auto_first && this.index === -1) { if (this.auto_first && this.index === -1) {
this.goto(0); this.goto(0);
} }
this.trigger("suggestion-box-open");
helpers.fire(this.input, "suggestion-box-open");
} }
destroy () { destroy () {
...@@ -250,20 +249,13 @@ ...@@ -250,20 +249,13 @@
} }
if (selected) { if (selected) {
const suggestion = this.suggestions[this.index], const suggestion = this.suggestions[this.index];
allowed = helpers.fire(this.input, "suggestion-box-select", {
'text': suggestion,
'origin': origin || selected
});
if (allowed) {
this.insertValue(suggestion); this.insertValue(suggestion);
this.close({'reason': 'select'}); this.close({'reason': 'select'});
this.auto_completing = false; this.auto_completing = false;
this.trigger("suggestion-box-selectcomplete", {'text': suggestion}); this.trigger("suggestion-box-selectcomplete", {'text': suggestion});
} }
} }
}
keyPressed (ev) { keyPressed (ev) {
if (this.opened) { if (this.opened) {
...@@ -309,17 +301,20 @@ ...@@ -309,17 +301,20 @@
return; return;
} }
let value = this.input.value; const list = typeof this._list === "function" ? this._list() : this._list;
if (this.match_current_word) { if (list.length === 0) {
value = u.getCurrentWord(this.input); return;
} }
const list = typeof this._list === "function" ? this._list() : this._list; let value = this.match_current_word ? u.getCurrentWord(this.input) : this.input.value;
if (list.length > 0 && (
(value.length >= this.min_chars) ||
(this.trigger_on_at && ev.keyCode === value.startsWith('@'))
)) {
let ignore_min_chars = false;
if (this.trigger_on_at && value.startsWith('@')) {
ignore_min_chars = true;
value = value.slice('1');
}
if ((value.length >= this.min_chars) || ignore_min_chars) {
this.index = -1; this.index = -1;
// Populate list with options that match // Populate list with options that match
this.ul.innerHTML = ""; this.ul.innerHTML = "";
...@@ -402,19 +397,6 @@ ...@@ -402,19 +397,6 @@
} }
}, },
fire (target, type, properties) {
const evt = document.createEvent("HTMLEvents");
evt.initEvent(type, true, true );
for (var j in properties) {
if (!Object.prototype.hasOwnProperty.call(properties, j)) {
continue;
}
evt[j] = properties[j];
}
return target.dispatchEvent(evt);
},
regExpEscape (s) { regExpEscape (s) {
return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
} }
......
...@@ -825,7 +825,8 @@ ...@@ -825,7 +825,8 @@
const cursor = input.selectionEnd || undefined, const cursor = input.selectionEnd || undefined,
current_word = _.last(input.value.slice(0, cursor).split(' ')), current_word = _.last(input.value.slice(0, cursor).split(' ')),
value = input.value; value = input.value;
input.value = value.slice(0, cursor - current_word.length) + new_value + value.slice(cursor); input.value = value.slice(0, cursor - current_word.length) + `${new_value} ` + value.slice(cursor);
input.selectionEnd = cursor - current_word.length + new_value.length + 1;
}; };
u.isVisible = function (el) { u.isVisible = function (el) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment