/** * @class Ext.core.Element */ Ext.applyIf(Ext.core.Element.prototype, { // @private override base Ext.util.Animate mixin for animate for backwards compatibility animate: function(config) { var me = this; if (!me.id) { me = Ext.get(me.dom); } if (Ext.fx.Manager.hasFxBlock(me.id)) { return me; } Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config))); return this; }, // @private override base Ext.util.Animate mixin for animate for backwards compatibility anim: function(config) { if (!Ext.isObject(config)) { return (config) ? {} : false; } var me = this, duration = config.duration || Ext.fx.Anim.prototype.duration, easing = config.easing || 'ease', animConfig; if (config.stopAnimation) { me.stopAnimation(); } Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id)); // Clear any 'paused' defaults. Ext.fx.Manager.setFxDefaults(me.id, { delay: 0 }); animConfig = { target: me, remove: config.remove, alternate: config.alternate || false, duration: duration, easing: easing, callback: config.callback, listeners: config.listeners, iterations: config.iterations || 1, scope: config.scope, block: config.block, concurrent: config.concurrent, delay: config.delay || 0, paused: true, keyframes: config.keyframes, from: config.from || {}, to: Ext.apply({}, config) }; Ext.apply(animConfig.to, config.to); // Anim API properties - backward compat delete animConfig.to.to; delete animConfig.to.from; delete animConfig.to.remove; delete animConfig.to.alternate; delete animConfig.to.keyframes; delete animConfig.to.iterations; delete animConfig.to.listeners; delete animConfig.to.target; delete animConfig.to.paused; delete animConfig.to.callback; delete animConfig.to.scope; delete animConfig.to.duration; delete animConfig.to.easing; delete animConfig.to.concurrent; delete animConfig.to.block; delete animConfig.to.stopAnimation; delete animConfig.to.delay; return animConfig; }, /** * Slides the element into view. An anchor point can be optionally passed to set the point of * origin for the slide effect. This function automatically handles wrapping the element with * a fixed-size container if needed. See the Fx class overview for valid anchor point options. * Usage: *<pre><code> // default: slide the element in from the top el.slideIn(); // custom: slide the element in from the right with a 2-second duration el.slideIn('r', { duration: 2 }); // common config options shown with default values el.slideIn('t', { easing: 'easeOut', duration: 500 }); </code></pre> * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't') * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ slideIn: function(anchor, obj, slideOut) { var me = this, elStyle = me.dom.style, beforeAnim, wrapAnim; anchor = anchor || "t"; obj = obj || {}; beforeAnim = function() { var animScope = this, listeners = obj.listeners, box, position, restoreSize, wrap, anim; if (!slideOut) { me.fixDisplay(); } box = me.getBox(); if ((anchor == 't' || anchor == 'b') && box.height == 0) { box.height = me.dom.scrollHeight; } else if ((anchor == 'l' || anchor == 'r') && box.width == 0) { box.width = me.dom.scrollWidth; } position = me.getPositioning(); me.setSize(box.width, box.height); wrap = me.wrap({ style: { visibility: slideOut ? 'visible' : 'hidden' } }); wrap.setPositioning(position); if (wrap.isStyle('position', 'static')) { wrap.position('relative'); } me.clearPositioning('auto'); wrap.clip(); // This element is temporarily positioned absolute within its wrapper. // Restore to its default, CSS-inherited visibility setting. // We cannot explicitly poke visibility:visible into its style because that overrides the visibility of the wrap. me.setStyle({ visibility: '', position: 'absolute' }); if (slideOut) { wrap.setSize(box.width, box.height); } switch (anchor) { case 't': anim = { from: { width: box.width + 'px', height: '0px' }, to: { width: box.width + 'px', height: box.height + 'px' } }; elStyle.bottom = '0px'; break; case 'l': anim = { from: { width: '0px', height: box.height + 'px' }, to: { width: box.width + 'px', height: box.height + 'px' } }; elStyle.right = '0px'; break; case 'r': anim = { from: { x: box.x + box.width, width: '0px', height: box.height + 'px' }, to: { x: box.x, width: box.width + 'px', height: box.height + 'px' } }; break; case 'b': anim = { from: { y: box.y + box.height, width: box.width + 'px', height: '0px' }, to: { y: box.y, width: box.width + 'px', height: box.height + 'px' } }; break; case 'tl': anim = { from: { x: box.x, y: box.y, width: '0px', height: '0px' }, to: { width: box.width + 'px', height: box.height + 'px' } }; elStyle.bottom = '0px'; elStyle.right = '0px'; break; case 'bl': anim = { from: { x: box.x + box.width, width: '0px', height: '0px' }, to: { x: box.x, width: box.width + 'px', height: box.height + 'px' } }; elStyle.right = '0px'; break; case 'br': anim = { from: { x: box.x + box.width, y: box.y + box.height, width: '0px', height: '0px' }, to: { x: box.x, y: box.y, width: box.width + 'px', height: box.height + 'px' } }; break; case 'tr': anim = { from: { y: box.y + box.height, width: '0px', height: '0px' }, to: { y: box.y, width: box.width + 'px', height: box.height + 'px' } }; elStyle.bottom = '0px'; break; } wrap.show(); wrapAnim = Ext.apply({}, obj); delete wrapAnim.listeners; wrapAnim = Ext.create('Ext.fx.Anim', Ext.applyIf(wrapAnim, { target: wrap, duration: 500, easing: 'ease-out', from: slideOut ? anim.to : anim.from, to: slideOut ? anim.from : anim.to })); // In the absence of a callback, this listener MUST be added first wrapAnim.on('afteranimate', function() { if (slideOut) { me.setPositioning(position); if (obj.useDisplay) { me.setDisplayed(false); } else { me.hide(); } } else { me.clearPositioning(); me.setPositioning(position); } if (wrap.dom) { wrap.dom.parentNode.insertBefore(me.dom, wrap.dom); wrap.remove(); } me.setSize(box.width, box.height); animScope.end(); }); // Add configured listeners after if (listeners) { wrapAnim.on(listeners); } }; me.animate({ duration: obj.duration ? obj.duration * 2 : 1000, listeners: { beforeanimate: { fn: beforeAnim }, afteranimate: { fn: function() { if (wrapAnim && wrapAnim.running) { wrapAnim.end(); } } } } }); return me; }, /** * Slides the element out of view. An anchor point can be optionally passed to set the end point * for the slide effect. When the effect is completed, the element will be hidden (visibility = * 'hidden') but block elements will still take up space in the document. The element must be removed * from the DOM using the 'remove' config option if desired. This function automatically handles * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options. * Usage: *<pre><code> // default: slide the element out to the top el.slideOut(); // custom: slide the element out to the right with a 2-second duration el.slideOut('r', { duration: 2 }); // common config options shown with default values el.slideOut('t', { easing: 'easeOut', duration: 500, remove: false, useDisplay: false }); </code></pre> * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't') * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ slideOut: function(anchor, o) { return this.slideIn(anchor, o, true); }, /** * Fades the element out while slowly expanding it in all directions. When the effect is completed, the * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document. * Usage: *<pre><code> // default el.puff(); // common config options shown with default values el.puff({ easing: 'easeOut', duration: 500, useDisplay: false }); </code></pre> * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ puff: function(obj) { var me = this, beforeAnim; obj = Ext.applyIf(obj || {}, { easing: 'ease-out', duration: 500, useDisplay: false }); beforeAnim = function() { me.clearOpacity(); me.show(); var box = me.getBox(), fontSize = me.getStyle('fontSize'), position = me.getPositioning(); this.to = { width: box.width * 2, height: box.height * 2, x: box.x - (box.width / 2), y: box.y - (box.height /2), opacity: 0, fontSize: '200%' }; this.on('afteranimate',function() { if (me.dom) { if (obj.useDisplay) { me.setDisplayed(false); } else { me.hide(); } me.clearOpacity(); me.setPositioning(position); me.setStyle({fontSize: fontSize}); } }); }; me.animate({ duration: obj.duration, easing: obj.easing, listeners: { beforeanimate: { fn: beforeAnim } } }); return me; }, /** * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television). * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired. * Usage: *<pre><code> // default el.switchOff(); // all config options shown with default values el.switchOff({ easing: 'easeIn', duration: .3, remove: false, useDisplay: false }); </code></pre> * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ switchOff: function(obj) { var me = this, beforeAnim; obj = Ext.applyIf(obj || {}, { easing: 'ease-in', duration: 500, remove: false, useDisplay: false }); beforeAnim = function() { var animScope = this, size = me.getSize(), xy = me.getXY(), keyframe, position; me.clearOpacity(); me.clip(); position = me.getPositioning(); keyframe = Ext.create('Ext.fx.Animator', { target: me, duration: obj.duration, easing: obj.easing, keyframes: { 33: { opacity: 0.3 }, 66: { height: 1, y: xy[1] + size.height / 2 }, 100: { width: 1, x: xy[0] + size.width / 2 } } }); keyframe.on('afteranimate', function() { if (obj.useDisplay) { me.setDisplayed(false); } else { me.hide(); } me.clearOpacity(); me.setPositioning(position); me.setSize(size); animScope.end(); }); }; me.animate({ duration: (obj.duration * 2), listeners: { beforeanimate: { fn: beforeAnim } } }); return me; }, /** * Shows a ripple of exploding, attenuating borders to draw attention to an Element. * Usage: <pre><code> // default: a single light blue ripple el.frame(); // custom: 3 red ripples lasting 3 seconds total el.frame("#ff0000", 3, { duration: 3 }); // common config options shown with default values el.frame("#C3DAF9", 1, { duration: 1 //duration of each individual ripple. // Note: Easing is not configurable and will be ignored if included }); </code></pre> * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9'). * @param {Number} count (optional) The number of ripples to display (defaults to 1) * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ frame : function(color, count, obj){ var me = this, beforeAnim; color = color || '#C3DAF9'; count = count || 1; obj = obj || {}; beforeAnim = function() { me.show(); var animScope = this, box = me.getBox(), proxy = Ext.getBody().createChild({ style: { position : 'absolute', 'pointer-events': 'none', 'z-index': 35000, border : '0px solid ' + color } }), proxyAnim; proxyAnim = Ext.create('Ext.fx.Anim', { target: proxy, duration: obj.duration || 1000, iterations: count, from: { top: box.y, left: box.x, borderWidth: 0, opacity: 1, height: box.height, width: box.width }, to: { top: box.y - 20, left: box.x - 20, borderWidth: 10, opacity: 0, height: box.height + 40, width: box.width + 40 } }); proxyAnim.on('afteranimate', function() { proxy.remove(); animScope.end(); }); }; me.animate({ duration: (obj.duration * 2) || 2000, listeners: { beforeanimate: { fn: beforeAnim } } }); return me; }, /** * Slides the element while fading it out of view. An anchor point can be optionally passed to set the * ending point of the effect. * Usage: *<pre><code> // default: slide the element downward while fading out el.ghost(); // custom: slide the element out to the right with a 2-second duration el.ghost('r', { duration: 2 }); // common config options shown with default values el.ghost('b', { easing: 'easeOut', duration: 500 }); </code></pre> * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b') * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ ghost: function(anchor, obj) { var me = this, beforeAnim; anchor = anchor || "b"; beforeAnim = function() { var width = me.getWidth(), height = me.getHeight(), xy = me.getXY(), position = me.getPositioning(), to = { opacity: 0 }; switch (anchor) { case 't': to.y = xy[1] - height; break; case 'l': to.x = xy[0] - width; break; case 'r': to.x = xy[0] + width; break; case 'b': to.y = xy[1] + height; break; case 'tl': to.x = xy[0] - width; to.y = xy[1] - height; break; case 'bl': to.x = xy[0] - width; to.y = xy[1] + height; break; case 'br': to.x = xy[0] + width; to.y = xy[1] + height; break; case 'tr': to.x = xy[0] + width; to.y = xy[1] - height; break; } this.to = to; this.on('afteranimate', function () { if (me.dom) { me.hide(); me.clearOpacity(); me.setPositioning(position); } }); }; me.animate(Ext.applyIf(obj || {}, { duration: 500, easing: 'ease-out', listeners: { beforeanimate: { fn: beforeAnim } } })); return me; }, /** * Highlights the Element by setting a color (applies to the background-color by default, but can be * changed using the "attr" config option) and then fading back to the original color. If no original * color is available, you should provide the "endColor" config option which will be cleared after the animation. * Usage: <pre><code> // default: highlight background to yellow el.highlight(); // custom: highlight foreground text to blue for 2 seconds el.highlight("0000ff", { attr: 'color', duration: 2 }); // common config options shown with default values el.highlight("ffff9c", { attr: "backgroundColor", //can be any valid CSS property (attribute) that supports a color value endColor: (current color) or "ffffff", easing: 'easeIn', duration: 1000 }); </code></pre> * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c') * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.core.Element} The Element */ highlight: function(color, o) { var me = this, dom = me.dom, from = {}, restore, to, attr, lns, event, fn; o = o || {}; lns = o.listeners || {}; attr = o.attr || 'backgroundColor'; from[attr] = color || 'ffff9c'; if (!o.to) { to = {}; to[attr] = o.endColor || me.getColor(attr, 'ffffff', ''); } else { to = o.to; } // Don't apply directly on lns, since we reference it in our own callbacks below o.listeners = Ext.apply(Ext.apply({}, lns), { beforeanimate: function() { restore = dom.style[attr]; me.clearOpacity(); me.show(); event = lns.beforeanimate; if (event) { fn = event.fn || event; return fn.apply(event.scope || lns.scope || window, arguments); } }, afteranimate: function() { if (dom) { dom.style[attr] = restore; } event = lns.afteranimate; if (event) { fn = event.fn || event; fn.apply(event.scope || lns.scope || window, arguments); } } }); me.animate(Ext.apply({}, o, { duration: 1000, easing: 'ease-in', from: from, to: to })); return me; }, /** * @deprecated 4.0 * Creates a pause before any subsequent queued effects begin. If there are * no effects queued after the pause it will have no effect. * Usage: <pre><code> el.pause(1); </code></pre> * @param {Number} seconds The length of time to pause (in seconds) * @return {Ext.Element} The Element */ pause: function(ms) { var me = this; Ext.fx.Manager.setFxDefaults(me.id, { delay: ms }); return me; }, /** * Fade an element in (from transparent to opaque). The ending opacity can be specified * using the <tt>{@link #endOpacity}</tt> config option. * Usage: <pre><code> // default: fade in from opacity 0 to 100% el.fadeIn(); // custom: fade in from opacity 0 to 75% over 2 seconds el.fadeIn({ endOpacity: .75, duration: 2}); // common config options shown with default values el.fadeIn({ endOpacity: 1, //can be any value between 0 and 1 (e.g. .5) easing: 'easeOut', duration: 500 }); </code></pre> * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.Element} The Element */ fadeIn: function(o) { this.animate(Ext.apply({}, o, { opacity: 1 })); return this; }, /** * Fade an element out (from opaque to transparent). The ending opacity can be specified * using the <tt>{@link #endOpacity}</tt> config option. Note that IE may require * <tt>{@link #useDisplay}:true</tt> in order to redisplay correctly. * Usage: <pre><code> // default: fade out from the element's current opacity to 0 el.fadeOut(); // custom: fade out from the element's current opacity to 25% over 2 seconds el.fadeOut({ endOpacity: .25, duration: 2}); // common config options shown with default values el.fadeOut({ endOpacity: 0, //can be any value between 0 and 1 (e.g. .5) easing: 'easeOut', duration: 500, remove: false, useDisplay: false }); </code></pre> * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.Element} The Element */ fadeOut: function(o) { this.animate(Ext.apply({}, o, { opacity: 0 })); return this; }, /** * @deprecated 4.0 * Animates the transition of an element's dimensions from a starting height/width * to an ending height/width. This method is a convenience implementation of {@link #shift}. * Usage: <pre><code> // change height and width to 100x100 pixels el.scale(100, 100); // common config options shown with default values. The height and width will default to // the element's existing values if passed as null. el.scale( [element's width], [element's height], { easing: 'easeOut', duration: .35 } ); </code></pre> * @param {Number} width The new width (pass undefined to keep the original width) * @param {Number} height The new height (pass undefined to keep the original height) * @param {Object} options (optional) Object literal with any of the Fx config options * @return {Ext.Element} The Element */ scale: function(w, h, o) { this.animate(Ext.apply({}, o, { width: w, height: h })); return this; }, /** * @deprecated 4.0 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity. * Any of these properties not specified in the config object will not be changed. This effect * requires that at least one new dimension, position or opacity setting must be passed in on * the config object in order for the function to have any effect. * Usage: <pre><code> // slide the element horizontally to x position 200 while changing the height and opacity el.shift({ x: 200, height: 50, opacity: .8 }); // common config options shown with default values. el.shift({ width: [element's width], height: [element's height], x: [element's x position], y: [element's y position], opacity: [element's opacity], easing: 'easeOut', duration: .35 }); </code></pre> * @param {Object} options Object literal with any of the Fx config options * @return {Ext.Element} The Element */ shift: function(config) { this.animate(config); return this; } });