diff --git a/ghost/admin/app/mixins/shortcuts.js b/ghost/admin/app/mixins/shortcuts.js index aa488590eb..8391f7fa60 100644 --- a/ghost/admin/app/mixins/shortcuts.js +++ b/ghost/admin/app/mixins/shortcuts.js @@ -44,27 +44,34 @@ key.setScope('default'); * Find out more at the keymaster docs */ export default Mixin.create({ + + _hasRegisteredShortcuts: false, + registerShortcuts() { - let shortcuts = this.get('shortcuts'); + if (!this._hasRegisteredShortcuts) { + let shortcuts = this.get('shortcuts'); - Object.keys(shortcuts).forEach((shortcut) => { - let scope = shortcuts[shortcut].scope || 'default'; - let action = shortcuts[shortcut]; - let options; + Object.keys(shortcuts).forEach((shortcut) => { + let scope = shortcuts[shortcut].scope || 'default'; + let action = shortcuts[shortcut]; + let options; - if (typeOf(action) !== 'string') { - options = action.options; - action = action.action; - } + if (typeOf(action) !== 'string') { + options = action.options; + action = action.action; + } - key(shortcut, scope, (event) => { - // stop things like ctrl+s from actually opening a save dialogue - event.preventDefault(); - run(this, function () { - this.send(action, options); + key(shortcut, scope, (event) => { + // stop things like ctrl+s from actually opening a save dialogue + event.preventDefault(); + run(this, function () { + this.send(action, options); + }); }); }); - }); + + this._hasRegisteredShortcuts = true; + } }, removeShortcuts() { @@ -74,5 +81,10 @@ export default Mixin.create({ let scope = shortcuts[shortcut].scope || 'default'; key.unbind(shortcut, scope); }); + }, + + willDestroy() { + this._super(...arguments); + this.removeShortcuts(); } }); diff --git a/ghost/admin/tests/helpers/destroy-app.js b/ghost/admin/tests/helpers/destroy-app.js index eb72281229..fe0a74698f 100644 --- a/ghost/admin/tests/helpers/destroy-app.js +++ b/ghost/admin/tests/helpers/destroy-app.js @@ -1,3 +1,4 @@ +/* global key */ import {run} from '@ember/runloop'; export default function destroyApp(application) { @@ -6,5 +7,9 @@ export default function destroyApp(application) { server.shutdown(); } + // extra check to ensure we don't have references hanging around via key + // bindings on supposedly destroyed objects + key.deleteScope('default'); + run(application, 'destroy'); }