From f78f42771f95911c8e9abc8ab6b70b3e800e25d1 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Wed, 16 May 2018 20:45:05 -0700 Subject: [PATCH] Pass in style attribute to style attachment Allows passing in a safe string as a style which will be applied to the tooltip or attachment element. --- addon/components/attach-popover.js | 20 +++++++--- addon/defaults.js | 1 + addon/templates/components/attach-popover.hbs | 2 +- .../components/attach-tooltip-test.js | 40 +++++++++++++++++++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/addon/components/attach-popover.js b/addon/components/attach-popover.js index ff01bee7..89cf49c3 100644 --- a/addon/components/attach-popover.js +++ b/addon/components/attach-popover.js @@ -5,9 +5,10 @@ import { cancel, debounce, later, next, run } from '@ember/runloop'; import { computed, observer } from '@ember/object'; import { getOwner } from '@ember/application'; import { guidFor } from '@ember/object/internals'; -import { htmlSafe } from '@ember/string'; +import { htmlSafe, isHTMLSafe } from '@ember/string'; import { stripInProduction } from 'ember-attacher/-debug/helpers'; import { warn } from '@ember/debug'; +import { isEmpty } from '@ember/utils'; export default Component.extend({ layout, @@ -56,6 +57,7 @@ export default Component.extend({ showDelay: DEFAULTS.showDelay, showDuration: DEFAULTS.showDuration, showOn: DEFAULTS.showOn, + style: DEFAULTS.style, /** * ================== PRIVATE IMPLEMENTATION DETAILS ================== @@ -110,6 +112,18 @@ export default Component.extend({ return `ember-attacher-${this.get('animation')} ${this.get('class') || ''} ${showOrHideClass}`; }), + _style: computed('style', '_transitionDuration', function () { + const style = this.get('style'); + const transitionDuration = this.get('_transitionDuration'); + warn( + '@ember/string/htmlSafe must be used for any `style` passed to ember-attacher', + isEmpty(style) || isHTMLSafe(style), + { id: 'ember-attacher-require-html-safe-style' } + ); + + return htmlSafe(`transition-duration: ${transitionDuration}ms; ${style}`); + }), + // This is memoized so it can be used by both attach-popover and attach-tooltip _config: computed(function() { return getOwner(this).resolveRegistration('config:environment').emberAttacher || {}; @@ -206,10 +220,6 @@ export default Component.extend({ _transitionDuration: 0, - _transitionDurationCss: computed('_transitionDuration', function() { - return htmlSafe(`transition-duration: ${this.get('_transitionDuration')}ms`); - }), - /** * ================== LIFECYCLE HOOKS ================== */ diff --git a/addon/defaults.js b/addon/defaults.js index 27f12b04..2b669bc8 100644 --- a/addon/defaults.js +++ b/addon/defaults.js @@ -18,5 +18,6 @@ export default { showDelay: 0, showDuration: 300, showOn: 'mouseenter focus', + style: null, tooltipClass: 'ember-attacher-popper ember-attacher-tooltip' }; diff --git a/addon/templates/components/attach-popover.hbs b/addon/templates/components/attach-popover.hbs index c0fa8849..5d20e4e1 100644 --- a/addon/templates/components/attach-popover.hbs +++ b/addon/templates/components/attach-popover.hbs @@ -11,7 +11,7 @@ popperTarget=_currentTarget registerAPI=(action 'registerAPI') renderInPlace=renderInPlace as |emberPopper|}} -
+
{{yield (hash emberPopper=emberPopper hide=(action 'hide'))}} {{#if arrow}} diff --git a/tests/integration/components/attach-tooltip-test.js b/tests/integration/components/attach-tooltip-test.js index 764d50be..1fc4d4c2 100644 --- a/tests/integration/components/attach-tooltip-test.js +++ b/tests/integration/components/attach-tooltip-test.js @@ -3,6 +3,7 @@ import hbs from 'htmlbars-inline-precompile'; import { find } from 'ember-native-dom-helpers'; import { getOwner } from '@ember/application'; import { moduleForComponent, test } from 'ember-qunit'; +import { htmlSafe } from '@ember/string'; QUnit.assert.contains = function(actual, expected, message) { this.pushResult({ @@ -96,6 +97,45 @@ test('uses the user-supplied default tooltip class', function(assert) { ); }); +test('uses style passed in by user', function (assert) { + this.set('style', htmlSafe('cursor: pointer;')); + this.render(hbs` +
+ {{#attach-tooltip id='tooltip-with-style' style=style}} + tooltip text + {{/attach-tooltip}} +
+ +
+ {{#attach-tooltip id='tooltip-with-no-style'}} + tooltip text + {{/attach-tooltip}} +
+ `); + + const tooltipWithStyle = find('#tooltip-with-style > .ember-attacher-tooltip'); + + assert.equal( + tooltipWithStyle.style.getPropertyValue('cursor'), + 'pointer', + 'it adds the user style to tooltips' + ); + + assert.equal( + tooltipWithStyle.style.getPropertyValue('transition-duration'), + '0ms', + 'it adds the default style to tooltips' + ); + + const tooltipWithNoStyle = find('#tooltip-with-no-style > .ember-attacher-tooltip'); + + assert.equal( + tooltipWithNoStyle.style.getPropertyValue('transition-duration'), + '0ms', + 'it adds the default style to tooltips with no user style' + ); +}); + test('adds aria-describedby to the target', function(assert) { this.set('showTooltip', true);