diff --git a/packages/@ember/-internals/glimmer/lib/component.ts b/packages/@ember/-internals/glimmer/lib/component.ts index c9ddb8d0364..3494db26f01 100644 --- a/packages/@ember/-internals/glimmer/lib/component.ts +++ b/packages/@ember/-internals/glimmer/lib/component.ts @@ -706,46 +706,6 @@ const Component = CoreView.extend( !eventNames.length ); } - - deprecate( - `${this}: Using \`mouseEnter\` event handler methods in components has been deprecated.`, - this.mouseEnter === undefined, - { - id: 'ember-views.event-dispatcher.mouseenter-leave-move', - until: '4.0.0', - url: 'https://deprecations.emberjs.com/v3.x#toc_component-mouseenter-leave-move', - for: 'ember-source', - since: { - enabled: '3.13.0-beta.1', - }, - } - ); - deprecate( - `${this}: Using \`mouseLeave\` event handler methods in components has been deprecated.`, - this.mouseLeave === undefined, - { - id: 'ember-views.event-dispatcher.mouseenter-leave-move', - until: '4.0.0', - url: 'https://deprecations.emberjs.com/v3.x#toc_component-mouseenter-leave-move', - for: 'ember-source', - since: { - enabled: '3.13.0-beta.1', - }, - } - ); - deprecate( - `${this}: Using \`mouseMove\` event handler methods in components has been deprecated.`, - this.mouseMove === undefined, - { - id: 'ember-views.event-dispatcher.mouseenter-leave-move', - until: '4.0.0', - url: 'https://deprecations.emberjs.com/v3.x#toc_component-mouseenter-leave-move', - for: 'ember-source', - since: { - enabled: '3.13.0-beta.1', - }, - } - ); }, get _dispatcher(): EventDispatcher | null { diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts index 0db021bbf4c..f1a8cc3435e 100644 --- a/packages/@ember/-internals/glimmer/lib/modifiers/action.ts +++ b/packages/@ember/-internals/glimmer/lib/modifiers/action.ts @@ -1,7 +1,7 @@ import { Owner } from '@ember/-internals/owner'; import { uuid } from '@ember/-internals/utils'; import { ActionManager, EventDispatcher, isSimpleClick } from '@ember/-internals/views'; -import { assert, deprecate } from '@ember/debug'; +import { assert } from '@ember/debug'; import { flaggedInstrument } from '@ember/instrumentation'; import { join } from '@ember/runloop'; import { registerDestructor } from '@glimmer/destroyable'; @@ -194,25 +194,8 @@ class ActionModifierManager implements InternalModifierManager { this.render(`{{#foo-bar}}{{/foo-bar}}`); - }, /You can not define `click,mouseEnter` function\(s\) to handle DOM event in the .* tagless component since it doesn't have any DOM element./); + }, /You can not define `click` function\(s\) to handle DOM event in the .* tagless component since it doesn't have any DOM element./); } ['@test throws an error if a custom defined event function is defined in a tagless component']() { diff --git a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js index e893ecc8a8a..aa8cb2ca634 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js @@ -270,266 +270,6 @@ moduleFor( this.$('#is-done').trigger('click'); } - - ['@test native event on text node does not throw on hasAttribute [ISSUE #16730]'](assert) { - this.registerComponent('x-foo', { - ComponentClass: Component.extend({ - actions: { - someAction() {}, - }, - }), - template: `test`, - }); - - this.render(`{{x-foo id="outer"}}`); - - let node = this.$('#inner')[0].childNodes[0]; - - runTask(() => { - let event = document.createEvent('HTMLEvents'); - event.initEvent('mousemove', true, true); - node.dispatchEvent(event); - }); - - assert.ok(true); - } - - ['@test [DEPRECATED] delegated event listeners work for mouseEnter/Leave'](assert) { - let receivedEnterEvents = []; - let receivedLeaveEvents = []; - - this.registerComponent('x-foo', { - ComponentClass: Component.extend({ - mouseEnter(event) { - receivedEnterEvents.push(event); - }, - mouseLeave(event) { - receivedLeaveEvents.push(event); - }, - }), - template: `
`, - }); - - expectDeprecation( - () => this.render(`{{x-foo id="outer"}}`), - /Using `mouse(Enter|Leave)` event handler methods in components has been deprecated./ - ); - - let parent = this.element; - let outer = this.$('#outer')[0]; - let inner = this.$('#inner')[0]; - - // mouse moves over #outer - runTask(() => { - this.$(outer).trigger('mouseenter', { canBubble: false, relatedTarget: parent }); - this.$(outer).trigger('mouseover', { relatedTarget: parent }); - this.$(parent).trigger('mouseout', { relatedTarget: outer }); - }); - assert.equal(receivedEnterEvents.length, 1, 'mouseenter event was triggered'); - assert.strictEqual(receivedEnterEvents[0].target, outer); - - // mouse moves over #inner - runTask(() => { - this.$(inner).trigger('mouseover', { relatedTarget: outer }); - this.$(outer).trigger('mouseout', { relatedTarget: inner }); - }); - assert.equal(receivedEnterEvents.length, 1, 'mouseenter event was not triggered again'); - - // mouse moves out of #inner - runTask(() => { - this.$(inner).trigger('mouseout', { relatedTarget: outer }); - this.$(outer).trigger('mouseover', { relatedTarget: inner }); - }); - assert.equal(receivedLeaveEvents.length, 0, 'mouseleave event was not triggered'); - - // mouse moves out of #outer - runTask(() => { - this.$(outer).trigger('mouseleave', { canBubble: false, relatedTarget: parent }); - this.$(outer).trigger('mouseout', { relatedTarget: parent }); - this.$(parent).trigger('mouseover', { relatedTarget: outer }); - }); - assert.equal(receivedLeaveEvents.length, 1, 'mouseleave event was triggered'); - assert.strictEqual(receivedLeaveEvents[0].target, outer); - } - - ['@test [DEPRECATED] delegated event listeners work for mouseEnter on SVG elements'](assert) { - let receivedEnterEvents = []; - let receivedLeaveEvents = []; - - this.registerComponent('x-foo', { - ComponentClass: Component.extend({ - tagName: 'svg', - mouseEnter(event) { - receivedEnterEvents.push(event); - }, - mouseLeave(event) { - receivedLeaveEvents.push(event); - }, - }), - template: ``, - }); - - expectDeprecation( - () => this.render(`{{x-foo id="outer"}}`), - /Using `mouse(Enter|Leave)` event handler methods in components has been deprecated./ - ); - - let parent = this.element; - let outer = this.$('#outer')[0]; - let inner = this.$('#inner')[0]; - - // mouse moves over #outer - runTask(() => { - this.$(outer).trigger('mouseenter', { canBubble: false, relatedTarget: parent }); - this.$(outer).trigger('mouseover', { relatedTarget: parent }); - this.$(parent).trigger('mouseout', { relatedTarget: outer }); - }); - assert.equal(receivedEnterEvents.length, 1, 'mouseenter event was triggered'); - assert.strictEqual(receivedEnterEvents[0].target, outer); - - // mouse moves over #inner - runTask(() => { - this.$(inner).trigger('mouseover', { relatedTarget: outer }); - this.$(outer).trigger('mouseout', { relatedTarget: inner }); - }); - assert.equal(receivedEnterEvents.length, 1, 'mouseenter event was not triggered again'); - - // mouse moves out of #inner - runTask(() => { - this.$(inner).trigger('mouseout', { relatedTarget: outer }); - this.$(outer).trigger('mouseover', { relatedTarget: inner }); - }); - assert.equal(receivedLeaveEvents.length, 0, 'mouseleave event was not triggered'); - - // mouse moves out of #outer - runTask(() => { - this.$(outer).trigger('mouseleave', { canBubble: false, relatedTarget: parent }); - this.$(outer).trigger('mouseout', { relatedTarget: parent }); - this.$(parent).trigger('mouseover', { relatedTarget: outer }); - }); - assert.equal(receivedLeaveEvents.length, 1, 'mouseleave event was triggered'); - assert.strictEqual(receivedLeaveEvents[0].target, outer); - } - - ['@test [DEPRECATED] delegated event listeners work for mouseEnter/Leave with skipped events']( - assert - ) { - let receivedEnterEvents = []; - let receivedLeaveEvents = []; - - this.registerComponent('x-foo', { - ComponentClass: Component.extend({ - mouseEnter(event) { - receivedEnterEvents.push(event); - }, - mouseLeave(event) { - receivedLeaveEvents.push(event); - }, - }), - template: `
`, - }); - - expectDeprecation( - () => this.render(`{{x-foo id="outer"}}`), - /Using `mouse(Enter|Leave)` event handler methods in components has been deprecated./ - ); - - let parent = this.element; - let outer = this.$('#outer')[0]; - let inner = this.$('#inner')[0]; - - // we replicate fast mouse movement, where mouseover is fired directly in #inner, skipping #outer - runTask(() => { - this.$(outer).trigger('mouseenter', { canBubble: false, relatedTarget: parent }); - this.$(inner).trigger('mouseover', { relatedTarget: parent }); - this.$(parent).trigger('mouseout', { relatedTarget: inner }); - }); - assert.equal(receivedEnterEvents.length, 1, 'mouseenter event was triggered'); - assert.strictEqual(receivedEnterEvents[0].target, inner); - - // mouse moves out of #outer - runTask(() => { - this.$(outer).trigger('mouseleave', { canBubble: false, relatedTarget: parent }); - this.$(inner).trigger('mouseout', { relatedTarget: parent }); - this.$(parent).trigger('mouseover', { relatedTarget: inner }); - }); - assert.equal(receivedLeaveEvents.length, 1, 'mouseleave event was triggered'); - assert.strictEqual(receivedLeaveEvents[0].target, inner); - } - - ['@test [DEPRECATED] delegated event listeners work for mouseEnter/Leave with skipped events and subcomponent']( - assert - ) { - let receivedEnterEvents = []; - let receivedLeaveEvents = []; - - this.registerComponent('x-outer', { - ComponentClass: Component.extend({ - mouseEnter(event) { - receivedEnterEvents.push(event); - }, - mouseLeave(event) { - receivedLeaveEvents.push(event); - }, - }), - template: `{{yield}}`, - }); - - this.registerComponent('x-inner', { - ComponentClass: Component.extend(), - template: ``, - }); - - expectDeprecation( - () => this.render(`{{#x-outer id="outer"}}{{x-inner id="inner"}}{{/x-outer}}`), - /Using `mouse(Enter|Leave)` event handler methods in components has been deprecated./ - ); - - let parent = this.element; - let outer = this.$('#outer')[0]; - let inner = this.$('#inner')[0]; - - // we replicate fast mouse movement, where mouseover is fired directly in #inner, skipping #outer - runTask(() => { - this.$(outer).trigger('mouseenter', { canBubble: false, relatedTarget: parent }); - this.$(inner).trigger('mouseover', { relatedTarget: parent }); - this.$(parent).trigger('mouseout', { relatedTarget: inner }); - }); - assert.equal(receivedEnterEvents.length, 1, 'mouseenter event was triggered'); - assert.strictEqual(receivedEnterEvents[0].target, inner); - - // mouse moves out of #inner - runTask(() => { - this.$(outer).trigger('mouseleave', { canBubble: false, relatedTarget: parent }); - this.$(inner).trigger('mouseout', { relatedTarget: parent }); - this.$(parent).trigger('mouseover', { relatedTarget: inner }); - }); - - assert.equal(receivedLeaveEvents.length, 1, 'mouseleave event was triggered'); - assert.strictEqual(receivedLeaveEvents[0].target, inner); - } - - ['@test [DEPRECATED] supports mouseMove events'](assert) { - let receivedEvent; - - this.registerComponent('x-foo', { - ComponentClass: Component.extend({ - mouseMove(event) { - receivedEvent = event; - }, - }), - template: `
`, - }); - - expectDeprecation( - /Using `mouseMove` event handler methods in components has been deprecated\./ - ); - - this.render(`{{x-foo}}`); - - runTask(() => this.$('#inner').trigger('mousemove')); - assert.ok(receivedEvent, 'mousemove event was triggered'); - } } ); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js index 8198e78d689..74296843a9d 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js @@ -1644,130 +1644,5 @@ moduleFor( "Element with action handler has properly updated it's conditional class" ); } - - ['@test [DEPRECATED] it should support mouseEnter events']() { - let showCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '
', - }); - - expectDeprecation( - () => this.render('{{example-component id="outer"}}'), - 'Using the `{{action}}` modifier with `mouseEnter` events has been deprecated.' - ); - - let parent = this.element; - let outer = this.$('#outer')[0]; - let inner = this.$('#inner')[0]; - - runTask(() => { - this.$(outer).trigger('mouseenter', { canBubble: false, relatedTarget: parent }); - this.$(inner).trigger('mouseover', { relatedTarget: parent }); - this.$(parent).trigger('mouseout', { relatedTarget: inner }); - }); - - this.assert.ok(showCalled, 'show action was called on mouseEnter'); - } - - ['@test [DEPRECATED] it should support mouseLeave events']() { - let showCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '
', - }); - - expectDeprecation( - () => this.render('{{example-component id="outer"}}'), - 'Using the `{{action}}` modifier with `mouseLeave` events has been deprecated.' - ); - - let parent = this.element; - let outer = this.$('#outer')[0]; - let inner = this.$('#inner')[0]; - - runTask(() => { - this.$(outer).trigger('mouseleave', { canBubble: false, relatedTarget: parent }); - this.$(inner).trigger('mouseout', { relatedTarget: parent }); - this.$(parent).trigger('mouseover', { relatedTarget: inner }); - }); - - this.assert.ok(showCalled, 'show action was called on mouseLeave'); - } - - ['@test [DEPRECATED] it should support mouseMove events']() { - let showCalled = false; - - let ExampleComponent = Component.extend({ - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '
', - }); - - expectDeprecation( - () => this.render('{{example-component id="outer"}}'), - 'Using the `{{action}}` modifier with `mouseMove` events has been deprecated.' - ); - - runTask(() => { - this.$('#inner').trigger('mousemove'); - }); - - this.assert.ok(showCalled, 'show action was called on mouseMove'); - } - - ['@test [DEPRECATED] it should support bound mouseMove events']() { - let showCalled = false; - - let ExampleComponent = Component.extend({ - eventType: 'mouseMove', - actions: { - show() { - showCalled = true; - }, - }, - }); - - this.registerComponent('example-component', { - ComponentClass: ExampleComponent, - template: '
', - }); - - expectDeprecation( - () => this.render('{{example-component id="outer"}}'), - 'Using the `{{action}}` modifier with `mouseMove` events has been deprecated.' - ); - - runTask(() => { - this.$('#inner').trigger('mousemove'); - }); - - this.assert.ok(showCalled, 'show action was called on mouseMove'); - } } ); diff --git a/packages/@ember/-internals/views/lib/system/event_dispatcher.js b/packages/@ember/-internals/views/lib/system/event_dispatcher.js index 94c6509aae2..db6821bf29f 100644 --- a/packages/@ember/-internals/views/lib/system/event_dispatcher.js +++ b/packages/@ember/-internals/views/lib/system/event_dispatcher.js @@ -4,8 +4,6 @@ import { get, set } from '@ember/-internals/metal'; import { Object as EmberObject } from '@ember/-internals/runtime'; import { getElementView } from '@ember/-internals/views'; import ActionManager from './action_manager'; -import { contains } from './utils'; -import { MOUSE_ENTER_LEAVE_MOVE_EVENTS } from '@ember/deprecated-features'; /** @module ember @@ -14,11 +12,6 @@ import { MOUSE_ENTER_LEAVE_MOVE_EVENTS } from '@ember/deprecated-features'; const ROOT_ELEMENT_CLASS = 'ember-application'; const ROOT_ELEMENT_SELECTOR = `.${ROOT_ELEMENT_CLASS}`; -const EVENT_MAP = { - mouseenter: 'mouseover', - mouseleave: 'mouseout', -}; - /** `Ember.EventDispatcher` handles delegating browser events to their corresponding `Ember.Views.` For example, when you click on a view, @@ -64,41 +57,32 @@ export default EmberObject.extend({ @type Object @private */ - events: Object.assign( - { - touchstart: 'touchStart', - touchmove: 'touchMove', - touchend: 'touchEnd', - touchcancel: 'touchCancel', - keydown: 'keyDown', - keyup: 'keyUp', - keypress: 'keyPress', - mousedown: 'mouseDown', - mouseup: 'mouseUp', - contextmenu: 'contextMenu', - click: 'click', - dblclick: 'doubleClick', - focusin: 'focusIn', - focusout: 'focusOut', - submit: 'submit', - input: 'input', - change: 'change', - dragstart: 'dragStart', - drag: 'drag', - dragenter: 'dragEnter', - dragleave: 'dragLeave', - dragover: 'dragOver', - drop: 'drop', - dragend: 'dragEnd', - }, - MOUSE_ENTER_LEAVE_MOVE_EVENTS - ? { - mouseenter: 'mouseEnter', - mouseleave: 'mouseLeave', - mousemove: 'mouseMove', - } - : {} - ), + events: { + touchstart: 'touchStart', + touchmove: 'touchMove', + touchend: 'touchEnd', + touchcancel: 'touchCancel', + keydown: 'keyDown', + keyup: 'keyUp', + keypress: 'keyPress', + mousedown: 'mouseDown', + mouseup: 'mouseUp', + contextmenu: 'contextMenu', + click: 'click', + dblclick: 'doubleClick', + focusin: 'focusIn', + focusout: 'focusOut', + submit: 'submit', + input: 'input', + change: 'change', + dragstart: 'dragStart', + drag: 'drag', + dragenter: 'dragEnter', + dragleave: 'dragLeave', + dragover: 'dragOver', + drop: 'drop', + dragend: 'dragEnd', + }, /** The root DOM element to which event listeners should be attached. Event @@ -314,90 +298,33 @@ export default EmberObject.extend({ return result; }; - // Special handling of events that don't bubble (event delegation does not work). - // Mimics the way this is handled in jQuery, - // see https://github.com/jquery/jquery/blob/899c56f6ada26821e8af12d9f35fa039100e838e/src/event.js#L666-L700 - if (MOUSE_ENTER_LEAVE_MOVE_EVENTS && EVENT_MAP[event] !== undefined) { - let mappedEventType = EVENT_MAP[event]; - let origEventType = event; - - let createFakeEvent = (eventType, event) => { - let fakeEvent = document.createEvent('MouseEvent'); - fakeEvent.initMouseEvent( - eventType, - false, - false, - event.view, - event.detail, - event.screenX, - event.screenY, - event.clientX, - event.clientY, - event.ctrlKey, - event.altKey, - event.shiftKey, - event.metaKey, - event.button, - event.relatedTarget - ); - - // fake event.target as we don't dispatch the event - Object.defineProperty(fakeEvent, 'target', { value: event.target, enumerable: true }); - - return fakeEvent; - }; - - let handleMappedEvent = (this._eventHandlers[mappedEventType] = (event) => { - let target = event.target; - let related = event.relatedTarget; - - while ( - target && - target.nodeType === 1 && - (related === null || (related !== target && !contains(target, related))) + let handleEvent = (this._eventHandlers[event] = (event) => { + let target = event.target; + + do { + if (getElementView(target)) { + if (viewHandler(target, event) === false) { + event.preventDefault(); + event.stopPropagation(); + break; + } else if (event.cancelBubble === true) { + break; + } + } else if ( + typeof target.hasAttribute === 'function' && + target.hasAttribute('data-ember-action') ) { - // mouseEnter/Leave don't bubble, so there is no logic to prevent it as with other events - if (getElementView(target)) { - viewHandler(target, createFakeEvent(origEventType, event)); - } else if (target.hasAttribute('data-ember-action')) { - actionHandler(target, createFakeEvent(origEventType, event)); + if (actionHandler(target, event) === false) { + break; } - - // separate mouseEnter/Leave events are dispatched for each listening element - // until the element (related) has been reached that the pointing device exited from/to - target = target.parentNode; } - }); - - rootElement.addEventListener(mappedEventType, handleMappedEvent); - } else { - let handleEvent = (this._eventHandlers[event] = (event) => { - let target = event.target; - do { - if (getElementView(target)) { - if (viewHandler(target, event) === false) { - event.preventDefault(); - event.stopPropagation(); - break; - } else if (event.cancelBubble === true) { - break; - } - } else if ( - typeof target.hasAttribute === 'function' && - target.hasAttribute('data-ember-action') - ) { - if (actionHandler(target, event) === false) { - break; - } - } + target = target.parentNode; + } while (target && target.nodeType === 1); + }); - target = target.parentNode; - } while (target && target.nodeType === 1); - }); + rootElement.addEventListener(event, handleEvent); - rootElement.addEventListener(event, handleEvent); - } this.lazyEvents.delete(event); }, diff --git a/packages/@ember/deprecated-features/index.ts b/packages/@ember/deprecated-features/index.ts index 45d9c852108..f21d2b32a2a 100644 --- a/packages/@ember/deprecated-features/index.ts +++ b/packages/@ember/deprecated-features/index.ts @@ -6,5 +6,4 @@ export const ROUTER_EVENTS = !!'4.0.0'; export const JQUERY_INTEGRATION = !!'3.9.0'; export const APP_CTRL_ROUTER_PROPS = !!'3.10.0-beta.1'; -export const MOUSE_ENTER_LEAVE_MOVE_EVENTS = !!'3.13.0-beta.1'; export const ASSIGN = !!'4.0.0-beta.1';