﻿/**
Lightbox function:
 * Init lightbox;
 Params: 
 * mode: 
   single: thread every node in wrapped set as a single lightbox (close onclick anywhere)
   multi: Thread all nodes as one slideshow (default)
 * width: default width (default 250)
 * heigth: default height (default 250)
 * loading: loading image (default "/views/global/images/lightbox/loading.gif")
 * click on content: End lightbox

 Usage:
jQuery(function() {
  jQuery.(".lightbox-me .lightbox").lightbox({
    // mode: "single",
    attach: [ "header", "description" ]
  });
});

 Steps:
 Start:
 1. Determine mode => Create click action for wrappedset

 Click on wrappedset item
 1. Create lightbox
 2. Create preloading div
 3. Dim screen
 4. Show empty lightbox with default width and height
 5. Preload current item
 6. Size the lightbox 
 7. Load content in lightbox
 8. Show content.
 
 End lightbox
 1. Fade content
 2. remove lightbox
 3. undim screen
 
 Attachments: 
 Navigation
 * Navigate through wrappedset.
 * Slideshow?
 Description
 * Show description based on function(). Defaults to alt/title
 
- Lightbox definition:
<div id="ip-lightbox">
  <div id="lightbox-container">
    <div id="lightbox-content">
    </div>
  </div>
</div>

* @author    Jacob Stellingwerf <jacob.stellingwerf@infoprojects.nl>
*/
(function($){
 /*
  Chain functions down here
  */

 /*
  Function description here
  */
  $.fn.lightbox = function(options) {
		// default configuration options
    var cfg = $.extend({
      mode: "multi", // single multi
      defaultWidth: 250,
      defaultHeight: 250,
      contentOffset: 10,
      loading: "/views/global/images/lightbox/loading.gif",
      size: "image", // Choose one of the size function or create your own size function.
      content: "image", // Choose one of the content function or create your own size function.
      attach: [ "description" ], // default show alt/title // extend name param for options, see navigation
      endOnClick: true,
      dimOptions: {}
    }, options||{});


    // Start:
    // 1. Determine mode => Create click action for wrappedset
    var lightboxset = $(this);
    // Stop if empty set
    if (lightboxset.size() == 0) {
      return lightboxset;
    }
    else if (lightboxset.size() == 1) {
      cfg.mode = "single";
    }
    
    if (cfg.mode=="single" && lightboxset.size() > 1) {
      // Create seperate lightbox for each node in the set
      lightboxset.each(function() {
        $(this).lightbox(cfg);
      });
      return lightboxset;
    }
    
    // Main variables here
    // Container
    var lightbox = null;
    // Container
    var container = null;
    // Content div
    var content = null;
    // Current lightbox item
    var lightboxItem = null;
    // loading div
    var loading = null;
    // loading div
    var preloaded = null;
    // Index of the current item
    var index = 0;
    // Content is loading
    var curSize = {  
      width: cfg.defaultWidth,
      height: cfg.defaultHeight
    };
    // Content is loading
    var busy = false;

    // Click on wrappedset item
    // 1. Create lightbox
    // 2. Create preloading div
    // 3. Dim screen
    // 4. Show empty lightbox with default width and height
    var create = function() {
      busy = false;
      // First remove old container
      removeLightbox();
      $(document).dim($.extend(cfg.dimOptions, {
        endEvent: removeLightbox
      }));
      // Create new lightbox - container
      $("body").append($('<div id="ip-lightbox"><div id="lightbox-container"><div id="lightbox-content"></div></div></div>').css("opacity", 0));
      
      // Set variables for use elsewhere
      lightbox = $("#ip-lightbox").css("z-index", 100000).hide();
      if (cfg.endOnClick) {
        lightbox.bind("click.end", end);
      }
      container = lightbox.find("#lightbox-container").css({
        padding: cfg.contentOffset,
        width: cfg.defaultWidth,
        height: cfg.defaultHeight
      });
      content = container.find("#lightbox-content");
      // Attach navigation if needed
      if (cfg.mode == "multi") {
        // Create navigation
        if (cfg.attach) {
          cfg.attach[cfg.attach.length] = "navigation";
        }
        else {
          cfg.attach = ["navigation"];
        }
      }
      // Attach all functionality
      if (cfg.attach) {
        // Make array unique
        cfg.attach = jQuery.unique(cfg.attach);
        jQuery.each(cfg.attach, function() {
          // $.log(this);
          if ($.isFunction(attachments[this])) {
            attachments[this]();
          }
        });
        
      }
      // Show lightbox
      lightbox.stop().show().animate({opacity: 1}, "fast", function() {
        lightbox.trigger("lightboxLoaded", [ lightbox ]);
      });
    };

    var end = function() {
      $(document).undim($.extend(cfg.dimOptions, {
        endEvent: removeLightbox
      }));
    };

    // Remove the lightbox forever
    var removeLightbox = function() {
      if (lightbox) {
        lightbox.animate({opacity: 0}, "fast", 
          function() {
            $(this).remove();
          }
        );
      }
    };

    // 5. Preload current item
    var preload = function(lightboxItem) {
      // Preload content in preloaded div
      if (preloaded && !lightboxItem.attr("lightbox-content-id")) {
        // $.log("preloading content");
        var preloadContainer = $('<div class="preloaded"></div').makeId();
        lightboxItem.attr("lightbox-content-id", preloadContainer.attr("id"));
        var preloadContent = cfg.content;
        // $.log(preloadContent);
        if ($.isFunction(preloadContent)) {
          preloadContent = preloadContent();
        }
        else if (contents[preloadContent] && $.isFunction(contents[preloadContent])) {
          preloadContent = contents[preloadContent]();
        }
        // $.log(preloadContent);
        preloadContainer.append(preloadContent);
        preloaded.append(preloadContainer);
        // $.log("Content loaded");
      }

    };
    // 6. Size the lightbox 
    var size = function() {
      var newSize = cfg.size;
      if ($.isFunction(newSize)) {
        newSize = newSize(lightboxItem);
      }
      else if (sizes[newSize] && $.isFunction(sizes[newSize])) {
        newSize = sizes[newSize]();
      }
      //$.log(newSize.width+"x"+newSize.height);
      curSize = newSize;
      return newSize;
    };
    // 7. Load content in lightbox
    var load = function(newIndex) {
      if (newIndex) {
        index = newIndex;
      }
      busy = true;
      lightboxItem = $(lightboxset.get(index));
      remove();
      // Show loading image
      //startLoading();
      // Show the content, busy set to false in show animate function
      show();
    };
    var remove = function() {
      content.trigger("contentUnload", [ lightboxItem ]);
      content.find("> *").animate({opacity: 0}, "fast", function() {
        $(this).remove();
      });
    };
    var startLoading = function() {
      if (!loading) {
        // $.log("Creating loading image");
        // Create loading img
        container.append('<img id="lightbox-loading" src="'+cfg.loading+'"/>');
        loading = lightbox.find("#lightbox-loading").hide();
        container.resize(function() {
          loading.css($.getCenterPoint(loading, container, "vertical"));
        }).show().resize();
      }
    };
    var endLoading = function() {
      if (loading) {
        loading.hide();
      }
    };
    // 8. Show content.
    var show = function() {
      // Append content
      var contentId = lightboxItem.attr("lightbox-content-id");
      var newContent = preloaded.find("#"+contentId).find("> *").clone(true);

      container.stop().animate(size(), "slow", function() {
        content.append(newContent);
        newContent.css("opacity", 0);
        newContent.animate({opacity: 1}, "fast");
        // Hide loading image
        //endLoading();
        busy = false;
        content.trigger("contentLoad", [ lightboxItem, newContent ]);
      });
    };
     
    // Attachments: 
    var attachments = {
      // Navigation
      // * Navigate through wrappedset.
      // * Slideshow?
      navigation: function() {
        // Check for navigation options
        var options = $.extend({
          next: "/views/global/images/lightbox/next.gif",
          previous: "/views/global/images/lightbox/prev.gif"
        }, cfg.attachNavigationOptions || {});
        // Check for container
        if (!container) {
          alert("first call create please, terminating function.");
        }
        // $.log("Setting navigation");
        if (lightboxset.size() > 1) {
          // Attach next and previous
          var next = $('<a id="lightbox-navigation-next" href="#"><img src="'+options.next+'" /></a>').click(function() {
            $(this).hide();
            index++;
            // $.log(index);
            lightbox.trigger("prevContent", [ $(lightboxset.get(index)) ]);
            load();
            return false;
          }).hide();
          var previous = $('<a id="lightbox-navigation-previous" href="#"><img src="'+options.previous+'" /></a>').click(function() {
            $(this).hide();
            index--;
            // $.log(index);
            lightbox.trigger("nextContent", [ $(lightboxset.get(index)) ]);
            load();
            return false;
          }).hide();
          
          container.append(next.add(previous));
          
          container.addon({ 
              upperleft: {
                x: -cfg.contentOffset, 
                y: -cfg.contentOffset 
              }, 
              bottomright: { 
                x: function() { 
                  return (container.width() + (4 * cfg.contentOffset)) / 2; 
                }, 
                y: function() { 
                  return (container.height() + (3 * cfg.contentOffset)); 
                } 
              } 
            }, 
            function(obj,config) { 
              // $.log("Previous fired ("+busy+")");
              if (index > 0 && !busy) {
                previous.css({left: 0, top: "20%"}).fadeIn(10);
              }
              else {
                previous.hide();
                obj.attr(config.name, "false");
              }
            },
            function() {
              // $.log("Previous unfired");
              previous.fadeOut(10);
            }
          ).addon({ upperleft: {x: function() { return (container.width() + (4 * cfg.contentOffset)) / 2; }, y: -cfg.contentOffset }, bottomright: { x: function() { return (container.width() + (3 * cfg.contentOffset)); }, y: function() { return (container.height() + (3 * cfg.contentOffset)); } } }, 
            function(obj,config) { 
              //$.log("Next fired ("+busy+")");
              if (index < lightboxset.size() - 1 && !busy) {
                next.css({right: 0, top: "20%"}).fadeIn(10);
              }
              else {
                next.hide();
                obj.attr(config.name, "false");
              }
            },
            function() {
              //$.log("Next unfired");
              next.fadeOut(10);
            }
          );   
        }
      },
      // Description
      // * Show description based on function(). Defaults to alt/title
      description: function() {
        // Check for container
        if (!container) {
          alert("first call create please, terminating function.");
        }
        var description = $('<div id="lightbox-description"><div class="lightbox-description-inner"></div></div>');
        var descriptionInner = description.find(".lightbox-description-inner");
        
        content.bind("contentLoad", function(event, item, bare) {
          // $.log("Description triggered");
          // Remove previous description
          description.remove();
          description = $('<div id="lightbox-description"><div class="lightbox-description-inner"></div></div>');
          descriptionInner = description.find(".lightbox-description-inner");
          
          if (item.attr("alt") || item.attr("title")) {
            // Create description if needed
            if (item.attr("alt")) {
              descriptionInner.text(item.attr("alt"));
            }
            else {
              descriptionInner.text(item.attr("title"));
            }
            content.append(description);
            curSize.height = parseInt(curSize.height, 10) + parseInt(description.height(), 10);
            container.animate(curSize);
          }
        });
      },
      // Header
      // * Show header based on function(). Defaults to only a close button
      header: function() {
        // Check for header options
        var options = $.extend({
          content: "",
          close: '<a href="#" class="close" onclick="try{showSelect();}catch(e){}return false;">X</a>'
        }, cfg.attachHeaderOptions || {});
        // Check for container
        if (!container) {
          alert("first call create please, terminating function.");
        }
        var header = $('<div id="lightbox-header"><div class="lightbox-header-inner"></div></div>');
        var headerInner = header.find(".lightbox-header-inner");
        var currentHeight = 0;

        var defaultTop;
        lightbox.bind("lightboxLoaded", function(event, lightbox) {
          defaultTop = lightbox.offset().top;
          // $.log("Defaulttop for header is "+ defaultTop);
        });

        lightbox.bind("nextContent prevContent", function(event, lightbox) {
          // $.log("Animate top to " + defaultTop + ", for header");
          lightbox.stop().animate({top: defaultTop}, "fast");
        });

        content.bind("contentLoad", function(event, item, bare) {
          // $.log("Attaching header");
          // Remove previous header and content of the header
          header.remove();
          header = $('<div id="lightbox-header"><div class="lightbox-header-inner"></div></div>');
          headerInner = header.find(".lightbox-header-inner");

          // Set header close button here
          var close = options.close;
          if (close) {
            if ($.isFunction(close)) {
              close = close();
            }
            // Style the button right
            // $.log("Appending close button");
            headerInner.append($(close).css("right", cfg.contentOffset).click(end));
            // TODO: remove click on lightbox to end lightbox.
          }
           
          // Set header content here
          var headerContent = options.content;
          if (headerContent) {
            if ($.isFunction(headerContent)) {
              headerContent = headerContent();
            }
            headerInner.append(headerContent);
          }
           
          content.prepend(header);
          var offsetTop = parseInt(lightbox.offset().top, 10) - parseInt(header.height(), 10);
          curSize.height = parseInt(curSize.height, 10) + parseInt(header.height(), 10);
          container.animate(curSize);
        });
      }
    };

    // Content functions
    var contents = {
      image: function() {
        var src;
        if (lightboxItem.find("img").size() == 0) {
          src = lightboxItem.attr("src");
        }
        else {
          src = lightboxItem.find("img:first").attr("src");
        }
        src = src.replace("thumb_", "");
        var img = $('<img src="' + src + '" class="lightbox-content-image" />');
        
        // Preload the image
			  var preloading = new Image();
			  preloading.onload = function() {
				  var width = preloading.width;
				  var height = preloading.height;
			    // $.log("image loaded ("+width+"x"+height+")");
				  img.attr("sizeWidth", width);
				  img.attr("sizeHeight", height);
				  preloading = null;
				  
			  };
			  preloading.src = src;
			  
			  return img;
      },
      replaceByLink: function() {
        lightboxItem.attr("sizeWidth", lightboxItem.width());
        lightboxItem.attr("sizeHeight", lightboxItem.height());
        var retVal = lightboxItem.clone(false);
        var button = $('<a href="#">[link]</a>');
        if (cfg.replaceByLinkOptions.button) {
          button = $(cfg.replaceByLinkOptions.button);
        }
        lightboxItem.replaceBy(button);
        lightboxItem = button;
        return retVal;
      }
    };
    
    // Size functions
    var sizes = {
      image: function() {
        var contentId = lightboxItem.attr("lightbox-content-id");
        var content = preloaded.find("div[id="+contentId+"] img:first");
        var image = new Image();
        image.src = content.attr("src");
        return {
          width: $.browser.safari ? content.attr("sizeWidth") : image.width,
          height: $.browser.safari ? content.attr("sizeHeight") : image.height
        };
      },
      content: function() {
        var contentId = lightboxItem.attr("lightbox-content-id");
        var content = preloaded.find("div[id="+contentId+"] > *");
        return {
          width: content.attr("sizeWidth") ? content.attr("sizeWidth") : content.width(),
          height: content.attr("sizeHeight") ? content.attr("sizeHeight") : content.height()
        };
      }
    };

    // Process lightbox items here
    // Create or set preloaded    
    preloaded = $("#ip-lightbox-preloaded").hide();
    if (preloaded.size() == 0) {
      $("body").append($('<div id="ip-lightbox-preloaded"></div>').css("width", cfg.defaultWidth));
      preloaded = $("#ip-lightbox-preloaded").hide();
    }
    
    // 4 Create click event for items;
    lightboxset.each(function() {
      // TODO: If click event exists add it to the lightbox content.
      lightboxItem = $(this);
      // Preload content
      preload(lightboxItem);
      
      lightboxItem.attr("lightbox-index", index++);
      lightboxItem.addClass("lightboxed");
      
      if (lightboxItem.attr("href")) {
        lightboxItem.attr("href", "#");
      }
      
      lightboxItem.click(function() {
        first = true;
        lightboxItem = $(this);
        // $.log("Item clicked.");
        create();
        index = $(this).attr("lightbox-index");
        load(index);
        return false;
      });
    });

    return lightboxset;
  };
})(jQuery);

