﻿//nemWidgetPanel.js
//2008 Paul Graves paul.graves@nemisys.uk.com
//Nemisys drag/drop widget panel
var x,y;
var myHeight,myWidth;

var nemWidgetPanel = new Class({

	options: {
		handles: false,
		snap: 0
	},
	initialize: function(list, cols, elem, holder, options){
		this.setOptions(options);
		this.list = $(list);
		this.cols = cols;
		this.elements = [];
		this.indexes = [];
		this.drag = false;
		
		this.holder = holder;
		this.elem=elem;
		this.init();
	},
	init:function(){
		this.initCookie();
		
		//populate the elements array
		this.cols.each(function(col, i) {
			var els = $$(col +" "+this.elem);
			this.indexes.push(0);
			els.each(function(el, k){
				this.indexes[i]++;
				el.holder = el.getElement(this.holder);
				el._index = i;
				el._i = k;
				el.holder._width = el.holder.offsetWidth;
				el.holder._height = el.holder.offsetHeight;
				this.elements.push(el);
			}, this);
		}, this);
		
		//now move the elements into their cookied positions
		var _arr = [];
		if (this.cookie) {
			for (i = 0; i < this.indexes.length; i ++)
			{
				this.indexes[i] = 0;
			}
			
			for (i = 0; i < this.cookie.length; i = i+4) {
				for (k = 0; k < this.elements.length; k ++) {
					if (this.cookie[i] == this.elements[k].id)
					{
						var em = this.elements[k].clone();
						var _c = $$(this.cols[this.cookie[i+1]]);
						em.inject(_c[0]);
						em._index = this.cookie[i+1];
						em.holder = em.getElement(this.holder);
						em.holder._width = em.holder.offsetWidth;
						em.holder._height = em.holder.offsetHeight;
						em.id = this.elements[k].id;
						//pg edit hide element if cookie says to hide it
						if(this.cookie[i+2] == 'none'){
					        em.style.display='none';
					    }else
					        em.style.display='';
					    
					    if(em.getFirst('.nemBody')!=null){ 
					        if(this.cookie[i+3] == 'false'){//is the content of this widget collapsed
					            em.getFirst('.nemBody').addClass('nemHidden');
					        }else{
					            em.getFirst('.nemBody').removeClass('nemHidden');
					        }    
					    }
						this.indexes[this.cookie[i+1]]++;
						_arr.push(em);
						this.elements[k].dispose();
						this.elements.erase(this.elements[k]);
					}
				}
			}
			//add in any elements not found in the cookie at the end
			//this deals with the case where a new widget is added to the source
			for (k = 0; k < this.elements.length; k ++) {
				_arr.push(this.elements[k]);
				this.elements.erase(this.elements[k]);
			}
			this.elements = _arr;
		}
		
		//create the nemWidgets
		for(i=0;i<this.elements.length;i++){
		    if(this.elements[i].hasClass('nemWidget'))
			    nemWidgets[this.elements[i].id] = new nemWidget(this.elements[i]);    
		}
		
		//create non draggable widgets
		$$('.nemNotDraggable').each(function(item){new nemWidget(item);});
		
		this.handles = (this.options.handles) ? $$(this.options.handles) : this.elements;
		this.bound = {
			'start': []
		};
		for (var i = 0, l = this.handles.length; i < l; i++){
			this.bound.start[i] = this.start.bindWithEvent(this, this.elements[i]);
		}
		if (this.options.initialize) this.options.initialize.call(this);
		this.bound.move = this.move.bindWithEvent(this);
		this.bound.end = this.end.bind(this);
		
		document.addListener('mousemove', this.updateOffset.bind(this));
		document.addListener('mousemove', this.getWindowHeight.bind(this));
		this.handles.each(function(handle, i){
			handle.holder.addEvent('mousedown', this.bound.start[i]);
		}, this);
		
	},
	nothing: function(){alert('nothing');},
	start: function(event, el){
		document.addListener('mousemove', this.bound.move);
		document.addListener('mouseup', this.bound.end);
		
		//stops the text being select during a drag
	    document.body.onselectstart = function () { return false; };
	    document.body.style.MozUserSelect="none";
		
		this.empty = new Element('div').injectBefore(el).setStyles({
			'width': el.offsetWidth,
			'height': el.offsetHeight
		});
		this.empty.id = "empty";
		this.empty.innerHTML="&nbsp;";
		
		this.previous = el.getPrevious(".nemWidget");
		this.next = el.getNext(".nemWidget");
		this.active = el;
		this.coordinates = this.list.getCoordinates();
		var position = this.empty.getPosition();
		this.offset = y - position.y;
		
	    this.trash = new Element('div').inject(document.body);
		el.inject(this.trash).setStyles({
			'position': 'absolute',
			'left': position.x,
			'top': y - this.offset
		});
	},
	move: function(event){		
		var _top = y - this.offset;
		var _left = x - this.offset;
		
		_top = _top.limit(this.coordinates.top, this.coordinates.bottom - this.active.offsetHeight + 300);
		_left = _left.limit(this.coordinates.left, this.coordinates.right - this.active.offsetWidth);
		
		this.active.setStyle('top', _top);
		this.active.setStyle('left', _left);
		
		//document.getElementById('mouse').innerHTML = y + " " + myHeight ;
		//scroll the page if near the bottom
		if(y>myHeight-100){
		    window.scrollBy(0,20);
		}
		
		this.elements.each(function(el, i){
			if (el != this.active)
			{
				el.top = el.getCoordinates().top;
				el.left = el.getCoordinates().left;
			
				if ((x > el.left) && (x <  (el.left + el.offsetWidth)))
				{
					if ((y > el.top) && (y <  (el.top + el.holder._height - 10)))
					{
						if (this.indexes[this.active._index] > 1)
						{
							this.empty.injectBefore(el);
							this.drag = el;
							this.drag._index = el._index;
							this.drag.where = "before";
						}
					}
					else if ((y > el.top) && (y >  (el.top + el.holder._height - 10) && (y <  (el.top + el.offsetHeight + 10))))
					{
						if (this.indexes[this.active._index] > 1)
						{
							this.empty.injectAfter(el);
							this.drag = el;
							this.drag._index = el._index;
							this.drag.where = "after";
						}
					}
				}
			}
		}, this);
	},
	serialize: function(){
		return this.elements.map(function(el){
		        var open;
		       if(nemWidgets[el.id]!=null)//for valid nemWidgets get whether the content is open or closed
		        open=nemWidgets[el.id].body.get('slide').open;
		        	        
			return el.id+","+ el._index+","+el.style.display+","+open;
		}, this);
	},
	end: function(){
		if (this.drag) {   
			if (this.cols[this.active._index] != this.cols[this.drag._index])
			{
				this.indexes[this.active._index]--;
				this.indexes[this.drag._index]++;
				this.active._index = this.drag._index;
			}
			
			if (this.drag.where == "after")
			{
				this.active.injectAfter(this.drag);
			}
			else if (this.drag.where == "before")
			{
				this.active.injectBefore(this.drag);
			}
			var _temp = this.active;
			var _arr = [];
			this.elements.erase(this.active);
			
			for (i = 0; i < this.elements.length; i ++) {
				
				if (this.elements[i] == this.drag) {
					if (this.drag.where == "before") {
						_arr.push(_temp);
						_arr.push(this.elements[i]);
					}
					else if (this.drag.where == "after") {
						_arr.push(this.elements[i]);
						_arr.push(_temp);
					}
				}
				else {
					_arr.push(this.elements[i]);
				}
			}
			this.elements = _arr;  
		}else{
		    if(this.previous)
		        this.active.injectAfter(this.previous);
		    else
		        this.active.injectBefore(this.next);    
		}
		
		this.drag = null;
		this.previous = null;
		this.next = null;
		    this.empty.dispose();
	        this.updateCookie();
	        this.active.setStyles({
			'position': 'static',
			'top': 0,
			'left': 0
			 });
		
		//allows the text to be selected after a drag
		document.body.onselectstart = function () { return true; };
	    document.body.style.MozUserSelect="";
		document.removeListener('mousemove', this.bound.move);
		document.removeListener('mouseup', this.bound.end);
	    
	},
	updateOffset:function(event){var myEvent = new Event(event);x=myEvent.page.x;y=myEvent.page.y},
	getWindowHeight:function(event){
	    if( typeof( window.innerWidth ) == 'number' ) {
            //Non-IE
            myWidth = window.innerWidth;
            myHeight = window.innerHeight;
          } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
            //IE 6+ in 'standards compliant mode'
            myWidth = document.documentElement.clientWidth;
            myHeight = document.documentElement.clientHeight;
          } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
            //IE 4 compatible
            myWidth = document.body.clientWidth;
            myHeight = document.body.clientHeight;
          }
	        },
    updateCookie: function(){
	    Cookie.dispose(this.cookie);
		Cookie.write("nemWidgetCookie", this.serialize());

	},
	initCookie: function(){
	    if (Cookie.read("nemWidgetCookie"))
	    {
		    this.cookie = Cookie.read("nemWidgetCookie").split(",");
		    Cookie.dispose(this.cookie);
	    }else{
	        this.cookie=false;
	        Cookie.write("nemWidgetCookie", this.serialize());
	    }

	},
	reset: function(){
	    Cookie.dispose("nemWidgetCookie");
	    window.location.reload( false );
	}

});

nemWidgetPanel.implement(new Events, new Options);