/*
|--------------------------------------------------------------------------
| Amedia Creative Frontend Framework > Coverflow
|--------------------------------------------------------------------------
|
| @package		Amedia Creative
| @subpackage	Frontend Framework
| @company		Amedia Creative, Inc.
| @phone		310/651/8733
| @fax			310/388/1210
| @author		Joey Avino
| @email		joey@amediacreative.com
| @link			http://www.amediacreative.com
| @copyright	2008 Amedia Creative, Inc.
| @requires 	mootools.1.2.js
|
*/

/*
|--------------------------------------------------------------------------
| Amedia Creative Frontend Framework > Coverflow > Core JavaScript
|--------------------------------------------------------------------------
|
*/


	/**
	* Class to initalize the coverflow and make it active.
	* This function has a lot of parameters that can be set
	* in the call
	*
	* @name 	Coverflow
	* @access 	public
	* @param 	var-type none
	* @return 	none
	* @author 	Joey Avino
	* @email	joey@amediacreative.com
	*/
	var coverflow = new Class({

		Implements: [Events, Options],

		options: {

			on_start: $empty,
			on_click_view: $empty,
			on_auto_play: $empty,
			on_auto_stop: $empty,
			on_request: $empty,
			on_resized: $empty,
			on_empty_init: $empty,
			reflection: 0.4, 				// Changes the reflection of the coverflow. 0 for nohting.
			height_ratio: 0.6, 				// Will move the controls down.
			offset_y: 0, 					// Will move the images down/
			start_index: 0, 				// This controls which card the coverflow starts on.
			interval: 3000, 				// This interval is for the play/stop command.
			factor: 115, 					// A factor of 176 made my 400x300 images their actual size.
			use_caption: false,				// Shows captions.
			use_resize: false,				// Needs to match window resize.
			use_slider: false,				// Will hide/show the slider.
			use_window_resize: false,		// Will hide/show the fullscreen option.
			use_mouse_wheel: true,			// Will allow you to use the mouse wheel.
			use_key_input: false,			// Will allow you to use arrow keys to work the coverflow.
			use_viewer: false,
			use_auto_play: true				// Will hide/show the play/stop option.

		},

		/**
		* This function initializes the coverflow
		*
		* @name 	Initialize
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		initialize: function(element, options) {

			this.coverflow_element = element;
			this.setOptions(options);
			this.foc = 150;
			this.factor = this.options.factor;
			this.offY = this.options.offset_y;
			this.isFull = false;
			this.isAutoPlay = false;
			this.isLoading = false;
			this.inMotion = false;

			this.coverflow_element.addClass('coverflow').setStyles({

				'height': this.coverflow_element.getSize().x*this.options.height_ratio,
				'opacity': 0

			});

			if (this.options.use_window_resize) window.addEvent('resize', this.update.bind(this, 'init'));
			if (this.options.use_mouse_wheel || this.options.use_slider) this.coverflow_element.addEvent('mousewheel', this.wheel_to.bind(this));
			if (this.options.use_key_input) document.addEvent('keydown', this.key_to.bind(this));

			this.get_elements(this.coverflow_element);

		},

		/**
		* Function to clear the Initialization.
		*
		* @name 	Clear Init
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		clear_init: function() {

			this.fireEvent('emptyinit');

		},

		/**
		* Function to clear the Initialization.
		*
		* @name 	Clear Init
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		get_elements: function(el) {

			this.master = {'images':[]};
			var els = el.getChildren();

			if (!els.length) {

				this.clear_init();
				return;

			}

			$$(els).each(function(el) {

				var hash = $H(el.getElement('img').getProperties('src','title','alt','longdesc'));
				if (el.get('tag') == 'a') { hash.combine(el.getProperties('href','rel','target')); }

				this.master['images'].push(hash.getClean());
				el.dispose();

			}, this);

			this.clear_main();

		},

		/**
		* Clear's the coverflow.
		*
		* @name 	Clear Main
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		clear_main: function() {

			if (this.cap)
				this.cap.fade(0);

			if (this.nav) {

				new Fx.Tween(this.nav, {

					'onComplete': function() {

						this.coverflow_element.empty();
						this.create_ani_obj();

					}.bind(this)
				}).start('bottom', -50);
			}

			if (!this.nav && !this.cap) {

				this.coverflow_element.empty();
				this.create_ani_obj();

			}
		},

		/**
		* Clear's the coverflow.
		*
		* @name 	Clear Main
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		get_coverflow_element: function(key) {

			var els = [];

			this.master.images.each(function(el) { 

				els.push(el[key]); 

			});

			return els;

		},

		/**
		* Clear's the coverflow animation object.
		*
		* @name 	Create Ani Object
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		create_ani_obj: function() {

			this.aniFx = new Fx.Value({

				'transition': Fx.Transitions.Expo.easeOut,
				'link': 'cancel',
				'duration': 750,
				onMotion: this.process.bind(this),
				'on_start': this.flow_start.bind(this),
				'onComplete': this.flow_complete.bind(this)

			});

			this.add_loader();

		},

		/**
		* Adds the preloader image and fadeout
		*
		* @name 	Add Loader
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		add_loader: function() {

			this.coverflow_element.store('height', this.coverflow_element.getSize().y);
			this.loader = new Element('div',{'class':'loader'}).inject(this.coverflow_element);

			new Fx.Tween(this.coverflow_element, {

				'duration': 800,
				'onComplete': this.preload_images.bind(this)

			}).start('opacity', 1);
		},

		/**
		* Set's the Coverflow to preload the images
		*
		* @name 	Preload Images
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		preload_images: function() {

			this.loadedImages = new Asset.images(this.get_coverflow_element('src'), {

				'onComplete': this.loaded.bind(this),
				'onProgress': this.create_coverflow_element.bind(this)

			});
		},

		/**
		* Create's the Coverflow Images and adds attributes.
		*
		* @name 	Create Coverflow Element
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		create_coverflow_element: function(counter, i) {

			var obj = this.get_current(i);
			var img = this.loadedImages[i];
			obj['width'] = img.width;
			obj['height'] = img.height;
			img.removeProperties('width','height');

			obj['div'] = new Element('div').setStyles({

				'position':'absolute',
				'display':'none',
				'height': this.coverflow_element.getSize().y

			}).inject(this.coverflow_element);

			obj['con'] = new Element('div').inject(obj['div']);
			obj['con'].addClass('obj_wrapper');

			obj['con2'] = new Element('div').inject(obj['con']);
			obj['con2'].addClass('obj_wrap_style1');

			obj['con3'] = new Element('div').inject(obj['con2']);
			obj['con3'].addClass('obj_wrap_style2');

			obj['con4'] = new Element('div').inject(obj['con3']);
			obj['con4'].addClass('obj_wrap_style3');

			img.setStyles({'vertical-align':'bottom', 'width':'100%', 'height':'50%'});
			img.addEvents({'click': this.click_to.bind(this, i), 'dblclick': this.view_call_back.bind(this, i)});
			img.inject(obj['con4']);

			new Element('div').reflect({

				'img': img,
				'ref': this.options.reflection,
				'height': obj.height,
				'width': obj.width,
				'color': this.options.background_color

			}).setStyles({'width':'100%','height':'50%','background-color': this.options.background_color}).inject(obj['con']);

			this.loader.set('text', (counter +1 ) + ' / ' + this.loadedImages.length);
			this.counter = counter + 1;
		

		},

		/**
		* When all attributes are created and the coverflow is loaded.
		*
		* @name 	Loaded
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		loaded: function() {

			this.index = this.options.start_index;

			if (this.counter <= this.index * 2)
			this.index = (this.index / 2).round();

			this.iL = this.master.images.length-1;

			new Fx.Tween(this.loader, {

				'duration': 800,
				'onComplete': this.create_ui.bind(this)

			}).start('opacity', 0);
		},

		/**
		* Takes params passed and creates the UI of the coverflow.
		*
		* @name 	Clear Main
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		create_ui: function() { 

			this.loader.dispose();

			if (this.options.use_caption) {

				this.cap = new Element('div').addClass('caption').set('opacity',0).inject(this.coverflow_element);

			}	

			/* ----- HTML Elements. -------------- */
			this.nav = new Element('div').addClass('coverflow_nav').setStyle('bottom','-100px');
			this.auto_play_con = new Element('div').addClass('auto_play_con');
			this.slider_wrapper  = new Element('div').addClass('slider_wrapper');
			this.slider_wrapper_left  = new Element('div').addClass('slider_wrapper_left');
			this.slider_wrapper_right  = new Element('div').addClass('slider_wrapper_right');

			this.slider_con = new Element('div').addClass('slider_con');
			this.resize_container = new Element('div').addClass('resize_container');	

			/* ----- If the user wants to use the auto play attributes. -------------- */
			if (this.options.use_auto_play) {

				this.auto_play_con.adopt(

					new Element('a',{'class':'stop','events': {'click':this.stop.bind(this)}}), 
					new Element('a',{'class':'play','events': {'click':this.play.bind(this)}})

				);
			}

			/* ----- If the user wants to use the slider. -------------- */
			if (this.options.use_slider) {

				this.sliPrev = new Element('a',{'class':'slider_next','events': {'click':this.prev.bind(this)}});
				this.sliNext = new Element('a',{'class':'slider_prev','events': {'click':this.next.bind(this)}});
				this.knob = new Element('div',{'class':'knob'});
				this.knob.adopt(new Element('div',{'class':'knobleft'}));
				this.slider = new Element('div',{'class':'slider'}).adopt(this.knob);

				/* ----- Set HTML elements order and nodes. -------------- */
				this.slider_wrapper.adopt(this.slider_wrapper_left, this.slider_con, this.slider_wrapper_right);
				this.slider_con.adopt(this.sliPrev, this.slider, this.sliNext);
				this.slider.store('parentWidth', this.slider_con.getSize().x-this.sliPrev.getSize().x-this.sliNext.getSize().x);

			}

			/* ----- If the user wants to use the re-size option. -------------- */
			/* ----- NOTE: The slider re-sizing was disabled in case the user needs rounded corners in their design. -------------- */
			if (this.options.use_resize) {

				this.resize_container.adopt(new Element('a',{'class':'resize','events': {'click':this.set_screen.bind(this)}}));

			}	

			/* ----- Setup Elements. -------------- */
			this.coverflow_element.adopt(this.nav.adopt(this.auto_play_con, this.slider_wrapper, this.resize_container));	
			this.show_ui();

		},

		/**
		* Once the UI and all of the attributes are setup, show it.
		*
		* @name 	Show UI
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		show_ui: function() {

			if (this.cap) this.cap.fade(1);
			this.nav.tween('bottom', 40);
			this.fireEvent('start');
			this.update();

		},

		/**
		* If using the re-size option, this will fire when the user resizes the coverflow.
		*
		* @name 	Show UI
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		update: function(e) {

			if (e == 'init') return;
			this.oW = this.coverflow_element.getSize().x;
			this.sz = this.oW * 0.5;

			if (this.options.use_slider) {	

				var obj_padding_left = parseInt(this.slider_con.getStyle('padding-left'));
				var obj_padding_right = parseInt(this.slider_con.getStyle('padding-right'));
				var obj_padding = obj_padding_right + obj_padding_right;
				var slider_con_width = this.slider_con.getSize().x;
				var slider_wrapper_left_width = this.slider_wrapper_left.getSize().x;
				var slider_wrapper_right_width = this.slider_wrapper_left.getSize().x;
				slider_wrapper_parse = slider_con_width + slider_wrapper_left_width + slider_wrapper_right_width;
				this.slider_wrapper.setStyle('width', slider_wrapper_parse+'px');
				this.slider_con.setStyle('width', slider_con_width - slider_wrapper_left_width - slider_wrapper_right_width +'px');
				var slider_wrapper_parent = this.slider_wrapper.getParent().getSize().x;
				this.slider_wrapper.setStyle('left', (slider_wrapper_parent - this.slider_wrapper.getSize().x) / 2+'px');
				this.slider.setStyle('width', this.slider.getParent().getSize().x-this.sliPrev.getSize().x-this.sliNext.getSize().x-obj_padding-1);
				this.knob.setStyle('width', (this.slider.getSize().x/this.iL));
				this.sli = new slider_ex(this.slider, this.knob, {steps: this.iL}).set(this.index);
				this.sli.addEvent('onChange', this.glide_to.bind(this));

			}

			this.glide_to(this.index);
			this.isLoading = false;

		},

		/**
		* Function to set the screen when the re-size button is fired.
		*
		* @name 	Set Screen
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		set_screen: function() {

			if (this.isFull = !this.isFull) {

				this.holder = new Element('div').inject(this.coverflow_element,'after');
				this.coverflow_element.wraps(new Element('div').inject(document.body));
				this.coverflow_element.setStyles({'position':'absolute','z-index':'100','top':'0','left':'0','width':window.getSize().x,'height':window.getSize().y});

				if (this.options.use_window_resize) {

					this._init_resize = this.init_resize.bind(this);
					window.addEvent('resize', this._init_resize);

				}
			}

			else {

				this.coverflow_element.wraps(this.holder);
				window.removeEvent('resize', this._init_resize);
				delete this.holder, this._init_resize;
				this.coverflow_element.setStyles({'position':'relative','z-index':'','top':'','left':'','width':'','height':this.coverflow_element.retrieve('height')});
				this.slider.setStyle('width',this.slider.retrieve('parentWidth'));

			}

			this.fireEvent('resized', this.isFull);
			this.update();

		},

		/**
		* Function to re-size the coverflow when the browser is re-sized and set_screen is enabled.
		*
		* @name 	Init Resize
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		init_resize: function() {

			this.coverflow_element.setStyles({'width':window.getSize().x,'height':window.getSize().y});
			this.update();

		},

		/**
		* Function to get current coverflow size for image animations.
		*
		* @name 	Get Current
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		get_current: function(index) {

			return this.master.images[$chk(index) ? index : this.index];

		},

		/**
		*
		* @name 	Load JSON.
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		load_json: function(url) {

			if (!url || this.isLoading) return;
			this.isLoading = true;

			new Request.JSON({

				'onComplete': function(data) {

					if ($chk(data)) {

						this.master = data;
						this.clear_main();
						this.fireEvent('request', data);

					}
				}.bind(this)
			}, this).get(url);
		},

		/**
		*
		* @name 	Load HTML.
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		load_html: function(url, filter) {

			if (!url || !filter || this.isLoading) return;
			this.isLoading = true;

			new Request.HTML({

				'onSuccess': function(tree, els, htm) {

					var result = new Element('div', {'html': htm}).getChildren(filter);
					this.get_elements(result);
					this.fireEvent('request', result);

				}.bind(this)
			}, this).get(url);
		},

		/**
		* 
		*
		* @name 	Flow Start.
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		flow_start: function() {

			this.inMotion = true;

		},

		/**
		* 
		*
		* @name 	Init Resize.
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		flow_complete: function() {

			this.inMotion = false;

		},

		/**
		* Fires the callback event
		*
		* @name 	view_call_back
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		view_call_back: function(index) {

			if (this.index != index || this.inMotion) return;
			var el = $H(this.get_current());
			var returnObj = {};
			returnObj['coords'] = el.div.getElement('img').getCoordinates();

			el.each(function(v, k) {

				if ($type(v) == 'number' || $type(v) == 'string') returnObj[k] = v;

			}, this);

			this.fireEvent('clickView', returnObj);

		},

		/**
		* Prev Button.
		*
		* @name 	Prev
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		prev: function() {

			if (this.index > 0)
				this.click_to(this.index-1);

		},

		/**
		* Next Button.
		*
		* @name 	Next
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		next: function() {

			if (this.index < this.iL)
				this.click_to(this.index+1);

		},

		/**
		* Stop Function for Autoplay.
		*
		* @name 	Stop
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		stop: function() {

			$clear(this.autoPlay);
			this.isAutoPlay = false;
			this.fireEvent('autoStop');

		},

		/**
		* Play function for Autoplay.
		*
		* @name 	Play
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		play: function() {

			this.autoPlay = this.auto.periodical(this.options.interval, this);
			this.isAutoPlay = true;
			this.fireEvent('autoPlay');

		},

		/**
		* If Autoplay is active.
		*
		* @name 	Auto
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		auto: function() {

			if (this.index < this.iL) this.next();
			else if (this.index == this.iL) this.click_to(0);

		},

		/**
		* Function to use the arrow keys.
		*
		* @name 	Key To
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		key_to: function(e) {

			switch (e.code) {

				case 37: e.stop(); this.prev();	break;
				case 39: e.stop(); this.next();

			}
		},

		/**
		* Function to use the mousewheel.
		*
		* @name 	Wheel To
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		wheel_to: function(e) {

			if (e.wheel > 0) this.prev();
			if (e.wheel < 0) this.next();
			e.stop().preventDefault();

		},

		/**
		* Function to click the slider bar.
		*
		* @name 	Click To
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		click_to: function(index) {

			if (this.index == index) return;
			//this.aniFx.cancel();
			if (this.sli) this.sli.set(index);
			this.glide_to(index);

		},

		/**
		* Function to drag the scroller peg.
		*
		* @name 	Glide To
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		glide_to: function(index) {

			this.index = index;
			this.aniFx.start(this.aniFx.get(), index*-this.foc);
			if (this.cap) this.cap.set('html', this.get_current().title);

		},

		/**
		* Process animation calculations.
		*
		* @name 	Process
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		process: function(x) {

			var z,W,H,zI=this.iL,foc=this.foc,f=this.factor,sz=this.sz,oW=this.oW,offY=this.offY,div,elh,elw;

			this.master.images.each(function(el) {

				div = el.div.style;
				elw = el.width;
				elh = el.height;

				if (x>-foc*6 && x<foc*6) {

					with (Math) {

						z = sqrt(10000 + x * x) + 100;
						H = round((elh / elw * f) / z * sz);
						W = round(elw * H / elh);
						if (H >= elw * 0.5) {W = round(f / z * sz);}
						div.left = round(((x / z * sz) + sz) - (f * 0.5) / z * sz) + 'px';
						div.top = round(oW * 0.4 - H) + offY + 'px';

					}	

					el.con.style.height = H*2 + 'px';		
					div.width = W + 'px';
					div.zIndex = x < 0 ? zI++ : zI--;
					div.display = 'block';

				}

				else {

					div.display = 'none';

				}

				x += foc;

			});
		}
	});

	/**
	* New Slider Class.
	*
	* @name 	Slider EX
	* @access 	public
	* @param 	var-type none
	* @return 	none
	* @author 	Joey Avino
	* @email	joey@amediacreative.com
	*/
	var slider_ex = new Class({

		Extends: Slider,

		set: function(step) {

			this.step = Math.round(step);
			this.fireEvent('tick', this.toPosition(this.step));
			return this;

		},

		clickedElement: function(event) {

			var dir = this.range < 0 ? -1 : 1;
			var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half;
			position = position.limit(-this.options.offset, this.full -this.options.offset);
			this.step = Math.round(this.min + dir * this.toStep(position));
			this.checkStep();
			this.fireEvent('tick', position);

		}
	});

	/**
	* FX Value Class
	*
	* @name 	Fx.Value
	* @access 	public
	* @param 	var-type none
	* @return 	none
	* @author 	Joey Avino
	* @email	joey@amediacreative.com
	*/
	Fx.Value = new Class({

		Extends: Fx,

		compute: function(from, to, delta) {

			this.value = Fx.compute(from, to, delta);
			this.fireEvent('motion', this.value);
			return this.value;

		},

		/**
		* Get Value
		*
		* @name 	Get
		* @access 	public
		* @param 	var-type none
		* @return 	none
		* @author 	Joey Avino
		* @email	joey@amediacreative.com
		*/
		get: function() {

			return this.value || 0;

		}
	});

	/**
	* Implement the reflection.
	*
	* @name 	Element.Implement
	* @access 	public
	* @param 	var-type none
	* @return 	none
	* @author 	Joey Avino
	* @email	joey@amediacreative.com
	*/
	Element.implement({

		reflect: function(arg) {

			i = arg.img.clone();

			if (Browser.Engine.trident) {

				i.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity=20, style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+100*arg.ref+')';
				i.setStyles({'width':'100%', 'height':'100%'});
				return new Element('div').adopt(i);

			}

			else {

				var can = new Element('canvas').setProperties({'width':arg.width, 'height':arg.height});

				if (can.getContext) {

					var ctx = can.getContext("2d");
					ctx.save();
					ctx.translate(0,arg.height-1);
					ctx.scale(1,-1);
					ctx.drawImage(i, 0, 0, arg.width, arg.height);
					ctx.restore();
					ctx.globalCompositeOperation = "destination-out";
					ctx.fillStyle = arg.color;
					ctx.fillRect(0, arg.height*0.5, arg.width, arg.height);
					var gra = ctx.createLinearGradient(0, 0, 0, arg.height*arg.ref);					
					gra.addColorStop(1, "rgba(255, 255, 255, 1.0)");
					gra.addColorStop(0, "rgba(255, 255, 255, "+(1-arg.ref)+")");
					ctx.fillStyle = gra;
					ctx.rect(0, 0, arg.width, arg.height);
					ctx.fill();
					delete ctx, gra;

				}

				return can;

			}
		}
	});

	window.addEvent('domready', function() {

		$$('.coverflow_init').each(function(coverflow_element) {

			new coverflow_element(coverflow_element);

		});
	});