/**
 * tools.expose 1.0.5 - Make HTML elements stand out
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/expose.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : June 2008
 * Date: ${date}
 * Revision: ${revision} 
 */
(function($) {  

  // static constructs
  $.tools = $.tools || {};
  
  $.tools.expose = {
    version: '1.0.5',  
    conf: { 

      // mask settings
      maskId: null,
      loadSpeed: 'slow',
      closeSpeed: 'fast',
      closeOnClick: true,
      closeOnEsc: true,
      
      // css settings
      zIndex: 9998,
      opacity: 0.8,
      color: '#456',
      api: false
    }
  };

  /* one of the greatest headaches in the tool. finally made it */
  function viewport() {
        
    // the horror case
    if ($.browser.msie) {
      
      // if there are no scrollbars then use window.height
      var d = $(document).height(), w = $(window).height();
      
      return [
        window.innerWidth ||              // ie7+
        document.documentElement.clientWidth ||   // ie6  
        document.body.clientWidth,          // ie6 quirks mode
        d - w < 20 ? w : d
      ];
    } 
    
    // other well behaving browsers
    return [$(window).width(), $(document).height()];
    
  } 
  
  function Expose(els, conf) { 
    // private variables
    var self = this, $self = $(this), mask = null, loaded = false, origIndex = 0;   
    
    // bind all callbacks from configuration
    $.each(conf, function(name, fn) {
      if ($.isFunction(fn)) { $self.bind(name, fn); }
    });  

    // adjust mask size when window is resized (or firebug is toggled)
    $(window).resize(function() {
      self.fit();
    }); 
    
    
    // public methods
    $.extend(this, {
    
      getMask: function() {
        return mask;  
      },
      
      getExposed: function() {
        return els; 
      },
      
      getConf: function() {
        return conf;  
      },    
      
      isLoaded: function() {
        return loaded;  
      },
      
      load: function(e) { 
        
        // already loaded ?
        if (loaded) { return self;  }
  
        origIndex = els.eq(0).css("zIndex");        
        
        // find existing mask
        if (conf.maskId) { mask = $("#" + conf.maskId); }
        if (!mask || !mask.length) {
          
          var size = viewport();
          
          mask = $('<div/>').css({        
            position:'absolute', 
            top:0, 
            left:0,
            width: size[0],
            height: size[1],
            display:'none',
            opacity: 0,             
            zIndex:conf.zIndex  
          });           
          
          // id
          if (conf.maskId) { mask.attr("id", conf.maskId); }          
          
          $("body").append(mask); 
          
          
          // background color 
          var bg = mask.css("backgroundColor");
          
          if (!bg || bg == 'transparent' || bg == 'rgba(0, 0, 0, 0)') {
            mask.css("backgroundColor", conf.color);  
          }   
          
          // esc button
          if (conf.closeOnEsc) {            
            $(document).bind("keydown.unexpose", function(evt) {              
              if (evt.keyCode == 27) {
                self.close(); 
              }   
            });     
          }
          
          // mask click closes
          if (conf.closeOnClick) {
            mask.bind("click.unexpose", function(e)  {
              self.close(e);    
            });         
          }         
        }       
        
        // possibility to cancel click action
        e = e || $.Event();
        e.type = "onBeforeLoad";
        $self.trigger(e);     
        
        if (e.isDefaultPrevented()) { return self; }
        
        // make sure element is positioned absolutely or relatively
        $.each(els, function() {
          var el = $(this);
          if (!/relative|absolute|fixed/i.test(el.css("position"))) {
            el.css("position", "relative");   
          }         
        });
       
        // make elements sit on top of the mask       
        els.css({zIndex:Math.max(conf.zIndex + 1, origIndex == 'auto' ? 0 : origIndex)});       

        
        // reveal mask
        var h = mask.height();
        
        if (!this.isLoaded()) { 
          
          mask.css({opacity: 0, display: 'block'}).fadeTo(conf.loadSpeed, conf.opacity, function() {

            // sometimes IE6 misses the height property on fadeTo method
            if (mask.height() != h) { mask.css("height", h); }
            e.type = "onLoad";            
            $self.trigger(e); 
             
          });         
        }
          
        loaded = true;
        
        return self;
      }, 
      
      
      close: function(e) {
                
        if (!loaded) { return self; }   

        e = e || $.Event();
        e.type = "onBeforeClose";
        $self.trigger(e);       
        if (e.isDefaultPrevented()) { return self; }
        
        mask.fadeOut(conf.closeSpeed, function() {
          e.type = "onClose";
          $self.trigger(e);
          els.css({zIndex: $.browser.msie ? origIndex : null});
        });                           
        
        loaded = false;
        return self; 
      },
      
      fit: function() {
        if (mask) {
          var size = viewport();        
          mask.css({ width: size[0], height: size[1]});
        } 
      },
      
      bind: function(name, fn) {
        $self.bind(name, fn);
        return self;  
      },      
      
      unbind: function(name) {
        $self.unbind(name);
        return self;  
      }       
      
    });   
    
    // callbacks  
    $.each("onBeforeLoad,onLoad,onBeforeClose,onClose".split(","), function(i, ev) {
      self[ev] = function(fn) {
        if ($.isFunction(fn)) {
          return self.bind(ev, fn);
        } 
      };
    });     

  }
  
  
  // jQuery plugin implementation
  $.fn.expose = function(conf) {
    
    var el = this.eq(typeof conf == 'number' ? conf : 0).data("expose");
    if (el) { return el; }
    
    if (typeof conf == 'string') {
      conf = {color: conf};
    }
    
    var globals = $.extend({}, $.tools.expose.conf);
    conf = $.extend(globals, conf);   

    // construct exposes
    this.each(function() {
      el = new Expose($(this), conf);
      $(this).data("expose", el);  
    });   
    
    return conf.api ? el: this;   
  };    


})(jQuery);


/**
 * tools.overlay 1.1.2 - Overlay HTML with eye candy.
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Date: ${date}
 * Revision: ${revision} 
 */
(function($) { 

  // static constructs
  $.tools = $.tools || {};
  
  $.tools.overlay = {
    
    version: '1.1.2',
    
    addEffect: function(name, loadFn, closeFn) {
      effects[name] = [loadFn, closeFn];  
    },
  
    conf: {  
      top: '10%', 
      left: 'center',
      absolute: false,
      
      speed: 'normal',
      closeSpeed: 'fast',
      effect: 'default',
      
      close: null,  
      oneInstance: true,
      closeOnClick: true,
      closeOnEsc: true, 
      api: false,
      expose: null,      
      // target element to be overlayed. by default taken from [rel]
      target: null,            
      gallery: false
    }
  };

  
  var effects = {};
    
  // the default effect. nice and easy!
  $.tools.overlay.addEffect('default', 
    
    /* 
      onLoad/onClose functions must be called otherwise none of the 
      user supplied callback methods won't be called
    */
    function(onLoad) { 
      this.getOverlay().fadeIn(this.getConf().speed, onLoad); 
    }, function(onClose) {      
      this.getOverlay().fadeOut(this.getConf().closeSpeed, onClose);
      if ($('#img').length > 0) {
        $('#img').css('visibility', 'hidden');
      }
    }   
  );
  
    
  var instances = [];   

  
  function Overlay(trigger, conf) {   
    
    // private variables
    var self = this, 
       $self = $(this),
       w = $(window), 
       closers,
       overlay,
       opened,
       expose = conf.expose && $.tools.expose.version;
    
    // get overlay and triggerr
    var jq = conf.target || trigger.attr("rel");
    overlay = jq ? $(jq) : null || trigger; 
    
    if (!overlay.length && conf.gallery) {
      $('body').append('<div class="imageOverlay" id="' + conf.target.substr(1,conf.target.length) + '"><a class="prev">prev</a><a class="next">next</a><div class="info"></div><img class="progress" src="' + base_url + 'web/images/overlay/loading.gif"/></div>');
      overlay = $(conf.target);
    }        
    // overlay not found. cannot continue
    if (!overlay.length) { throw "Could not find Overlay: " + jq; }
    
    // if trigger is given - assign it's click event
    if (trigger && trigger.index(overlay) == -1) {
      trigger.click(function(e) {       
        self.load(e);
        return e.preventDefault();
      });
    }         
    
    // bind all callbacks from configuration
    $.each(conf, function(name, fn) {
      if ($.isFunction(fn)) { $self.bind(name, fn); }
    });   
        
    // API methods  
    $.extend(self, {

      load: function(e) {
        
        // can be opened only once
        if (self.isOpened()) { return self; } 
        
        // find the effect
        var eff = effects[conf.effect];
        if (!eff) { throw "Overlay: cannot find effect : \"" + conf.effect + "\""; }
        
        // close other instances?
        if (conf.oneInstance) {
          $.each(instances, function() {
            this.close(e);
          });
        }
        
        // onBeforeLoad
        e = e || $.Event();
        e.type = "onBeforeLoad";
        $self.trigger(e);       
        if (e.isDefaultPrevented()) { return self; }        

        // opened
        opened = true;
        
        // possible expose effect
        if (expose) { overlay.expose().load(e); }       
        
        // calculate end position 
        var top = conf.top;         
        var left = conf.left;

        // get overlay dimensions
        var oWidth = overlay.outerWidth({margin:true});
        
        var oHeight = overlay.outerHeight({margin:true}); 
        
        if (typeof top == 'string')  {
          top = top == 'center' ? Math.max((w.height() - oHeight) / 2, 0) : 
            parseInt(top, 10) / 100 * w.height();     
        }       
        
        if (left == 'center') { left = Math.max((w.width() - oWidth) / 2, 0); }
        
        if (!conf.absolute)  {
          top += w.scrollTop();
          left += w.scrollLeft();
        } 
        // position overlay
        overlay.css({top: top, left: left, position: 'absolute'}); 
        
        // onStart
        e.type = "onStart";
        $self.trigger(e); 
        
        // load effect          
        eff[0].call(self, function() {          
          if (opened) {
            e.type = "onLoad";
            $self.trigger(e);
          }
        });         
    
        // when window is clicked outside overlay, we close
        if (conf.closeOnClick) {          
          $(document).bind("click.overlay", function(e) { 
            if (!self.isOpened()) { return; }
            var et = $(e.target); 
            if (et.parents(overlay).length > 1) { return; }
            $.each(instances, function() {
              this.close(e);
            }); 
          });           
        }           
        
        // keyboard::escape
        if (conf.closeOnEsc) {
          
          // one callback is enough if multiple instances are loaded simultaneously
          $(document).unbind("keydown.overlay").bind("keydown.overlay", function(e) {
            if (e.keyCode == 27) {
              $.each(instances, function() {
                this.close(e);                
              });  
            }
          });     
        }

        return self; 
      }, 
      
      close: function(e) {

        if (!self.isOpened()) { return self; }
        
        e = e || $.Event();
        e.type = "onBeforeClose";
        $self.trigger(e);       
        if (e.isDefaultPrevented()) { return; }       
        
        opened = false;
        
        // close effect
        effects[conf.effect][1].call(self, function() {
          e.type = "onClose";
          $self.trigger(e); 
        });
        
        // if all instances are closed then we unbind the keyboard / clicking actions
        var allClosed = true;
        $.each(instances, function() {
          if (this.isOpened()) { allClosed = false; }
        });       
        
        if (allClosed) {
          $(document).unbind("click.overlay").unbind("keydown.overlay");    
        }
        return self;
      }, 
      
      // @deprecated
      getContent: function() {
        return overlay; 
      }, 
      
      getOverlay: function() {
        return overlay; 
      },
      
      getTrigger: function() {
        return trigger; 
      },
      
      getClosers: function() {
        return closers; 
      },      

      isOpened: function()  {
        return opened;
      },
      
      // manipulate start, finish and speeds
      getConf: function() {
        return conf;  
      },

      // bind
      bind: function(name, fn) {
        $self.bind(name, fn);
        return self;  
      },    
      
      // unbind
      unbind: function(name) {
        $self.unbind(name);
        return self;  
      }     
      
    });
    
    // callbacks  
    $.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","), function(i, ev) {
      self[ev] = function(fn) {
        if ($.isFunction(fn))
          return self.bind(ev, fn); 
      };
    });
    
    
    // exposing effect
    if (expose) {
      
      // expose configuration
      if (typeof conf.expose == 'string') { conf.expose = {color: conf.expose}; }
            
      $.extend(conf.expose, {
        api: true,
        closeOnClick: conf.closeOnClick,
        
        // only overlay control's the esc button
        closeOnEsc: false
      });
      
      // initialize expose api
      var ex = overlay.expose(conf.expose);
      
      ex.onBeforeClose(function(e) {
        self.close(e);    
      });
      
      self.onClose(function(e) {
        ex.close(e);    
      });
    }   
    
    // close button
    closers = overlay.find(conf.close || ".close");   
    
    if (!closers.length && !conf.close) {
      closers = $('<div class="close"></div>');
      overlay.prepend(closers); 
    }   
    
    closers.click(function(e) { 
      self.close(e);  
    });         
  }
  
  // jQuery plugin initialization
  $.fn.overlay = function(conf) {   
    
    // already constructed --> return API
    var el = this.eq(typeof conf == 'number' ? conf : 0).data("overlay");
    if (el) { return el; }         
    
    if ($.isFunction(conf)) {
      conf = {onBeforeLoad: conf};  
    }
    
    var globals = $.extend({}, $.tools.overlay.conf); 
    conf = $.extend(true, globals, conf);
    
    this.each(function() {    
      el = new Overlay($(this), conf);
      instances.push(el);
      $(this).data("overlay", el);  
    });
    
    return conf.api ? el: this;   
  }; 
  
})(jQuery);

/**
 * Overlay Gallery plugin, version: 1.0.0
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html#gallery
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Since  : July 2009
 * Date: ${date}
 * Revision: ${revision} 
 */
(function($) { 
  var first = true;   
  // TODO: next(), prev(), getIndex(), onChange event
  
  // version number
  var t = $.tools.overlay; 
  t.plugins = t.plugins || {};
  
  t.plugins.gallery = {
    version: '1.0.0', 
    conf: { 
      imgId: 'img',
      next: '.next',
      prev: '.prev',
      info: '.info',
      progress: '.progress',
      disabledClass: 'disabled',
      activeClass: 'active',
      opacity: 0.8,
      speed: 'slow',
      templateSingle: '<strong>${title}</strong>',
      template: '<strong>${title}</strong> <span>Image ${index} of ${total}</span>',  
      autohide: true,
      preload: true,
      api: false,
      single: false
    }
  };      
  
  $.fn.gallery = function(opts) {
    
    var conf = $.extend({}, t.plugins.gallery.conf), api;
    $.extend(conf, opts);     

    // common variables for all gallery images
    api = this.overlay();
    
    var links = this,
       overlay = api.getOverlay(),
       next = overlay.find(conf.next),
       prev = overlay.find(conf.prev),
       info = conf.info ? overlay.find(conf.info) : null,
       progress = overlay.find(conf.progress),       
       close = api.getClosers(),       
       els = null, index;
    if (info) {   
      els = prev.add(next).add(info).css({opacity: conf.opacity});
    } else {
      els = prev.add(next).css({opacity: conf.opacity});
    }
    
       
    if (conf.single) {
      next.remove();
      prev.remove();
    }
    
    
//{{{ load 

    function load(el) {
      progress.fadeIn();
      els.hide(); close.hide();
      
      var url = el.attr("href"); 
      
      // download the image 
      var image = new Image();
      
      image.onload = function() {
        image.onload = null;
        image.onerror = null;
        
        progress.fadeOut();
        
        // find image inside overlay
        var img = $("#" + conf.imgId, overlay); 
        
        // or append it to the overlay 
        if (!img.length) { 
          img = $("<img/>").attr("id", conf.imgId).css("visibility", "hidden");
          overlay.prepend(img);
        }
        
        // make initially invisible to get it's dimensions
        img.attr("src", url).css("display", "none");
        img.removeAttr('width');
        img.removeAttr('height');
        // Resizing large images - orginal by Christian Montoya edited by me.
        var pagesize = getPageSize();
        var x = pagesize[0] - 90;
        var y = pagesize[1] - 90;
        var width = image.width;
        var height = image.height;       
        
        if (width > x) {
          height = height * (x / width); 
          width = x; 
          if (height > y) { 
            width = width * (y / height); 
            height = y; 
          }
        } else if (height > y) { 
          width = width * (y / height); 
          height = y; 
          if (width > x) { 
            height = height * (x / width); 
            width = x;
          }
        }

        img.attr('width', width);
        img.attr('height', height);
        
        // End Resizing
        
        // animate overlay to fit the image dimensions
//        var width = image.width;
        var left = ($(window).width() - width) / 2;
          
        // calculate index number
        index = links.index(links.filter("[href=" +url+ "]"));  
        
        // activate trigger
        links.removeClass(conf.activeClass).eq(index).addClass(conf.activeClass);
        
        // enable/disable next/prev links
        var cls = conf.disabledClass;
        els.removeClass(cls);

        if (index === 0) { prev.addClass(cls); }
        if (index == links.length -1) { next.addClass(cls); }
        
        // set info text & width
        var text = conf.single ? conf.templateSingle : conf.template;
        
        text = text
          .replace("${title}", el.attr("title") || el.data("title"))
          .replace("${index}", index + 1)
          .replace("${total}", links.length);
                 
        if (info) {
          var padd = parseInt(info.css("paddingLeft"), 10) +  parseInt(info.css("paddingRight"), 10);
          info.html(text).css({width: width - padd});
        }
        
        setTimeout(function() {
          overlay.animate({'width': width, 'height': height, 'left': left}, conf.speed, function() {
            // gradually show the image
            img.hide().css("visibility", "visible").fadeIn(function() {           
              if (!conf.autohide) { 
                els.show(); close.show(); 
              }                           
            });               
          });
        }, 10)
      };
      
      image.onerror = function() {
        overlay.fadeIn().html("Cannot find image " + url); 
      };
      
      image.src = url;
      
      if (conf.preload) {
        links.filter(":eq(" +(index-1)+ "), :eq(" +(index+1)+ ")").each(function()  {
          var img = new Image();
          img.src = $(this).attr("href");         
        });
      }
      
    }
    
//}}}
    
    function getPageSize(){
      var de = document.documentElement;
      var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
      var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
      arrayPageSize = [w,h];
      return arrayPageSize;
    }


    // function to add click handlers to next/prev links   
    function addClick(el, isNext)  {
      
      el.click(function() {
          
        if (el.hasClass(conf.disabledClass)) { return; }        
        
        // find the triggering link
        var trigger = links.eq(i = index + (isNext ? 1 : -1));      
           
        // if found load it's href
        if (trigger.length) { load(trigger); }
        
      });       
    }

    // assign next/prev click handlers
    addClick(next, true);
    addClick(prev);

    
    // arrow keys
    $(document).keydown(function(evt) {
        
      if (!overlay.is(":visible") || evt.altKey || evt.ctrlKey) { return; }
      
      if (evt.keyCode == 37 || evt.keyCode == 39) {         
        var btn = evt.keyCode == 37 ? prev : next;
        btn.click();
        return evt.preventDefault();
      } 
      return true;      
    });   
    
    function showEls() {
      if (!overlay.is(":animated")) {
        
        if (!prev.hasClass(conf.disabledClass)) {         
          prev.show().css("visibility", "visible");
        }
        if (!next.hasClass(conf.disabledClass)) {
          next.show().css("visibility", "visible");;
        }
        if (info) {
          info.show().css("visibility", "visible");
        }
        close.show().css("visibility", "visible");
        
      } 
    }
    
    // autohide functionality
    if (conf.autohide) { 
      overlay.hover(showEls, function() { els.hide();  close.hide(); els.css("visibility", "hidden"); close.css("visibility", "hidden") }).mousemove(showEls);
    }   
    
    // load a proper gallery image when overlay trigger is clicked
    var ret;
    
    this.each(function() {
        
      var el = $(this), api = $(this).overlay(), ret = api;
      
      api.onBeforeLoad(function() {
        load(el);
      });
      
      api.onClose(function() {
        links.removeClass(conf.activeClass);        
      });     
    });     
    
    return conf.api ? ret : this;
    
  };
  
})(jQuery);

/**
 * tools.overlay "Apple Effect" 1.0.1
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html#apple
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Since  : July 2009
 * Date: ${date}
 * Revision: ${revision} 
 */
(function($) { 

  // version number
  var t = $.tools.overlay;
  t.effects = t.effects || {};
  t.effects.apple = {version: '1.0.1'}; 
    
  // extend global configuragion with effect specific defaults
  $.extend(t.conf, { 
    start: { 
      absolute: true,
      top: null,
      left: null
    },
    
    fadeInSpeed: 'fast',
    zIndex: 9999
  });     
  
  // utility function
  function getPosition(el) {
    var p = el.offset();
    return [p.top + el.height() / 2, p.left + el.width() / 2]; 
  }
  
//{{{ load 

  var loadEffect = function(onLoad) {
    
    var overlay = this.getOverlay(),
       opts = this.getConf(),
       trigger = this.getTrigger(),
       self = this,
       oWidth = overlay.outerWidth({margin:true}),
       img = overlay.data("img");  
        
    // growing image is required.
    if (!img) { 
      var bg = overlay.css("backgroundImage");
      
      if (!bg) { 
        throw "background-image CSS property not set for overlay"; 
      }
      
      // url("bg.jpg") --> bg.jpg
      bg = bg.substring(bg.indexOf("(") + 1, bg.indexOf(")")).replace(/\"/g, "");
      overlay.css("backgroundImage", "none");
      
      img = $('<img src="' + bg + '"/>');
      img.css({border:0,position:'absolute',display:'none'}).width(oWidth);     
      $('body').append(img); 
      overlay.data("img", img);
    }
    
    // initial top & left
    var w = $(window),
       itop = opts.start.top || Math.round(w.height() / 2), 
       ileft = opts.start.left || Math.round(w.width() / 2);
    
    if (trigger) {
      var p = getPosition(trigger);
      itop = p[0];
      ileft = p[1];
    } 
    
    // adjust positioning relative toverlay scrolling position
    if (!opts.start.absolute) {
      itop += w.scrollTop();
      ileft += w.scrollLeft();
    }
    
    // initialize background image and make it visible
    img.css({
      top: itop, 
      left: ileft,
      width: 0,
      zIndex: opts.zIndex
    }).show();
    
    // begin growing
    img.animate({
      top: overlay.css("top"), 
      left: overlay.css("left"), 
      width: oWidth}, opts.speed, function() { 

      // set close button and content over the image
      overlay.css("zIndex", opts.zIndex + 1).fadeIn(opts.fadeInSpeed, function()  { 
        
        if (self.isOpened() && !$(this).index(overlay)) {          
          onLoad.call(); 
        } else {
          overlay.hide(); 
        } 
      });
    });
    
  };
//}}}
  
  
  var closeEffect = function(onClose) {

    // variables
    var overlay = this.getOverlay(), 
       opts = this.getConf(),
       trigger = this.getTrigger(),
       top = opts.start.top,
       left = opts.start.left;
    
    // hide overlay & closers
    overlay.hide();
    
    // trigger position
    if (trigger) {
      var p = getPosition(trigger);
      top = p[0];
      left = p[1];
    } 
    
    // shrink image   
    overlay.data("img").animate({top: top, left: left, width:0}, opts.closeSpeed, onClose); 
  };
  
  
  // add overlay effect 
  t.addEffect("apple", loadEffect, closeEffect); 
  
})(jQuery);
