/** * @class Ext.ux.Spotlight * UX used to provide a spotlight around a specified component/element. */ Ext.define('Ext.ux.Spotlight', { /** * @private * The baseCls for the spotlight elements */ baseCls: 'x-spotlight', /** * @cfg animate {Boolean} True to animate the spotlight change * (defaults to true) */ animate: true, /** * @cfg duration {Integer} The duration of the animation, in milliseconds * (defaults to 250) */ duration: 250, /** * @cfg easing {String} The type of easing for the spotlight animatation * (defaults to null) */ easing: null, /** * @private * True if the spotlight is active on the element */ active: false, constructor: function(config){ Ext.apply(this, config); }, /** * Create all the elements for the spotlight */ createElements: function() { var me = this, baseCls = me.baseCls, body = Ext.getBody(); me.right = body.createChild({ cls: baseCls }); me.left = body.createChild({ cls: baseCls }); me.top = body.createChild({ cls: baseCls }); me.bottom = body.createChild({ cls: baseCls }); me.all = Ext.create('Ext.CompositeElement', [me.right, me.left, me.top, me.bottom]); }, /** * Show the spotlight */ show: function(el, callback, scope) { var me = this; //get the target element me.el = Ext.get(el); //create the elements if they don't already exist if (!me.right) { me.createElements(); } if (!me.active) { //if the spotlight is not active, show it me.all.setDisplayed(''); me.active = true; Ext.EventManager.onWindowResize(me.syncSize, me); me.applyBounds(me.animate, false); } else { //if the spotlight is currently active, just move it me.applyBounds(false, false); } }, /** * Hide the spotlight */ hide: function(callback, scope) { var me = this; Ext.EventManager.removeResizeListener(me.syncSize, me); me.applyBounds(me.animate, true); }, /** * Resizes the spotlight with the window size. */ syncSize: function() { this.applyBounds(false, false); }, /** * Resizes the spotlight depending on the arguments * @param {Boolean} animate True to animate the changing of the bounds * @param {Boolean} reverse True to reverse the animation */ applyBounds: function(animate, reverse) { var me = this, box = me.el.getBox(), //get the current view width and height viewWidth = Ext.Element.getViewWidth(true), viewHeight = Ext.Element.getViewHeight(true), i = 0, config = false, from, to, clone; //where the element should start (if animation) from = { right: { x: box.right, y: viewHeight, width: (viewWidth - box.right), height: 0 }, left: { x: 0, y: 0, width: box.x, height: 0 }, top: { x: viewWidth, y: 0, width: 0, height: box.y }, bottom: { x: 0, y: (box.y + box.height), width: 0, height: (viewHeight - (box.y + box.height)) + 'px' } }; //where the element needs to finish to = { right: { x: box.right, y: box.y, width: (viewWidth - box.right) + 'px', height: (viewHeight - box.y) + 'px' }, left: { x: 0, y: 0, width: box.x + 'px', height: (box.y + box.height) + 'px' }, top: { x: box.x, y: 0, width: (viewWidth - box.x) + 'px', height: box.y + 'px' }, bottom: { x: 0, y: (box.y + box.height), width: (box.x + box.width) + 'px', height: (viewHeight - (box.y + box.height)) + 'px' } }; //reverse the objects if (reverse) { clone = Ext.clone(from); from = to; to = clone; } if (animate) { Ext.Array.forEach(['right', 'left', 'top', 'bottom'], function(side) { me[side].setBox(from[side]); me[side].animate({ duration: me.duration, easing: me.easing, to: to[side] }); }, this); } else { Ext.Array.forEach(['right', 'left', 'top', 'bottom'], function(side) { me[side].setBox(Ext.apply(from[side], to[side])); me[side].repaint(); }, this); } }, /** * Removes all the elements for the spotlight */ destroy: function() { var me = this; Ext.destroy(me.right, me.left, me.top, me.bottom); delete me.el; delete me.all; } });