Expand test case and improve code.

This commit is contained in:
JC Brand 2018-08-14 14:05:33 +02:00
parent 2a593a03b7
commit 86fab99c54
4 changed files with 105 additions and 58 deletions

View File

@ -12,7 +12,6 @@
const $pres = converse.env.$pres; const $pres = converse.env.$pres;
const Strophe = converse.env.Strophe; const Strophe = converse.env.Strophe;
const u = converse.env.utils; const u = converse.env.utils;
const sizzle = converse.env.sizzle;
return describe("A groupchat textarea", function () { return describe("A groupchat textarea", function () {
@ -25,7 +24,7 @@
.then(() => { .then(() => {
const view = _converse.chatboxviews.get('lounge@localhost'); const view = _converse.chatboxviews.get('lounge@localhost');
expect(view.model.occupants.length).toBe(1); expect(view.model.occupants.length).toBe(1);
const presence = $pres({ let presence = $pres({
'to': 'dummy@localhost/resource', 'to': 'dummy@localhost/resource',
'from': 'lounge@localhost/some1' 'from': 'lounge@localhost/some1'
}) })
@ -42,12 +41,57 @@
textarea.value = "hello som"; textarea.value = "hello som";
// Press tab // Press tab
view.keyPressed({ const tab_event = {
target: textarea, 'target': textarea,
preventDefault: _.noop, 'preventDefault': _.noop,
keyCode: 9 'keyCode': 9
}); }
view.keyPressed(tab_event);
view.keyUp(tab_event);
expect(view.el.querySelector('.suggestion-box__results').hidden).toBeFalsy(); expect(view.el.querySelector('.suggestion-box__results').hidden).toBeFalsy();
expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(1);
expect(view.el.querySelector('.suggestion-box__results li').textContent).toBe('some1');
const backspace_event = {
'target': textarea,
'preventDefault': _.noop,
'keyCode': 8
}
for (var i=0; i<3; i++) {
// Press backspace 3 times to remove "som"
view.keyPressed(backspace_event);
textarea.value = textarea.value.slice(0, textarea.value.length-1)
view.keyUp(backspace_event);
}
expect(view.el.querySelector('.suggestion-box__results').hidden).toBeTruthy();
presence = $pres({
'to': 'dummy@localhost/resource',
'from': 'lounge@localhost/some2'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'some2@localhost/resource',
'role': 'participant'
});
_converse.connection._dataRecv(test_utils.createRequest(presence));
textarea.value = "hello s";
view.keyPressed(tab_event);
view.keyUp(tab_event);
expect(view.el.querySelector('.suggestion-box__results').hidden).toBeFalsy();
expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(2);
const up_arrow_event = {
'target': textarea,
'preventDefault': () => (up_arrow_event.defaultPrevented = true),
'stopPropagation': _.noop,
'keyCode': 38
}
view.keyPressed(up_arrow_event);
view.keyUp(up_arrow_event);
done(); done();
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
})); }));

View File

@ -58,7 +58,7 @@
class AutoComplete { class AutoComplete {
constructor (el, o) { constructor (el, config={}) {
this.is_opened = false; this.is_opened = false;
if (u.hasClass('.suggestion-box', el)) { if (u.hasClass('.suggestion-box', el)) {
@ -73,8 +73,6 @@
this.ul = this.container.querySelector('.suggestion-box__results'); this.ul = this.container.querySelector('.suggestion-box__results');
this.status = this.container.querySelector('.suggestion-box__additions'); this.status = this.container.querySelector('.suggestion-box__additions');
o = o || {};
_.assignIn(this, { _.assignIn(this, {
'match_current_word': false, // Match only the current word, otherwise all input is matched 'match_current_word': false, // Match only the current word, otherwise all input is matched
'match_on_tab': false, // Whether matching should only start when tab's pressed 'match_on_tab': false, // Whether matching should only start when tab's pressed
@ -84,50 +82,31 @@
'auto_first': false, 'auto_first': false,
'data': _.identity, 'data': _.identity,
'filter': _converse.FILTER_CONTAINS, 'filter': _converse.FILTER_CONTAINS,
'sort': o.sort === false ? false : SORT_BYLENGTH, 'sort': config.sort === false ? false : SORT_BYLENGTH,
'item': ITEM, 'item': ITEM,
'replace': REPLACE 'replace': REPLACE
}, o); }, config);
this.index = -1; this.index = -1;
const input = { this.bindEvents()
"blur": this.close.bind(this, {'reason': "blur" }),
"keydown": () => this.onKeyDown()
}
if (this.auto_evaluate) {
input["input"] = this.evaluate.bind(this);
}
this.bindEvents(input)
if (this.input.hasAttribute("list")) { if (this.input.hasAttribute("list")) {
this.list = "#" + this.input.getAttribute("list"); this.list = "#" + this.input.getAttribute("list");
this.input.removeAttribute("list"); this.input.removeAttribute("list");
} else { } else {
this.list = this.input.getAttribute("data-list") || o.list || []; this.list = this.input.getAttribute("data-list") || config.list || [];
} }
} }
onKeyDown (evt) { bindEvents () {
const c = evt.keyCode;
// If the dropdown `ul` is in view, then act on keydown for the following keys:
// Enter / Esc / Up / Down
if (this.opened) {
if (c === _converse.keycodes.ENTER && this.selected) {
evt.preventDefault();
this.select();
} else if (c === _converse.keycodes.ESCAPE) {
this.close({ reason: "esc" });
} else if (c === _converse.keycodes.UP_ARROW || c === _converse.keycodes.DOWN_ARROW) {
evt.preventDefault();
this[c === _converse.keycodes.UP_ARROW ? "previous" : "next"]();
}
}
}
bindEvents (input) {
// Bind events // Bind events
const input = {
"blur": this.close.bind(this, {'reason': "blur"}),
}
if (this.auto_evaluate) {
input["input"] = this.evaluate.bind(this);
}
this._events = { this._events = {
'input': input, 'input': input,
'form': { 'form': {
@ -239,26 +218,21 @@
this.goto(this.selected && pos !== -1 ? pos : count - 1); this.goto(this.selected && pos !== -1 ? pos : count - 1);
} }
// Should not be used, highlights specific item without any checks!
goto (i) { goto (i) {
var lis = this.ul.children; // Should not be used directly, highlights specific item without any checks!
const list = this.ul.children;
if (this.selected) { if (this.selected) {
lis[this.index].setAttribute("aria-selected", "false"); list[this.index].setAttribute("aria-selected", "false");
} }
this.index = i; this.index = i;
if (i > -1 && lis.length > 0) { if (i > -1 && list.length > 0) {
lis[i].setAttribute("aria-selected", "true"); list[i].setAttribute("aria-selected", "true");
this.status.textContent = lis[i].textContent; list[i].focus();
this.status.textContent = list[i].textContent;
// scroll to highlighted element in case parent's height is fixed // scroll to highlighted element in case parent's height is fixed
this.ul.scrollTop = lis[i].offsetTop - this.ul.clientHeight + lis[i].clientHeight; this.ul.scrollTop = list[i].offsetTop - this.ul.clientHeight + list[i].clientHeight;
this.trigger("suggestion-box-highlight", {'text': this.suggestions[this.index]});
helpers.fire(this.input, "suggestion-box-highlight", {
text: this.suggestions[this.index]
});
} }
} }
@ -286,6 +260,22 @@
} }
keyPressed (ev) { keyPressed (ev) {
if (this.opened) {
if (ev.keyCode === _converse.keycodes.ENTER && this.selected) {
ev.preventDefault();
ev.stopPropagation();
return false;
} else if (ev.keyCode === _converse.keycodes.ESCAPE) {
this.close({'reason': 'esc'});
return false;
} else if (ev.keyCode === _converse.keycodes.UP_ARROW || ev.keyCode === _converse.keycodes.DOWN_ARROW) {
ev.preventDefault();
ev.stopPropagation();
this[ev.keyCode === _converse.keycodes.UP_ARROW ? "previous" : "next"]();
return false;
}
}
if (_.includes([ if (_.includes([
_converse.keycodes.SHIFT, _converse.keycodes.SHIFT,
_converse.keycodes.META, _converse.keycodes.META,
@ -299,12 +289,17 @@
ev.preventDefault(); ev.preventDefault();
this.auto_completing = true; this.auto_completing = true;
} }
if (this.auto_completing) {
this.evaluate();
}
} }
evaluate (ev) { evaluate (ev) {
const arrow_pressed = (
ev.keyCode === _converse.keycodes.UP_ARROW ||
ev.keyCode === _converse.keycodes.DOWN_ARROW
);
if (!this.auto_completing || (this.selected && arrow_pressed)) {
return;
}
let value = this.input.value; let value = this.input.value;
if (this.match_current_word) { if (this.match_current_word) {
value = u.getCurrentWord(this.input); value = u.getCurrentWord(this.input);

View File

@ -909,6 +909,7 @@
keyPressed (ev) { keyPressed (ev) {
/* Event handler for when a key is pressed in a chat box textarea. /* Event handler for when a key is pressed in a chat box textarea.
*/ */
console.log('keypressed in chatview');
if (ev.ctrlKey) { if (ev.ctrlKey) {
// When ctrl is pressed, no chars are entered into the textarea. // When ctrl is pressed, no chars are entered into the textarea.
return; return;

View File

@ -534,6 +534,7 @@
'click .toggle-smiley': 'toggleEmojiMenu', 'click .toggle-smiley': 'toggleEmojiMenu',
'click .upload-file': 'toggleFileUpload', 'click .upload-file': 'toggleFileUpload',
'keydown .chat-textarea': 'keyPressed', 'keydown .chat-textarea': 'keyPressed',
'keyup .chat-textarea': 'keyUp',
'input .chat-textarea': 'inputChanged' 'input .chat-textarea': 'inputChanged'
}, },
@ -624,10 +625,16 @@
}, },
keyPressed (ev) { keyPressed (ev) {
this.auto_complete.keyPressed(ev); if (!this.auto_complete.keyPressed(ev)) {
return;
}
return _converse.ChatBoxView.prototype.keyPressed.apply(this, arguments); return _converse.ChatBoxView.prototype.keyPressed.apply(this, arguments);
}, },
keyUp (ev) {
this.auto_complete.evaluate(ev);
},
showRoomDetailsModal (ev) { showRoomDetailsModal (ev) {
ev.preventDefault(); ev.preventDefault();
if (_.isUndefined(this.model.room_details_modal)) { if (_.isUndefined(this.model.room_details_modal)) {