/*
 *         developed by Matteo Bicocchi on JQuery
 *        © 2002-2009 Open Lab srl, Matteo Bicocchi
 *			    www.open-lab.com - info@open-lab.com
 *       	version 2.7.2
 *       	tested on: 	Explorer and FireFox for PC
 *                  		FireFox and Safari for Mac Os X
 *                  		FireFox for Linux
 *         MIT (MIT-LICENSE.txt) licenses.
 */
// to get the element that is fireing a contextMenu event you have $.mbMenu.lastContextMenuEl that returns an object.

(function($) {
  $.mbMenu = {
    actualMenuOpener:false,
    options: {
      template:"yourMenuVoiceTemplate",// the url that returns the menu voices via ajax. the data passed in the request is the "menu" attribute value as "menuId"
      additionalData:"",
      menuSelector:".menuContainer",
      menuWidth:150,
      openOnRight:false,
      containment:"window",
      iconPath:"ico/",
      hasImages:true,
      fadeInTime:100,
      fadeOutTime:200,
      menuTop:0,
      menuLeft:0,
      submenuTop:0,
      submenuLeft:4,
      opacity:1,
      shadow:false,
      shadowColor:"transparent",
      shadowOpacity:.2,
      openOnClick:true,
      closeOnMouseOut:false,
      closeAfter:500,
      minZindex:"auto", // or number
      hoverIntent:0, //if you use jquery.hoverIntent.js set this to time in milliseconds; 0= false;
      submenuHoverIntent:0, //if you use jquery.hoverIntent.js set this to time in milliseconds; 0= false;
      onContextualMenu:function(){} //it pass 'o' (the menu you clicked on) and 'e' (the event)
    },
    buildMenu : function (options){
      return this.each (function ()
      {
        var thisMenu =this;
        thisMenu.id = !this.id ? "menu_"+Math.floor (Math.random () * 1000): this.id;
        this.options = {};
        $.extend (this.options, $.mbMenu.options);
        $.extend (this.options, options);

        $(".menu").hide();
        thisMenu.clicked = false;
        thisMenu.rootMenu=false;
        thisMenu.clearClicked=false;
        thisMenu.actualOpenedMenu=false;
        thisMenu.menuvoice=false;
        var root=$(this);
        var openOnClick=this.options.openOnClick;
        var closeOnMouseOut=this.options.closeOnMouseOut;

        //build roots
        $(root).each(function(){

          /*
           *using metadata plugin you can add attribut writing them inside the class attr with a JSON sintax
           * for ex: class="rootVoice {menu:'menu_2'}"
           */
          if ($.metadata){
            $.metadata.setType("class");
            thisMenu.menuvoice=$(this).find(".rootVoice");
            $(thisMenu.menuvoice).each(function(){
              if ($(this).metadata().menu) $(this).attr("menu",$(this).metadata().menu);
            });
          }

          thisMenu.menuvoice=$(this).find("[menu]");

          $(thisMenu.menuvoice).each(function(){
            $(this).addClass("rootVoice");
            $(this).attr("nowrap","nowrap");
          });
          if(openOnClick){
            $(thisMenu.menuvoice).bind("click",function(){
              if (!$(this).attr("isOpen")){
                $(this).buildMbMenu(thisMenu,$(this).attr("menu"));
                $(this).attr("isOpen","true");
              }else{
                $(this).removeMbMenu(thisMenu,true);
                $(this).addClass("selected");
              }

              //empty
              if($(this).attr("menu")=="empty"){
                if(thisMenu.actualOpenedMenu){
                  $(thisMenu.actualOpenedMenu).removeClass("selected");
                  thisMenu.clicked=true;
                  $(this).removeAttr("isOpen");
                  clearTimeout(thisMenu.clearClicked);
                }
                //$(this).removeMbMenu(thisMenu);
              }
              return false;
            });
          }
          var mouseOver=$.browser.msie?"mouseenter":"mouseover";
          var mouseOut=$.browser.msie?"mouseleave":"mouseout";
          if (this.options.hoverIntent==0){
            $(thisMenu.menuvoice).bind(mouseOver,function(){
              if (closeOnMouseOut) clearTimeout($.mbMenu.deleteOnMouseOut);
              if (!openOnClick) $(thisMenu).find(".selected").removeClass("selected");
              if(thisMenu.actualOpenedMenu){ $(thisMenu.actualOpenedMenu).removeClass("selected");}
              $(this).addClass("selected");
              if((thisMenu.clicked || !openOnClick) && !$(this).attr("isOpen")){
                clearTimeout(thisMenu.clearClicked);
                $(this).buildMbMenu(thisMenu,$(this).attr("menu"));
                if ($(this).attr("menu")=="empty"){
                 // $(this).removeMbMenu(thisMenu);
                  $(this).removeAttr("isOpen");
                }
              }
            });
            $(thisMenu.menuvoice).bind(mouseOut,function(){
              if (closeOnMouseOut)
                $.mbMenu.deleteOnMouseOut= setTimeout(function(){$(this).removeMbMenu(thisMenu,true);},$(root)[0].options.closeAfter);
              if ($(this).attr("menu")=="empty"){
                $(this).removeClass("selected");
                thisMenu.clearClicked= setTimeout(function(){thisMenu.rootMenu=false;thisMenu.clicked=false;},$(root)[0].options.closeAfter);
              }
              if(!thisMenu.clicked)
                $(this).removeClass("selected");
              $(document).one("click",function(){
                 if ($(this).attr("menu")=="empty"){
                   clearTimeout(thisMenu.clearClicked);
                   return;
                 }
                $(this).removeClass("selected");
                $(this).removeMbMenu(thisMenu,true);
              });
            });
          }else{
            // HOVERHINTENT
            $(thisMenu.menuvoice).hoverIntent({
              over:function(){
                if (closeOnMouseOut) clearTimeout($.mbMenu.deleteOnMouseOut);
                if (!openOnClick) $(thisMenu).find(".selected").removeClass("selected");
                if(thisMenu.actualOpenedMenu){ $(thisMenu.actualOpenedMenu).removeClass("selected");}
                $(this).addClass("selected");
                if((thisMenu.clicked || !openOnClick)  && !$(this).attr("isOpen")){
                  clearTimeout(thisMenu.clearClicked);
                  $(this).buildMbMenu(thisMenu,$(this).attr("menu"));
                  if ($(this).attr("menu")=="empty"){
                    $(this).removeMbMenu(thisMenu);
                    $(this).removeAttr("isOpen");
                  }
                }
              },
              sensitivity: 30,
              interval: this.options.hoverIntent,
              timeout: 0,
              out:function(){
                if (closeOnMouseOut)
                  $.mbMenu.deleteOnMouseOut= setTimeout(function(){$(this).removeMbMenu(thisMenu,true);},$(root)[0].options.closeAfter);
                if ($(this).attr("menu")=="empty"){
                  $(this).removeClass("selected");
                  thisMenu.clearClicked= setTimeout(function(){thisMenu.rootMenu=false;thisMenu.clicked=false;},$(root)[0].options.closeAfter);
                }
                if(!thisMenu.clicked)
                  $(this).removeClass("selected");
                $(document).one("click",function(){
                  if ($(this).attr("menu")=="empty"){
                    clearTimeout(thisMenu.clearClicked);
                    return;
                  }
                  $(this).removeClass("selected");
                  $(this).removeMbMenu(thisMenu,true);
                });
              }
            });
          }

        });
      });
    },
    buildContextualMenu :  function (options){
      return this.each (function ()
      {
        var thisMenu = this;
        thisMenu.options = {};
        $.extend (thisMenu.options, $.mbMenu.options);
        $.extend (thisMenu.options, options);
        $(".mbmenu").hide();
        thisMenu.clicked = false;
        thisMenu.rootMenu=false;
        thisMenu.clearClicked=false;
        thisMenu.actualOpenedMenu=false;
        thisMenu.menuvoice=false;

        /*
         *using metadata plugin you can add attribut writing them inside the class attr with a JSON sintax
         * for ex: class="rootVoice {menu:'menu_2'}"
         */
        var cMenuEls;
        if ($.metadata){
          $.metadata.setType("class");
          cMenuEls= $(this).find(".cmVoice");
          $(cMenuEls).each(function(){
            if ($(this).metadata().cMenu) $(this).attr("cMenu",$(this).metadata().cMenu);
          });
        }
        cMenuEls= $(this).find("[cMenu]");

        $(cMenuEls).each(function(){
          $(this).css("-khtml-user-select","none");
          var cm=this;
          cm.id = !cm.id ? "menu_"+Math.floor (Math.random () * 100): cm.id;
          $(cm).css({cursor:"default"});
          $(cm).bind("contextmenu","mousedown",function(event){
            event.preventDefault();
            event.stopPropagation();
            event.cancelBubble=true;

            $.mbMenu.lastContextMenuEl=cm;

            if ($.mbMenu.options.actualMenuOpener) {
              $(thisMenu).removeMbMenu($.mbMenu.options.actualMenuOpener);
            }
            /*add custom behavior to contextMenuEvent passing the el and the event
             *you can for example store to global var the obj that is fireing the event
             *mbActualContextualMenuObj=cm;
             *
             * you can for example create a function that manipulate the voices of the menu
             * you are opening according to a certain condition...
             */

            thisMenu.options.onContextualMenu(this,event);

            $(this).buildMbMenu(thisMenu,$(this).attr("cMenu"),"cm",event);
            $(this).attr("isOpen","true");

          });
        });
      });
    }
  };
  $.fn.extend({
    buildMbMenu: function(op,m,type,e){
      var msie6=$.browser.msie && $.browser.version=="6.0";
      var mouseOver=$.browser.msie?"mouseenter":"mouseover";
      var mouseOut=$.browser.msie?"mouseleave":"mouseout";
      if (e) {
        this.mouseX=$(this).getMouseX(e);
        this.mouseY=$(this).getMouseY(e);
      }

      if ($.mbMenu.options.actualMenuOpener && $.mbMenu.options.actualMenuOpener!=op)
        $(op).removeMbMenu($.mbMenu.options.actualMenuOpener);
      $.mbMenu.options.actualMenuOpener=op;
      if(!type || type=="cm")	{
        if (op.rootMenu) {
          $(op.rootMenu).removeMbMenu(op);
          $(op.actualOpenedMenu).removeAttr("isOpen");
        }
        op.clicked=true;
        op.actualOpenedMenu=this;
        $(op.actualOpenedMenu).attr("isOpen","true");
        $(op.actualOpenedMenu).addClass("selected");
      }
      var opener=this;
      var where=(!type|| type=="cm")?$(document.body):$(this).parent().parent();

      //empty
      if($(this).attr("menu")=="empty"){
        return;
      }

      var menuClass= op.options.menuSelector.replace(".","");
      where.append("<div class='menuDiv'><div class='"+menuClass+"' style='display:table'></div></div>");
      this.menu  = where.find(".menuDiv");
      $(this.menu).css({width:0, height:0});
      if (op.options.minZindex!="auto"){
        $(this.menu).css({zIndex:op.options.minZindex++});
      }else{
        $(this.menu).mb_BringToFront();
      }
      this.menuContainer  = $(this.menu).find(op.options.menuSelector);
      $(this.menuContainer).bind(mouseOver,function(){
        $(opener).addClass("selected");
      });
      $(this.menuContainer).css({
        position:"absolute",
        opacity:op.options.opacity
      });
      if (!$("#"+m).html()){
        $.ajax({
          type: "POST",
          url: op.options.template,
          cache: false,
          async: false,
          data:"menuId="+m+(op.options.additionalData!=""?"&"+op.options.additionalData:""),
          success: function(html){
            $("body").append(html);
            $("#"+m).hide();
          }
        });
      }
      $(this.menuContainer).hide();
      this.voices= $("#"+m).find("a").clone();


      if (op.options.shadow) {
        var shadow = $("<div class='menuShadow'></div>").hide();
        if(msie6)
          shadow = $("<iframe class='menuShadow'></iframe>").hide();
      }

      /*
       *using metadata plugin you can add attribut writing them inside the class attr with a JSON sintax
       * for ex: class="rootVoice {menu:'menu_2'}"
       */
      if ($.metadata){
        $.metadata.setType("class");
        $(this.voices).each(function(){
          if ($(this).metadata().disabled) $(this).attr("disabled",$(this).metadata().disabled);
          if ($(this).metadata().img) $(this).attr("img",$(this).metadata().img);
          if ($(this).metadata().menu) $(this).attr("menu",$(this).metadata().menu);
          if ($(this).metadata().action) $(this).attr("action",$(this).metadata().action);
          if ($(this).metadata().disabled) $(this).attr("disabled",$(this).metadata().disabled);
        });
      }

      // build each voices of the menu
      $(this.voices).each(function(i){

        var voice=this;
        var imgPlace="";
        var isText=$(voice).attr("rel")=="text";
        var isTitle=$(voice).attr("rel")=="title";
        var isDisabled=$(voice).is("[disabled]");
        var isSeparator=$(voice).attr("rel")=="separator";

        if (op.options.hasImages && !isText){

          var imgPath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif";
          imgPath=(imgPath.length>3 && imgPath.indexOf(".")>-1)?"<img class='imgLine' src='"+op.options.iconPath+imgPath+"'>":imgPath;
          imgPlace="<td class='img'>"+imgPath+"</td>";
        }
        var line="<table id='"+m+"_"+i+"' class='line"+(isTitle?" title":"")+"' cellspacing='0' cellpadding='0' border='0' style='width:100%; display:table' width='100%'><tr>"+imgPlace+"<td class='voice' nowrap></td></tr></table>";
        if(isSeparator)
          line="<div class='separator' style='width:100%; display:inline-block'><img src='"+op.options.iconPath+"blank.gif' width='1' height='1'></div>";
        if(isText)
          line="<div style='width:100%; display:table' class='line' id='"+m+"_"+i+"'><div class='voice'></div></div>";

        $(opener.menuContainer).append(line);

        if(!isSeparator){
          $(opener.menuContainer).find("#"+m+"_"+i).find(".voice").append(this);
          if($(this).attr("menu")){
            $(opener.menuContainer).find("#"+m+"_"+i).find(".voice a").wrap("<div class='menuArrow'></div>");
            $(opener.menuContainer).find("#"+m+"_"+i).find(".menuArrow").addClass("subMenuOpener");
            $(opener.menuContainer).find("#"+m+"_"+i).css({cursor:"default"});
            this.isOpener=true;
          }
          if(isText){
            $(opener.menuContainer).find("#"+m+"_"+i).find(".voice").addClass("textBox");
            this.isOpener=true;
          }
          if(isDisabled){
            $(opener.menuContainer).find("#"+m+"_"+i)
                    .addClass("disabled")
                    .css({cursor:"default"});
          }

          if(!(isText || isTitle || isDisabled)){
            $(opener.menuContainer)
                    .find("#"+m+"_"+i)
                    .css({cursor:"pointer"});
            if (op.options.submenuHoverIntent==0){
              $(opener.menuContainer).find("#"+m+"_"+i)
                      .bind("mouseover",function(event){
                clearTimeout($.mbMenu.deleteOnMouseOut);
                $(this).addClass("selected");
                if(opener.menuContainer.actualSubmenu && !$(voice).attr("menu")){
                  $(opener.menu).find(".menuDiv").remove();
                  $(opener.menuContainer.actualSubmenu).removeClass("selected");
                  opener.menuContainer.actualSubmenu=false;
                  //return false;
                }
                if ($(voice).attr("menu")){

                  if(opener.menuContainer.actualSubmenu && opener.menuContainer.actualSubmenu!=this){
                    $(opener.menu).find(".menuDiv").remove();
                    $(opener.menuContainer.actualSubmenu).removeClass("selected");
                    opener.menuContainer.actualSubmenu=false;
                  }
                  if (!$(voice).attr("action")) $(opener.menuContainer).find("#"+m+"_"+i).css("cursor","default");
                  if (!opener.menuContainer.actualSubmenu || opener.menuContainer.actualSubmenu!=this){
                    $(opener.menu).find(".menuDiv").remove();

                    opener.menuContainer.actualSubmenu=false;
                    $(this).buildMbMenu(op,$(voice).attr("menu"),"sm",event);
                    opener.menuContainer.actualSubmenu=this;
                  }
                  $(this).attr("isOpen","true");
                  return false;
                }
              });
            }else{
              // HOVERHINTENT
              $(opener.menuContainer).find("#"+m+"_"+i)
                      .bind("mouseover",function(){
                clearTimeout($.mbMenu.deleteOnMouseOut);
                $(this).addClass("selected");
              });
              $(opener.menuContainer).find("#"+m+"_"+i).hoverIntent({
                over:function(event){
                  if(opener.menuContainer.actualSubmenu && !$(voice).attr("menu")){
                    $(opener.menu).find(".menuDiv").remove();
                    $(opener.menuContainer.actualSubmenu).removeClass("selected");
                    opener.menuContainer.actualSubmenu=false;
                  }
                  if ($(voice).attr("menu")){

                    if(opener.menuContainer.actualSubmenu && opener.menuContainer.actualSubmenu!=this){
                      $(opener.menu).find(".menuDiv").remove();
                      $(opener.menuContainer.actualSubmenu).removeClass("selected");
                      opener.menuContainer.actualSubmenu=false;
                    }
                    if (!$(voice).attr("action")) $(opener.menuContainer).find("#"+m+"_"+i).css("cursor","default");
                    if (!opener.menuContainer.actualSubmenu || opener.menuContainer.actualSubmenu!=this){
                      $(opener.menu).find(".menuDiv").remove();

                      opener.menuContainer.actualSubmenu=false;
                      $(this).buildMbMenu(op,$(voice).attr("menu"),"sm",event);
                      opener.menuContainer.actualSubmenu=this;
                    }
                    $(this).attr("isOpen","true");
                    return false;
                  }
                },
                out:function(){},
                sensitivity: 30,
                interval: op.options.submenuHoverIntent,
                timeout: 0
              });
            }

            $(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOut,function(){
              $(this).removeClass("selected");
            });
          }
          if(isDisabled || isTitle || isText){
            $(this).removeAttr("href");
            $(opener.menuContainer).find("#"+m+"_"+i).bind(mouseOver,function(){
              $(document).unbind("click");
              if (closeOnMouseOut) clearTimeout($.mbMenu.deleteOnMouseOut);
              if(opener.menuContainer.actualSubmenu){
                $(opener.menu).find(".menuDiv").remove();
                opener.menuContainer.actualSubmenu=false;
              }
            }).css("cursor","default");
          }
          $(opener.menuContainer).find("#"+m+"_"+i).bind("click",function(){
            if (($(voice).attr("action") || $(voice).attr("href")) && !isDisabled){
              var target=$(voice).attr("target")?$(voice).attr("target"):"_self";
              if ($(voice).attr("href") && $(voice).attr("href").indexOf("javascript:")>-1){
                $(voice).attr("action",$(voice).attr("href").replace("javascript:",""));
              }
              var link=$(voice).attr("action")?$(voice).attr("action"):"window.open('"+$(voice).attr("href")+"', '"+target+"')";
              if (!$(voice).attr("href") || ($(voice).attr("href") && $(voice).attr("href").indexOf("javascript:")>-1)){
                $(voice).removeAttr("href");
                eval(link);
              }
              $(this).removeMbMenu(op,true);
            }else if($(voice).attr("menu"))
              return false;
          });
        }
      });

      // Close on Mouseout

      var closeOnMouseOut=$(op)[0].options.closeOnMouseOut;
      if (closeOnMouseOut){
        $(opener.menuContainer).bind("mouseenter",function(){
          clearTimeout($.mbMenu.deleteOnMouseOut);
        });
        $(opener.menuContainer).bind("mouseleave",function(){
          var menuToRemove=$.mbMenu.options.actualMenuOpener;
          $.mbMenu.deleteOnMouseOut= setTimeout(function(){$(this).removeMbMenu(menuToRemove,true);},$(op)[0].options.closeAfter);
        });
      }

      //positioning opened
      var t=0,l=0;
      $(this.menuContainer).css({
        width:op.options.menuWidth
      });
      if ($.browser.msie) $(this.menuContainer).css("width",$(this.menuContainer).width()+2);


      switch(type){
        case "sm":
          t=$(this).position().top+op.options.submenuTop;

          l=$(this).position().left+$(this).width()-op.options.submenuLeft;
          break;
        case "cm":
          t=this.mouseY-5;
          l=this.mouseX-5;
          break;
        default:
          if (op.options.openOnRight){
            t=$(this).offset().top-($.browser.msie?2:0)+op.options.menuTop;
            l=$(this).offset().left+$(this).outerWidth()-op.options.menuLeft-($.browser.msie?2:0);
          }else{
            t=$(this).offset().top+$(this).outerHeight()-(!$.browser.mozilla?2:0)+op.options.menuTop;
            l=$(this).offset().left+op.options.menuLeft;
          }
          break;
      }

      $(this.menu).css({
        position:"absolute",
        top:t,
        left:l
      });

      if (!type || type=="cm") op.rootMenu=this.menu;
      $(this.menuContainer).bind(mouseOut,function(){
        $(document).one("click",function(){$(document).removeMbMenu(op,true);});
      });

      if (op.options.fadeInTime>0) $(this.menuContainer).fadeIn(op.options.fadeInTime);
      else $(this.menuContainer).show();

      if (op.options.shadow) {
        $(this.menu).prepend(shadow);
        shadow.css({
          width:$(this.menuContainer).outerWidth(),
          height:$(this.menuContainer).outerHeight()-1,
          position:'absolute',
          backgroundColor:op.options.shadowColor,
          border:0,
          opacity:op.options.shadowOpacity
        }).show();
      }
      var wh= (op.options.containment=="window")?$(window).height():$("#"+op.options.containment).offset().top+$("#"+op.options.containment).outerHeight();
      var ww=(op.options.containment=="window")?$(window).width():$("#"+op.options.containment).offset().left+$("#"+op.options.containment).outerWidth();

      var mh=$(this.menuContainer).outerHeight();
      var mw=shadow?shadow.outerWidth():$(this.menuContainer).outerWidth();

      var actualX=$(where.find(".menuDiv:first")).offset().left-$(window).scrollLeft();
      var actualY=$(where.find(".menuDiv:first")).offset().top-$(window).scrollTop();
      switch(type){
        case "sm":
          if ((actualX+mw)>= ww && mw<ww){
            l-=((op.options.menuWidth*2)-(op.options.submenuLeft*2));
          }
          break;
        case "cm":
          if ((actualX+(op.options.menuWidth*1.5))>= ww && mw<ww){
            l-=((op.options.menuWidth)-(op.options.submenuLeft));
          }
          break;
        default:
          if ((actualX+mw)>= ww && mw<ww){
            l-=($(this.menuContainer).offset().left+mw)-ww+1;
          }
          break;
      }
      if ((actualY+mh)>= wh-10 && mh<wh){
        t-=((actualY+mh)-wh)+10;
      }

      $(this.menu).css({
        top:t,
        left:l
      });
	  
	  // ADDED BY SAM SHEPEHRD - SAM@SHEPBOX.COM
	  quicktime_toggle('hide');
	  
    },
    removeMbMenu: function(op,fade){
      if(!op)op=$.mbMenu.options.actualMenuOpener;
      if (op.rootMenu) {
        $(op.actualOpenedMenu)
                .removeAttr("isOpen")
                .removeClass("selected");
        $(op.rootMenu)
                .css({width:1, height:1});
        if (fade) $(op.rootMenu).fadeOut(op.options.fadeOutTime,function(){$(this).remove();});
        else $(op.rootMenu).remove();
        op.rootMenu=false;
        op.clicked=false;
        $(document).unbind("click");
	  
		// ADDED BY SAM SHEPEHRD - SAM@SHEPBOX.COM
		quicktime_toggle('show');
      }
	  
    },

    //mouse  Position
    getMouseX : function (e){
      var mouseX;
      if ($.browser.msie)mouseX = e.clientX + document.documentElement.scrollLeft;
      else mouseX = e.pageX;
      if (mouseX < 0) mouseX = 0;
      return mouseX;
    },
    getMouseY : function (e){
      var mouseY;
      if ($.browser.msie)	mouseY = e.clientY + document.documentElement.scrollTop;
      else mouseY = e.pageY;
      if (mouseY < 0)	mouseY = 0;
      return mouseY;
    },
    //get max z-inedex of the page
    mb_BringToFront: function(){
      var zi=10;
      $('*').each(function() {
        if($(this).css("position")=="absolute"){
          var cur = parseInt($(this).css('zIndex'));
          zi = cur > zi ? parseInt($(this).css('zIndex')) : zi;
        }
      });

      $(this).css('zIndex',zi+=10);
    }

  });
  $.fn.buildMenu = $.mbMenu.buildMenu;
  $.fn.buildContextualMenu = $.mbMenu.buildContextualMenu;
})(jQuery);

/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J?örn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are four supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *   html5: Values are stored in data-* attributes.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @example <p id="one" class="some_class" data-item_id="1" data-item_label="Label">This is a p</p>
 * @before $.metadata.setType("html5")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a series of data-* attributes
 *
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
  metadata : {
    defaults : {
      type: 'class',
      name: 'metadata',
      cre: /({.*})/,
      single: 'metadata'
    },
    setType: function( type, name ){
      this.defaults.type = type;
      this.defaults.name = name;
    },
    get: function( elem, opts ){
      var settings = $.extend({},this.defaults,opts);
      // check for empty string in single property
      if ( !settings.single.length ) settings.single = 'metadata';
      
      var data = $.data(elem, settings.single);
      // returned cached data if it already exists
      if ( data ) return data;
      
      data = "{}";
      
      var getData = function(data) {
        if(typeof data != "string") return data;
        
        if( data.indexOf('{') < 0 ) {
          data = eval("(" + data + ")");
        }
      }
      
      var getObject = function(data) {
        if(typeof data != "string") return data;
        
        data = eval("(" + data + ")");
        return data;
      }
      
      if ( settings.type == "html5" ) {
        var object = {};
        $( elem.attributes ).each(function() {
          var name = this.nodeName;
          if(name.match(/^data-/)) name = name.replace(/^data-/, '');
          else return true;
          object[name] = getObject(this.nodeValue);
        });
      } else {
        if ( settings.type == "class" ) {
          var m = settings.cre.exec( elem.className );
          if ( m )
            data = m[1];
        } else if ( settings.type == "elem" ) {
          if( !elem.getElementsByTagName ) return;
          var e = elem.getElementsByTagName(settings.name);
          if ( e.length )
            data = $.trim(e[0].innerHTML);
        } else if ( elem.getAttribute != undefined ) {
          var attr = elem.getAttribute( settings.name );
          if ( attr )
            data = attr;
        }
        object = getObject(data.indexOf("{") < 0 ? "{" + data + "}" : data);
      }
      
      $.data( elem, settings.single, object );
      return object;
    }
  }
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
  return $.metadata.get( this[0], opts );
};

})(jQuery);

/*
 * 	 imBannerRotater - a JQuery Plugin
 * 	 @author Les Green
 * 	 Copyright (C) 2009 Intriguing Minds, Inc.
 *   Version 0.5
 * 
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.

 *   Demo and Documentation can be found at:   
 *   http://www.grasshopperpebbles.com
 *   
 */
 
;(function($) {
	$.fn.extend({
        imBannerRotater: function(options) { 
        	opts = $.extend({}, $.bannerRotater.defaults, options);
			return this.each(function() {
				new $.bannerRotater(this, opts);
			});
        }
    });	

$.bannerRotater = function(obj, opts)
{
	var $this = $(obj);
	var imgCnt = 0;
	var total_image_cnt = 0;
	var has_caption = false;
	if (opts.image_url)
	{
		var d = getDataString();
		doAjax('GET', opts.image_url, d, '', doCreate);
	}
	else
	{
		doCreate(opts.images);
	};
	
	function getDataString()
	{
		var str = '';
		$.each(opts.data, function(i, itm) {
			str += itm.name + "=" + itm.value + "&";							
		});
		//remove last "&"
		str = str.substr(0, (str.length-1));
		return str;
	};
	
	function doAjax(t, u, d, fnBefore, fnSuccess)
	{
		var dt = (opts.return_type == 'json') ? 'json' : 'text';
		$.ajax({
			type: t,
			url: u,
			data: d,
			dataType: dt,
			beforeSend: fnBefore, //function(){$("#loading").show("fast");}, //show loading just when link is clicked
			//complete: function(){ $("#loading").hide("fast");}, //stop showing loading when the process is complete
			success: fnSuccess,
			error: showError
	 	}); //close $.ajax(
	};
	
	function showError(XMLHttpRequest, textStatus, errorThrown)
	{
		console.log(textStatus);
	};
	
	function doCreate(data)
	{
		// LIST
		if (opts.return_type == 'list')
		{
			var data_array = data.split(',');
		}
		
		// JSON
		else
		{
			var data_array = data;
		}
		
		// RANDOM
		if (opts.mode == 'random')
		{
			var random_index = Math.floor(Math.random() * data_array.length);
			var random_array = data_array[random_index];
			outputMarkup(random_array);
		}
		
		// ROTATE
		else
		{
			// Loop through each image.
			$.each(data_array, function(i, item)
			{
				var show = (i == 0) ? true : false; 
				outputMarkup(item, show);
				total_image_cnt++;
			});
			
			imgCnt = 0;
			imgFadeIn();
		}
		// MODIFY HEIGHT
		if(has_caption)
		{
			$this.css('height', parseInt($this.css('height').replace('px', '')) + 20);
		}
	};
	
	function outputMarkup(data_array_row, show)
	{
		// DEFAULTS
		show = (show == undefined) ? true : show;
		
		// VARIABLES
		var $this_div = $(document.createElement('div'));
		var img = new Image();
		$this_div.addClass('container');
		
		// URL
		if(data_array_row[opts.data_map.url_name].length > 0)
		{
			// Populate Variables
			var url = data_array_row[opts.data_map.url_name];
			var url_target = (data_array_row[opts.data_map.url_target].length > 0) ? data_array_row[opts.data_map.url_target] : '_self';
			var img_url = opts.base_path + data_array_row[opts.data_map.image_name];
			var img_alt = (data_array_row[opts.data_map.caption].length > 0) ? data_array_row[opts.data_map.caption] : img_url;
			// INSERT HTML MARKUP
			$this_div.append(
				$('<a></a>').attr({'href': url, 'target': url_target})
					.append($(img).attr({ src: img_url, alt: img_alt}))
			);
		}
		
		// NO URL
		else
		{
			// Populate Variables
			var img_url = opts.base_path + data_array_row[opts.data_map.image_name];
			var img_alt = (data_array_row[opts.data_map.caption].length > 0) ? data_array_row[opts.data_map.caption] : img_url;
			// INSERT HTML MARKUP
			$this_div.append(
				$(img).attr({ src: img_url, alt: img_alt})
			);
		}
		
		// CAPTION
		if(opts.show_caption && data_array_row[opts.data_map.caption].length > 0)
		{
			has_caption = true;
			// INSERT HTML MARKUP
			$this_div.append('<div class="caption">' + data_array_row[opts.data_map.caption] + '</div>');
		}
		
		// SHOW
		if(!show)
		{
			$this_div.css('display', 'none');
		}
		
		// ADD TO CONTAINER
		$this.append($this_div);
		
		// Set Class and Deminsions
		$this.addClass('content_image');
	}
	
	function checkLoaded($this, $this_div, final_call)
	{
		var img_width = 0;
		var img_height = 0;
		img_width = $('img', $this_div).width();
		img_height = $('img', $this_div).height();
		if(img_width == 0 || img_height == 0)
		{
			setTimeout(function(){checkLoaded($this, $this_div, false)}, 100);
		} else {
			$this.css({width: img_width, height: img_height + 35});
			$this_div.css({width: img_width, height: img_height + 35});
			//setTimeout(function(){checkLoaded($this, $this_div, true)}, 1000);
		}
		if(final_call)
		{
			$this.css({width: img_width, height: img_height + 35});
			$this_div.css({width: img_width, height: img_height});
			
		}
	}
	
	function imgFadeIn()
	{
		$this.children().eq(imgCnt).fadeIn(opts.speed, function(){
			setTimeout(function(){imgFadeOut()}, opts.delay);
		});
	};
	
	function imgFadeOut() 
	{
		$this.children().eq(imgCnt).fadeOut(opts.speed);
		imgCnt = (imgCnt == (total_image_cnt - 1)) ? 0 : (imgCnt + 1);
		imgFadeIn();
	};
};

$.bannerRotater.defaults = {
	mode: 'random', //rotate
	image_url: '',
	data: '',
	images: '', //can be used instead of image_url. contains comma delimited list of images
	return_type: 'json', //list, json
	base_path: '',
	data_map: {caption: 'title', image_name: 'image_name', url_name: 'url_name', url_target: 'url_target'},
	speed: 1500,
	delay: 5000,
	show_caption: true
};
})(jQuery);		   
