﻿		
		// +--------------------------------------------------------+ 
		// | js version .x														 | 
		// +--------------------------------------------------------+ 
		// | Copyright : heo woong <comefeel.com>            | 
		// +--------------------------------------------------------+ 
		// | License  : GPLv3												| 
		// +--------------------------------------------------------+ 


		var rolling = {

			__constructor : function( init ){

				var Left = 'left';
				var Top = 'top';
				var Width = 'width';
				var Height = 'height';
				var ClientWidth = 'offsetWidth';
				var ClientHeight = 'offsetHeight';
				//var ClientWidth = 'clientWidth';
				//var ClientHeight = 'clientHeight';

				this.error = new Array();
				this.graduation = 'px';
				this.coordinates = {

					'init' : new Array( Width , Width , Height , Height ) ,
					'motion' : new Array( Left , Left , Top , Top ) ,
					'area' : new Array( ClientWidth , ClientWidth , ClientHeight , ClientHeight )
				};

				this.variable = new Object();
				this.foundIt( init , this );
				this.appending( this.spear , this.spearLeft , this.spearRight );
			},

			appending : function( spear , spearLeft , spearRight ){

				if( typeof this.roll_instant != this.ty.fn ) return this.error.push( 1000 );

					var i = spear.length-1;
					var direction = !( this.move % 2 );
					var coordinatesInit = this.coordinates.init[this.move];
					var move = this.coordinates.motion[this.move];
					var capture = this.coordinates.area[this.move];

					if( i >= 0 )
					do {

						var obj = spear[i];
						var objParent = obj.parentNode;

						var obj_left = typeof spearLeft != this.ty.not && typeof spearLeft[i] == this.ty.ob ? spearLeft[i] : false ;
						var obj_right = typeof spearRight != this.ty.not && typeof spearRight[i] == this.ty.ob ? spearRight[i] : false ;
						var size = objParent[capture];

						var divideCut = divide = this.divide;
						var divideLength = 0;

						var Element = obj.getElementsByTagName( this.tagTarget );
						var ElementLength = Element.length - 1;

						var tagElement = new Array();
						var stack = new Array();
						var stackTotal = 0;


						// Tag element size extraction
						for( var j = 0 , stop = n = ElementLength; j <= stop; j++ , n--){

							// flock
							if( direction == true ){

								e = Element[n];
								obj.appendChild( e );

							} else e = Element[j];

							// reconstitute
							tagElement[j] = e;

							// element size
							stack[j] = e[capture];
							stackTotal += stack[j];

							if( divideCut > 0 ){

								divideLength += stack[j];
								divideCut--;
							}
						}


						var size = size > stackTotal ? size : stackTotal;
						var otherAppend = Math.floor(( size - stackTotal ) / ElementLength );

						// option assign
						obj.style[coordinatesInit] = size + this.graduation;
						
						// matrix assign
						objParent.style[coordinatesInit] = ( divideLength + ( otherAppend * divide )) + this.graduation;


						if( typeof obj.events != this.ty.not ){

							this.eventRemove( obj , 'mouseover' , obj.events.mouseover );
							this.eventRemove( obj , 'mouseout' , obj.events.mouseout );
						}

						obj.events = {

							mouseover : this.bind( this.stop , this , obj ) ,
							mouseout : this.bind( this.play , obj )
						};


						obj.roll = new this.roll_instant({

								// roll args
								//'eventElement' : extraElement , // target Element args
								'eventArgs' : this.rollEventArgs,
								'exec' : this.rollExec ,
								'eventID' : this.rollEventID,
								'spear' : obj ,
								'move' : move ,
								'sec' : this.rollSec,

								// rolling args
								'stack' : stack ,
								'expandCycle' : 0 ,
								'secInit' : this.rollSec ,
								'direction' : direction ,
								'otherAppend' : otherAppend ,
								'expandIntervalID' : false ,
								'tagElement' : tagElement ,
								'tagElementLength' : ElementLength
						});

						// center
						void( this.eventCatch ( obj , 'mouseover' , obj.events.mouseover ));
						void( this.eventCatch ( obj , 'mouseout' , obj.events.mouseout ));

						// left click
						if( obj_left != false ){

							if( typeof obj_left.events != this.ty.not )
								this.eventRemove( obj_left , 'click' , obj_left.events.click );

							obj_left.events = { click : this.bind( this.leftPlay , this , obj ) };
							void( this.eventCatch ( obj_left , 'click' , obj_left.events.click ));
						}

						// right click
						if( obj_left != false ){

							if( typeof obj_right.events != this.ty.not )
								this.eventRemove( obj_right , 'dblclick' , obj_right.events.click );

							obj_right.events = { click : this.bind( this.rightPlay , this , obj ) };
							void( this.eventCatch ( obj_right , 'click' , obj_right.events.click ));
						}

						// auto start
						void( obj.events.mouseout());

					} while( i-- )

				return spear;
			},

			play : function(){

				// this <== Roll{ object }
				var that = arguments[arguments.length-1];

				if( typeof this.roll.expandIntervalID != that.ty.num )
					this.roll.expandIntervalID = setInterval( that.bind( that.moving , this ) , that.stopSec );
			},

			moving : function(){

					// this <== Roll{ object }
					var that = arguments[arguments.length-1];

					// overlapping test
					if( typeof this.roll.intervalID == that.ty.num )
						return;

					// speed change
					if( this.roll.sec != this.roll.secInit )
						this.roll.sec = this.roll.secInit;

					// initialize
					if( this.roll.direction == true ){

						var element = this.roll.tagElement.pop();
						var stack = this.roll.stack.pop();
						var point = -( stack + this.roll.otherAppend );

						this.insertBefore( element , this.roll.tagElement[0] );

						this.roll.tagElement.unshift( element );
						this.roll.stack.unshift( stack );

						this.style[this.roll.move] = point + that.graduation;

						this.roll.firstPoint = point;
						this.roll.clearPoint = 0;

					} else {

						if( this.roll.expandCycle > 0 ){

							var element = this.roll.tagElement.shift();
							var stack = this.roll.stack.shift();

							this.appendChild( element );

							this.roll.tagElement[this.roll.tagElementLength] = element;
							this.roll.stack[this.roll.tagElementLength] = stack;

						} else this.roll.expandCycle++;

						this.style[this.roll.move] = 0;

						this.roll.firstPoint = 0;
						this.roll.clearPoint = -( this.roll.stack[0] + this.roll.otherAppend );
					}

					this.roll.fire( true );

				return;
			},

			stop : function( Event , obj ){

				// overlapping test
				if( typeof obj.roll.expandIntervalID != this.ty.num ) return;

					void( clearInterval( obj.roll.expandIntervalID ));
					obj.roll.expandIntervalID = false;
			},

			leftPlay : function( Event , obj ){

				obj.roll.sec = this.fastSec;
				if( obj.roll.direction == true ) return;

				var point = 0;

				obj.roll.direction = !obj.roll.direction;
				obj.roll.stop( obj.roll.point );

				point = Math.round(obj.roll.point);
				point = !point ? 0 : point;

				obj.style[obj.roll.move] = point + this.graduation;

				obj.roll.firstPoint = point;
				obj.roll.clearPoint = 0;

				obj.roll.fire( true );
			},

			rightPlay : function( Event , obj ){

				obj.roll.sec = this.fastSec;
				if( obj.roll.direction == false ) return;

				var point = 0;

				obj.roll.direction = !obj.roll.direction;
				obj.roll.stop( obj.roll.point );

				point = Math.round( obj.roll.point );
				point = !point ? 0 : point;

				obj.style[obj.roll.move] = point + this.graduation;

				obj.roll.expandCycle = 0;

				obj.roll.firstPoint = point;
				obj.roll.clearPoint = 0;
				obj.roll.fire( true );

			}
		};
