// #########################################
// Script developped by http://www.iMatt.ch
// Version 0.9
// Not licenced yet, will be free and open source soon. You can contact me on my website to get to last version of this script.
// #################################

(function() {  
	
    jQuery.fn.jZoom = function(settings) {  

        settings = jQuery.extend({
			shadow: true,				/* Display shadow */
			margin: 80,					/* Margin between image and screen border, in pixel */
			duration: 280,				/* Animation duration, in milliseconds */
			transition_duration: 350,
			diaporama_duration: 4000,
			images_dir: '/graef-voyages-culturels.ch/images/jzoom/',		/* Images directory - absolute or relative path */
			group: false		/*...*/
        }, settings);



		var window_width, window_height, window_offset_top, window_offset_left;
		var thumb_width, thumb_height, thumb_top, thumb_left;
		var image_width, image_height, image_top, image_left;
			
		var spinner_frame = 12;
		
		var group_name, group_prev, group_next;
		
		var timeout_id = false;
		
		
		// #########################
		// Images preload
		// #########################

		/*var imgCloseBox = new Image();
		imgCloseBox.src = settings['images_dir'] + 'close.png';*/

		var imgSpinner = new Image();
		imgSpinner.src = settings['images_dir'] + 'spinner.png';

		if (settings['shadow']) {
			var imgShadow1 = new Image();
			imgShadow1.src = settings['images_dir'] + 'shadow-1.png';
			var imgShadow2 = new Image();
			imgShadow2.src = settings['images_dir'] + 'shadow-2.png';
			var imgShadow3 = new Image();
			imgShadow3.src = settings['images_dir'] + 'shadow-3.png';
			var imgShadow4 = new Image();
			imgShadow4.src = settings['images_dir'] + 'shadow-4.png';
			var imgShadow5 = new Image();
			imgShadow5.src = settings['images_dir'] + 'shadow-5.png';
			var imgShadow6 = new Image();
			imgShadow6.src = settings['images_dir'] + 'shadow-6.png';
			var imgShadow7 = new Image();
			imgShadow7.src = settings['images_dir'] + 'shadow-7.png';
			var imgShadow8 = new Image();
			imgShadow8.src = settings['images_dir'] + 'shadow-8.png';
		}
		
		
		$('.jZoom').click(function() { return controller(this); });
		
		
		function controller(object) {
			
			
			
			if (document.getElementById('jZoom_image')) {
				image_transition(object);
			}
			
			else {
				freeze_click();
				open_image(object);
			}
			
			return false;
			
			
		}
		
		/* 
			In charge of calling functions to open an image with zoom effet
		*/
		function open_image(object) {
			
			save_window_sizes_and_offset();

			save_thumb_sizes_and_positions(object);
			
			var img = new Image();
			img.src = $(object).attr('href');
			
			if (!img.complete) load_spinner(thumb_top + (thumb_height / 2) - 15, thumb_left + (thumb_width / 2) - 15);
			
			load_image(object, function() {
				
				define_image_sizes();
				
				remove_spinner();
				
				zoom(function() {
					
					load_struct_objects(object);
					
					unfreeze_click();
					
				});
			});
		}
		
		/* 
			Loads various elements (shadow, closebox, buttons)
		*/
		function load_struct_objects(object) {
			
			if (settings['shadow']) display_shadows();
			if (settings['group']) load_navbar(object);
			
			//load_closebox();
			
			assign_close_function();
			
			
		}
		
		/*
			This will load the image linked in <a>'s href and position it
		*/
		function load_image(object, callback) {

			var img = $('<img src="'+$(object).attr('href')+'" id="jZoom_image"></img>');
			$(img).css('opacity','0');
			$(img).css('position', 'absolute');
			if (!$.browser.opera) $(img).css('display', 'none'); // Opera doesn't execute the callback on load if the css display is none. This creates a small bug for Opera : scrollbar can appear in flash when the image is loaded.
			$(img).css('top', thumb_top + 'px');
			$(img).css('left', thumb_left + 'px');
		
			$(img).bind('load', callback);
		
			$(img).appendTo("body");
		}
			
		
		/*
			Saves window's width & Height in global vars
		*/
		function save_window_sizes_and_offset() {
			
			if (parseInt(navigator.appVersion)>3) {
				if (navigator.appName.indexOf("Microsoft")!=-1) {
					window_width = document.documentElement.clientWidth;
					window_height = document.documentElement. clientHeight;
				}
				else {
					window_width = window.innerWidth;
			  		window_height = window.innerHeight;
				}
			}
			
			window_offset_top = $(window).scrollTop();
			window_offset_left = $(window).scrollLeft();
		}
		
		/*
			Save clicked thumb's sizes and positions
		*/
		function save_thumb_sizes_and_positions(object) {
			
			var thumb = object.firstChild;
			
			var thumb_position = $(thumb).offset({ scroll: false });
			
			thumb_top = parseInt(thumb_position['top']);
			thumb_left = parseInt(thumb_position['left']);
			
			thumb_width = parseInt($(thumb).width());
			thumb_height = parseInt($(thumb).height());
		}
		
		/* 
			Define final image sizes with max width and height constraints depending 
		*/
		function define_image_sizes() {
			
			/* We save the image's width and height */
			image_width = parseInt($('#jZoom_image').width());
			image_height = parseInt($('#jZoom_image').height());
			
			/* If the image's width is too big, we resize the image to the max width */
			if (image_width + settings['margin'] * 2 > window_width) {
				var max_width = parseInt(window_width - settings['margin'] * 2);
				image_height = parseInt(image_height / image_width * max_width);
				image_width = parseInt(max_width);
			}
			
			/* If the image's height is too big, we resize the image to the max height */
			if (image_height + settings['margin'] * 2 > window_height) {
				var max_height = parseInt(window_height - settings['margin'] * 2);
				image_width = parseInt(image_width / image_height * max_height);
				image_height = parseInt(max_height);
			}
			
			/* We define the image's top and left positions */
			image_top = parseInt(window_offset_top + (window_height - image_height) / 2);
			image_left = parseInt(window_offset_left + (window_width - image_width) / 2);
			
		}
		
		/*
			Show Zoom effet
		*/
		function zoom(callback) {
			
			$('#jZoom_image').css('width', thumb_width + 'px');
			$('#jZoom_image').css('height', thumb_height + 'px');
			$('#jZoom_image').css('dipslay', 'block');
			
			$('#jZoom_image').animate({ 
				width: image_width+'px',
				height: image_height+'px',
				top: image_top+'px',
				left: image_left+'px',
				opacity: '1'
			}, settings['duration'], callback );
		}
		
		/* 
			Load Close Box
		*/
		/*function load_closebox() {
			var closebox = $('<div id="jZoom_closebox"></div>');
			$(closebox).css('background', 'url(' +settings['images_dir'] + 'close.png)');
			$(closebox).css('position', 'absolute');
			$(closebox).css('width', '28px');
			$(closebox).css('height', '28px');
			$(closebox).css('top', (image_top - 12) + 'px');
			$(closebox).css('left', (image_left - 14) + 'px');
			$(closebox).css('display', 'none');
			
			if ($.browser.msie && parseInt(jQuery.browser.version) < 7) {
				$(closebox).css('background', 'url(' + settings['images_dir'] + 'blank.gif)');
				$(closebox).css('filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + settings['images_dir'] + 'close.png", sizingMethod="scale")');
			}			
			
			$(closebox).appendTo('body');
			
			if (!$.browser.msie) {
				$('#jZoom_image').bind('mouseover, mousemove', function() { $('#jZoom_closebox').fadeIn('fast'); });
				$('#jZoom_image').bind('mouseout', function() { $('#jZoom_closebox').fadeOut('fast'); });
			}
			else {
				$('#jZoom_image').bind('mouseover, mousemove', function() { $('#jZoom_closebox').css('display', 'inline'); });
				$('#jZoom_image').bind('mouseout', function() { $('#jZoom_closebox').css('display','none'); });
			}

		}*/
		
		/*
			Assign the close function to the image and close box
		*/
		function assign_close_function() {
			
			$('#jZoom_image').css('cursor','pointer');
			
			$('#jZoom_image').click(function() { close_image(); });
		}
		
		function load_navbar(object) {
				
			group_name = $(object).attr('rel');
			group_prev = $(object).prevAll("[rel='"+group_name+"']");
			group_next = $(object).nextAll("[rel='"+group_name+"']");
		
			var navbar = $('<div id="jZoom_navbar" style="display: none;"></div>');
			$(navbar).css('position', 'absolute');
			//$(navbar).css('width', '155px');
			$(navbar).css('height', '74px');
			$(navbar).css('top', image_top + image_height - 44 + 'px');
			$(navbar).css('left', image_left + image_width / 2 - 77 + 'px');
		
		
			var prev = $('<div style="float: left; width: 55px; height: 39px; background: url('+settings['images_dir']+'prev.png); cursor: pointer"></div>');
			if (group_prev.size()>0) $(prev).click(function() { image_transition(group_prev[0]); });
			else $(prev).click(function() { close_image(); });
			$(prev).appendTo(navbar);
		
		
			var play = $('<div id="jZoom_play" style="float: left; width: 45px; height: 39px; background: url('+settings['images_dir']+'play.png); cursor: pointer"></div>');
			if (timeout_id) { $(play).css('display', 'none'); }
			$(play).bind('click', function() {
				play_diaporama();
				$('#jZoom_play').css('display','none');
				$('#jZoom_stop').css('display','block');
			});
			$(play).appendTo(navbar);
		
			
			var stop = $('<div id="jZoom_stop" style="float: left; width: 45px; height: 39px; background: url('+settings['images_dir']+'stop.png); cursor: pointer"></div>');
			if (!timeout_id) { $(stop).css('display', 'none'); }
			$(stop).click(function() { 
				stop_diaporama();
				$('#jZoom_stop').css('display','none');
				$('#jZoom_play').css('display','block');
			});
			$(stop).appendTo(navbar);
		
			
			var next = $('<div style="float: left; width: 55px; height: 39px; background: url('+settings['images_dir']+'next.png); cursor: pointer"></div>');
			if (group_next.size()>0) $(next).click(function() { image_transition(group_next[0]); });
			else $(next).click(function() { close_image(); });
			$(next).appendTo(navbar);
			
			
			if ($.browser.msie && parseInt(jQuery.browser.version) < 7) {
				$(prev).css('background', 'url(' + settings['images_dir'] + 'blank.gif)');
				$(next).css('background', 'url(' + settings['images_dir'] + 'blank.gif)');
				$(play).css('background', 'url(' + settings['images_dir'] + 'blank.gif)');
				$(stop).css('background', 'url(' + settings['images_dir'] + 'blank.gif)');
				$(prev).css('filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + settings['images_dir'] + 'prev.png", sizingMethod="scale")');
				$(next).css('filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + settings['images_dir'] + 'next.png", sizingMethod="scale")');
				$(play).css('filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + settings['images_dir'] + 'play.png", sizingMethod="scale")');
				$(stop).css('filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + settings['images_dir'] + 'stop.png", sizingMethod="scale")');
			}
		
		
			$(navbar).appendTo('body');
			
			
			var timeout;
			$('#jZoom_image').bind('mouseover mousemove', function() { 
				$('#jZoom_navbar').show();
				if (timeout) clearTimeout(timeout);
				timeout = setTimeout(function() { $('#jZoom_navbar').hide(); }, 2000);	
			});
			
			$('#jZoom_navbar').bind('mouseover mousemove', function() {
				clearTimeout(timeout);
			});
			
		}
			
		
		
		/*
			Manage transition to next or previous image
		*/
		function image_transition(object) {
			
			$('#jZoom_navbar').remove();
			freeze2();
			
			if (timeout_id) {
				stop_diaporama();
				timeout_id = true;
			}
			
			var obj = $('<div></div>');
			$(obj).css('position', 'absolute');
			$(obj).css('display', 'none');
			$(obj).css('width', image_width);
			$(obj).css('height', image_height);
			$(obj).css('top', image_top);
			$(obj).css('left', image_left);
			$(obj).css('background', '#fff');
			
			$(obj).appendTo('body');
			
			//remove_struct_objects();
			
			//$('#jZoom_closebox').remove();
			
			var img = new Image();
			img.src = $(object).attr('href');
			if (!img.complete) load_spinner(image_top + image_height - 40, image_left + image_width / 2 - 15);
			
			$('#jZoom_image').attr('id','jZoom_image2');
			
			save_thumb_sizes_and_positions(object); // if need to close / unzoom
			
			load_image(object, function() {
				
				save_window_sizes_and_offset();
				
				$('.jZoom_shadow').remove();
				$('#jZoom_spinner').remove();
				
				define_image_sizes();
			
				$(obj).fadeIn(300, function() {
				
					$('#jZoom_image2').remove();
					
					$('#jZoom_image').css('width', image_width);
					$('#jZoom_image').css('height', image_height);
					$('#jZoom_image').css('top', image_top);
					$('#jZoom_image').css('left', image_left);
					$('#jZoom_image').css('display', 'block');
					
					$(obj).animate({
						width: image_width + 'px',
						height: image_height + 'px',
						top: image_top + 'px',
						left: image_left + 'px',
						opacity: 1
					}, settings['transition_duration'], function() {
						$('#jZoom_image').animate({
							opacity: 1
						}, 300, function() {

							$(obj).remove();
							
							load_struct_objects(object);

							//unfreeze_click();
							
							unfreeze2();
							
							if (timeout_id) timeout_id = window.setTimeout(function() { play_diaporama(); }, settings['diaporama_duration']);
							
						});
					});
					
				});
			});
		}
		
		
		/*
			Create our DOM spinner element if the image isn't already cached
		*/
		//function load_spinner(object) {
		function load_spinner(top, left) {
		
			var spinner = $('<div id="jZoom_spinner"></div>');
			$(spinner).css('background', 'url(' + settings['images_dir'] + 'spinner.png)');
			$(spinner).css('position', 'absolute');
			$(spinner).css('top', top + 'px');
			$(spinner).css('left', left + 'px');
			$(spinner).css('width', '30px');
			$(spinner).css('height', '30px');

			$(spinner).appendTo('body');
			
			anime_spinner();

		}


		/*
			Anime the spinner with changing his background position every 60 microseconds
		*/
		function anime_spinner() {
			
			if (document.getElementById('jZoom_spinner')) {
				
				if (spinner_frame > 1) {
					$('#jZoom_spinner').css('backgroundPosition','0px '+spinner_frame*30+'px');
					spinner_frame--;
				}
				
				else {
					$('#jZoom_spinner').css('backgroundPosition','0px 0px');
					spinner_frame = 12;
				}
				
				setTimeout(function() { anime_spinner(); }, 60);
				
			}
		}


		/*
			Remove spinner
		*/
		function remove_spinner() {
			if (document.getElementById('jZoom_spinner')) {
				document.body.removeChild(document.getElementById('jZoom_spinner'));
			}
		}		

	
		/* 
			Create shadow DOM element
		*/
		function load_shadow_element(id, width, height, top, left) {
			
			var object = $('<div></div>');
			$(object).attr('id', 'jZoom_shadow'+id);
			$(object).attr('class', 'jZoom_shadow');
			$(object).css('background', 'url(' + settings['images_dir'] + 'shadow-' + id + '.png)');
			$(object).css('position', 'absolute');
			$(object).css('width', width+'px');
			$(object).css('height', height+'px');
			$(object).css('top', top+'px');
			$(object).css('left', left+'px');
			
			if (!$.browser.msie) { $(object).css('display', 'none'); }
	
			if ($.browser.msie && parseInt(jQuery.browser.version) < 7) {
				$(object).css('background', 'url(' + settings['images_dir'] + 'blank.gif)');
				$(object).css('filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + settings['images_dir'] + 'shadow-'+id+'.png", sizingMethod="scale")');
			}
			
			$(object).appendTo('body');
			
			if (!$.browser.msie) { $(object).fadeIn('fast');}
			
		}
		
		
		/* 
			Display shadows if option is set
		*/
		function display_shadows() {
			load_shadow_element(1, 135, 135, image_top - 59, image_left - 65);
			load_shadow_element(2, image_width - 140, 59, image_top - 59, image_left + 70);
			load_shadow_element(3, 135, 135, image_top - 59, image_left + image_width - 70);
			load_shadow_element(4, 65, image_height - 147, image_top + 76, image_left + image_width);
			load_shadow_element(5, 135, 135, image_top + image_height - 71, image_left + image_width - 70);
			load_shadow_element(6, image_width - 140, 64, image_top + image_height, image_left + 70);
			load_shadow_element(7, 135, 135, image_top + image_height - 71, image_left - 65);
			load_shadow_element(8, 65, image_height - 147, image_top + 76, image_left - 65);
		}
		
		
		/*
			Remove shadows
		*/
		function remove_shadows() {
			
			for (var i = 1; i<= 8; i++) 
				$('.jZoom_shadow').remove();
				
		}
		
		
		/*
			In charge of calling functions to close an image with zoom effet
		*/
		function close_image(callback) {
			
			remove_struct_objects();
			stop_diaporama();
			
			unzoom(function() {
				$('#jZoom_image').remove();
				callback;
			});
			
		}
		
		
		/*
			Removes structure objects : shadows, closebox, diaporama menus
		*/
		function remove_struct_objects() {
			if (settings['shadow']) remove_shadows();
			if (settings['group']) $('#jZoom_navbar').remove();
			//$('#jZoom_closebox').remove();
		}
		
		
		/*
			unzoom visual effect
		*/
		function unzoom(callback) {
			
			$('#jZoom_image').animate({ 
				width: thumb_width + 'px',
				height: thumb_height + 'px',
				top: thumb_top + 'px',
				left: thumb_left + 'px',
				opacity: '0'
			}, settings['duration'], callback );
				
		}
		
		
		/*
			Freeze click
		*/
		function freeze_click() {
			$('.jZoom').unbind('click').bind('click', function() { return false; });

			///////$('<div style="position: absolute; width: 100%; height: 100%; top: '+window_offset_top+'px; left: '+window_offset_left+'px; background: blue; z-index: 999;"></div>').appendTo('body');
		}
		
		function freeze2() {
			$('.jZoom').unbind('click').bind('click', function() { return false; });
			
			$('#jZoom_image').unbind('click').bind('click', function() { return false; });
		}
		
		/*
			Unfreeze click
		*/
		function unfreeze_click() {
			$('.jZoom').click( function() { return controller(this); });
		}
		
		function unfreeze2() {
			$('.jZoom').bind('click', function() { return controller(this); });
			$('#jZoom_image').bind('click', function() { close_image(); });
			
		}
		
		
		/*
			Play diaporama using a timeout
		*/
		function play_diaporama() {
			if (group_next.size()>0 && document.getElementById('jZoom_image')) {
				stop_diaporama();
				image_transition(group_next[0]);
				timeout_id = window.setTimeout(function() { play_diaporama(); }, settings['diaporama_duration']);
			}
			else {
				close_image();
			}
		}
		
		
		/*
			Stop diaporama
		*/
		function stop_diaporama() {
			clearTimeout(timeout_id);
			timeout_id = false;
		}
  
    };  
  
})(jQuery);
