diff --git a/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/PropertiesPanelKeyoardBindings.js b/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/PropertiesPanelKeyoardBindings.js index 6b9581f692..7bb86ef9d0 100644 --- a/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/PropertiesPanelKeyoardBindings.js +++ b/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/PropertiesPanelKeyoardBindings.js @@ -8,77 +8,85 @@ * except in compliance with the MIT License. */ -import { - isCmd as isCommandOrControl, - isKey, - isShift -} from 'diagram-js/lib/features/keyboard/KeyboardUtil'; - - -export default class PropertiesPanelKeyboardBindings { - constructor(commandStack, eventBus, propertiesPanel) { - this._commandStack = commandStack; - this._eventBus = eventBus; - this._propertiesPanel = propertiesPanel; - - eventBus.on('propertiesPanel.attach', this._addEventListeners); - - eventBus.on('propertiesPanel.detach', this._removeEventListeners); - } - - _addEventListeners = () => { - const container = this._getContainer(); - - container.addEventListener('focusin', this.handleFocusin); - container.addEventListener('focusout', this.handleFocusout); - container.addEventListener('keydown', this.handleKeydown); - } - - _removeEventListeners = () => { - const container = this._getContainer(); - - container.removeEventListener('focusin', this.handleFocusin); - container.removeEventListener('focusout', this.handleFocusout); - container.removeEventListener('keydown', this.handleKeydown); - } - - handleFocusin = () => { - this._eventBus.fire('propertiesPanel.focusin'); - } - - handleFocusout = () => { - this._eventBus.fire('propertiesPanel.focusout'); - } - - handleKeydown = event => { - const commandStack = this._commandStack; - - if (isUndo(event)) { - commandStack.canUndo() && commandStack.undo(); - - event.preventDefault(); - } - - if (isRedo(event)) { - commandStack.canRedo() && commandStack.redo(); - - event.preventDefault(); - } - } - - _getContainer() { - return this._propertiesPanel._container; - } -} - -PropertiesPanelKeyboardBindings.$inject = [ 'commandStack', 'eventBus', 'propertiesPanel' ]; - -// helpers ////////// - -function isUndo(event) { - return isCommandOrControl(event) && !isShift(event) && isKey([ 'z', 'Z' ], event); -} - -function isRedo(event) { - return isCommandOrControl(event) && (isKey([ 'y', 'Y' ], event) || (isKey([ 'z', 'Z' ], event) && isShift(event))); -} \ No newline at end of file +import { + isCmd as isCommandOrControl, + isKey, + isShift +} from 'diagram-js/lib/features/keyboard/KeyboardUtil'; + + +export default class PropertiesPanelKeyboardBindings { + constructor(commandStack, eventBus, propertiesPanel) { + this._commandStack = commandStack; + this._eventBus = eventBus; + this._propertiesPanel = propertiesPanel; + + eventBus.on('propertiesPanel.attach', this._addEventListeners); + + eventBus.on('propertiesPanel.detach', this._removeEventListeners); + } + + _addEventListeners = () => { + const container = this._getContainer(); + + container.addEventListener('focusin', this.handleFocusin); + container.addEventListener('focusout', this.handleFocusout); + container.addEventListener('keydown', this.handleKeydown); + } + + _removeEventListeners = () => { + const container = this._getContainer(); + + container.removeEventListener('focusin', this.handleFocusin); + container.removeEventListener('focusout', this.handleFocusout); + container.removeEventListener('keydown', this.handleKeydown); + } + + handleFocusin = () => { + this._eventBus.fire('propertiesPanel.focusin'); + } + + handleFocusout = () => { + this._eventBus.fire('propertiesPanel.focusout'); + } + + handleKeydown = event => { + const commandStack = this._commandStack; + + if (isUndo(event)) { + commandStack.canUndo() && commandStack.undo(); + + this._cancel(event); + } + + if (isRedo(event)) { + commandStack.canRedo() && commandStack.redo(); + + this._cancel(event); + } + } + + _getContainer() { + return this._propertiesPanel._container; + } + + /** + * @param {KeyboardEvent} event + */ + _cancel(event) { + event.preventDefault(); + event.stopPropagation(); + } +} + +PropertiesPanelKeyboardBindings.$inject = [ 'commandStack', 'eventBus', 'propertiesPanel' ]; + +// helpers ////////// + +function isUndo(event) { + return isCommandOrControl(event) && !isShift(event) && isKey([ 'z', 'Z' ], event); +} + +function isRedo(event) { + return isCommandOrControl(event) && (isKey([ 'y', 'Y' ], event) || (isKey([ 'z', 'Z' ], event) && isShift(event))); +} diff --git a/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/__tests__/PropertiesPanelKeyboardBindingsSpec.js b/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/__tests__/PropertiesPanelKeyboardBindingsSpec.js index 466a2e4160..8119882cf5 100644 --- a/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/__tests__/PropertiesPanelKeyboardBindingsSpec.js +++ b/client/src/app/tabs/bpmn/modeler/features/properties-panel-keyboard-bindings/__tests__/PropertiesPanelKeyboardBindingsSpec.js @@ -1,184 +1,184 @@ -/** - * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH - * under one or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information regarding copyright - * ownership. - * - * Camunda licenses this file to you under the MIT; you may not use this file - * except in compliance with the MIT License. - */ - -/* global sinon */ - -import Modeler from 'test/mocks/bpmn-js/Modeler'; - -import PropertiesPanelKeyboardBindings from '../PropertiesPanelKeyoardBindings'; - -import { - assign, - isString -} from 'min-dash'; - -const spy = sinon.spy; - - -describe('PropertiesPanelKeyboardBindings', function() { - - let container; - - beforeEach(function() { - container = document.createElement('div'); - }); - - - it('should undo', function() { - - // given - const undoSpy = spy(); - - const modeler = createModeler({ - commandStack: { - canUndo: () => true, - undo: undoSpy - }, - eventBus: { - on: (_, callback) => callback() - }, - propertiesPanel: { - _container: container - } - }); - - const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); - - const event = createKeyEvent('Z', { ctrlKey: true }); - - // when - propertiesPanelKeyboardBindings.handleKeydown(event); - - // then - expect(undoSpy).to.have.been.called; - }); - - - it('should redo', function() { - - // given - const redoSpy = spy(); - - const modeler = createModeler({ - commandStack: { - canRedo: () => true, - redo: redoSpy - }, - eventBus: { - on: (_, callback) => callback() - }, - propertiesPanel: { - _container: container - } - }); - - const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); - - const event = createKeyEvent('Y', { ctrlKey: true }); - - // when - propertiesPanelKeyboardBindings.handleKeydown(event); - - // then - expect(redoSpy).to.have.been.called; - }); - - - it('should handle focusin', function() { - - // given - const fireSpy = spy(); - - const modeler = createModeler({ - eventBus: { - fire: fireSpy, - on: (_, callback) => callback() - }, - propertiesPanel: { - _container: container - } - }); - - const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); - - // when - propertiesPanelKeyboardBindings.handleFocusin(); - - // then - expect(fireSpy).to.have.been.called; - }); - - - it('should handle focusout', function() { - - // given - const fireSpy = spy(); - - const modeler = createModeler({ - eventBus: { - fire: fireSpy, - on: (_, callback) => callback() - }, - propertiesPanel: { - _container: container - } - }); - - const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); - - // when - propertiesPanelKeyboardBindings.handleFocusout(); - - // then - expect(fireSpy).to.have.been.called; - }); - -}); - -// helpers ////// - -/** - * Create and return a modeler instance with a module that was instanciated with - * dependencies. - * - * @param {Object} Module - Module constructor. - * @param {Object} dependencies - Dependencies. - * - * @returns {Object} - */ -function createModeler(dependencies) { - return new Modeler({ - modules: { - ...dependencies, - propertiesPanelKeyboardBindings: new PropertiesPanelKeyboardBindings( - ...PropertiesPanelKeyboardBindings.$inject.map(name => dependencies[ name ] || {}) - ) - } - }); -} - -/** - * Create a fake key event for testing purposes. - * - * @param {string|number} key the key or keyCode/charCode - * @param {Object} [attrs] - * - * @return {Event} - */ -function createKeyEvent(key, attrs) { - var event = document.createEvent('Events') || new document.defaultView.CustomEvent('keyEvent'); - - // init and mark as bubbles / cancelable - event.initEvent('keydown', false, true); - - var keyAttrs = isString(key) ? { key: key } : { keyCode: key, which: key }; - - return assign(event, keyAttrs, attrs || {}); -} \ No newline at end of file +/** + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. + * + * Camunda licenses this file to you under the MIT; you may not use this file + * except in compliance with the MIT License. + */ + +/* global sinon */ + +import Modeler from 'test/mocks/bpmn-js/Modeler'; + +import PropertiesPanelKeyboardBindings from '../PropertiesPanelKeyoardBindings'; + +import { + assign, + isString +} from 'min-dash'; + +const spy = sinon.spy; + + +describe('PropertiesPanelKeyboardBindings', function() { + + let container; + + beforeEach(function() { + container = document.createElement('div'); + }); + + + it('should undo', function() { + + // given + const undoSpy = spy(); + + const modeler = createModeler({ + commandStack: { + canUndo: () => true, + undo: undoSpy + }, + eventBus: { + on: (_, callback) => callback() + }, + propertiesPanel: { + _container: container + } + }); + + const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); + + const event = createKeyEvent('Z', { ctrlKey: true }); + + // when + propertiesPanelKeyboardBindings.handleKeydown(event); + + // then + expect(undoSpy).to.have.been.called; + }); + + + it('should redo', function() { + + // given + const redoSpy = spy(); + + const modeler = createModeler({ + commandStack: { + canRedo: () => true, + redo: redoSpy + }, + eventBus: { + on: (_, callback) => callback() + }, + propertiesPanel: { + _container: container + } + }); + + const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); + + const event = createKeyEvent('Y', { ctrlKey: true }); + + // when + propertiesPanelKeyboardBindings.handleKeydown(event); + + // then + expect(redoSpy).to.have.been.called; + }); + + + it('should handle focusin', function() { + + // given + const fireSpy = spy(); + + const modeler = createModeler({ + eventBus: { + fire: fireSpy, + on: (_, callback) => callback() + }, + propertiesPanel: { + _container: container + } + }); + + const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); + + // when + propertiesPanelKeyboardBindings.handleFocusin(); + + // then + expect(fireSpy).to.have.been.called; + }); + + + it('should handle focusout', function() { + + // given + const fireSpy = spy(); + + const modeler = createModeler({ + eventBus: { + fire: fireSpy, + on: (_, callback) => callback() + }, + propertiesPanel: { + _container: container + } + }); + + const propertiesPanelKeyboardBindings = modeler.get('propertiesPanelKeyboardBindings'); + + // when + propertiesPanelKeyboardBindings.handleFocusout(); + + // then + expect(fireSpy).to.have.been.called; + }); + +}); + +// helpers ////// + +/** + * Create and return a modeler instance with a module that was instanciated with + * dependencies. + * + * @param {Object} Module - Module constructor. + * @param {Object} dependencies - Dependencies. + * + * @returns {Object} + */ +function createModeler(dependencies) { + return new Modeler({ + modules: { + ...dependencies, + propertiesPanelKeyboardBindings: new PropertiesPanelKeyboardBindings( + ...PropertiesPanelKeyboardBindings.$inject.map(name => dependencies[ name ] || {}) + ) + } + }); +} + +/** + * Create a fake key event for testing purposes. + * + * @param {string|number} key the key or keyCode/charCode + * @param {Object} [attrs] + * + * @return {Event} + */ +function createKeyEvent(key, attrs) { + var event = document.createEvent('Events') || new document.defaultView.CustomEvent('keyEvent'); + + // init and mark as bubbles / cancelable + event.initEvent('keydown', false, true); + + var keyAttrs = isString(key) ? { key: key } : { keyCode: key, which: key }; + + return assign(event, keyAttrs, attrs || {}); +}