Przeglądaj źródła

Expand test case and improve code.

JC Brand 7 lat temu
rodzic
commit
86fab99c54

+ 51 - 7
spec/autocomplete.js

@@ -12,7 +12,6 @@
     const $pres = converse.env.$pres;
     const Strophe = converse.env.Strophe;
     const u = converse.env.utils;
-    const sizzle = converse.env.sizzle;
 
     return describe("A groupchat textarea", function () {
 
@@ -25,7 +24,7 @@
             .then(() => {
                 const view = _converse.chatboxviews.get('lounge@localhost');
                 expect(view.model.occupants.length).toBe(1);
-                const presence = $pres({
+                let presence = $pres({
                         'to': 'dummy@localhost/resource',
                         'from': 'lounge@localhost/some1'
                     })
@@ -42,12 +41,57 @@
                 textarea.value = "hello som";
 
                 // Press tab
-                view.keyPressed({
-                    target: textarea,
-                    preventDefault: _.noop,
-                    keyCode: 9
-                });
+                const tab_event = {
+                    'target': textarea,
+                    'preventDefault': _.noop,
+                    'keyCode': 9
+                }
+                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(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();
             }).catch(_.partial(console.error, _));
         }));

+ 45 - 50
src/converse-autocomplete.js

@@ -58,7 +58,7 @@
 
             class AutoComplete {
                 
-                constructor (el, o) {
+                constructor (el, config={}) {
                     this.is_opened = false;
 
                     if (u.hasClass('.suggestion-box', el)) {
@@ -73,8 +73,6 @@
                     this.ul = this.container.querySelector('.suggestion-box__results');
                     this.status = this.container.querySelector('.suggestion-box__additions');
 
-                    o = o || {};
-
                     _.assignIn(this, {
                         '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
@@ -84,50 +82,31 @@
                         'auto_first': false,
                         'data': _.identity,
                         'filter': _converse.FILTER_CONTAINS,
-                        'sort': o.sort === false ? false : SORT_BYLENGTH,
+                        'sort': config.sort === false ? false : SORT_BYLENGTH,
                         'item': ITEM,
                         'replace': REPLACE
-                    }, o);
+                    }, config);
 
                     this.index = -1;
 
-                    const input = {
-                        "blur": this.close.bind(this, {'reason': "blur" }),
-                        "keydown": () => this.onKeyDown()
-                    }
-                    if (this.auto_evaluate) {
-                        input["input"] = this.evaluate.bind(this);
-                    }
-
-                    this.bindEvents(input)
+                    this.bindEvents()
 
                     if (this.input.hasAttribute("list")) {
                         this.list = "#" + this.input.getAttribute("list");
                         this.input.removeAttribute("list");
                     } else {
-                        this.list = this.input.getAttribute("data-list") || o.list || [];
+                        this.list = this.input.getAttribute("data-list") || config.list || [];
                     }
                 }
 
-                onKeyDown (evt) {
-                    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) {
+                bindEvents () {
                     // Bind events
+                    const input = {
+                        "blur": this.close.bind(this, {'reason': "blur"}),
+                    }
+                    if (this.auto_evaluate) {
+                        input["input"] = this.evaluate.bind(this);
+                    }
                     this._events = {
                         'input': input,
                         'form': {
@@ -239,26 +218,21 @@
                     this.goto(this.selected && pos !== -1 ? pos : count - 1);
                 }
 
-                // Should not be used, highlights specific item without any checks!
                 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) {
-                        lis[this.index].setAttribute("aria-selected", "false");
+                        list[this.index].setAttribute("aria-selected", "false");
                     }
-
                     this.index = i;
 
-                    if (i > -1 && lis.length > 0) {
-                        lis[i].setAttribute("aria-selected", "true");
-                        this.status.textContent = lis[i].textContent;
-
+                    if (i > -1 && list.length > 0) {
+                        list[i].setAttribute("aria-selected", "true");
+                        list[i].focus();
+                        this.status.textContent = list[i].textContent;
                         // scroll to highlighted element in case parent's height is fixed
-                        this.ul.scrollTop = lis[i].offsetTop - this.ul.clientHeight + lis[i].clientHeight;
-
-                        helpers.fire(this.input, "suggestion-box-highlight", {
-                            text: this.suggestions[this.index]
-                        });
+                        this.ul.scrollTop = list[i].offsetTop - this.ul.clientHeight + list[i].clientHeight;
+                        this.trigger("suggestion-box-highlight", {'text': this.suggestions[this.index]});
                     }
                 }
 
@@ -286,6 +260,22 @@
                 }
 
                 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([
                                 _converse.keycodes.SHIFT,
                                 _converse.keycodes.META,
@@ -299,12 +289,17 @@
                         ev.preventDefault();
                         this.auto_completing = true;
                     }
-                    if (this.auto_completing) {
-                        this.evaluate();
-                    }
                 }
 
                 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;
                     if (this.match_current_word) {
                         value = u.getCurrentWord(this.input);

+ 1 - 0
src/converse-chatview.js

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

+ 8 - 1
src/converse-muc-views.js

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