diff --git a/js/src/dropdown.js b/js/src/dropdown.js index b05d92cf78..d37886d898 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -8,6 +8,7 @@ import * as Popper from '@popperjs/core' import { defineJQueryPlugin, + execute, getElement, getNextActiveElement, isDisabled, @@ -319,7 +320,7 @@ class Dropdown extends BaseComponent { return { ...defaultBsPopperConfig, - ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) + ...execute(this._config.popperConfig, [defaultBsPopperConfig]) } } diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 70198c81bf..a3f3377c07 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -6,7 +6,7 @@ */ import * as Popper from '@popperjs/core' -import { defineJQueryPlugin, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index' +import { defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index' import { DefaultAllowlist } from './util/sanitizer' import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' @@ -370,9 +370,7 @@ class Tooltip extends BaseComponent { } _createPopper(tip) { - const placement = typeof this._config.placement === 'function' ? - this._config.placement.call(this, tip, this._element) : - this._config.placement + const placement = execute(this._config.placement, [this, tip, this._element]) const attachment = AttachmentMap[placement.toUpperCase()] return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment)) } @@ -392,7 +390,7 @@ class Tooltip extends BaseComponent { } _resolvePossibleFunction(arg) { - return typeof arg === 'function' ? arg.call(this._element) : arg + return execute(arg, [this._element]) } _getPopperConfig(attachment) { @@ -438,7 +436,7 @@ class Tooltip extends BaseComponent { return { ...defaultBsPopperConfig, - ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) + ...execute(this._config.popperConfig, [defaultBsPopperConfig]) } } diff --git a/js/src/util/index.js b/js/src/util/index.js index 7c24116651..ad99f85ed9 100644 --- a/js/src/util/index.js +++ b/js/src/util/index.js @@ -249,10 +249,8 @@ const defineJQueryPlugin = plugin => { }) } -const execute = callback => { - if (typeof callback === 'function') { - callback() - } +const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { + return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue } const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { diff --git a/js/src/util/template-factory.js b/js/src/util/template-factory.js index c6d52a50db..16ec6c28d2 100644 --- a/js/src/util/template-factory.js +++ b/js/src/util/template-factory.js @@ -6,7 +6,7 @@ */ import { DefaultAllowlist, sanitizeHtml } from './sanitizer' -import { getElement, isElement } from '../util/index' +import { execute, getElement, isElement } from '../util/index' import SelectorEngine from '../dom/selector-engine' import Config from './config' @@ -143,7 +143,7 @@ class TemplateFactory extends Config { } _resolvePossibleFunction(arg) { - return typeof arg === 'function' ? arg(this) : arg + return execute(arg, [this]) } _putElementInTemplate(element, templateElement) { diff --git a/js/tests/unit/util/index.spec.js b/js/tests/unit/util/index.spec.js index 9f28ce0aa0..6edc494335 100644 --- a/js/tests/unit/util/index.spec.js +++ b/js/tests/unit/util/index.spec.js @@ -631,6 +631,25 @@ describe('Util', () => { Util.execute(spy) expect(spy).toHaveBeenCalled() }) + + it('should execute if arg is function & return the result', () => { + const functionFoo = (num1, num2 = 10) => num1 + num2 + const resultFoo = Util.execute(functionFoo, [4, 5]) + expect(resultFoo).toBe(9) + + const resultFoo1 = Util.execute(functionFoo, [4]) + expect(resultFoo1).toBe(14) + + const functionBar = () => 'foo' + const resultBar = Util.execute(functionBar) + expect(resultBar).toBe('foo') + }) + + it('should not execute if arg is not function & return default argument', () => { + const foo = 'bar' + expect(Util.execute(foo)).toBe('bar') + expect(Util.execute(foo, [], 4)).toBe(4) + }) }) describe('executeAfterTransition', () => {