/******************************************************************************
@owner: SVSi
@author: Arthur Johnson
@functions: Mouse Controls object handles all mouse/touch event listeners
@MouseControls
*******************************************************************************/

//*************  MOUSE/TOUCH/MOUSECONTROLS CLASS  ***************//
function MouseControls(opts){ 
 
	if (undef(opts)) opts = {};

	this.name = opts.hasOwnProperty('name') ? opts['name'] : null;	
	this.responsive = opts.hasOwnProperty('responsive') ? opts['responsive'] : false;
	this.update = opts.hasOwnProperty('update') ? opts['update'] : noop;
    
	this.action = null;
    
    this.x = 0;
    this.y = 0;
	
	this.pagex = 0;
    this.pagey = 0;
	
	this.elementoverx = 0;
    this.elementovery = 0;
	
	this.itemoverx = 0;
    this.itemovery = 0;
	
	this.draggedoffsetx = 0;
	this.draggedoffsety = 0;
	this.movedoffsetx = 0;
	this.movedoffsety = 0;
	
	this.elementover = null;
	this.elementdownover = null;
	this.elementsover = null;
	this.itemover = null;
	this.olditemover = null;
    this.touches = [];
	this.selectionitem = null;
    
    this.down = false;
	this.downx = 0;
	this.downy = 0;
	this.distancefromdown = 0;
	this.vectortodown = {x: 0, y: 0};
    this.touchesdown = 0; 
	
	this.rectangle = null;
	
	this.dblclicktimer = null;
	this.dblclickready = false;
	this.lastitemclicked = false;
    this.downinterval = opts.hasOwnProperty('downinterval') ? opts.downinterval : null;
    this.touchdowninterval = opts.hasOwnProperty('touchdowninterval') ? opts.touchdowninterval : null;
	
    this.unclicked = opts.hasOwnProperty('unclicked') ? opts.unclicked : noop;
    this.unclickedup = opts.hasOwnProperty('unclickedup') ? opts.unclickedup : noop;
    
    this.selected = [];
    this.intersected = [];
    this.oldintersected = [];
    this.dragged = [];
	this.moved = []; //need to remove, this is overcomplicated
	
	this.clickdown = noop;
	this.clickup = noop;
    
	this.init();
	if (activepanel) this.inittouch(document.body);
	
}
MouseControls.prototype = {
    toggle: function(){
		if (this.responsive) {
			this.responsive = false;
		}
		else{ 
			this.responsive = true;
		}
	},
    init: function(){

		if (!this.container) {
			this.container = document.body;
		}
		
		if (this.container.addEventListener){
		
			this.container.addEventListener( 'mousemove', this.mousemove.bind(this), false );
			this.container.addEventListener( 'mousedown', this.mousedown.bind(this), false );
			this.container.addEventListener( 'mouseup', this.mouseup.bind(this), false );
			
			var mousewheelevent=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel";
			
			this.container.addEventListener(mousewheelevent, function(event){
				//stops mousewheel
				//event.preventDefault();
			}, false);

		}
		else {
		
			this.container.attachEvent( 'mousemove', this.mousemove.bind(this), false );
			this.container.attachEvent( 'mousedown', this.mousedown.bind(this), false );
			this.container.attachEvent( 'mouseup', this.mouseup.bind(this), false );
			
			this.container.attachEvent("wheel", function(event){
				event.preventDefault();
			}, false);
			
		}  
		
		$('.scrollpanel').bind('DOMMouseScroll', function(e){
			if (!pb.currentpanel ||
				pb.mouse.isOverElement(document.getElementById('menubar')) ||
				pb.mouse.isOverElement(document.getElementById('labels-bar')) ||
				pb.mouse.isOverElement(document.getElementById('dialog-pane')) ||
				pb.mouse.isOverElement(document.getElementById('resources-panel')) ||
				pb.mouse.isOverElement(document.getElementById('tools-panel'))
				) return;
			if (e.originalEvent.detail > 0){
				pb.currentpanel.element.style.marginTop =
					(parseInt($(pb.currentpanel.element).css('margin-top')) - 10) + 'px';
			} 
			else {
				pb.currentpanel.element.style.marginTop =
					(parseInt($(pb.currentpanel.element).css('margin-top')) + 10) + 'px';
			}
		});
		 
		$('.scrollpanel, body').bind('mousewheel', function(e){
			if (!pb.currentpanel ||
				pb.mouse.isOverElement(document.getElementById('menubar')) ||
				pb.mouse.isOverElement(document.getElementById('labels-bar')) ||
				pb.mouse.isOverElement(document.getElementById('dialog-pane')) ||
				pb.mouse.isOverElement(document.getElementById('resources-panel')) ||
				pb.mouse.isOverElement(document.getElementById('tools-panel'))
				) return;
			if (e.originalEvent.wheelDelta < 0){
				pb.currentpanel.element.style.marginTop =
					(parseInt($(pb.currentpanel.element).css('margin-top')) - 10) + 'px';
				if ($('[id*="cke_Button"]').exists())
					$('[id*="cke_Button"]')[0].style.marginTop =
						(parseInt($('[id*="cke_Button"]').css('margin-top')) - 10) + 'px';
				if ($('[id*="cke_Widget"]').exists())
					$('[id*="cke_Widget"]')[0].style.marginTop =
						(parseInt($('[id*="cke_Widget"]').css('margin-top')) - 10) + 'px';
			} 
			else {
				pb.currentpanel.element.style.marginTop =
					(parseInt($(pb.currentpanel.element).css('margin-top')) + 10) + 'px';
				if ($('[id*="cke_Button"]').exists())
					$('[id*="cke_Button"]')[0].style.marginTop =
						(parseInt($('[id*="cke_Button"]').css('margin-top')) + 10) + 'px';
				if ($('[id*="cke_Widget"]').exists())
					$('[id*="cke_Widget"]')[0].style.marginTop =
						(parseInt($('[id*="cke_Widget"]').css('margin-top')) + 10) + 'px';
			}
		 });

		window.onscroll = function(e){
			if (!pb.ready) return;
			if (!activepanel){ document.body.scrollTop = 0; document.body.scrollLeft = 0; }
		};
		
    },
	inittouch: function(m_container){
		
		if (undef(m_container)) return;
		
		var touchToMouse = function(event){
			event.preventDefault();
			//if (event.touches.length > 1) return;
			var touch = event.changedTouches[0];
			var type = "";
			
			switch (event.type){
				case "touchstart": 
					type = "mousedown"; break;
				case "touchmove":  
					type="mousemove";   break;
				case "touchend":   
					type="mouseup";     break;
				default: 
					return;
			}
			
			if (event.type != 'touchmove'){
				var simulatedEvent = document.createEvent("MouseEvent");
				simulatedEvent.initMouseEvent("mousemove", true, true, window, 1, 
						touch.screenX, touch.screenY, 
						touch.clientX, touch.clientY, false, 
						false, false, false, 0, null);
				
				touch.target.dispatchEvent(simulatedEvent);
			}
			
			var simulatedEvent = document.createEvent("MouseEvent");
			simulatedEvent.initMouseEvent(type, true, true, window, 1, 
					touch.screenX, touch.screenY, 
					touch.clientX, touch.clientY, false, 
					false, false, false, 0, null);
			
			touch.target.dispatchEvent(simulatedEvent);
			
		};
		m_container.ontouchstart = touchToMouse;
		m_container.ontouchmove = touchToMouse;
		m_container.ontouchend = touchToMouse;
		
		return;
		
		///for multitouches have to remove above code ^
		if (!oldIE){
			m_container.addEventListener( 'touchstart', this.touchstart.bind(this), false );
			m_container.addEventListener( 'touchmove', this.touchmove.bind(this), false );
			m_container.addEventListener( 'touchend', this.touchend.bind(this), false );
			m_container.addEventListener( 'touchcancel', function(e) {
				//too many touch events for OS, 3 on Android, 12 on iPad
				//add code to drop all touches I guess...or do nothing
			}.bind(this), false);	
		}
		
    },
    mousedown: function(event){
	
		//console.log('element',this.elementover);	//debugging
		//console.log('item',this.itemover);		//debugging
		
		if (event.which == 3) return;
		
		if (pb.itemeditor && pb.itemeditor.open == true) return;
		

		if (this.elementover){
			if (this.elementover.className && this.elementover.className.indexOf)
				if (this.elementover.className.indexOf('menu') != -1) event.preventDefault();
			if (this.elementover.tagName === "IMG" || this.elementover.tagName === "img")
				event.preventDefault();
			if (this.elementover.id == 'move-button-image'){
				event.preventDefault();
				$('#move-button').css('z-index', 300000000);
				this.movingpanel = true;
			}
		}	

		if ((this.itemover && this.itemover instanceof Panel) || this.elementover.id == 'thebody'){
			if (pb.tool == 'hand') this.movingpanel = true;
		}

		if (pb.project.textEditing && (this.elementover)
			&& (this.elementover.className.indexOf('ck_edit') == -1 
			&& this.elementover.className.indexOf('cke') == -1
			&& this.elementover.nodeName != 'SPAN'
			&& !isDescendant(pb.project.textEditing.textnode, this.elementover)
			&& this.elementover.className.indexOf('cke_dialog') == -1
			&& this.elementover.className.indexOf('cke_specialchar') == -1)){
			

			for (k in CKEDITOR.instances){
				var instance = CKEDITOR.instances[k];
				instance.destroy();
			}
			
			if (pb.project.textEditing.textnode){
			
				$(pb.project.textEditing.textnode).attr('contenteditable', 'false');
				$(pb.project.textEditing.textnode).blur();
				$(pb.project.textEditing.textnode).addClass('item_child');
				allDescendantsAddClass(pb.project.textEditing.textnode, 'ck_edit');
				$(pb.project.textEditing.textnode).children().addClass( 'ck_edit' );
				
				var theight = ($(pb.project.textEditing.element).outerHeight()/2) - ($(pb.project.textEditing.textnode).outerHeight()/2);
			
				$(pb.project.textEditing.textnode).css('top', theight + 'px');
			}
			else {
		
				$(pb.project.textEditing.element).attr('contenteditable', 'false');
				$(pb.project.textEditing.element).blur();
				$(pb.project.textEditing.element).addClass('item_child');
				allDescendantsItemChild(pb.project.textEditing.element);
				if (pb.project.textEditing.element) 
					allDescendantsAddClass(pb.project.textEditing.element, 'ck_edit');
				$(pb.project.textEditing.element).children().addClass( 'ck_edit' );
			}
			$(pb.project.textEditing.textnode).removeClass('selectable');
			pb.project.textEditing = false;
			
		}

		if (this.responsive && event.which == 1){
		
			this.elementover = document.elementFromPoint(this.x, this.y);
			this.itemover = this.elementover;
			
		///console.log('over?1', this.itemover);
			
			if (this.itemover){
				var bbox = this.elementover.getBoundingClientRect();
				
				this.elementoverx = this.x - bbox.left,
				this.elementovery = this.y - bbox.top;
				
				if (this.itemover.className.indexOf && this.itemover.className.indexOf('item_child') != -1){
					
					while (this.itemover.parentNode.className.indexOf('item_child') != -1) {
						this.itemover = this.itemover.parentNode;
					}
					
					this.itemover = this.itemover.parentNode;
					
				}
				///console.log('over?1.1', this.itemover);
				if (this.olditemover){
					if (this.itemover !== this.olditemover){ 
						if (pb.getItemById(this.itemover.id)){
							if (pb.getItemById(this.itemover.id).hoverin){
								pb.getItemById(this.itemover.id).hoverin();
							}
						}
						if (pb.getItemById(this.olditemover.id)){
							if (pb.getItemById(this.olditemover.id).hoverout){
								pb.getItemById(this.olditemover.id).hoverout();
							}
						}
					}
				}
				///console.log('over?1.2', this.itemover);
				this.olditemover = this.itemover;
				var bbox = this.itemover.getBoundingClientRect();
				
				this.itemoverx = this.pagex - bbox.left,
				this.itemovery = this.pagey - bbox.top;
				this.itemover = pb.getItemById(this.itemover.id);
				///console.log('over?1.3', this.itemover);
			}
		///console.log('over?2', this.itemover);
			var classValue = this.elementover.className;
			
			if (!undef(pb.closeMenu)){
				if (classValue.indexOf('filemenu') == -1) pb.closeMenu('file');
				if (classValue.indexOf('editmenu') == -1) pb.closeMenu('edit');
				if (classValue.indexOf('addmenu') == -1) pb.closeMenu('add');
				if (classValue.indexOf('viewmenu') == -1) pb.closeMenu('view');
				if (classValue.indexOf('windowmenu') == -1) pb.closeMenu('window');
				if (classValue.indexOf('unitmenu') == -1) pb.closeMenu('unit');
				if (classValue.indexOf('helpmenu') == -1) pb.closeMenu('help');
				if (classValue.indexOf('recentmenu') == -1) pb.closeMenu('recent');
			}

			this.down = true;
			this.downx = event.clientX,
			this.downy = event.clientY;
			this.elementdownover = this.elementover;
			this.distancefromdown = distance2d({x: this.x, y: this.y}, {x: this.downx, y: this.downy});
			this.vectortodown = {x: this.x-this.downx, y: -(this.y-this.downy)};
			
			if (this.dblclickready){
				if (this.itemover) if (this.itemover.doubleclick)
					if (this.itemover == this.lastitemclicked){
						this.itemover.doubleclick();
						return;
					}
			}
		///console.log('over?3', this.itemover);
			this.dblclickready = true;
			runTimeout(function(){pb.mouse.dblclickready = false;}, 250);

			if ((this.elementover.className.indexOf('selectables') != -1 && 
				!inScrollRange(event)) || this.elementover.id == 'thebody'|| this.elementover.className.indexOf('panel-space') != -1 || 
				this.itemover == pb.currentpanel){
			
				if (!(this.itemover && this.itemover instanceof Panel && this.itemover.core.type == 'template')){
				
					if (pb.ready){
					
						$('.dvr-playlist-item').css({backgroundColor: 'rgba(0,0,0,0.0)', color: 'white'});
						$('.dvr-playlist-item').removeClass('dvr-selected');
					
						this.offsetdownx = event.offsetX;
						this.offsetdowny = event.offsetY;
						this.offsetbodydownx = this.x;
						this.offsetbodydowny = this.y;
						this.selectionitem = this.elementover;
						this.rectangle = document.getElementById('selectorbox');
						
						if (this.elementover.className.indexOf('panel-space') != -1||this.elementover.id.indexOf('Panel') != -1)
							$('#selectorbox').css({display: 'none'}).appendTo( document.body );
						else $('#selectorbox').css({display: 'none'}).appendTo( this.elementover );
						
						if (this.elementover.className.indexOf &&
							this.elementover.className.indexOf('tools-pane') != -1)
								this.updateDragBox(event.offsetX,event.offsetY, event, true);
						else
							this.updateDragBox(event.offsetX,event.offsetY, event, false);
							
						$('#selectorbox').css({display: 'block'});
						
					}
					
				}
			}
		///console.log('over?4', this.itemover);
			if (this.itemover) this.itemover.click();
			
			if (this.itemover){
			
				if (this.itemover.element.className.indexOf('draggable') != -1){

					if (pb.currentpanel && !this.itemover.panel) var tscale = pb.currentpanel.core.scale;
					else var tscale = 1;
				
					if (this.itemover.element.className.indexOf('cloneable') != -1){
						
						this.itemover.core.draggedoffsetx = this.itemoverx;
						this.itemover.core.draggedoffsety = this.itemovery;
						
						var clone = this.itemover.clone({extrastyle: 'position: absolute;\
							background-size: 100% 100%; margin: 0; z-index: 4000000;\
						'});
						
						this.dragged.push(clone);

					}
					else {
					
						this.dragged.push(this.itemover);
						this.itemover.core.draggedoffsetx = this.itemoverx;
						this.itemover.core.draggedoffsety = this.itemovery;
						
						var tempoutlined = $( '.outlined' ).toArray();
						
						for (var i=0; i<tempoutlined.length; i++) {
						
							var kitem = pb.getItemById(tempoutlined[i].id);
							
							if (kitem != this.itemover){
								this.dragged.push(kitem);
								kitem.core.draggedoffsetx = this.getDraggedOffset(kitem).x;
								kitem.core.draggedoffsety = this.getDraggedOffset(kitem).y;
							}

						}
						
					}
					
					this.draggedoffsetx = this.itemoverx*tscale;
					this.draggedoffsety = this.itemovery*tscale;
					
					this.dragged[0].element.style.position = 'absolute';
					
					event.preventDefault();
					
					var toldvalues = [];
					
					for (var pk=0; pk<this.dragged.length; pk++){
						if (this.dragged[pk].panel) {
							toldvalues.push({left: this.dragged[pk].element.style.left,
								top: this.dragged[pk].element.style.top});
						}
						
						this.dragged[pk].dragging();
						
						if (!this.dragged[pk]._dragwait){
						
							if (pb.getItemById(this.dragged[pk].element.id) instanceof Button || 
								pb.getItemById(this.dragged[pk].element.id) instanceof Widget){
									this.dragged[pk].element.style.transform =
										'scale('+pb.currentpanel.core.scale+','+
												pb.currentpanel.core.scale+')';
									$(this.dragged[pk].element).css({ 
										'transform': 'scale('+pb.currentpanel.core.scale+','+
											pb.currentpanel.core.scale+')',
										'-webkit-transform': 'scale('+pb.currentpanel.core.scale+','+
											pb.currentpanel.core.scale+')',
										'-moz-transform': 'scale('+pb.currentpanel.core.scale+','+
											pb.currentpanel.core.scale+')',
										'-ms-transform': 'scale('+pb.currentpanel.core.scale+','+
											pb.currentpanel.core.scale+')'
									});
							}

							
							document.body.appendChild(this.dragged[pk].element);
						
						}
					}
					
					if (this.dragged[0].panel) this.action = new Action({
						type: 'move',
						items: this.dragged,
						oldvalues: toldvalues
					});

				}	
				else if (this.itemover.element.className.indexOf('movable') != -1){
					
					event.preventDefault();
					
					this.movedoffsetx = this.itemoverx;
					this.movedoffsety = this.itemovery;
					
					this.moved.push(this.itemover);
					
				}
				
				this.lastitemclicked = this.itemover;
			}

		}

	},
    mousemove: function(event){
	
		if (this.responsive){ 
		
			//console.log(this.x, this.y);
			//event.preventDefault();
		
			this.x = event.clientX,
			this.y = event.clientY;
			
			this.pagex = event.pageX;
			this.pagey = event.pageY;
			
			this.vectortodown = {x: this.x-this.downx, y: -(this.y-this.downy)};
			this.distancefromdown = distance2d({x: this.x, y: this.y}, {x: this.downx, y: this.downy});
			
			this.elementover = document.elementFromPoint(this.x, this.y);
			this.itemover = this.elementover;
			
			if (this.itemover){ 
			
				var bbox = this.elementover.getBoundingClientRect();
				
				this.elementoverx = this.x - bbox.left,
				this.elementovery = this.y - bbox.top;
				
				if (this.itemover.className.indexOf('item_child') != -1){
					
					while (this.itemover.parentNode.className.indexOf('item_child') != -1) {
						this.itemover = this.itemover.parentNode;
						
					}
						
					this.itemover = this.itemover.parentNode;
				}
				
				if (this.olditemover){
					if (this.itemover !== this.olditemover){
						if (pb.getItemById(this.itemover.id)){
							if (pb.getItemById(this.itemover.id).hoverin){
								try {	
									pb.getItemById(this.itemover.id).hoverin();
								} catch (e){};
							}
						}
						if (pb.getItemById(this.olditemover.id)){
							if (pb.getItemById(this.olditemover.id).hoverout){
								try {
									pb.getItemById(this.olditemover.id).hoverout();
								} catch (e){};
							}
						}
					}
				}
				
				this.olditemover = this.itemover;
				
				var bbox = this.itemover.getBoundingClientRect();
				
				this.itemoverx = this.pagex - bbox.left,
				this.itemovery = this.pagey - bbox.top;
				
				this.itemover = pb.getItemById(this.itemover.id);

			}
		
			if (this.rectangle) this.updateDragBox(event.offsetX,event.offsetY, event);
			
			if (this.dragged.length > 0) {
				event.preventDefault();
				for (var i=0; i<this.dragged.length; i++){
					if (this.dragged[i].dragging) this.dragged[i].dragging(event);
				}
			}
			if (this.moved.length > 0) {
				event.preventDefault();
				for (var i=0; i<this.moved.length; i++){
					this.moved[i].moving(event);
				}	
			}
			
        }	
            
	},
    mouseup: function(event){
	
		this.clickup();
	
		if (pb.itemeditor && pb.itemeditor.open == true) return;
	
		if (this.movingpanel){
		
			this.movingpanel = false;
			
			$('#move-button').css('z-index', 1700);
			
			tweencss({
				object: $('#move-button')[0],
				time: 0.5,
				ease: TWEEN.Easing.Elastic.Out,
				props: {top: parseInt($('#move-button')[0].style.top), left: parseInt($('#move-button')[0].style.left)},
				to: {top: 34, left: 100}
			});
			
			$('#move-button').css('opacity', 0.9);
			
		}

		if (this.responsive){ 
			
			this.down = false;
			
			if (this.rectangle){ 
				this.selectFromRectangle();
				$(this.rectangle).css({display: 'none'});
				this.rectangle = null;
			}
			
			if (this.dragged.length > 0) {
			
				for (var i=0; i<this.dragged.length; i++){
					if (this.dragged[i].drop) this.dragged[i].drop();
				}
				
				
				if (this.action) {
					this.action.newvalues = [];
					for (var i=0; i<this.dragged.length; i++){
						this.action.newvalues.push({left: this.dragged[i].element.style.left,
							top: this.dragged[i].element.style.top});
					}
					pb.undoactions.push(this.action);
				}
			}
			this.dragged = [];
			
			if (this.moved.length > 0) {
				if (this.moved[0].drop) this.moved[0].drop();
			}
			this.moved = [];
			
			this.elementdownover = null;
			
			if (this.distancefromdown <= 2 && this.itemover && this.itemover instanceof Button) this.itemover.clickup();
			else if (this.itemover) this.itemover.clickup();

		}
		
	},
    touchstart: function(e){
   
      e.preventDefault();
	  
	  var touch = event;
			var simulatedEvent = document.createEvent("MouseEvent");
			simulatedEvent.initMouseEvent('mousedown', true, true, window, 1, 
					touch.screenX, touch.screenY, 
					touch.clientX, touch.clientY, false, 
					false, false, false, 0, null);
			
			touch.target.dispatchEvent(simulatedEvent);

			return;

      this.forEachChangedFinger(e, function(event, id) {
        
        var newtouch = {};
        newtouch.points = [];
        newtouch.id = id;
        newtouch.dragged = false;
        newtouch.moved = false;
        newtouch.intersected = false;
        newtouch.oldintersected = false;
        newtouch.selected = false;
        newtouch.touchdowninterval = 0;

        this.touchdown++;
        this.touches.push(newtouch);
		  
		var touch = event;
		var simulatedEvent = document.createEvent("MouseEvent");
		simulatedEvent.initMouseEvent('mousedown', true, true, window, 1, 
				touch.screenX, touch.screenY, 
				touch.clientX, touch.clientY, false, 
				false, false, false, 0, null);
		
		touch.target.dispatchEvent(simulatedEvent);

		return;

		
		if (this.responsive){
		
			newtouch.x = event.clientX,
			newtouch.y = event.clientY;
			newtouch.pagex = event.pageX,
			newtouch.pagey = event.pageY;
			newtouch.vectortodown = {x: newtouch.x-newtouch.downx, y: -(newtouch.y-newtouch.downy)};
			newtouch.distancefromdown = distance2d({x: newtouch.x, y: newtouch.y}, 
				{x: newtouch.downx, y: newtouch.downy});
			newtouch.elementover = document.elementFromPoint(newtouch.x, newtouch.y);
			newtouch.itemover = newtouch.elementover;
			if (newtouch.itemover){ 
				var bbox = newtouch.elementover.getBoundingClientRect();
				newtouch.elementoverx = newtouch.x - bbox.left,
				newtouch.elementovery = newtouch.y - bbox.top;
				if (newtouch.itemover.className.indexOf && newtouch.itemover.className.indexOf('item_child') != -1){
					while (newtouch.itemover.parentNode.className.indexOf('item_child') != -1) {
						newtouch.itemover = newtouch.itemover.parentNode;
					}
					newtouch.itemover = newtouch.itemover.parentNode;
				}
				else if (newtouch.itemover.className.baseVal){
					var setitem;
					while (undef(setitem)){
						setitem = pb.getItemById(newtouch.itemover.parentNode.id.replace('_svg', ''));
						newtouch.itemover = newtouch.itemover.parentNode;
					}
					newtouch.itemover = setitem.element;
				}
				if (newtouch.olditemover){
					if (newtouch.itemover !== newtouch.olditemover){ 
						if (pb.getItemById(newtouch.itemover.id)){
							if (pb.getItemById(newtouch.itemover.id).hoverin){
								pb.getItemById(newtouch.itemover.id).hoverin();
							}
						}
						if (pb.getItemById(newtouch.olditemover.id)){
							if (pb.getItemById(newtouch.olditemover.id).hoverout){
								pb.getItemById(newtouch.olditemover.id).hoverout();
							}
						}
					}
				}
				newtouch.olditemover = newtouch.itemover;
				var bbox = newtouch.itemover.getBoundingClientRect();
				newtouch.itemoverx = newtouch.x - bbox.left,
				newtouch.itemovery = newtouch.y - bbox.top;
				newtouch.itemover = pb.getItemById(newtouch.itemover.id);
			}
		
			if (newtouch.rectangle) newtouch.updateDragBox(event.offsetX,event.offsetY, event);
			
			if (newtouch.dragged.length > 0) {
				newtouch.dragged[0].dragging();
			}
			if (newtouch.moved.length > 0) {
				newtouch.moved[0].moving(event);
			}
		
		}
		
      }.bind(this));
	  
   },
   touchmove: function(e){

		//e.preventDefault(); // prevent page scroll

		this.forEachChangedFinger(e, function(event, id){
		  
			for (var i in this.touches){
				if (this.touches[i].id==id){
					var thistouch = this.touches[i];
				}
			}
			
			if (this.responsive){
	  
			}    
			
		}.bind(this));
    },
    touchend: function(e){

        this.forEachChangedFinger(e, function(event, id) {
         
			//event.preventDefault();
              
           	for (var i in this.touches){
				if (this.touches[i].id==id){
					var thistouch = this.touches[i];
				}
			}
              
            if (this.responsive){ 
                
            }
			
            this.touchdown--;
            removeFromArray(this.touches, thistouch);
              
        }.bind(this));
    },
    forEachChangedFinger: function (e, cb){
      
		if (e.originalEvent) e = e.originalEvent;

		for (var i = 0; i < e.changedTouches.length; i++){
			var finger = e.changedTouches[i];
			var id = finger.identifier;
			cb(finger, id);
		}
    },
	elementsOver: function(){
		var clickX = this.pagex;
		var clickY = this.pagey;
		
		var list;
		var s = pb.currentpanel.core.scale;

		var $list = $('#'+pb.currentpanel.core.id+' *').filter(function(){
			var offset = $(this).offset();

			var range = {
				x: [offset.left, (offset.left + $(this).width()*s)],
				y: [offset.top, (offset.top + $(this).height()*s)]
			};

			return (clickX >= range.x[0] && clickX <= range.x[1]) && (clickY >= range.y[0] && clickY <= range.y[1])

		});

		list = $list.map(function(){
			return this;
		}).get();
		
		//return $(':hover').toArray();

		return list;
	},
	itemsOver: function(selector){
		var clickX = this.pagex;
		var clickY = this.pagey;
		
		var list;
		if (undef(selector)) var selector = 'body *';

		var $list = $(selector).filter(function(){
			var offset = $(this).offset();
			
			var bbox = this.getBoundingClientRect();

			var range = {
				x: [offset.left, offset.left + $(this).width()],
				y: [offset.top, offset.top + $(this).height()]
			};
			
			if (bbox.left == 0 && bbox.right == 0 && bbox.top == 0 && bbox.bottom == 0) return false;

			return (clickX >= range.x[0] && clickX <= range.x[1]) && (clickY >= range.y[0] && clickY <= range.y[1])

		});

		list = $list.map(function() {
			return this;
		}).get();
		
		i = list.length;
		while (i--){
			if (!list[i].id || list[i].className.indexOf('item_child') != -1 ||
				$(list[i]).css('display') == 'none' ||
				list[i].id.indexOf('dialog') != -1 ||
				list[i].id.indexOf('Asset') != -1)
				removeFromArray(list, list[i]);
		}

		return list;
	},
	isOverElement: function(element){
		if (!element) return; false
		var bbox = element.getBoundingClientRect();
		var result = false;
		if ((this.pagex >= bbox.left && this.pagex <= bbox.right) &&
			(this.pagey >= bbox.top && this.pagey <= bbox.bottom)) return true;
		else return false;
	},
	getOffsetOverElement: function(element){
		var bbox = element.getBoundingClientRect();
		var result = {x: 0, y: 0};
		result.x = (this.pagex + element.scrollLeft - bbox.left);
		result.y = (this.pagey + element.scrollTop - bbox.top);
		return result;
	},
	getDraggedOffset: function(item){
	
		var bbox = item.element.getBoundingClientRect();
		var ioverx = this.pagex - bbox.left;
		var iovery = this.pagey - bbox.top;
		
		var doffsetx = ioverx;
		var doffsety = iovery;
		return {x: doffsetx, y: doffsety};
		
	},
	updateDragBox: function(offsetX, offsetY, event, toolspane){
	
		if (!pb.ready) return;
	
		if (this.rectangle) {
			if (!toolspane){
				var offset = this.getOffsetOverElement(document.body);
				var odx = this.offsetbodydownx;
				var ody = this.offsetbodydowny;
			}
			else{
				var offset = this.getOffsetOverElement(this.elementdownover);
				var odx = this.offsetdownx;
				var ody = this.offsetdowny;
			}
			$('#selectorbox').css({
				top: Math.min( ody, offset.y ),
				left: Math.min(  odx, offset.x ),
				height: Math.abs( offset.y - ody ),
				width: Math.abs( offset.x - odx )});
		}
	},
	selectFromRectangle: function(){
		
		if (this.rectangle){

			if (pb.currentpanel.buttons || pb.currentpanel.widgets){

				if (pb.currentpanel.buttons) 
					for (var i=0;i<pb.currentpanel.buttons.length;i++){
						if (aabbOverlap(getAabb(pb.currentpanel.buttons[i].element.getBoundingClientRect()),
																	getAabb(this.rectangle.getBoundingClientRect()))){
							$(pb.currentpanel.buttons[i].element).addClass('outlined');
						}
						else {
							if (!pb.shiftdown) $(pb.currentpanel.buttons[i].element).removeClass('outlined first');
							
						}
					}
				if (pb.currentpanel.widgets) 
					for (var i=0;i<pb.currentpanel.widgets.length;i++){
						if (aabbOverlap(getAabb(pb.currentpanel.widgets[i].element.getBoundingClientRect()),
																	getAabb(this.rectangle.getBoundingClientRect()))){
							$(pb.currentpanel.widgets[i].element).addClass('outlined');
						}
						else {
							if (!pb.shiftdown) $(pb.currentpanel.widgets[i].element).removeClass('outlined first');
						}
					}
				if (pb.currentpanel.subpanels) 
					for (var i=0;i<pb.currentpanel.subpanels.length;i++){
						if (aabbOverlap(getAabb(pb.currentpanel.subpanels[i].element.getBoundingClientRect()),
																	getAabb(this.rectangle.getBoundingClientRect()))){
							$(pb.currentpanel.subpanels[i].element).addClass('outlined');
						}
						else {
							if (!pb.shiftdown) $(pb.currentpanel.subpanels[i].element).removeClass('outlined first');
						}
					}

			}
			
			if (!$('.first').exists()){
				$($('.outlined')[0]).addClass('first');
			}
			
			if ($('.outlined').exists()){
				var r = [];
				$('.outlined').each(function(){
					var type = false, set = false;
					var item = pb.getItem(this.id);
					if (item instanceof Button) type = 'button';
					if (item instanceof Widget){
						type = 'widget'; set = item.core.set;
					}
					r.push({id: this.id, type: type, set: set});
				});
				ng.selected = r;
				array = [];
				$('.outlined').each(function(){
					var item = pb.getItem(this.id);
					if (item instanceof Button) for (var i=0; i<item.core.states.length; i++){
						var found = false;
						for (var j=0; j<array.length; j++){
							if (item.core.states[i].name == array[j].name) found = true;
						}
						if (!found) array.push(item.core.states[i]);
					}
				});
				ng.buttonstates = array;
				if ($('.first')[0] && pb.getItem($('.first')[0].id) && pb.getItem($('.first')[0].id).core){
					$('#item-width-input').val(pb.getItem($('.first')[0].id).core.actualwidth);
					$('#item-height-input').val(pb.getItem($('.first')[0].id).core.actualheight);
					pb.getItem($('.first')[0].id).core.actualtop = parseFloat(pb.getItem($('.first')[0].id).element.style.top);
					pb.getItem($('.first')[0].id).core.actualleft = parseFloat(pb.getItem($('.first')[0].id).element.style.left);
					$('#item-top-input').val(pb.getItem($('.first')[0].id).core.actualtop);
					$('#item-left-input').val(pb.getItem($('.first')[0].id).core.actualleft);
				}
				$('#props-props-label').click();
				if ($('#props_props').css('display') == 'none'){
					$('.item-options').each(function(){
						$(this).css({display: 'none'});
					});
					setTimeout(function(){
						$('#item-basics-container').slideDown(400);
					}, 200);
				}
				if (ng.selected.length && pb.getItem(ng.selected[0].id) && pb.getItem(ng.selected[0].id).core && pb.getItem(ng.selected[0].id).core.touchpanelkey) 
					$('#touchpanelkey-radio'+pb.getItem(ng.selected[0].id).core.touchpanelkey).click();
				else $('#touchpanelkey-radio9').click();
			}
			else {
				ng.selected = false, ng.buttonstates = [];
				$('.item-options').each(function(){
					if ($(this).css('display') != 'none') $(this).slideUp();
				});
			}
			
		}
	}
}
  //**************  END MOUSE  ****************// 