fade.opacity = 1;
fade.resolution = 25; // Lower value => smoother transition (milliseconds between opacity changes)
fade.timer = null;
fade.change_direction = 0;
new_img = {src : '', alt : ''};
recentHash = '';

function array_search(needle, haystack, strict) {
   var strict = !!strict;

   for(var key in haystack)
      if((strict && haystack[key] === needle) || (!strict && haystack[key] == needle))
         return key;

   return false;
}

// Let every image have an unique url (#). Make sure the correct image is displayed.
function pollHash(img, regexp) {
   if((window.location.hash == '' || window.location.hash.substr(1) == parseInt(window.location.hash.substr(1))) && window.location.hash != recentHash) {
      recentHash = window.location.hash;
      if(window.location.hash == '')
         view_slide = window.location.search.substr(window.location.search.search(regexp) + 12, window.location.search.substr(window.location.search.search(regexp) + 12).search(/(&|$)/));
      else
         view_slide = recentHash.substr(1);

      if(parseInt(view_slide) == view_slide)
         if(typeof slide_paths[view_slide] != 'undefined')
            if(get_relative_src(img.src) != slide_paths[view_slide])
               navigate(view_slide.toString(), 0);
   }
}

// Get relative source from absolute source
function get_relative_src(src) {
   offset = 0;
   for(level = -1; offset > -1; ++level)
      offset = slide_paths[0].indexOf('/', offset + 1);
   offset = src.length;
   for(i = level; i > -1; --i)
      offset = src.lastIndexOf('/', offset - 1);
   return src.substr(offset + 1);
}

// Cache images
function cache_images() {
   slide_cache = new Array;
   for(i = 0; i < slide_paths.length; ++i) {
   	slide_cache[i] = new Image;
   	slide_cache[i].src = slide_paths[i];
   }
}

function fade(img, img_text, img_nr, img_count, elm_previous, elm_next, elm_gallery, regexp, change_direction, time) {
   fade.img = img;
   fade.text = img_text;
   fade.nr = img_nr;
   fade.count = img_count;
   fade.elm_previous = elm_previous;
   fade.elm_next = elm_next;
   fade.elm_gallery = elm_gallery;
   fade.regexp = regexp;
   fade.time = time / 2;

   // Get relative image source
   fade.relative_src = get_relative_src(fade.img.src);

   // Get id of the new image. Prevent "wrap around"
   if(typeof change_direction == 'string') {
      new_img.id = parseInt(change_direction);
      change_direction = 0;
   } else {
      fade.change_direction += change_direction;
      new_img.id = parseInt(array_search(fade.relative_src, slide_paths)) + parseInt(fade.change_direction);
      if(new_img.id < 0 || typeof slide_paths[new_img.id] == 'undefined') {
         fade.change_direction -= change_direction;
         if(fade.change_direction == 0)
            return false;
         new_img.id = parseInt(array_search(fade.relative_src, slide_paths)) + parseInt(fade.change_direction);
      }
   }

   // Display or hide navigation arrows
   if(new_img.id == 0)
      fade.elm_previous.style.display = 'none';
   else if(fade.elm_previous.style.display == 'none')
      fade.elm_previous.style.display = 'block';
   if(new_img.id == slide_paths.length - 1)
      fade.elm_next.style.display = 'none';
   else if(fade.elm_next.style.display == 'none')
      fade.elm_next.style.display = 'block';

   // Highlight navigation arrows
   if(!next_over) {
      if(change_direction < 0)
         fade.elm_next.className = 'next';
      else if(change_direction > 0)
         fade.elm_next.className = 'next_over';
   }
   if(!previous_over) {
      if(change_direction > 0)
         fade.elm_previous.className = 'previous';
      else if(change_direction < 0)
         fade.elm_previous.className = 'previous_over';
   }

   // Get supported browser opacity type
	if(typeof fade.img.style.opacity != 'undefined')
		fade.type = 'w3c';
	else if(typeof fade.img.style.MozOpacity != 'undefined')
		fade.type = 'moz';
	else if(typeof fade.img.style.KhtmlOpacity != 'undefined')
		fade.type = 'khtml';
	else if(typeof fade.img.filters == 'object')
		fade.type = (fade.img.filters.length > 0 && typeof fade.img.filters.alpha == 'object' && typeof fade.img.filters.alpha.opacity == 'number') ? 'ie' : 'none';
	else
		fade.type = 'none';

   new_img.src = slide_paths[new_img.id];
   new_img.alt = slide_texts[new_img.id];

   if(time == 0 || fade.type == 'none')
      fade.change_image();
   else {
      if(fade.timer != null)
   		clearInterval(fade.timer);

      fade.direction = 'out';
		fade.timer = setInterval('fade.fader()', fade.resolution);
   }

   return false;
}

fade.change_image = function() {
   fade.img.alt = new_img.alt;
   fade.text.innerHTML = new_img.alt;
   fade.nr.innerHTML = new_img.id + 1;
   fade.img.src = new_img.src;
   fade.change_direction = 0;

   // Set the unique url if image not the same as the image parameter in the url and the unique url is not set
   if(window.location.hash != '' || new_img.id != window.location.search.substr(window.location.search.search(fade.regexp) + 12, window.location.search.substr(window.location.search.search(fade.regexp) + 12).search(/(&|$)/)))
      window.location.hash = new_img.id;

   // Change the navigation urls
   fade.elm_gallery.href = fade.elm_gallery.href.substr(0, fade.elm_gallery.href.search(/(\?|&)gallery=/i) + 9) + Math.floor((fade.nr.innerHTML - 1) / 25) + fade.elm_gallery.href.substr(fade.elm_gallery.href.substr(fade.elm_gallery.href.search(/(\?|&)gallery=/i) + 9).search(/(&|$)/) + fade.elm_gallery.href.search(/(\?|&)gallery=/i) + 9);
   fade.elm_previous.href = fade.elm_previous.href.substr(0, fade.elm_previous.href.search(fade.regexp) + 12) + parseInt(new_img.id - 1) + fade.elm_previous.href.substr(fade.elm_previous.href.substr(fade.elm_previous.href.search(fade.regexp) + 12).search(/(&|$)/) + fade.elm_previous.href.search(fade.regexp) + 12);
   fade.elm_next.href = fade.elm_next.href.substr(0, fade.elm_next.href.search(fade.regexp) + 12) + parseInt(new_img.id + 1) + fade.elm_next.href.substr(fade.elm_next.href.substr(fade.elm_next.href.search(fade.regexp) + 12).search(/(&|$)/) + fade.elm_next.href.search(fade.regexp) + 12);
}

fade.fader = function() {
   if(fade.opacity == 0)
      fade.change_image();
   if(fade.direction == 'out') {
      fade.opacity -= (fade.resolution / fade.time);

      if(fade.opacity < (fade.resolution / fade.time)) {
         fade.direction = 'in';
         fade.opacity = 0;
      }
   } else {
      fade.opacity += (fade.resolution / fade.time);

      if((fade.opacity + (fade.resolution / fade.time)) > 1) {
         fade.direction = 'out';
         fade.opacity = 1;
   		clearInterval(fade.timer);
   		fade.timer = null;

   		// Stop heighlighting navigation arrows
         if(!previous_over)
            fade.elm_previous.className = 'previous';
         if(!next_over)
            fade.elm_next.className = 'next';
      }
   }

   switch(fade.type) {
      case 'ie' :
         fade.img.filters.alpha.opacity = fade.opacity * 100;
         break;
      case 'khtml' :
         fade.img.style.KhtmlOpacity = fade.opacity;
         break;
      case 'moz' :
         fade.img.style.MozOpacity = (fade.opacity == 1 ? 0.9999999 : fade.opacity); // Restrict max opacity to prevent a visual popping effect in Firefox
         break;
      default :
         fade.img.style.opacity = (fade.opacity == 1 ? 0.9999999 : fade.opacity); // Restrict max opacity to prevent a visual popping effect in Firefox
         break;
   }
}
