$.fn.pano = function(options){
	
	// get a handle on the panorama and controls
	var $pano = this;
	var $leftCtrl = $pano.find(".controls").find("a.left");
	var $rightCtrl = $pano.find(".controls").find("a.right");
	
	var getImageWidth = function(imgSrc) {
		var img = new Image;
		img.src = imgSrc;
		return img.width;
	};
	
	var moveBackgroundTo = function(newPos, duration, cb) {		
		duration = duration || 0;
		cb = cb || function(){};
		$pano.animate({
			"background-position": newPos.toString() + "px"
		}, duration, "linear", cb);
	};
	
	var moveBackgroundBy = function(distance, duration, cb) {
		duration = duration || 0;
		cb = cb || function(){};
		moveBackgroundTo(getCurrentPosition() + distance, duration, cb);
	};
	
	var getCurrentPosition = function() {
		return parseInt($pano.css("background-position").split(" ")[0].replace("px", ""));
	};
	
	var indicateMovement = function() {
		$pano.addClass("moving");
	};
	
	var noMovement = function() {
		$pano.removeClass("moving");
	};
	
	var insideImage = function(mouseXPos) {
		var $offsetLeft = $pano.offset().left;
        var maxLeft = $offsetLeft;
        var maxRight = $offsetLeft + $pano.width();
        if( mouseXPos < maxLeft || mouseXPos > maxRight) {
        	return false;
        }
        return true;
	};
	
	var dragMove = function(xPos, startPosition, cb) {
	
        // dont move if you're outside the image
        if (!insideImage(xPos)) {
            return false;
        } 
        
        // calculate the change in position
		var diff = (xPos - startPosition);
		
		// move it
		moveBackgroundBy(diff, 0, cb);
		
	}
	
	var leftMover,
		rightMover,
		ctrlInterval = 100,
		ctrlSpeed = 50;
		
	// setup the initial styling
	$pano.css({
		"background-image": "url('" + options.img + "')",
		"background-position": "50% 50%",
	    "background-size": "auto 100%",
	    "background-repeat": "repeat-x"
	});
	
	// set the initial position in pixels (easier math)
	var halfWidth = (getImageWidth(options.img) / 2);
	moveBackgroundTo(halfWidth);
		
	$leftCtrl.on("mousedown", function(event){
		
		// dont process the drag events
		event.stopPropagation();
		
		// indicate movement
		indicateMovement();
		
		// immediately move 
		moveBackgroundBy(ctrlSpeed, 100);
		
		// move left on interval
		leftMover = setInterval(function(){
			moveBackgroundBy(ctrlSpeed, 100);
		}, ctrlInterval);
		
	}).on("touchstart", function(event){
		
		// dont process the drag events
		event.stopPropagation();
		
		// don't show the context menu while holding
		event.preventDefault();
		
		// indicate movement
		indicateMovement();
		
		// immediately move 
		moveBackgroundBy(ctrlSpeed, 100);
		
		// move left on interval
		leftMover = setInterval(function(){
			moveBackgroundBy(ctrlSpeed, 100);
		}, ctrlInterval);
		
	});
	
	$rightCtrl.on("mousedown", function(event){
		
		// dont process the drag events
		event.stopPropagation();
		
		// indicate movement
		indicateMovement();
		
		// immediately move 
		moveBackgroundBy(-ctrlSpeed, 100);
		
		// move right on interval
		rightMover = setInterval(function(){
			moveBackgroundBy(-ctrlSpeed, 100);
		}, ctrlInterval);
		
	}).on("touchstart", function(event){
		
		// dont process the drag events
		event.stopPropagation();
		
		// don't show the context menu while holding
		event.preventDefault();
		
		// indicate movement
		indicateMovement();
		
		// immediately move 
		moveBackgroundBy(-ctrlSpeed, 100);
		
		// move right on interval
		rightMover = setInterval(function(){
			moveBackgroundBy(-ctrlSpeed, 100);
		}, ctrlInterval);
		
	});
	
	$pano.on("mousedown", function(event){
		
		// indicate movement
		indicateMovement();
		
		var startPosition = event.pageX;
		
		$pano.on("mousemove", function(event){
            
            var xPos = event.pageX;
            dragMove(xPos, startPosition, function(){
    			// after animation is complete, set the "start" position to the current position
    			startPosition =xPos;
    		});
            
		});
		
	}).on("touchstart", function(event){
		
		// indicate movement
		indicateMovement();
		
		// don't show the context menu while holding
		event.preventDefault();
		
		var startPosition = event.pageX;
		
		$pano.on("touchmove", function(event){
			
            var xPos = event.originalEvent.changedTouches[0].pageX;
            dragMove(xPos, startPosition, function(){
    			// after animation is complete, set the "start" position to the current position
    			startPosition = xPos;
    		});
            
		});
		
	});
	
	$("body").on("mouseup", function(){
        $pano.off("mousemove");
		$pano.stop(true, true);
		clearInterval(leftMover);
		clearInterval(rightMover);
		noMovement();
	}).on("touchend", function(){
		$pano.off("touchmove");
		$pano.stop(true, true);
		clearInterval(leftMover);
		clearInterval(rightMover);
		noMovement();
	});
	
};
@@ -1,8 +1,154 @@
+/*%0A%0APano%0AjQuery plugin to display a 360 degree panoramic image%0ASean Coyne%0Ahttps://github.com/seancoyne/pano%0Ahttps://seancoyne.github.io/pano%0A%0A*/%0A%0A
 $.fn.pan

add comment header