|
72 | 72 | arrowElement: '[x-arrow]', |
73 | 73 |
|
74 | 74 | // list of functions used to modify the offsets before they are applied to the popper |
75 | | - modifiers: [ 'shift', 'offset', 'preventOverflow', 'keepTogether', 'arrow', 'flip'], |
| 75 | + modifiers: [ 'shift', 'offset', 'preventOverflow', 'keepTogether', 'arrow', 'flip', 'applyStyle'], |
76 | 76 |
|
77 | 77 | modifiersIgnored: [], |
78 | 78 | }; |
|
124 | 124 | * how alter the placement when a flip is needed. (eg. in the above example, it would first flip from right to left, |
125 | 125 | * then, if even in its new placement, the popper is overlapping its trigger, it will be moved to top) |
126 | 126 | * |
127 | | - * @param {Array} [options.modifiers=[ 'shift', 'offset', 'preventOverflow', 'keepTogether', 'arrow', 'flip']] |
| 127 | + * @param {Array} [options.modifiers=[ 'shift', 'offset', 'preventOverflow', 'keepTogether', 'arrow', 'flip', 'applyStyle']] |
128 | 128 | * List of functions used to modify the data before they are applied to the popper, add your custom functions |
129 | 129 | * to this array to edit the offsets and placement. |
130 | 130 | * The function should reflect the @params and @returns of preventOverflow |
131 | 131 | * |
132 | 132 | * @param {Array} [options.modifiersIgnored=[]] |
133 | 133 | * Put here any built-in modifier name you want to exclude from the modifiers list |
134 | 134 | * The function should reflect the @params and @returns of preventOverflow |
135 | | - * |
136 | | - * @param {Function} |
137 | | - * If the last argument of Popper.js is a function, it will be executed after the initialization of the popper |
138 | | - * it's scope will be window, the first argument will be the Popper.js instance. |
139 | 135 | */ |
140 | | - function Popper(trigger, popper, options/*, callback*/) { |
| 136 | + function Popper(trigger, popper, options) { |
141 | 137 | this._trigger = trigger; |
142 | 138 | this.state = {}; |
143 | 139 |
|
144 | 140 | // if the popper variable is a configuration object, parse it to generate an HTMLElement |
145 | 141 | // generate a default popper if is not defined |
146 | 142 | var isNotDefined = popper === undefined || popper === null; |
147 | | - var isFunction = typeof popper === 'function'; |
148 | 143 | var isConfig = popper && popper.constructor.name === 'Object'; |
149 | | - if ( isNotDefined || isFunction || isConfig) { |
| 144 | + if ( isNotDefined || isConfig) { |
150 | 145 | this._popper = this.parse(isConfig ? popper : {}); |
151 | 146 | } |
152 | 147 | // otherwise, use the given HTMLElement as popper |
|
179 | 174 |
|
180 | 175 | // setup event listeners, they will take care of update the position in specific situations |
181 | 176 | this._setupEventListeners(); |
182 | | - |
183 | | - if (typeof arguments[arguments.length -1] === 'function') { |
184 | | - arguments[arguments.length -1].call(root, this); |
185 | | - } |
186 | 177 | } |
187 | 178 |
|
188 | 179 |
|
|
224 | 215 |
|
225 | 216 | data = this.runModifiers(data, this._options.modifiers); |
226 | 217 |
|
227 | | - // apply the final offsets to the popper |
228 | | - // NOTE: 1 DOM access here |
229 | | - var styles = { |
230 | | - position: data.offsets.popper.position |
231 | | - }; |
232 | | - |
233 | | - // round top and left to avoid blurry text |
234 | | - var left = Math.round(data.offsets.popper.left); |
235 | | - var top = Math.round(data.offsets.popper.top); |
236 | | - |
237 | | - // if gpuAcceleration is set to true and transform is supported, we use `translate3d` to apply the position to the popper |
238 | | - // we automatically use the supported prefixed version if needed |
239 | | - var prefixedProperty; |
240 | | - if (this._options.gpuAcceleration && (prefixedProperty = getSupportedPropertyName('transform'))) { |
241 | | - styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; |
242 | | - styles.top = 0; |
243 | | - styles.left = 0; |
244 | | - } |
245 | | - // othwerise, we use the standard `left` and `top` properties |
246 | | - else { |
247 | | - styles.left =left; |
248 | | - styles.top = top; |
| 218 | + if (typeof this.state.updateCallback === 'function') { |
| 219 | + this.state.updateCallback(data); |
249 | 220 | } |
250 | 221 |
|
251 | | - setStyle(this._popper, styles); |
| 222 | + }; |
252 | 223 |
|
253 | | - // set an attribute which will be useful to style the tooltip (use it to properly position its arrow) |
254 | | - // NOTE: 1 DOM access here |
255 | | - this._popper.setAttribute('x-placement', data.placement); |
| 224 | + /** |
| 225 | + * If a function is passed, it will be executed after the initialization of popper with as first argument the Popper instance. |
| 226 | + * @method |
| 227 | + * @memberof Popper |
| 228 | + * @param {Function} callback |
| 229 | + */ |
| 230 | + Popper.prototype.onCreate = function(callback) { |
| 231 | + // the createCallbacks return as first argument the popper instance |
| 232 | + callback(this); |
| 233 | + }; |
| 234 | + |
| 235 | + /** |
| 236 | + * If a function is passed, it will be executed after each update of popper with as first argument the set of coordinates and informations |
| 237 | + * used to style popper and its arrow. |
| 238 | + * @method |
| 239 | + * @memberof Popper |
| 240 | + * @param {Function} callback |
| 241 | + */ |
| 242 | + Popper.prototype.onUpdate = function(callback) { |
| 243 | + this.state.updateCallback = callback; |
256 | 244 | }; |
257 | 245 |
|
258 | 246 | /** |
|
565 | 553 | */ |
566 | 554 | Popper.prototype.modifiers = {}; |
567 | 555 |
|
| 556 | + /** |
| 557 | + * Apply the computed styles to the popper element |
| 558 | + * @method |
| 559 | + * @memberof Popper.modifiers |
| 560 | + * @argument {Object} data - The data object generated by `update` method |
| 561 | + * @returns {Object} The same data object |
| 562 | + */ |
| 563 | + Popper.prototype.modifiers.applyStyle = function(data) { |
| 564 | + // apply the final offsets to the popper |
| 565 | + // NOTE: 1 DOM access here |
| 566 | + var styles = { |
| 567 | + position: data.offsets.popper.position |
| 568 | + }; |
| 569 | + |
| 570 | + // round top and left to avoid blurry text |
| 571 | + var left = Math.round(data.offsets.popper.left); |
| 572 | + var top = Math.round(data.offsets.popper.top); |
| 573 | + |
| 574 | + // if gpuAcceleration is set to true and transform is supported, we use `translate3d` to apply the position to the popper |
| 575 | + // we automatically use the supported prefixed version if needed |
| 576 | + var prefixedProperty; |
| 577 | + if (this._options.gpuAcceleration && (prefixedProperty = getSupportedPropertyName('transform'))) { |
| 578 | + styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; |
| 579 | + styles.top = 0; |
| 580 | + styles.left = 0; |
| 581 | + } |
| 582 | + // othwerise, we use the standard `left` and `top` properties |
| 583 | + else { |
| 584 | + styles.left =left; |
| 585 | + styles.top = top; |
| 586 | + } |
| 587 | + |
| 588 | + setStyle(this._popper, styles); |
| 589 | + |
| 590 | + // set an attribute which will be useful to style the tooltip (use it to properly position its arrow) |
| 591 | + // NOTE: 1 DOM access here |
| 592 | + this._popper.setAttribute('x-placement', data.placement); |
| 593 | + |
| 594 | + // if the arrow modifier is required and the arrow style has been computed, apply the arrow style |
| 595 | + if (this.isModifierRequired(this.modifiers.applyStyle, this.modifiers.arrow) && data.offsets.arrow) { |
| 596 | + setStyle(data.arrowElement, data.offsets.arrow); |
| 597 | + } |
| 598 | + |
| 599 | + return data; |
| 600 | + }; |
| 601 | + |
568 | 602 | /** |
569 | 603 | * Modifier used to shift the popper on the start or end of its reference element side |
570 | 604 | * @method |
|
889 | 923 | arrowStyle.left = left; |
890 | 924 | arrowStyle.top = ''; // make sure to remove any old style from the arrow |
891 | 925 | } |
892 | | - |
893 | | - setStyle(arrow, arrowStyle); |
| 926 | + data.offsets.arrow = arrowStyle; |
| 927 | + data.arrowElement = arrow; |
894 | 928 |
|
895 | 929 | return data; |
896 | 930 | }; |
|
0 commit comments