From da9e2792ebd1a4c19298247c55382aebb774e4cc Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 6 Apr 2015 14:04:22 -0400 Subject: [PATCH] FIX: Bugs with autocomplete It wasn't tearing itself down properly. It was swallowing events. --- .../discourse/components/user-selector.js.es6 | 4 +++ .../discourse/lib/autocomplete.js.es6 | 26 ++++++++++++++----- .../javascripts/discourse/views/modal.js.es6 | 23 +++++++++++----- .../javascripts/integration/modal-test.js.es6 | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/discourse/components/user-selector.js.es6 b/app/assets/javascripts/discourse/components/user-selector.js.es6 index f008c599b36..d0d210a6891 100644 --- a/app/assets/javascripts/discourse/components/user-selector.js.es6 +++ b/app/assets/javascripts/discourse/components/user-selector.js.es6 @@ -57,6 +57,10 @@ export default TextField.extend({ }); }.on('didInsertElement'), + _removeAutocomplete: function() { + this.$().autocomplete('destroy'); + }.on('willDestroyElement'), + // THIS IS A HUGE HACK TO SUPPORT CLEARING THE INPUT _clearInput: function() { if (arguments.length > 1) { diff --git a/app/assets/javascripts/discourse/lib/autocomplete.js.es6 b/app/assets/javascripts/discourse/lib/autocomplete.js.es6 index 5dc9b87fd14..d3f2ea0d179 100644 --- a/app/assets/javascripts/discourse/lib/autocomplete.js.es6 +++ b/app/assets/javascripts/discourse/lib/autocomplete.js.es6 @@ -33,11 +33,23 @@ var keys = { }; +let inputTimeout; + export default function(options) { var autocompletePlugin = this; if (this.length === 0) return; + if (options === 'destroy') { + Ember.run.cancel(inputTimeout); + + $(this).off('keypress.autocomplete') + .off('keydown.autocomplete') + .off('paste.autocomplete'); + + return; + } + if (options && options.cancel && this.data("closeAutocomplete")) { this.data("closeAutocomplete")(); return this; @@ -252,13 +264,13 @@ export default function(options) { closeAutocomplete(); }); - $(this).on('paste', function() { + $(this).on('paste.autocomplete', function() { _.delay(function(){ me.trigger("keydown"); }, 50); }); - $(this).keypress(function(e) { + $(this).on('keypress.autocomplete', function(e) { var caretPosition, term; // keep hunting backwards till you hit a the @ key @@ -277,7 +289,7 @@ export default function(options) { } }); - $(this).keydown(function(e) { + $(this).on('keydown.autocomplete', function(e) { var c, caretPosition, i, initial, next, prev, prevIsGood, stopFound, term, total, userToComplete; if(e.ctrlKey || e.altKey || e.metaKey){ @@ -286,7 +298,9 @@ export default function(options) { if(options.allowAny){ // saves us wiring up a change event as well, keypress is while its pressed - _.delay(function(){ + + Ember.run.cancel(inputTimeout); + inputTimeout = Ember.run.later(function(){ if(inputSelectedItems.length === 0) { inputSelectedItems.push(""); } @@ -299,7 +313,7 @@ export default function(options) { } } - },50); + }, 50); } if (!options.key) { @@ -332,7 +346,7 @@ export default function(options) { // ESC if (e.which === keys.esc) { - if (completeStart !== null) { + if (div !== null) { closeAutocomplete(); return false; } diff --git a/app/assets/javascripts/discourse/views/modal.js.es6 b/app/assets/javascripts/discourse/views/modal.js.es6 index 04f086afbcb..e69cd3c517f 100644 --- a/app/assets/javascripts/discourse/views/modal.js.es6 +++ b/app/assets/javascripts/discourse/views/modal.js.es6 @@ -2,6 +2,22 @@ export default Ember.View.extend({ elementId: 'discourse-modal', templateName: 'modal/modal', classNameBindings: [':modal', ':hidden', 'controller.modalClass'], + attributeBindings: ['data-keyboard'], + + // We handle ESC ourselves + 'data-keyboard': 'false', + + _bindOnInsert: function() { + $('html').on('keydown.discourse-modal', e => { + if (e.which === 27) { + Em.run.next(() => $('.modal-header a.close').click()); + } + }); + }.on('didInsertElement'), + + _bindOnDestroy: function() { + $('html').off('keydown.discourse-modal'); + }.on('willDestroyElement'), click(e) { const $target = $(e.target); @@ -12,12 +28,5 @@ export default Ember.View.extend({ // the backdrop and makes it unclickable. $('.modal-header a.close').click(); } - }, - - keyDown(e) { - // Delegate click to modal close when pressing ESC - if (e.which === 27) { - Em.run.next(() => $('.modal-header a.close').click()); - } } }); diff --git a/test/javascripts/integration/modal-test.js.es6 b/test/javascripts/integration/modal-test.js.es6 index 6eeb6da1031..2c5cc7f53a2 100644 --- a/test/javascripts/integration/modal-test.js.es6 +++ b/test/javascripts/integration/modal-test.js.es6 @@ -22,7 +22,7 @@ test("modal", () => { ok(find('#discourse-modal:visible').length === 1, 'modal should reappear'); }); - keyEvent('#main-outlet', 'keyup', 27); + keyEvent('#main-outlet', 'keydown', 27); andThen(() => { ok(find('#discourse-modal:visible').length === 0, 'ESC should close the modal'); });