/** * @class Ext.ux.Spotlight * UX used to provide a spotlight around a specified component/element. */ Ext.define('Ext.ux.Spotlight', { extend: 'Object', /** * @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, /** * Create all the elements for the spotlight */ createElements: function() { var body = Ext.getBody(); this.right = body.createChild({ cls: this.baseCls }); this.left = body.createChild({ cls: this.baseCls }); this.top = body.createChild({ cls: this.baseCls }); this.bottom = body.createChild({ cls: this.baseCls }); this.all = Ext.create('Ext.CompositeElement', [this.right, this.left, this.top, this.bottom]); }, /** * Show the spotlight */ show: function(el, callback, scope) { //get the target element this.el = Ext.get(el); //create the elements if they don't already exist if (!this.right) { this.createElements(); } if (!this.active) { //if the spotlight is not active, show it this.all.setDisplayed(''); this.active = true; Ext.EventManager.onWindowResize(this.syncSize, this); this.applyBounds(this.animate, false); } else { //if the spotlight is currently active, just move it this.applyBounds(false, false); } }, /** * Hide the spotlight */ hide: function(callback, scope) { Ext.EventManager.removeResizeListener(this.syncSize, this); this.applyBounds(this.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} animate True to reverse the animation */ applyBounds: function(animate, reverse) { var me = this, box = me.el.getBox(); //get the current view width and height var viewWidth = Ext.core.Element.getViewWidth(true); var viewHeight = Ext.core.Element.getViewHeight(true); var i = 0, config = false, from, to; //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) { var clone = Ext.clone(from); from = to; to = clone; delete clone; } if (animate) { Ext.each(['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.each(['right', 'left', 'top', 'bottom'], function(side) { me[side].setBox(Ext.apply(from[side], to[side])); }, this); } }, /** * Removes all the elements for the spotlight */ destroy: function() { Ext.destroy(this.right, this.left, this.top, this.bottom); delete this.el; delete this.all; } });