diff --git a/.eslintrc.js b/.eslintrc.js
index be39b117..2bd66417 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -17,5 +17,10 @@ module.exports = {
'ember-suave/no-direct-property-access': 1,
'ember-suave/require-access-in-comments': 0,
'prefer-const': 2,
+ 'indent': ['error', 2, {
+ "CallExpression": { 'arguments': 'first' },
+ 'FunctionDeclaration': { 'parameters': 'first' },
+ 'FunctionExpression': { 'parameters': 'first' }
+ }],
}
};
diff --git a/tests/index.html b/tests/index.html
index 5209b852..57560c2a 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -14,6 +14,19 @@
+
+
{{content-for "head-footer"}}
{{content-for "test-head-footer"}}
diff --git a/tests/integration/components/ember-attacher/hide-on-mouseleave-test.js b/tests/integration/components/ember-attacher/hide-on-mouseleave-test.js
new file mode 100644
index 00000000..faef011a
--- /dev/null
+++ b/tests/integration/components/ember-attacher/hide-on-mouseleave-test.js
@@ -0,0 +1,218 @@
+import hbs from 'htmlbars-inline-precompile';
+import wait from 'ember-test-helpers/wait';
+import { click, find, triggerEvent } from 'ember-native-dom-helpers';
+import { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('ember-attacher', 'Integration | Component | hideOn "mouseleave"', {
+ integration: true
+});
+
+test('hides when the mouse leaves the target', function(assert) {
+ assert.expect(2);
+
+ this.render(hbs`
+
+ {{#ember-attacher id='attachment'
+ hideOn='mouseleave'
+ isShown=true}}
+ hideOn mouseleave
+ {{/ember-attacher}}
+
+ `);
+
+ const innerAttacher = find('#attachment > .inner');
+
+ assert.equal(innerAttacher.style.display, '', 'Initially shown');
+
+ return triggerEvent('#target', 'mouseleave').then(() => {
+ assert.equal(innerAttacher.style.display, 'none', 'Now hidden');
+ });
+});
+
+test("with interactive=true: doesn't hide if mouse over target or attachment", function(assert) {
+ assert.expect(5);
+
+ this.render(hbs`
+
+ something else in the target
+
+ {{#ember-attacher id='hello'
+ hideOn='mouseleave'
+ interactive=true
+ isShown=true}}
+ hideOn mouseleave
+ {{/ember-attacher}}
+
+
+
+ `);
+
+ const innerAttacher = find('#hello > .inner');
+ const target = find('#target');
+
+ assert.equal(innerAttacher.style.display, '', 'Initially shown');
+
+ return triggerEvent(target, 'mouseleave').then(() => {
+ // Sanity check still shown
+ assert.equal(innerAttacher.style.display, '', 'Still shown after mouseleave');
+
+ return triggerEvent(document, 'mousemove', { target: innerAttacher }).then(() => {
+ assert.equal(innerAttacher.style.display, '', 'Still shown after mousemove into attachment');
+
+ return triggerEvent(document, 'mousemove', { target: find('#other') }).then(() => {
+ assert.equal(innerAttacher.style.display, '', 'Still shown after mousemove into target');
+
+ return triggerEvent(document, 'mousemove', { target: find('#outside') }).then(() => {
+ assert.equal(innerAttacher.style.display,
+ 'none',
+ 'Hidden after mousemove outside target and attachment');
+ });
+ });
+ });
+ });
+});
+
+// Regression test
+test('with interactive=true: still hides when mouse leaves target + attachment '
+ + 'after a manual hide', function(assert) {
+ assert.expect(4);
+
+ this.set('isShown', true);
+
+ this.render(hbs`
+
+ {{#ember-attacher id='hello'
+ hideOn='mouseleave'
+ interactive=true
+ isShown=isShown
+ onChange=(action (mut isShown)) as |attacher|}}
+ hideOn mouseleave
+
+
+ {{/ember-attacher}}
+
+
+
+ `);
+
+ const innerAttacher = find('#hello > .inner');
+
+ assert.equal(innerAttacher.style.display, '', 'Initially shown');
+
+ return click(find('#manual-hide')).then(() => {
+ assert.equal(innerAttacher.style.display, 'none', 'Hidden after manual hide');
+
+ // Make visible again
+ this.set('isShown', true);
+
+ // Need to wait for mouseleave listener to be set, then trigger it
+ return wait().then(() => {
+ return triggerEvent('#target', 'mouseleave').then(() => {
+ // Sanity check. Also note how the mouseleave didn't trigger a hide event
+ assert.equal(innerAttacher.style.display, '', 'Shown again');
+
+ return triggerEvent(document, 'mousemove', { target: find('#outside') }).then(() => {
+ assert.equal(innerAttacher.style.display, 'none', 'Hidden after mousemove');
+ });
+ });
+ });
+ });
+});
+
+test('with interactive=true and isOffset=false: hides if mouse between '
+ + 'target and attachment', function(assert) {
+ assert.expect(3);
+
+ this.render(hbs`
+
+
+
+ {{#ember-attacher id='attachment'
+ hideOn='mouseleave'
+ interactive=true
+ placement='bottom'
+ isShown=true}}
+ hideOn mouseleave
+ {{/ember-attacher}}
+
+ `);
+
+ const innerAttacher = find('#attachment > .inner');
+ const target = find('#target');
+
+ assert.equal(innerAttacher.style.display, '', 'Initially shown');
+
+ return triggerEvent(target, 'mouseleave').then(() => {
+ // Sanity check still shown
+ assert.equal(innerAttacher.style.display, '', 'Still shown after mouseleave');
+
+ const attachmentPosition = find('#attachment').getBoundingClientRect();
+
+ return triggerEvent(document,
+ 'mousemove',
+ {
+ clientX: attachmentPosition.left + 1,
+ clientY: attachmentPosition.top - 1
+ }).then(() => {
+ assert.equal(innerAttacher.style.display, 'none', 'Hidden after mousemove between');
+ });
+ });
+});
+
+test("with interactive=true and isOffset=true: doesn't hide if mouse between "
+ + 'target and attachment', function(assert) {
+ assert.expect(4);
+
+ this.render(hbs`
+
+
+
+ {{#ember-attacher id='attachment'
+ hideOn='mouseleave'
+ interactive=true
+ isOffset=true
+ placement='bottom'
+ isShown=true}}
+ hideOn mouseleave
+ {{/ember-attacher}}
+
+ `);
+
+ const innerAttacher = find('#attachment > .inner');
+ const target = find('#target');
+
+ assert.equal(innerAttacher.style.display, '', 'Initially shown');
+
+ return triggerEvent(target, 'mouseleave').then(() => {
+ // Sanity check still shown
+ assert.equal(innerAttacher.style.display, '', 'Still shown after mouseleave');
+
+ const attachmentPosition = find('#attachment').getBoundingClientRect();
+
+ return triggerEvent(document,
+ 'mousemove',
+ {
+ clientX: attachmentPosition.left + 1,
+ clientY: attachmentPosition.top - 1
+ }).then(() => {
+ assert.equal(innerAttacher.style.display, '', 'Still shown after mousemove into between');
+
+ return triggerEvent(document,
+ 'mousemove',
+ {
+ clientX: attachmentPosition.left - 1,
+ clientY: attachmentPosition.bottom + 1
+ }).then(() => {
+ assert.equal(innerAttacher.style.display, 'none', 'hidden after mousemove outside');
+ });
+ });
+ });
+});