// jquery.jparallax.js// 0.9.1// Stephen Band//// Dependencies:// jQuery 1.2.6 (jquery.com)//// Project and documentation site:// http://webdev.stephband.info/parallax.html// CLOSURE(function(jQuery) {// PRIVATE FUNCTIONSfunction stripFiletype(ref) {  var x=ref.replace('.html', '');  return x.replace('#', '');}function initOrigin(l) {  if (l.xorigin=='left')	{l.xorigin=0;}	else if (l.xorigin=='middle' || l.xorigin=='centre' || l.xorigin=='center')	{l.xorigin=0.5;}	else if (l.xorigin=='right')	{l.xorigin=1;}  if (l.yorigin=='top')		{l.yorigin=0;}	else if (l.yorigin=='middle' || l.yorigin=='centre' || l.yorigin=='center')	{l.yorigin=0.5;}	else if (l.yorigin=='bottom')	{l.yorigin=1;}}function positionMouse(mouseport, localmouse, virtualmouse) {  var difference = {x: 0, y: 0, sum: 0};  	// Set where the virtual mouse is, if not on target  if (!mouseport.ontarget) {        // Calculate difference    difference.x    = virtualmouse.x - localmouse.x;    difference.y    = virtualmouse.y - localmouse.y;    difference.sum  = Math.sqrt(difference.x*difference.x + difference.y*difference.y);        // Reset virtualmouse    virtualmouse.x = localmouse.x + difference.x * mouseport.takeoverFactor;    virtualmouse.y = localmouse.y + difference.y * mouseport.takeoverFactor;        // If mouse is inside the takeoverThresh set ontarget to true    if (difference.sum < mouseport.takeoverThresh && difference.sum > mouseport.takeoverThresh*-1) {    	mouseport.ontarget=true;    }  }  // Set where the layer is if on target  else {    virtualmouse.x = localmouse.x;    virtualmouse.y = localmouse.y;  }}function setupPorts(viewport, mouseport) {	var offset = mouseport.element.offset();		  jQuery.extend(viewport, {    width: 		viewport.element.width(),    height: 	viewport.element.height()  });    jQuery.extend(mouseport, {    width:		mouseport.element.width(),    height:		mouseport.element.height(),    top:			offset.top,    left:			offset.left  });}function parseTravel(travel, origin, dimension) {    var offset;  var cssPos;    if (typeof(travel) === 'string') {    if (travel.search(/^\d+\s?px$/) != -1) {      travel = travel.replace('px', '');      travel = parseInt(travel, 10);      // Set offset constant used in moveLayers()      offset = origin * (dimension-travel);      // Set origin now because it won't get altered in moveLayers()      cssPos = origin * 100 + '%';         return {travel: travel, travelpx: true, offset: offset, cssPos: cssPos};    }    else if (travel.search(/^\d+\s?%$/) != -1) {      travel.replace('%', '');      travel = parseInt(travel, 10) / 100;    }    else {      travel=1;    }  }  // Set offset constant used in moveLayers()  offset = origin * (1 - travel);  return {travel: travel, travelpx: false, offset: offset}}function setupLayer(layer, i, mouseport) {  var xStuff;  var yStuff;  var cssObject = {};  layer[i]=jQuery.extend({}, {  	width:		layer[i].element.width(),  	height:		layer[i].element.height()  }, layer[i]);  xStuff = parseTravel(layer[i].xtravel, layer[i].xorigin, layer[i].width);  yStuff = parseTravel(layer[i].ytravel, layer[i].yorigin, layer[i].height);  jQuery.extend(layer[i], {  	// Used in triggerResponse  	diffxrat:    mouseport.width / (layer[i].width - mouseport.width),  	diffyrat:    mouseport.height / (layer[i].height - mouseport.height),  	// Used in moveLayers  	xtravel:     xStuff.travel,  	ytravel:     yStuff.travel,  	xtravelpx:   xStuff.travelpx,  	ytravelpx:   yStuff.travelpx,  	xoffset:     xStuff.offset,  	yoffset:     yStuff.offset  });    // Set origin now if it won't be altered in moveLayers()  if (xStuff.travelpx) {cssObject.left = xStuff.cssPos;}  if (yStuff.travelpx) {cssObject.top = yStuff.cssPos;}  if (xStuff.travelpx || yStuff.travelpx) {layer[i].element.css(cssObject);}}function setupLayerContents(layer, i, viewportOffset) {  var contentOffset;  // Give layer a content object  jQuery.extend(layer[i], {content: []});  // Layer content: get positions, dimensions and calculate element offsets for centering children of layers  for (var n=0; n<layer[i].element.children().length; n++) {	  	  if (!layer[i].content[n])          layer[i].content[n]             = {};	  if (!layer[i].content[n].element)  layer[i].content[n]['element']  = layer[i].element.children().eq(n);	  	  // Store the anchor name if one has not already been specified.  You can specify anchors in Layer Options rather than html if you want.    if(!layer[i].content[n].anchor && layer[i].content[n].element.children('a').attr('name')) {    	layer[i].content[n]['anchor'] = layer[i].content[n].element.children('a').attr('name');	  }	  	  // Only bother to store child's dimensions if child has an anchor.  What's the point otherwise?	  if(layer[i].content[n].anchor) {      contentOffset = layer[i].content[n].element.offset();	  	jQuery.extend(layer[i].content[n], {	  		width: 		layer[i].content[n].element.width(),	  		height:		layer[i].content[n].element.height(),	  		x:			  contentOffset.left - viewportOffset.left,	  		y:			  contentOffset.top - viewportOffset.top	  	});	  	jQuery.extend(layer[i].content[n], { 	  	  posxrat:  (layer[i].content[n].x + layer[i].content[n].width/2) / layer[i].width,	  	  posyrat:  (layer[i].content[n].y + layer[i].content[n].height/2) / layer[i].height      });	  }  }}function moveLayers(layer, xratio, yratio) {	var xpos;	var ypos;	var cssObject;		for (var i=0; i<layer.length; i++) {        // Calculate the moving factor  	xpos = layer[i].xtravel * xratio + layer[i].xoffset;    ypos = layer[i].ytravel * yratio + layer[i].yoffset;    cssObject = {};  	// Do the moving by pixels or by ratio depending on travelpx    if (layer[i].xparallax) {      if (layer[i].xtravelpx) {        cssObject.marginLeft = xpos * -1 + 'px';      }       else {        cssObject.left = xpos * 100 + '%';        cssObject.marginLeft = xpos * layer[i].width *-1 + 'px';      }	  }	  if (layer[i].yparallax) {      if (layer[i].ytravelpx) {        cssObject.marginTop = ypos * -1 + 'px';      }      else {        cssObject.top = ypos * 100 + '%';        cssObject.marginTop = ypos * layer[i].height * -1 + 'px';      }    }    layer[i].element.css(cssObject);	}}// PLUGIN DEFINITION **********************************************************************jQuery.fn.jparallax = function(options) {		// Organise settings into objects (Is this a bit of a mess, or is it efficient?)	var settings = jQuery().extend({}, jQuery.fn.jparallax.settings, options);	var settingsLayer = {  			xparallax:				settings.xparallax,  			yparallax:				settings.yparallax,  			xorigin:					settings.xorigin,  			yorigin:					settings.yorigin,  			xtravel:          settings.xtravel,  			ytravel:          settings.ytravel  		};  var settingsMouseport = {  			element:					settings.mouseport,				takeoverFactor:		settings.takeoverFactor,				takeoverThresh:		settings.takeoverThresh			};	if (settings.mouseport) settingsMouseport['element'] = settings.mouseport;		// Populate layer array with default settings	var layersettings = [];	for(var a=1; a<arguments.length; a++) {		layersettings.push( jQuery.extend( {}, settingsLayer, arguments[a]) );	}		// Iterate matched elements	return this.each(function() {    // VAR    		var localmouse = {					x:				0.5,					y:				0.5		};		    var virtualmouse = {					x:				0.5,					y:				0.5		};				var timer = {		  running:		false,		  frame:			settings.frameDuration,		  fire:				function(x, y) {		  	  				  positionMouse(mouseport, localmouse, virtualmouse);                    moveLayers(layer, virtualmouse.x, virtualmouse.y);		  	  				  this.running = setTimeout(function() {		  	  				  	if ( localmouse.x!=x || localmouse.y!=y || !mouseport.ontarget ) {		  	  				  		timer.fire(localmouse.x, localmouse.y);		  	  				  	}		  	  				  	else if (timer.running) {		  	  				  		timer.running=false;		  	  				  	}		  	  				  }, timer.frame);		  	  				}		};		var viewport	=	{element: jQuery(this)};				var mouseport = jQuery.extend({}, {element: viewport.element}, settingsMouseport, {		  xinside:          false,		// is the mouse inside the mouseport's dimensions?			yinside:	        false,			active:		        false,		// are the mouse coordinates still being read?			ontarget:         false			// is the top layer inside the takeoverThresh?		});    		var layer			= [];        // FUNCTIONS        function matrixSearch(layer, ref, callback) {      for (var i=0; i<layer.length; i++) {        var gotcha=false;        for (var n=0; n<layer[i].content.length; n++) {          if (layer[i].content[n].anchor==ref) {            callback(i, n);            return [i, n];          }        }      }      return false;    }        // RUN        setupPorts(viewport, mouseport);				// Cycle through and create layers    for (var i=0; i<viewport.element.children().length; i++) {			// Create layer from settings if it doesn't exist			layer[i]=jQuery.extend({}, settingsLayer, layersettings[i], {				element:	viewport.element.children('*:eq('+i+')')			});					  setupLayer(layer, i, mouseport);            if (settings.triggerResponse) {		    setupLayerContents(layer, i, viewport.element.offset());		  }		}				        // Set up layers CSS and initial position    viewport.element.children().css('position', 'absolute');		moveLayers(layer, 0.5, 0.5);				// Mouse Response		if (settings.mouseResponse) {			jQuery().mousemove(function(mouse){				// Is mouse inside?				mouseport.xinside = (mouse.pageX >= mouseport.left && mouse.pageX < mouseport.width+mouseport.left) ? true : false;				mouseport.yinside = (mouse.pageY >= mouseport.top  && mouse.pageY < mouseport.height+mouseport.top)  ? true : false;				// Then switch active on.				if (mouseport.xinside && mouseport.yinside && !mouseport.active) {					mouseport.ontarget = false;					mouseport.active = true;				}				// If active is on give localmouse coordinates				if (mouseport.active) {					if (mouseport.xinside) { localmouse.x = (mouse.pageX - mouseport.left) / mouseport.width; }					else { localmouse.x = (mouse.pageX < mouseport.left) ? 0 : 1; }					if (mouseport.yinside) { localmouse.y = (mouse.pageY - mouseport.top) / mouseport.height; } 					else { localmouse.y = (mouse.pageY < mouseport.top) ? 0 : 1; }				}								// If mouse is inside, fire timer				if (mouseport.xinside && mouseport.yinside)  { if (!timer.running) timer.fire(localmouse.x, localmouse.y); }				else if (mouseport.active) { mouseport.active = false; }						});		}				// Trigger Response		if (settings.triggerResponse) {		  viewport.element.bind("jparallax", function(event, ref){		    		    ref = stripFiletype(ref);		                  matrixSearch(layer, ref, function(i, n) {          localmouse.x = layer[i].content[n].posxrat * (layer[i].diffxrat + 1) - (0.5 * layer[i].diffxrat);          localmouse.y = layer[i].content[n].posyrat * (layer[i].diffyrat + 1) - (0.5 * layer[i].diffyrat);            if (!settings.triggerExposesEdges) {            if (localmouse.x < 0) localmouse.x = 0;            if (localmouse.x > 1) localmouse.x = 1;            if (localmouse.y < 0) localmouse.y = 0;            if (localmouse.y > 1) localmouse.y = 1;          }                    mouseport.ontarget = false;                    if (!timer.running) timer.fire(localmouse.x, localmouse.y);        });		  });		}				// Window Resize Response		jQuery(window).resize(function() {		  setupPorts(viewport, mouseport);		  for (var i=0; i<layer.length; i++) {		    setupLayer(layer, i, mouseport);      }		});					});};// END OF PLUGIN DEFINITION **********************************************************************// PLUGIN DEFAULTSjQuery.fn.jparallax.settings = {	mouseResponse:		    true,						// Sets mouse response	mouseActiveOutside:		false,					// Makes mouse affect layers from outside of the mouseport. 	triggerResponse:	    true,					  // Sets trigger response  triggerExposesEdges:  false,          // Sets whether the trigger pulls layer edges into view in trying to centre layer content.	xparallax:				    true,						// Sets directions to move in	yparallax:				    true,						//	xorigin:					    0.5,				    // Sets default alignment - only comes into play when travel is not 1	yorigin:					    0.5,				    //	xtravel:              1,              // Factor by which travel is amplified	ytravel:              1,              //	takeoverFactor:		    0.65,						// Sets rate of decay curve for catching up with target mouse position	takeoverThresh:		    0.002,					// Sets the distance within which virtualmouse is considered to be on target, as a multiple of mouseport width.	frameDuration:        25							// In milliseconds};// RUNinitOrigin(jQuery.fn.jparallax.settings);jQuery(function() {	});// END CLOSURE})(jQuery);