﻿/*************************************************************
Script		: CMSX
Version		: 4.0
Author		: Fabio Di Lupo
Desc		: Raccolta script AJAX per Sistema Gestione Contenuti
Licence		: Open Source MIT Licence
**************************************************************/

// codice per dispositivi Apple

if ((navigator.userAgent.indexOf('iPhone') != -1) || (navigator.userAgent.indexOf('iPod') != -1) || (navigator.userAgent.indexOf('iPad') != -1)) {
    document.write('<link href="/App_Themes/1/idevice.css" type="text/css" rel="stylesheet" />');
    document.write('<link rel="apple-touch-icon" href="/apple-touch-icon.png" /><link rel="apple-touch-startup-image" href="/apple-touch-startup-image.png" /><meta name="format-detection" content="telephone=no" /><meta name="viewport" content="width=920; maximum-scale=1.5" />');
}

/*
*
 * jQuery Nivo Slider v2.1
 * http://nivo.dev7studios.com
 *
 * Copyright 2010, Gilbert Pellegrom
 * Free to use and abuse under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * May 2010 - Pick random effect from specified set of effects by toronegro
 * May 2010 - controlNavThumbsFromRel option added by nerd-sh
 * May 2010 - Do not start nivoRun timer if there is only 1 slide by msielski
 * April 2010 - controlNavThumbs option added by Jamie Thompson (http://jamiethompson.co.uk)
 * March 2010 - manualAdvance option added by HelloPablo (http://hellopablo.co.uk)
 */

(function($) {

	$.fn.nivoSlider = function(options) {

		//Defaults are below
		var settings = $.extend({}, $.fn.nivoSlider.defaults, options);

		return this.each(function() {
			//Useful variables. Play carefully.
			var vars = {
				currentSlide: 0,
				currentImage: '',
				totalSlides: 0,
				randAnim: '',
				running: false,
				paused: false,
				stop:false
			};
		
			//Get this slider
			var slider = $(this);
			slider.data('nivo:vars', vars);
			slider.css('position','relative');
			slider.addClass('nivoSlider');
			
			//Find our slider children
			var kids = slider.children();
			kids.each(function() {
				var child = $(this);
				var link = '';
				if(!child.is('img')){
					if(child.is('a')){
						child.addClass('nivo-imageLink');
						link = child;
					}
					child = child.find('img:first');
				}
				//Get img width & height
                var childWidth = child.width();
                if(childWidth == 0) childWidth = child.attr('width');
                var childHeight = child.height();
                if(childHeight == 0) childHeight = child.attr('height');
                //Resize the slider
                if(childWidth > slider.width()){
                    slider.width(childWidth);
                }
                if(childHeight > slider.height()){
                    slider.height(childHeight);
                }
                if(link != ''){
                    link.css('display','none');
                }
                child.css('display','none');
                vars.totalSlides++;
			});
			
			//Set startSlide
			if(settings.startSlide > 0){
				if(settings.startSlide >= vars.totalSlides) settings.startSlide = vars.totalSlides - 1;
				vars.currentSlide = settings.startSlide;
			}
			
			//Get initial image
			if($(kids[vars.currentSlide]).is('img')){
				vars.currentImage = $(kids[vars.currentSlide]);
			} else {
				vars.currentImage = $(kids[vars.currentSlide]).find('img:first');
			}
			
			//Show initial link
			if($(kids[vars.currentSlide]).is('a')){
				$(kids[vars.currentSlide]).css('display','block');
			}
			
			//Set first background
			slider.css('background','url('+ vars.currentImage.attr('src') +') no-repeat');
			
			//Add initial slices
			for(var i = 0; i < settings.slices; i++){
				var sliceWidth = Math.round(slider.width()/settings.slices);
				if(i == settings.slices-1){
					slider.append(
						$('<div class="nivo-slice"></div>').css({ left:(sliceWidth*i)+'px', width:(slider.width()-(sliceWidth*i))+'px' })
					);
				} else {
					slider.append(
						$('<div class="nivo-slice"></div>').css({ left:(sliceWidth*i)+'px', width:sliceWidth+'px' })
					);
				}
			}
			
			//Create caption
			slider.append(
				$('<div class="nivo-caption"><p></p></div>').css({ display:'none', opacity:settings.captionOpacity })
			);			
			//Process initial  caption
			if(vars.currentImage.attr('title') != ''){
                var title = vars.currentImage.attr('title');
                if(title.substr(0,1) == '#') title = $(title).html();
                $('.nivo-caption p', slider).html(title);					
				$('.nivo-caption', slider).fadeIn(settings.animSpeed);
			}
			
			//In the words of Super Mario "let's a go!"
			var timer = 0;
			if(!settings.manualAdvance && kids.length > 1){
				timer = setInterval(function(){ nivoRun(slider, kids, settings, false); }, settings.pauseTime);
			}

			//Add Direction nav
			if(settings.directionNav){
				slider.append('<div class="nivo-directionNav"><a class="nivo-prevNav">Prev</a><a class="nivo-nextNav">Next</a></div>');
				
				//Hide Direction nav
				if(settings.directionNavHide){
					$('.nivo-directionNav', slider).hide();
					slider.hover(function(){
						$('.nivo-directionNav', slider).show();
					}, function(){
						$('.nivo-directionNav', slider).hide();
					});
				}
				
				$('a.nivo-prevNav', slider).live('click', function(){
					if(vars.running) return false;
					clearInterval(timer);
					timer = '';
					vars.currentSlide-=2;
					nivoRun(slider, kids, settings, 'prev');
				});
				
				$('a.nivo-nextNav', slider).live('click', function(){
					if(vars.running) return false;
					clearInterval(timer);
					timer = '';
					nivoRun(slider, kids, settings, 'next');
				});
			}
			
			//Add Control nav
			if(settings.controlNav){
				var nivoControl = $('<div class="nivo-controlNav"></div>');
				slider.append(nivoControl);
				for(var i = 0; i < kids.length; i++){
					if(settings.controlNavThumbs){
						var child = kids.eq(i);
						if(!child.is('img')){
							child = child.find('img:first');
						}
                        if (settings.controlNavThumbsFromRel) {
                            nivoControl.append('<a class="nivo-control" rel="'+ i +'"><img src="'+ child.attr('rel') + '" alt="" /></a>');
                        } else {
                            nivoControl.append('<a class="nivo-control" rel="'+ i +'"><img src="'+ child.attr('src').replace(settings.controlNavThumbsSearch, settings.controlNavThumbsReplace) +'" alt="" /></a>');
                        }
					} else {
						nivoControl.append('<a class="nivo-control" rel="'+ i +'">'+ (i + 1) +'</a>');
					}
					
				}
				//Set initial active link
				$('.nivo-controlNav a:eq('+ vars.currentSlide +')', slider).addClass('active');
				
				$('.nivo-controlNav a', slider).live('click', function(){
					if(vars.running) return false;
					if($(this).hasClass('active')) return false;
					clearInterval(timer);
					timer = '';
					slider.css('background','url('+ vars.currentImage.attr('src') +') no-repeat');
					vars.currentSlide = $(this).attr('rel') - 1;
					nivoRun(slider, kids, settings, 'control');
				});
			}
			
			//Keyboard Navigation
			if(settings.keyboardNav){
				$(window).keypress(function(event){
					//Left
					if(event.keyCode == '37'){
						if(vars.running) return false;
						clearInterval(timer);
						timer = '';
						vars.currentSlide-=2;
						nivoRun(slider, kids, settings, 'prev');
					}
					//Right
					if(event.keyCode == '39'){
						if(vars.running) return false;
						clearInterval(timer);
						timer = '';
						nivoRun(slider, kids, settings, 'next');
					}
				});
			}
			
			//For pauseOnHover setting
			if(settings.pauseOnHover){
				slider.hover(function(){
					vars.paused = true;
					clearInterval(timer);
					timer = '';
				}, function(){
					vars.paused = false;
					//Restart the timer
					if(timer == '' && !settings.manualAdvance){
						timer = setInterval(function(){ nivoRun(slider, kids, settings, false); }, settings.pauseTime);
					}
				});
			}
			
			//Event when Animation finishes
			slider.bind('nivo:animFinished', function(){ 
				vars.running = false; 
				//Hide child links
				$(kids).each(function(){
					if($(this).is('a')){
						$(this).css('display','none');
					}
				});
				//Show current link
				if($(kids[vars.currentSlide]).is('a')){
					$(kids[vars.currentSlide]).css('display','block');
				}
				//Restart the timer
				if(timer == '' && !vars.paused && !settings.manualAdvance){
					timer = setInterval(function(){ nivoRun(slider, kids, settings, false); }, settings.pauseTime);
				}
				//Trigger the afterChange callback
				settings.afterChange.call(this);
			});
		});
		
		function nivoRun(slider, kids, settings, nudge){
			//Get our vars
			var vars = slider.data('nivo:vars');
			if((!vars || vars.stop) && !nudge) return false;
			
			//Trigger the beforeChange callback
			settings.beforeChange.call(this);
					
			//Set current background before change
			if(!nudge){
				slider.css('background','url('+ vars.currentImage.attr('src') +') no-repeat');
			} else {
				if(nudge == 'prev'){
					slider.css('background','url('+ vars.currentImage.attr('src') +') no-repeat');
				}
				if(nudge == 'next'){
					slider.css('background','url('+ vars.currentImage.attr('src') +') no-repeat');
				}
			}
			vars.currentSlide++;
			if(vars.currentSlide == vars.totalSlides){ 
				vars.currentSlide = 0;
				//Trigger the slideshowEnd callback
				settings.slideshowEnd.call(this);
			}
			if(vars.currentSlide < 0) vars.currentSlide = (vars.totalSlides - 1);
			//Set vars.currentImage
			if($(kids[vars.currentSlide]).is('img')){
				vars.currentImage = $(kids[vars.currentSlide]);
			} else {
				vars.currentImage = $(kids[vars.currentSlide]).find('img:first');
			}
			
			//Set acitve links
			if(settings.controlNav){
				$('.nivo-controlNav a', slider).removeClass('active');
				$('.nivo-controlNav a:eq('+ vars.currentSlide +')', slider).addClass('active');
			}
			
			//Process caption
			if(vars.currentImage.attr('title') != ''){
                var title = vars.currentImage.attr('title');
                if(title.substr(0,1) == '#') title = $(title).html();	
                    
				if($('.nivo-caption', slider).css('display') == 'block'){
					$('.nivo-caption p', slider).fadeOut(settings.animSpeed, function(){
						$(this).html(title);
						$(this).fadeIn(settings.animSpeed);
					});
				} else {
					$('.nivo-caption p', slider).html(title);
				}					
				$('.nivo-caption', slider).fadeIn(settings.animSpeed);
			} else {
				$('.nivo-caption', slider).fadeOut(settings.animSpeed);
			}
			
			//Set new slice backgrounds
			var  i = 0;
			$('.nivo-slice', slider).each(function(){
				var sliceWidth = Math.round(slider.width()/settings.slices);
				$(this).css({ height:'0px', opacity:'0', 
					background: 'url('+ vars.currentImage.attr('src') +') no-repeat -'+ ((sliceWidth + (i * sliceWidth)) - sliceWidth) +'px 0%' });
				i++;
			});
			
			if(settings.effect == 'random'){
				var anims = new Array("sliceDownRight","sliceDownLeft","sliceUpRight","sliceUpLeft","sliceUpDown","sliceUpDownLeft","fold","fade");
				vars.randAnim = anims[Math.floor(Math.random()*(anims.length + 1))];
				if(vars.randAnim == undefined) vars.randAnim = 'fade';
			}
            
            //Run random effect from specified set (eg: effect:'fold,fade')
            if(settings.effect.indexOf(',') != -1){
                var anims = settings.effect.split(',');
                vars.randAnim = $.trim(anims[Math.floor(Math.random()*anims.length)]);
            }
		
			//Run effects
			vars.running = true;
			if(settings.effect == 'sliceDown' || settings.effect == 'sliceDownRight' || vars.randAnim == 'sliceDownRight' ||
				settings.effect == 'sliceDownLeft' || vars.randAnim == 'sliceDownLeft'){
				var timeBuff = 0;
				var i = 0;
				var slices = $('.nivo-slice', slider);
				if(settings.effect == 'sliceDownLeft' || vars.randAnim == 'sliceDownLeft') slices = $('.nivo-slice', slider)._reverse();
				slices.each(function(){
					var slice = $(this);
					slice.css('top','0px');
					if(i == settings.slices-1){
						setTimeout(function(){
							slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
						}, (100 + timeBuff));
					} else {
						setTimeout(function(){
							slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed);
						}, (100 + timeBuff));
					}
					timeBuff += 50;
					i++;
				});
			} 
			else if(settings.effect == 'sliceUp' || settings.effect == 'sliceUpRight' || vars.randAnim == 'sliceUpRight' ||
					settings.effect == 'sliceUpLeft' || vars.randAnim == 'sliceUpLeft'){
				var timeBuff = 0;
				var i = 0;
				var slices = $('.nivo-slice', slider);
				if(settings.effect == 'sliceUpLeft' || vars.randAnim == 'sliceUpLeft') slices = $('.nivo-slice', slider)._reverse();
				slices.each(function(){
					var slice = $(this);
					slice.css('bottom','0px');
					if(i == settings.slices-1){
						setTimeout(function(){
							slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
						}, (100 + timeBuff));
					} else {
						setTimeout(function(){
							slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed);
						}, (100 + timeBuff));
					}
					timeBuff += 50;
					i++;
				});
			} 
			else if(settings.effect == 'sliceUpDown' || settings.effect == 'sliceUpDownRight' || vars.randAnim == 'sliceUpDown' || 
					settings.effect == 'sliceUpDownLeft' || vars.randAnim == 'sliceUpDownLeft'){
				var timeBuff = 0;
				var i = 0;
				var v = 0;
				var slices = $('.nivo-slice', slider);
				if(settings.effect == 'sliceUpDownLeft' || vars.randAnim == 'sliceUpDownLeft') slices = $('.nivo-slice', slider)._reverse();
				slices.each(function(){
					var slice = $(this);
					if(i == 0){
						slice.css('top','0px');
						i++;
					} else {
						slice.css('bottom','0px');
						i = 0;
					}
					
					if(v == settings.slices-1){
						setTimeout(function(){
							slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
						}, (100 + timeBuff));
					} else {
						setTimeout(function(){
							slice.animate({ height:'100%', opacity:'1.0' }, settings.animSpeed);
						}, (100 + timeBuff));
					}
					timeBuff += 50;
					v++;
				});
			} 
			else if(settings.effect == 'fold' || vars.randAnim == 'fold'){
				var timeBuff = 0;
				var i = 0;
				$('.nivo-slice', slider).each(function(){
					var slice = $(this);
					var origWidth = slice.width();
					slice.css({ top:'0px', height:'100%', width:'0px' });
					if(i == settings.slices-1){
						setTimeout(function(){
							slice.animate({ width:origWidth, opacity:'1.0' }, settings.animSpeed, '', function(){ slider.trigger('nivo:animFinished'); });
						}, (100 + timeBuff));
					} else {
						setTimeout(function(){
							slice.animate({ width:origWidth, opacity:'1.0' }, settings.animSpeed);
						}, (100 + timeBuff));
					}
					timeBuff += 50;
					i++;
				});
			}  
			else if(settings.effect == 'fade' || vars.randAnim == 'fade'){
				var i = 0;
				$('.nivo-slice', slider).each(function(){
					$(this).css('height','100%');
					if(i == settings.slices-1){
						$(this).animate({ opacity:'1.0' }, (settings.animSpeed*2), '', function(){ slider.trigger('nivo:animFinished'); });
					} else {
						$(this).animate({ opacity:'1.0' }, (settings.animSpeed*2));
					}
					i++;
				});
			}
		}
	};
	
	//Default settings
	$.fn.nivoSlider.defaults = {
		effect:'random',
		slices:15,
		animSpeed:500,
		pauseTime:3000,
		startSlide:0,
		directionNav:true,
		directionNavHide:true,
		controlNav:true,
		controlNavThumbs:false,
        controlNavThumbsFromRel:false,
		controlNavThumbsSearch:'.jpg',
		controlNavThumbsReplace:'_thumb.jpg',
		keyboardNav:true,
		pauseOnHover:true,
		manualAdvance:false,
		captionOpacity:0.8,
		beforeChange: function(){},
		afterChange: function(){},
		slideshowEnd: function(){}
	};
	
	$.fn._reverse = [].reverse;
	
})(jQuery);

/*  jMP3 v0.2.1 - 10.10.2006 (w/Eolas fix & jQuery object replacement)
* an MP3 Player jQuery Plugin (http://www.sean-o.com/jquery/jmp3)
***/
jQuery.fn.jmp3 = function (passedOptions) {
    // hard-wired options
    var playerpath = "/obj/flash/"; 				// SET THIS FIRST: path to singlemp3player.swf
    // passable options
    var options = {
        "filepath": "/obj/media/", 						// path to MP3 file (default: current directory)
        "backcolor": "", 								// background color
        "forecolor": "ffffff", 							// foreground color (buttons)
        "width": "900", 								// width of player
        "repeat": "no", 								// repeat mp3?
        "volume": "50", 								// mp3 volume (0-100)
        "autoplay": "true", 							// play immediately on page load?
        "showdownload": "false", 						// show download button in player
        "showfilename": "false"							// show .mp3 filename after player
    };
    // use passed options, if they exist
    if (passedOptions) {
        jQuery.extend(options, passedOptions);
    }
    // iterate through each object
    return this.each(function () {
        // filename needs to be enclosed in tag (e.g. <span class='mp3'>mysong.mp3</span>)
        var filename = options.filepath + jQuery(this).html();
        // do nothing if not an .mp3 file
        var validfilename = filename.indexOf(".mp3");
        if (validfilename == -1) { return false; }
        // build the player HTML
        var mp3html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
        mp3html += 'width="' + options.width + '" height="20" ';
        mp3html += 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">';
        mp3html += '<param name="movie" value="' + playerpath + 'singlemp3player.swf?';
        mp3html += 'showDownload=' + options.showdownload + '&file=' + filename + '&autoStart=' + options.autoplay;
        mp3html += '&backColor=' + options.backcolor + '&frontColor=' + options.forecolor;
        mp3html += '&repeatPlay=' + options.repeat + '&songVolume=' + options.volume + '" />';
        mp3html += '<param name="wmode" value="transparent" />';
        mp3html += '<embed wmode="transparent" width="' + options.width + '" height="20" ';
        mp3html += 'src="' + playerpath + 'singlemp3player.swf?'
        mp3html += 'showDownload=' + options.showdownload + '&file=' + filename + '&autoStart=' + options.autoplay;
        mp3html += '&backColor=' + options.backcolor + '&frontColor=' + options.forecolor;
        mp3html += '&repeatPlay=' + options.repeat + '&songVolume=' + options.volume + '" ';
        mp3html += 'type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />';
        mp3html += '</object>';
        // don't display filename if option is set
        if (options.showfilename == "false") { jQuery(this).html(""); }
        jQuery(this).prepend(mp3html + "&nbsp;");
        // Eolas workaround for IE (Thanks Kurt!)
        if (jQuery.browser.msie) { this.outerHTML = this.outerHTML; }
    });
};

/**
* jQuery Galleriffic plugin
*
* Copyright (c) 2008 Trent Foley (http://trentacular.com)
* Licensed under the MIT License:
*   http://www.opensource.org/licenses/mit-license.php
*
* Much thanks to primary contributer Ponticlaro (http://www.ponticlaro.com)
*/
; (function($) {
    // Globally keep track of all images by their unique hash.  Each item is an image data object.
    var allImages = {};
    var imageCounter = 0;

    // Galleriffic static class
    $.galleriffic = {
        version: '2.0.1',

        // Strips invalid characters and any leading # characters
        normalizeHash: function(hash) {
            return hash.replace(/^.*#/, '').replace(/\?.*$/, '');
        },

        getImage: function(hash) {
            if (!hash)
                return undefined;

            hash = $.galleriffic.normalizeHash(hash);
            return allImages[hash];
        },

        // Global function that looks up an image by its hash and displays the image.
        // Returns false when an image is not found for the specified hash.
        // @param {String} hash This is the unique hash value assigned to an image.
        gotoImage: function(hash) {
            var imageData = $.galleriffic.getImage(hash);
            if (!imageData)
                return false;

            var gallery = imageData.gallery;
            gallery.gotoImage(imageData);

            return true;
        },

        // Removes an image from its respective gallery by its hash.
        // Returns false when an image is not found for the specified hash or the
        // specified owner gallery does match the located images gallery.
        // @param {String} hash This is the unique hash value assigned to an image.
        // @param {Object} ownerGallery (Optional) When supplied, the located images
        // gallery is verified to be the same as the specified owning gallery before
        // performing the remove operation.
        removeImageByHash: function(hash, ownerGallery) {
            var imageData = $.galleriffic.getImage(hash);
            if (!imageData)
                return false;

            var gallery = imageData.gallery;
            if (ownerGallery && ownerGallery != gallery)
                return false;

            return gallery.removeImageByIndex(imageData.index);
        }
    };

    var defaults = {
        delay: 3000,
        numThumbs: 20,
        preloadAhead: 40, // Set to -1 to preload all images
        enableTopPager: false,
        enableBottomPager: true,
        maxPagesToShow: 7,
        imageContainerSel: '',
        captionContainerSel: '',
        controlsContainerSel: '',
        loadingContainerSel: '',
        renderSSControls: true,
        renderNavControls: true,
        playLinkText: 'Play',
        pauseLinkText: 'Pause',
        prevLinkText: 'Previous',
        nextLinkText: 'Next',
        nextPageLinkText: 'Next &rsaquo;',
        prevPageLinkText: '&lsaquo; Prev',
        enableHistory: false,
        enableKeyboardNavigation: true,
        autoStart: false,
        syncTransitions: false,
        defaultTransitionDuration: 1000,
        onSlideChange: undefined, // accepts a delegate like such: function(prevIndex, nextIndex) { ... }
        onTransitionOut: undefined, // accepts a delegate like such: function(slide, caption, isSync, callback) { ... }
        onTransitionIn: undefined, // accepts a delegate like such: function(slide, caption, isSync) { ... }
        onPageTransitionOut: undefined, // accepts a delegate like such: function(callback) { ... }
        onPageTransitionIn: undefined, // accepts a delegate like such: function() { ... }
        onImageAdded: undefined, // accepts a delegate like such: function(imageData, $li) { ... }
        onImageRemoved: undefined  // accepts a delegate like such: function(imageData, $li) { ... }
    };

    // Primary Galleriffic initialization function that should be called on the thumbnail container.
    $.fn.galleriffic = function(settings) {
        //  Extend Gallery Object
        $.extend(this, {
            // Returns the version of the script
            version: $.galleriffic.version,

            // Current state of the slideshow
            isSlideshowRunning: false,
            slideshowTimeout: undefined,

            // This function is attached to the click event of generated hyperlinks within the gallery
            clickHandler: function(e, link) {
                this.pause();

                if (!this.enableHistory) {
                    // The href attribute holds the unique hash for an image
                    var hash = $.galleriffic.normalizeHash($(link).attr('href'));
                    $.galleriffic.gotoImage(hash);
                    e.preventDefault();
                }
            },

            // Appends an image to the end of the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
            // @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
            appendImage: function(listItem) {
                this.addImage(listItem, false, false);
                return this;
            },

            // Inserts an image into the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
            // @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
            // @param {Integer} position The index within the gallery where the item shouold be added.
            insertImage: function(listItem, position) {
                this.addImage(listItem, false, true, position);
                return this;
            },

            // Adds an image to the gallery and optionally inserts/appends it to the DOM (thumbExists)
            // @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
            // @param {Boolean} thumbExists Specifies whether the thumbnail already exists in the DOM or if it needs to be added.
            // @param {Boolean} insert Specifies whether the the image is appended to the end or inserted into the gallery.
            // @param {Integer} position The index within the gallery where the item shouold be added.
            addImage: function(listItem, thumbExists, insert, position) {
                var $li = (typeof listItem === "string") ? $(listItem) : listItem;
                var $aThumb = $li.find('a.thumb');
                var slideUrl = $aThumb.attr('href');
                var title = $aThumb.attr('title');
                var $caption = $li.find('.caption').remove();
                var hash = $aThumb.attr('name');

                // Increment the image counter
                imageCounter++;

                // Autogenerate a hash value if none is present or if it is a duplicate
                if (!hash || allImages['' + hash]) {
                    hash = imageCounter;
                }

                // Set position to end when not specified
                if (!insert)
                    position = this.data.length;

                var imageData = {
                    title: title,
                    slideUrl: slideUrl,
                    caption: $caption,
                    hash: hash,
                    gallery: this,
                    index: position
                };

                // Add the imageData to this gallery's array of images
                if (insert) {
                    this.data.splice(position, 0, imageData);

                    // Reset index value on all imageData objects
                    this.updateIndices(position);
                }
                else {
                    this.data.push(imageData);
                }

                var gallery = this;

                // Add the element to the DOM
                if (!thumbExists) {
                    // Update thumbs passing in addition post transition out handler
                    this.updateThumbs(function() {
                        var $thumbsUl = gallery.find('ul.thumbs');
                        if (insert)
                            $thumbsUl.children(':eq(' + position + ')').before($li);
                        else
                            $thumbsUl.append($li);

                        if (gallery.onImageAdded)
                            gallery.onImageAdded(imageData, $li);
                    });
                }

                // Register the image globally
                allImages['' + hash] = imageData;

                // Setup attributes and click handler
                $aThumb.attr('rel', 'history')
					.attr('href', '#' + hash)
					.removeAttr('name')
					.click(function(e) {
					    gallery.clickHandler(e, this);
					});

                return this;
            },

            // Removes an image from the gallery based on its index.
            // Returns false when the index is out of range.
            removeImageByIndex: function(index) {
                if (index < 0 || index >= this.data.length)
                    return false;

                var imageData = this.data[index];
                if (!imageData)
                    return false;

                this.removeImage(imageData);

                return true;
            },

            // Convenience method that simply calls the global removeImageByHash method.
            removeImageByHash: function(hash) {
                return $.galleriffic.removeImageByHash(hash, this);
            },

            // Removes an image from the gallery.
            removeImage: function(imageData) {
                var index = imageData.index;

                // Remove the image from the gallery data array
                this.data.splice(index, 1);

                // Remove the global registration
                delete allImages['' + imageData.hash];

                // Remove the image's list item from the DOM
                this.updateThumbs(function() {
                    var $li = gallery.find('ul.thumbs')
						.children(':eq(' + index + ')')
						.remove();

                    if (gallery.onImageRemoved)
                        gallery.onImageRemoved(imageData, $li);
                });

                // Update each image objects index value
                this.updateIndices(index);

                return this;
            },

            // Updates the index values of the each of the images in the gallery after the specified index
            updateIndices: function(startIndex) {
                for (i = startIndex; i < this.data.length; i++) {
                    this.data[i].index = i;
                }

                return this;
            },

            // Scraped the thumbnail container for thumbs and adds each to the gallery
            initializeThumbs: function() {
                this.data = [];
                var gallery = this;

                this.find('ul.thumbs > li').each(function(i) {
                    gallery.addImage($(this), true, false);
                });

                return this;
            },

            isPreloadComplete: false,

            // Initalizes the image preloader
            preloadInit: function() {
                if (this.preloadAhead == 0) return this;

                this.preloadStartIndex = this.currentImage.index;
                var nextIndex = this.getNextIndex(this.preloadStartIndex);
                return this.preloadRecursive(this.preloadStartIndex, nextIndex);
            },

            // Changes the location in the gallery the preloader should work
            // @param {Integer} index The index of the image where the preloader should restart at.
            preloadRelocate: function(index) {
                // By changing this startIndex, the current preload script will restart
                this.preloadStartIndex = index;
                return this;
            },

            // Recursive function that performs the image preloading
            // @param {Integer} startIndex The index of the first image the current preloader started on.
            // @param {Integer} currentIndex The index of the current image to preload.
            preloadRecursive: function(startIndex, currentIndex) {
                // Check if startIndex has been relocated
                if (startIndex != this.preloadStartIndex) {
                    var nextIndex = this.getNextIndex(this.preloadStartIndex);
                    return this.preloadRecursive(this.preloadStartIndex, nextIndex);
                }

                var gallery = this;

                // Now check for preloadAhead count
                var preloadCount = currentIndex - startIndex;
                if (preloadCount < 0)
                    preloadCount = this.data.length - 1 - startIndex + currentIndex;
                if (this.preloadAhead >= 0 && preloadCount > this.preloadAhead) {
                    // Do this in order to keep checking for relocated start index
                    setTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);
                    return this;
                }

                var imageData = this.data[currentIndex];
                if (!imageData)
                    return this;

                // If already loaded, continue
                if (imageData.image)
                    return this.preloadNext(startIndex, currentIndex);

                // Preload the image
                var image = new Image();

                image.onload = function() {
                    imageData.image = this;
                    gallery.preloadNext(startIndex, currentIndex);
                };

                image.alt = imageData.title;
                image.src = imageData.slideUrl;

                return this;
            },

            // Called by preloadRecursive in order to preload the next image after the previous has loaded.
            // @param {Integer} startIndex The index of the first image the current preloader started on.
            // @param {Integer} currentIndex The index of the current image to preload.
            preloadNext: function(startIndex, currentIndex) {
                var nextIndex = this.getNextIndex(currentIndex);
                if (nextIndex == startIndex) {
                    this.isPreloadComplete = true;
                } else {
                    // Use setTimeout to free up thread
                    var gallery = this;
                    setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);
                }

                return this;
            },

            // Safe way to get the next image index relative to the current image.
            // If the current image is the last, returns 0
            getNextIndex: function(index) {
                var nextIndex = index + 1;
                if (nextIndex >= this.data.length)
                    nextIndex = 0;
                return nextIndex;
            },

            // Safe way to get the previous image index relative to the current image.
            // If the current image is the first, return the index of the last image in the gallery.
            getPrevIndex: function(index) {
                var prevIndex = index - 1;
                if (prevIndex < 0)
                    prevIndex = this.data.length - 1;
                return prevIndex;
            },

            // Pauses the slideshow
            pause: function() {
                this.isSlideshowRunning = false;
                if (this.slideshowTimeout) {
                    clearTimeout(this.slideshowTimeout);
                    this.slideshowTimeout = undefined;
                }

                if (this.$controlsContainer) {
                    this.$controlsContainer
						.find('div.ss-controls a').removeClass().addClass('play')
						.attr('title', this.playLinkText)
						.attr('href', '#play')
						.html(this.playLinkText);
                }

                return this;
            },

            // Plays the slideshow
            play: function() {
                this.isSlideshowRunning = true;

                if (this.$controlsContainer) {
                    this.$controlsContainer
						.find('div.ss-controls a').removeClass().addClass('pause')
						.attr('title', this.pauseLinkText)
						.attr('href', '#pause')
						.html(this.pauseLinkText);
                }

                if (!this.slideshowTimeout) {
                    var gallery = this;
                    this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
                }

                return this;
            },

            // Toggles the state of the slideshow (playing/paused)
            toggleSlideshow: function() {
                if (this.isSlideshowRunning)
                    this.pause();
                else
                    this.play();

                return this;
            },

            // Advances the slideshow to the next image and delegates navigation to the
            // history plugin when history is enabled
            // enableHistory is true
            ssAdvance: function() {
                if (this.isSlideshowRunning)
                    this.next(true);

                return this;
            },

            // Advances the gallery to the next image.
            // @param {Boolean} dontPause Specifies whether to pause the slideshow.
            // @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.  
            next: function(dontPause, bypassHistory) {
                this.gotoIndex(this.getNextIndex(this.currentImage.index), dontPause, bypassHistory);
                return this;
            },

            // Navigates to the previous image in the gallery.
            // @param {Boolean} dontPause Specifies whether to pause the slideshow.
            // @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
            previous: function(dontPause, bypassHistory) {
                this.gotoIndex(this.getPrevIndex(this.currentImage.index), dontPause, bypassHistory);
                return this;
            },

            // Navigates to the next page in the gallery.
            // @param {Boolean} dontPause Specifies whether to pause the slideshow.
            // @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
            nextPage: function(dontPause, bypassHistory) {
                var page = this.getCurrentPage();
                var lastPage = this.getNumPages() - 1;
                if (page < lastPage) {
                    var startIndex = page * this.numThumbs;
                    var nextPage = startIndex + this.numThumbs;
                    this.gotoIndex(nextPage, dontPause, bypassHistory);
                }

                return this;
            },

            // Navigates to the previous page in the gallery.
            // @param {Boolean} dontPause Specifies whether to pause the slideshow.
            // @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
            previousPage: function(dontPause, bypassHistory) {
                var page = this.getCurrentPage();
                if (page > 0) {
                    var startIndex = page * this.numThumbs;
                    var prevPage = startIndex - this.numThumbs;
                    this.gotoIndex(prevPage, dontPause, bypassHistory);
                }

                return this;
            },

            // Navigates to the image at the specified index in the gallery
            // @param {Integer} index The index of the image in the gallery to display.
            // @param {Boolean} dontPause Specifies whether to pause the slideshow.
            // @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
            gotoIndex: function(index, dontPause, bypassHistory) {
                if (!dontPause)
                    this.pause();

                if (index < 0) index = 0;
                else if (index >= this.data.length) index = this.data.length - 1;

                var imageData = this.data[index];

                if (!bypassHistory && this.enableHistory)
                    $.historyLoad(String(imageData.hash));  // At the moment, historyLoad only accepts string arguments
                else
                    this.gotoImage(imageData);

                return this;
            },

            // This function is garaunteed to be called anytime a gallery slide changes.
            // @param {Object} imageData An object holding the image metadata of the image to navigate to.
            gotoImage: function(imageData) {
                var index = imageData.index;

                if (this.onSlideChange)
                    this.onSlideChange(this.currentImage.index, index);

                this.currentImage = imageData;
                this.preloadRelocate(index);

                this.refresh();

                return this;
            },

            // Returns the default transition duration value.  The value is halved when not
            // performing a synchronized transition.
            // @param {Boolean} isSync Specifies whether the transitions are synchronized.
            getDefaultTransitionDuration: function(isSync) {
                if (isSync)
                    return this.defaultTransitionDuration;
                return this.defaultTransitionDuration / 2;
            },

            // Rebuilds the slideshow image and controls and performs transitions
            refresh: function() {
                var imageData = this.currentImage;
                if (!imageData)
                    return this;

                var index = imageData.index;

                // Update Controls
                if (this.$controlsContainer) {
                    this.$controlsContainer
						.find('div.nav-controls a.prev').attr('href', '#' + this.data[this.getPrevIndex(index)].hash).end()
						.find('div.nav-controls a.next').attr('href', '#' + this.data[this.getNextIndex(index)].hash);
                }

                var previousSlide = this.$imageContainer.find('span.current').addClass('previous').removeClass('current');
                var previousCaption = 0;

                if (this.$captionContainer) {
                    previousCaption = this.$captionContainer.find('span.current').addClass('previous').removeClass('current');
                }

                // Perform transitions simultaneously if syncTransitions is true and the next image is already preloaded
                var isSync = this.syncTransitions && imageData.image;

                // Flag we are transitioning
                var isTransitioning = true;
                var gallery = this;

                var transitionOutCallback = function() {
                    // Flag that the transition has completed
                    isTransitioning = false;

                    // Remove the old slide
                    previousSlide.remove();

                    // Remove old caption
                    if (previousCaption)
                        previousCaption.remove();

                    if (!isSync) {
                        if (imageData.image && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
                            gallery.buildImage(imageData, isSync);
                        } else {
                            // Show loading container
                            if (gallery.$loadingContainer) {
                                gallery.$loadingContainer.show();
                            }
                        }
                    }
                };

                if (previousSlide.length == 0) {
                    // For the first slide, the previous slide will be empty, so we will call the callback immediately
                    transitionOutCallback();
                } else {
                    if (this.onTransitionOut) {
                        this.onTransitionOut(previousSlide, previousCaption, isSync, transitionOutCallback);
                    } else {
                        previousSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0, transitionOutCallback);
                        if (previousCaption)
                            previousCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0);
                    }
                }

                // Go ahead and begin transitioning in of next image
                if (isSync)
                    this.buildImage(imageData, isSync);

                if (!imageData.image) {
                    var image = new Image();

                    // Wire up mainImage onload event
                    image.onload = function() {
                        imageData.image = this;

                        // Only build image if the out transition has completed and we are still on the same image hash
                        if (!isTransitioning && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
                            gallery.buildImage(imageData, isSync);
                        }
                    };

                    // set alt and src
                    image.alt = imageData.title;
                    image.src = imageData.slideUrl;
                }

                // This causes the preloader (if still running) to relocate out from the currentIndex
                this.relocatePreload = true;

                return this.syncThumbs();
            },

            // Called by the refresh method after the previous image has been transitioned out or at the same time
            // as the out transition when performing a synchronous transition.
            // @param {Object} imageData An object holding the image metadata of the image to build.
            // @param {Boolean} isSync Specifies whether the transitions are synchronized.
            buildImage: function(imageData, isSync) {
                var gallery = this;
                var nextIndex = this.getNextIndex(imageData.index);

                // Construct new hidden span for the image
                var newSlide = this.$imageContainer
					.append('<span class="image-wrapper current"><a class="advance-link" rel="history" href="#' + this.data[nextIndex].hash + '" title="' + imageData.title + '">&nbsp;</a></span>')
					.find('span.current').css('opacity', '0');

                newSlide.find('a')
					.append(imageData.image)
					.click(function(e) {
					    gallery.clickHandler(e, this);
					});

                var newCaption = 0;
                if (this.$captionContainer) {
                    // Construct new hidden caption for the image
                    newCaption = this.$captionContainer
						.append('<span class="image-caption current"></span>')
						.find('span.current').css('opacity', '0')
						.append(imageData.caption);
                }

                // Hide the loading conatiner
                if (this.$loadingContainer) {
                    this.$loadingContainer.hide();
                }

                // Transition in the new image
                if (this.onTransitionIn) {
                    this.onTransitionIn(newSlide, newCaption, isSync);
                } else {
                    newSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
                    if (newCaption)
                        newCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
                }

                if (this.isSlideshowRunning) {
                    if (this.slideshowTimeout)
                        clearTimeout(this.slideshowTimeout);

                    this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
                }

                return this;
            },

            // Returns the current page index that should be shown for the currentImage
            getCurrentPage: function() {
                return Math.floor(this.currentImage.index / this.numThumbs);
            },

            // Applies the selected class to the current image's corresponding thumbnail.
            // Also checks if the current page has changed and updates the displayed page of thumbnails if necessary.
            syncThumbs: function() {
                var page = this.getCurrentPage();
                if (page != this.displayedPage)
                    this.updateThumbs();

                // Remove existing selected class and add selected class to new thumb
                var $thumbs = this.find('ul.thumbs').children();
                $thumbs.filter('.selected').removeClass('selected');
                $thumbs.eq(this.currentImage.index).addClass('selected');

                return this;
            },

            // Performs transitions on the thumbnails container and updates the set of
            // thumbnails that are to be displayed and the navigation controls.
            // @param {Delegate} postTransitionOutHandler An optional delegate that is called after
            // the thumbnails container has transitioned out and before the thumbnails are rebuilt.
            updateThumbs: function(postTransitionOutHandler) {
                var gallery = this;
                var transitionOutCallback = function() {
                    // Call the Post-transition Out Handler
                    if (postTransitionOutHandler)
                        postTransitionOutHandler();

                    gallery.rebuildThumbs();

                    // Transition In the thumbsContainer
                    if (gallery.onPageTransitionIn)
                        gallery.onPageTransitionIn();
                    else
                        gallery.show();
                };

                // Transition Out the thumbsContainer
                if (this.onPageTransitionOut) {
                    this.onPageTransitionOut(transitionOutCallback);
                } else {
                    this.hide();
                    transitionOutCallback();
                }

                return this;
            },

            // Updates the set of thumbnails that are to be displayed and the navigation controls.
            rebuildThumbs: function() {
                var needsPagination = this.data.length > this.numThumbs;

                // Rebuild top pager
                if (this.enableTopPager) {
                    var $topPager = this.find('div.top');
                    if ($topPager.length == 0)
                        $topPager = this.prepend('<div class="top pagination"></div>').find('div.top');
                    else
                        $topPager.empty();

                    if (needsPagination)
                        this.buildPager($topPager);
                }

                // Rebuild bottom pager
                if (this.enableBottomPager) {
                    var $bottomPager = this.find('div.bottom');
                    if ($bottomPager.length == 0)
                        $bottomPager = this.append('<div class="bottom pagination"></div>').find('div.bottom');
                    else
                        $bottomPager.empty();

                    if (needsPagination)
                        this.buildPager($bottomPager);
                }

                var page = this.getCurrentPage();
                var startIndex = page * this.numThumbs;
                var stopIndex = startIndex + this.numThumbs - 1;
                if (stopIndex >= this.data.length)
                    stopIndex = this.data.length - 1;

                // Show/Hide thumbs
                var $thumbsUl = this.find('ul.thumbs');
                $thumbsUl.find('li').each(function(i) {
                    var $li = $(this);
                    if (i >= startIndex && i <= stopIndex) {
                        $li.show();
                    } else {
                        $li.hide();
                    }
                });

                this.displayedPage = page;

                // Remove the noscript class from the thumbs container ul
                $thumbsUl.removeClass('noscript');

                return this;
            },

            // Returns the total number of pages required to display all the thumbnails.
            getNumPages: function() {
                return Math.ceil(this.data.length / this.numThumbs);
            },

            // Rebuilds the pager control in the specified matched element.
            // @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
            buildPager: function(pager) {
                var gallery = this;
                var numPages = this.getNumPages();
                var page = this.getCurrentPage();
                var startIndex = page * this.numThumbs;
                var pagesRemaining = this.maxPagesToShow - 1;

                var pageNum = page - Math.floor((this.maxPagesToShow - 1) / 2) + 1;
                if (pageNum > 0) {
                    var remainingPageCount = numPages - pageNum;
                    if (remainingPageCount < pagesRemaining) {
                        pageNum = pageNum - (pagesRemaining - remainingPageCount);
                    }
                }

                if (pageNum < 0) {
                    pageNum = 0;
                }

                // Prev Page Link
                if (page > 0) {
                    var prevPage = startIndex - this.numThumbs;
                    pager.append('<a rel="history" href="#' + this.data[prevPage].hash + '" title="' + this.prevPageLinkText + '">' + this.prevPageLinkText + '</a>');
                }

                // Create First Page link if needed
                if (pageNum > 0) {
                    this.buildPageLink(pager, 0, numPages);
                    if (pageNum > 1)
                        pager.append('<span class="ellipsis">&hellip;</span>');

                    pagesRemaining--;
                }

                // Page Index Links
                while (pagesRemaining > 0) {
                    this.buildPageLink(pager, pageNum, numPages);
                    pagesRemaining--;
                    pageNum++;
                }

                // Create Last Page link if needed
                if (pageNum < numPages) {
                    var lastPageNum = numPages - 1;
                    if (pageNum < lastPageNum)
                        pager.append('<span class="ellipsis">&hellip;</span>');

                    this.buildPageLink(pager, lastPageNum, numPages);
                }

                // Next Page Link
                var nextPage = startIndex + this.numThumbs;
                if (nextPage < this.data.length) {
                    pager.append('<a rel="history" href="#' + this.data[nextPage].hash + '" title="' + this.nextPageLinkText + '">' + this.nextPageLinkText + '</a>');
                }

                pager.find('a').click(function(e) {
                    gallery.clickHandler(e, this);
                });

                return this;
            },

            // Builds a single page link within a pager.  This function is called by buildPager
            // @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
            // @param {Integer} pageNum The page number of the page link to build.
            // @param {Integer} numPages The total number of pages required to display all thumbnails.
            buildPageLink: function(pager, pageNum, numPages) {
                var pageLabel = pageNum + 1;
                var currentPage = this.getCurrentPage();
                if (pageNum == currentPage)
                    pager.append('<span class="current">' + pageLabel + '</span>');
                else if (pageNum < numPages) {
                    var imageIndex = pageNum * this.numThumbs;
                    pager.append('<a rel="history" href="#' + this.data[imageIndex].hash + '" title="' + pageLabel + '">' + pageLabel + '</a>');
                }

                return this;
            }
        });

        // Now initialize the gallery
        $.extend(this, defaults, settings);

        // Verify the history plugin is available
        if (this.enableHistory && !$.historyInit)
            this.enableHistory = false;

        // Select containers
        if (this.imageContainerSel) this.$imageContainer = $(this.imageContainerSel);
        if (this.captionContainerSel) this.$captionContainer = $(this.captionContainerSel);
        if (this.loadingContainerSel) this.$loadingContainer = $(this.loadingContainerSel);

        // Initialize the thumbails
        this.initializeThumbs();

        if (this.maxPagesToShow < 3)
            this.maxPagesToShow = 3;

        this.displayedPage = -1;
        this.currentImage = this.data[0];
        var gallery = this;

        // Hide the loadingContainer
        if (this.$loadingContainer)
            this.$loadingContainer.hide();

        // Setup controls
        if (this.controlsContainerSel) {
            this.$controlsContainer = $(this.controlsContainerSel).empty();

            if (this.renderSSControls) {
                if (this.autoStart) {
                    this.$controlsContainer
						.append('<div class="ss-controls"><a href="#pause" class="pause" title="' + this.pauseLinkText + '">' + this.pauseLinkText + '</a></div>');
                } else {
                    this.$controlsContainer
						.append('<div class="ss-controls"><a href="#play" class="play" title="' + this.playLinkText + '">' + this.playLinkText + '</a></div>');
                }

                this.$controlsContainer.find('div.ss-controls a')
					.click(function(e) {
					    gallery.toggleSlideshow();
					    e.preventDefault();
					    return false;
					});
            }

            if (this.renderNavControls) {
                this.$controlsContainer
					.append('<div class="nav-controls"><a class="prev" rel="history" title="' + this.prevLinkText + '">' + this.prevLinkText + '</a><a class="next" rel="history" title="' + this.nextLinkText + '">' + this.nextLinkText + '</a></div>')
					.find('div.nav-controls a')
					.click(function(e) {
					    gallery.clickHandler(e, this);
					});
            }
        }

        var initFirstImage = !this.enableHistory || !location.hash;
        if (this.enableHistory && location.hash) {
            var hash = $.galleriffic.normalizeHash(location.hash);
            var imageData = allImages[hash];
            if (!imageData)
                initFirstImage = true;
        }

        // Setup gallery to show the first image
        if (initFirstImage)
            this.gotoIndex(0, false, true);

        // Setup Keyboard Navigation
        if (this.enableKeyboardNavigation) {
            $(document).keydown(function(e) {
                var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
                switch (key) {
                    case 32: // space
                        gallery.next();
                        e.preventDefault();
                        break;
                    case 33: // Page Up
                        gallery.previousPage();
                        e.preventDefault();
                        break;
                    case 34: // Page Down
                        gallery.nextPage();
                        e.preventDefault();
                        break;
                    case 35: // End
                        gallery.gotoIndex(gallery.data.length - 1);
                        e.preventDefault();
                        break;
                    case 36: // Home
                        gallery.gotoIndex(0);
                        e.preventDefault();
                        break;
                    case 37: // left arrow
                        gallery.previous();
                        e.preventDefault();
                        break;
                    case 39: // right arrow
                        gallery.next();
                        e.preventDefault();
                        break;
                }
            });
        }

        // Auto start the slideshow
        if (this.autoStart)
            this.play();

        // Kickoff Image Preloader after 1 second
        setTimeout(function() { gallery.preloadInit(); }, 1000);

        return this;
    };
})(jQuery);

/**
* jQuery Opacity Rollover plugin
*
* Copyright (c) 2009 Trent Foley (http://trentacular.com)
* Licensed under the MIT License:
*   http://www.opensource.org/licenses/mit-license.php
*/
; (function($) {
    var defaults = {
        mouseOutOpacity: 0.67,
        mouseOverOpacity: 1.0,
        fadeSpeed: 'fast',
        exemptionSelector: '.selected'
    };

    $.fn.opacityrollover = function(settings) {
        // Initialize the effect
        $.extend(this, defaults, settings);

        var config = this;

        function fadeTo(element, opacity) {
            var $target = $(element);

            if (config.exemptionSelector)
                $target = $target.not(config.exemptionSelector);

            $target.fadeTo(config.fadeSpeed, opacity);
        }

        this.css('opacity', this.mouseOutOpacity)
			.hover(
				function() {
				    fadeTo(this, config.mouseOverOpacity);
				},
				function() {
				    fadeTo(this, config.mouseOutOpacity);
				});

        return this;
    };
})(jQuery);

/* JQUERY OVERLAY ATTIVAZIONE */
$(function () {
    // if the function argument is given to overlay,
    // it is assumed to be the onBeforeLoad event listener
    $("a[rel]").overlay({
        mask: 'darkred',
        effect: 'apple',
        onBeforeLoad: function () {
            // grab wrapper element inside content
            var wrap = this.getOverlay().find(".contentWrap");
            // load the page specified in the trigger
            wrap.load(this.getTrigger().attr("href"));
        }
    });
});


/* -------------------- Inizio funzioni CMSX ----------------------- */
function maxLunghezza(obj, lunghezza) {
    var mlength = obj.getAttribute ? parseInt(lunghezza) : ""
    if (obj.getAttribute && obj.value.length > mlength) {
        obj.value = obj.value.substring(0, mlength);
        alert("Raggiunta la massima lunghezza disponibile del testo in questo campo.")
    }
}
/* apre finestra popup centrata */
var win = null;
function Finestra(mypage, myname, w, h) {
    var winl = (screen.width - w) / 2;
    var wint = (screen.height - h) / 2;
    var settings = 'height=' + h + ',';
    settings += 'width=' + w + ',';
    settings += 'top=' + wint + ',';
    settings += 'left=' + winl + ',';
    settings += 'scrollbars=no,resizable=no,toolbar=no';
    win = window.open(mypage, myname, settings);
    if (parseInt(navigator.appVersion) >= 4) { win.window.focus(); }
}
function MM_openBrWindow(theURL, winName, features) {
    window.open(theURL, winName, features);
}

/* apre finestra popup centrata con scroll*/
var winmia = null;
function FinestraScroll(mypage, myname, w, h) {
    var winl = (screen.width - w) / 2;
    var wint = (screen.height - h) / 2;
    var settings = 'height=' + h + ',';
    settings += 'width=' + w + ',';
    settings += 'top=' + wint + ',';
    settings += 'left=' + winl + ',';
    settings += 'scrollbars=yes,resizable=no,toolbar=no';
    winmia = window.open(mypage, myname, settings);
    if (parseInt(navigator.appVersion) >= 4) { winmia.window.focus(); }
}
function MM_openBrWindow(theURL, winName, features) {
    window.open(theURL, winName, features);
}

function Nascondi() {
    document.getElementById("BottoneMagico").style.visibility = 'hidden';
    document.getElementById("RigaMagica").style.visibility = 'visible';
}

function ControllaCF(cf) {
    var validi, i, s, set1, set2, setpari, setdisp;
    if (cf == '') return '';
    cf = cf.toUpperCase();
    if (cf.length != 16)
        return "La lunghezza del codice fiscale non è\n"
		+ "corretta: il codice fiscale dovrebbe essere lungo\n"
		+ "esattamente 16 caratteri.\n";
    validi = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    for (i = 0; i < 16; i++) {
        if (validi.indexOf(cf.charAt(i)) == -1)
            return "Il codice fiscale contiene un carattere non valido `" +
				cf.charAt(i) +
				"'.\nI caratteri validi sono le lettere e le cifre.\n";
    }
    set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    set2 = "ABCDEFGHIJABCDEFGHIJKLMNOPQRSTUVWXYZ";
    setpari = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    setdisp = "BAKPLCQDREVOSFTGUHMINJWZYX";
    s = 0;
    for (i = 1; i <= 13; i += 2)
        s += setpari.indexOf(set2.charAt(set1.indexOf(cf.charAt(i))));
    for (i = 0; i <= 14; i += 2)
        s += setdisp.indexOf(set2.charAt(set1.indexOf(cf.charAt(i))));
    if (s % 26 != cf.charCodeAt(15) - 'A'.charCodeAt(0))
        return "Il codice fiscale non è corretto:\n" +
			"il codice di controllo non corrisponde.\n";
    return "";
}

// piccoli effetti animazione con jquery
function mostra_box() {
    $("#boxnascosto").show("slow");
}

// carico le google maps api in asincrono x velocizzare il rendering
function loadScript() {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "http://maps.google.com/maps/api/js??v=3.1&sensor=false&callback=initialize&amp;region=IT";
    document.body.appendChild(script);
}

/* BAD Browser */
function badBrowser() {
    if ($.browser.msie && parseInt($.browser.version) <= 6) { return true; }

    return false;
}

function getBadBrowser(c_name) {
    if (document.cookie.length > 0) {
        c_start = document.cookie.indexOf(c_name + "=");
        if (c_start != -1) {
            c_start = c_start + c_name.length + 1;
            c_end = document.cookie.indexOf(";", c_start);
            if (c_end == -1) c_end = document.cookie.length;
            return unescape(document.cookie.substring(c_start, c_end));
        }
    }
    return "";
}

function setBadBrowser(c_name, value, expiredays) {
    var exdate = new Date();
    exdate.setDate(exdate.getDate() + expiredays);
    document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
}

//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:::                                                                         :::
//:::  This routine calculates the distance between two points (given the     :::
//:::  latitude/longitude of those points). It is being used to calculate     :::
//:::  the distance between two ZIP Codes or Postal Codes using our           :::
//:::  ZIPCodeWorld(TM) and PostalCodeWorld(TM) products.                     :::
//:::                                                                         :::
//:::  Definitions:                                                           :::
//:::    South latitudes are negative, east longitudes are positive           :::
//:::                                                                         :::
//:::  Passed to function:                                                    :::
//:::    lat1, lon1 = Latitude and Longitude of point 1 (in decimal degrees)  :::
//:::    lat2, lon2 = Latitude and Longitude of point 2 (in decimal degrees)  :::
//:::    unit = the unit you desire for results                               :::
//:::           where: 'M' is statute miles                                   :::
//:::                  'K' is kilometers (default) modificata per solo KM     :::
//:::                  'N' is nautical miles                                  :::
//:::                                                                         :::
//:::  United States ZIP Code/ Canadian Postal Code databases with latitude   :::
//:::  & longitude are available at http://www.zipcodeworld.com               :::
//:::                                                                         :::
//:::  For enquiries, please contact sales@zipcodeworld.com                   :::
//:::                                                                         :::
//:::  Official Web site: http://www.zipcodeworld.com                         :::
//:::                                                                         :::
//:::  Hexa Software Development Center © All Rights Reserved 2004            :::
//:::                                                                         :::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

function distance(lat1, lon1, lat2, lon2) {
    var radlat1 = Math.PI * lat1 / 180
    var radlat2 = Math.PI * lat2 / 180
    var radlon1 = Math.PI * lon1 / 180
    var radlon2 = Math.PI * lon2 / 180
    var theta = lon1 - lon2
    var radtheta = Math.PI * theta / 180
    var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
    dist = Math.acos(dist)
    dist = dist * 180 / Math.PI
    dist = dist * 60 * 1.1515 * 1.609344
    return dist
} 

/* Attivazioni su evento domready */
$(document).ready(function() {
    // Blocco tasto destro
    //$(document).bind("contextmenu", function (e) { return false;  });
    // Inietto tag rel su bottone per login
    $('.modalInput').attr('rel', '#prompt');
    // animazione per scroll
    $("a[href='#top']").click(function() {
        $("html").animate({ scrollTop: 0 }, "slow");
        return false;
    });
    // Inietto stili sperimentali CSS 3.0 supportati da Safari, Firefox, Chrome
    $('fieldset').css('-moz-border-radius', '5px');
    $('fieldset').css('-webkit-border-radius', '5px');
    $('button').css('-moz-border-radius', '5px');
    $('button').css('-webkit-border-radius', '5px');
    $('button').css('-moz-box-shadow', '0px 0px 5px #999999');
    $('button').css('-webkit-box-shadow', '0px 0px 5px #999999');
    $('label').css('-moz-border-radius-topleft', '5px');
    $('label').css('-webkit-border-top-left-radius', '5px');
    $('.privacy').css('-moz-border-radius', '5px');
    $('.privacy').css('-webkit-border-radius', '5px');
    $('.bottoni').css('-moz-border-radius', '5px');
    $('.bottoni').css('-webkit-border-radius', '5px');
    $('.bottoni').css('-moz-box-shadow', '0px 0px 5px #000000');
    $('.bottoni').css('-webkit-box-shadow', '0px 0px 5px #000000');
    $('img.sx').css('-moz-box-shadow', '0px 0px 5px #000000');
    $('img.sx').css('-webkit-box-shadow', '0px 0px 5px #000000');
    $('img.dx').css('-moz-box-shadow', '0px 0px 5px #000000');
    $('img.dx').css('-webkit-box-shadow', '0px 0px 5px #000000');
    $('img.cx').css('-moz-box-shadow', '0px 0px 5px #000000');
    $('img.cx').css('-webkit-box-shadow', '0px 0px 5px #000000');
    $('.aiuto').css('-moz-border-radius', '5px');
    $('.aiuto').css('-webkit-border-radius', '5px');
    $('.menuCMS').css('-moz-border-radius', '5px');
    $('.menuCMS').css('-webkit-border-radius', '5px');
    $('#lastupdate').css('-moz-border-radius', '5px');
    $('#lastupdate').css('-webkit-border-radius', '5px');        
    $('caption').css('-moz-border-radius-topleft', '5px');
    $('caption').css('-webkit-border-top-left-radius', '5px');
    $('caption').css('-moz-border-radius-topright', '5px');
    $('caption').css('-webkit-border-top-right-radius', '5px');
    $('#slider').css('-moz-box-shadow', '0px 0px 5px #000000');
    $('#slider').css('-webkit-box-shadow', '0px 0px 5px #000000');
    $('#accordion').css('-moz-border-radius', '10px');
    $('#accordion').css('-webkit-border-radius', '10px');
    $('#accordion').css('-moz-box-shadow', '0px 0px 5px #000000');
    $('#accordion').css('-webkit-box-shadow', '0px 0px 5px #000000');

    // Attivo Accordion verticale che è su tutte le pagine
    $(function() {
        $("#accordion").tabs("#accordion div.pane", { tabs: 'h2', effect: 'slide', initialIndex: null });
    });

    // ACCORDION - FINE
    
    // rendo Menù riservato verticale flottante
    if ($("#menuriservato").length) {
        function moveMenuRiservato() {
            var menuRiservatoOffset = menuRiservatoYloc.top + $(this).scrollTop() + "px";
            $('#menuriservato').animate({ top: menuRiservatoOffset }, { duration: 500, queue: false });
        }
        menuRiservatoYloc = $('#menuriservato').offset();
        $(window).scroll(moveMenuRiservato);
        moveMenuRiservato();
    };
    
    // Attivo Accordion orizzontale se presente
    if ($("#haccordion").length) {
        $(function() {
            $("#haccordion").tabs("#haccordion div", { tabs: 'img', effect: 'horizontal' });
        });
    };

//------------------ localizzazione validatore Jquery
    $.tools.validator.fn("[data-equals]", "Valore non uguale nel campo $1", function(input) {
        var name = input.attr("data-equals"),
		 field = this.getInputs().filter("[name=" + name + "]");
        return input.val() == field.val() ? true : [name];
    });

    $.tools.validator.localize("it", {
        '*': 'Per cortesia correggi questo valore',
        ':email': 'Per cortesia inserisci email valida',
        ':number': 'Per cortesia inserisci valore numerico',
        ':url': 'Per cortesia inserisci URL valido',
        '[data-equals]': 'Valore non uguale al campo $1',
        '[max]': 'Per cortesia inserire valore minore di $1',
        '[min]': 'Per cortesia inserire valore maggiore di $1',
        '[required]': 'Per cortesia questo è un campo richiesto'
    });
    
    // italiano localization
    $.tools.dateinput.localize("it", {
        months: 'gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre',
        shortMonths: 'gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic',
        days: 'domenica,lunedi,martedi,mercoledi,giovedi,venerdi,sabato',
        shortDays: 'dom,lun,mar,mer,gio,ven,sab'
    });    
    
//------------------ Trigger per overlay autenticazione
    var triggers = $(".modalInput").overlay({
        // some mask tweaks suitable for modal dialogs
        mask: {
            color: '#465B6F',
            loadSpeed: 400,
            opacity: 0.4
        },
        closeOnClick: false
    });
// ---- Attivo Galleriffic se presente
    if ($("#gallery").length) {
        // We only want these styles applied when javascript is enabled
        $('div.navigation').css({ 'width': '200px', 'float': 'left' });
        $('div.content').css('display', 'block');

        // Initially set opacity on thumbs and add additional styling for hover effect on thumbs
        var onMouseOutOpacity = 0.67;
        $('#thumbs ul.thumbs li').opacityrollover({
            mouseOutOpacity: onMouseOutOpacity,
            mouseOverOpacity: 1.0,
            fadeSpeed: 'fast',
            exemptionSelector: '.selected'
        });

        // Initialize Advanced Galleriffic Gallery
        var gallery = $('#thumbs').galleriffic({
            delay: 2500,
            numThumbs: 14,
            preloadAhead: 6,
            enableTopPager: true,
            enableBottomPager: true,
            maxPagesToShow: 7,
            imageContainerSel: '#slideshow',
            controlsContainerSel: '#controls',
            captionContainerSel: '#caption',
            loadingContainerSel: '#loading',
            renderSSControls: true,
            renderNavControls: true,
            playLinkText: 'Inizia Slideshow',
            pauseLinkText: 'Ferma Slideshow',
            prevLinkText: '&lsaquo; Foto precedente',
            nextLinkText: 'Foto successiva &rsaquo;',
            nextPageLinkText: 'Succ &rsaquo;',
            prevPageLinkText: '&lsaquo; Prec',
            enableHistory: false,
            autoStart: true,
            syncTransitions: true,
            defaultTransitionDuration: 900,
            onSlideChange: function(prevIndex, nextIndex) {
                // 'this' refers to the gallery, which is an extension of $('#thumbs')
                this.find('ul.thumbs').children()
							.eq(prevIndex).fadeTo('fast', onMouseOutOpacity).end()
							.eq(nextIndex).fadeTo('fast', 1.0);
            },
            onPageTransitionOut: function(callback) {
                this.fadeTo('fast', 0.0, callback);
            },
            onPageTransitionIn: function() {
                this.fadeTo('fast', 1.0);
            }
        });
    };
    
    // Attivo Musica se presente la div
    if ($("#musica").length) { $('#musica').jmp3({ volume:'20' }); };

    // Attivo Target
    for (var ik = 0; ik < document.links.length; ik++) {
        if (document.links[ik].className == "blank") { document.links[ik].target = "_blank"; };
        if (document.links[ik].className == "anteprima") { document.links[ik].target = "_blank"; };
    }

    // Attivo Timer sessione
    if ($("#ChiudiSessione").length) {
        $('#testa').append("<div id='FXTimer'><p><b>Warning Message</b><br />La tua sessione sarà chiusa tra 5 minuti. Salva il tuo lavoro!</p></div>");
    };
    // Inserisco messaggio bad browser
    if (badBrowser() && getBadBrowser('browserWarning') != 'seen') {
        $(function() {
        $("<div id='browserWarning'><b>Attenzione! Stai usando un browser insicuro ed obsoleto</b> (rilasciato nel 2001) per cui questo sito non è progettato.<br />Per cortesia passa a <a href='http://getfirefox.com'>FireFox</a>, <a href='http://www.apple.com/safari/'>Safari</a>, <a href='http://www.opera.com/download/'>Opera</a> o <a href='http://www.microsoft.com/windows/downloads/ie/getitnow.mspx'>Internet Explorer 9</a>.<br />Questi nuovi browser sono gratuiti e molto più veloci!&nbsp;&nbsp;&nbsp;[<a href='#' id='warningClose'>Chiudi</a>] </div> ")
			.css({
			    backgroundColor: '#fcfdde',
			    'width': '100%',
			    'border-top': 'solid 1px #000',
			    'border-bottom': 'solid 1px #000',
			    'text-align': 'center',
			    padding: '5px 0px 5px 0px'
			})
			.prependTo("body");

            $('#warningClose').click(function() {
                setBadBrowser('browserWarning', 'seen');
                $('#browserWarning').slideUp('slow');
                return false;
            });
        });
    }    
});


/* Attivazioni su evento onload */
$(window).load(function() {
    // Attivo NivoSlider se presente
    if ($("#slider").length) {
        $('#slider').nivoSlider({
            effect: 'random', //Specify sets like: 'fold,fade,sliceDown'
            slices: 15,
            animSpeed: 800, //Slide transition speed
            pauseTime: 6000,
            startSlide: 0, //Set starting Slide (0 index)
            directionNav: false, //Next & Prev
            directionNavHide: true, //Only show on hover
            controlNav: false, //1,2,3...
            controlNavThumbs: false, //Use thumbnails for Control Nav
            controlNavThumbsFromRel: false, //Use image rel for thumbs
            controlNavThumbsSearch: '.jpg', //Replace this with...
            controlNavThumbsReplace: '_thumb.jpg', //...this in thumb Image src
            keyboardNav: true, //Use left & right arrows
            pauseOnHover: true, //Stop animation while hovering
            manualAdvance: false, //Force manual transitions
            captionOpacity: 0.7, //Universal caption opacity
            beforeChange: function() { },
            afterChange: function() { },
            slideshowEnd: function() { } //Triggers after all slides have been shown
        });
    };

    /* Setto Timeout a 15 minuti = 900000 millesimi usando solo javascript nativo senza jquery */
    var ChiudiSessione = document.getElementById("ChiudiSessione")
    if (ChiudiSessione != null) {
        var TimerSessione = setTimeout(function() {
            document.getElementById('FXTimer').style.display = 'block';
        }, 900000)
    };
    /* Settaggi iphone usando solo javascript nativo senza jquery */
    var EsisteAccount = document.getElementById("Account")
    if (EsisteAccount != null) {
        EsisteAccount.setAttribute("placeholder", "Nickname");
        EsisteAccount.setAttribute("autocorrect", "off");
        EsisteAccount.setAttribute("autocapitalize", "off");
    };
    var EsistePW = document.getElementById("Password")
    if (EsistePW != null) {
        EsistePW.setAttribute("placeholder", "Password");
        EsistePW.setAttribute("autocorrect", "off");
        EsistePW.setAttribute("autocapitalize", "off");
    };
    var EsistePlaceholder = document.getElementById("TSearchUser")
    if (EsistePlaceholder != null) {
        EsistePlaceholder.setAttribute("placeholder", "Stringa da cercare");
        EsistePlaceholder.setAttribute("required", "required");
    };
});


