// ===========================================================================
var ContextMenu = Class.create();
Object.extend(ContextMenu, {
// ContextMenu provides an easy to use dynamic context menu for your page.
// It injects all the necessary HTML and CSS into your document to display the
// menu, so it's easy to use.  You just give the menu a name, an array of 
// items to display in the menu, and apply the menu name as a class to any
// element you want the menu to active on.
//
// IE is of course brain dead and minimum styling is applied.  Firefox looks 
// much nicer.
//
// Any HTML should work fine in the menu items.  In Firefox the CSS will
// style <A\> tags to look like a regular context menu item in Windows.
//
// Overload the ContextMenu.prototype.modifyMenu() method to make it into a 
// dynamic menu.  You can also overload the ContextMenu.menu_style 
// attribute, or ContextMenu.menu_style_css() method to apply your own style. 
//
// Example: Simple static menu
//
//     <script type="text/javascript"\>
//     new ContextMenu('context_menu',
//        new Array(
//           "My context menu",
//           "<hr/\>",
//           "<a href=\"http://yahoo.com\"\>yahoo</a\>",
//           "<a href=\"http://prototypejs.org\"\>prototype</a\>"
//        )
//     );
//     </script\>
//     <div id="my_div" class="context_menu"\>Right click on me</div\>
//
// Example: Dynamic menu
//
//     <script type="text/javascript"\>
//     Object.extend(
//        new ContextMenu('dynamic_menu',
//           new Array(
//              "item_menu for ___replace___",
//              "<a href=\"http://prototypejs.org\"\>prototype</a\>"
//           )
//        ),
//        {
//           modifyMenu: function(context) {
//              // You can really put anything in here, AJAX if you want.
//              ContextMenu.gsub(/___replace___/,context.id);
//           }
//        }
//     );
//     </script\>
//     <div id="your_div" class="dynamic_menu"\>Right click on me</div\>
// ===========================================================================

   // ========================================================================
   // ContextMenu static class methods and attributes
   // ========================================================================
   context_menu_div: null,  // after init holds ref to menu div, so the DOM doesn't have to be search repeatedly
   menus:            new Array(), // staticly shared list of all menus in use on this page    
   menu_style:       'background-color:#cccccc; border-style:solid; border-color:#808080; border-width:1px; padding:2px; font-family:sans-serif; font-size:14px; z-index: 1000',
   menu_style_css:   function() {  // this is only a function so the reference to ContextMenu.menu_style works 
      // This is css that is ignored by brain dead IE.
      // menu_style is applied via an IE hack to make sure a minimal amount of styling occurs in IE.
      return '<style type="text/css">' +
             '#__context_menu {' + ContextMenu.menu_style + '}' +
             '#__context_menu * {cursor:default;}' +
             '#__context_menu > * {display:block; padding:2px 20px;}' +
             '#__context_menu > div {font-style:italic;}' +
             '#__context_menu > hr {padding:0px;}' +
             '#__context_menu > a {text-decoration:none; color:black;}' +
             '#__context_menu > a:hover {background-color:#0A246A; color:white;}' +
             '</style>';
   },

   // ----------------------------------------------------
   gsub: function (pattern, replacement) {
   // Convienience method to perform gsub on the menu div.
   // Useful in extensions to modifyMenu()
   // ----------------------------------------------------
      ContextMenu.context_menu_div.innerHTML = ContextMenu.context_menu_div.innerHTML.gsub(pattern,replacement);
   },
   
   // --------------------------------------------------------------------------------
   onContextMenu: function(event) {
   // Handler that calls each menu object in menus array, seeing if one of those menus 
   // is going to handle the oncontextmenu event. The first one to handle it wins. 
   // Nested elements using unique menus be ware.
   //
   // This is registered as a global handler that reissues to all known menus, because
   // having each menu register it's own handler would cause them to clobber each
   // other because they share a common div for displaying their menus, and
   // oncontextmenu is a fussy thing.
   // --------------------------------------------------------------------------------
      var ret = true;
      if (ContextMenu.context_menu_div.visible()) {
         // onMouseDownOrClick happens first, so a click outside the menu is already handled there.
         // if the menu is still visible here, the onContextMenu happened inside the menu, just ignore it.
         ret = false;
      } else {
         // loop until a menu catches and handles the event, then break.
         // Or none catch, return true, and let the browser handle it.
         ContextMenu.menus.each(function(m) {
            ret = m.showContextMenu(event);  // returning false means it handled it.
            if (ret == false) {
               throw $break;
            }
         });
      }
      return ret;
   },
   
   // ----------------------------------------------------
   onMouseDownOrClick: function(event) {
   // This handler hides the menu on the appropriate click
   // ----------------------------------------------------
      var element = Event.element(event);
      if (ContextMenu.context_menu_div.visible()) {
         if ((!Position.within(ContextMenu.context_menu_div, Event.pointerX(event), Event.pointerY(event))) ||
            (event.type == 'click' && element.tagName == 'A')) {
            ContextMenu.context_menu_div.hide();
         }
      }
   },
   

   // ========================================================================
   // ContextMenu instance methods and attributes
   // ========================================================================
   prototype: {

      // ------------------------------------------
      initialize: function(menu_name, menu_items) {
      // ------------------------------------------
         this.menu_name  = menu_name;
         this.menu_items = menu_items;
         for (var idx = 0; idx < menu_items.size(); idx++) {
            // If the menu_item is not an <A> or <HR> item, wrap it inside a DIV tag
            // HACK: For IE wrap everything in a DIV, because it can't properly convert tags to block style via CSS.
            if (Prototype.Browser.IE || (this.menu_items[idx].search(/^ *<[a].+<\/[a]> *$|^ *<hr\/?> *$/i) == -1)) {
               this.menu_items[idx] = '<div>' + this.menu_items[idx] + '</div>';
            }
         }
         if (ContextMenu.menus.size() == 0) {  // do initialization of static class members if this is the first menu
            // This code references elements in the DOM that must be loaded before being referenced,
            // so it is wrapped inside an event handler tied to window 'load'.
            Event.observe(window, 'load', function() {
               // HACK: IE is brain dead and ignores the style sheet injected.  So for IE we insert a minimal amount
               //       of inline CSS, so it doesn't look completely awful.
               // display:none must be done inline or javascript can't override the CSS on the div for some reason.
               if (Prototype.Browser.IE) {
                  new Insertion.Top(document.body, ContextMenu.menu_style_css() + '<div id="__context_menu" style="display:none; position:absolute; z-index:1000; width:250px;' + ContextMenu.menu_style + '"> text replaced by showContextMenu </div>');
               } else {
                  new Insertion.Top(document.body, ContextMenu.menu_style_css() + '<div id="__context_menu" style="display:none; position:absolute; z-index:1000;"> text replaced by showContextMenu </div>');
               }
               ContextMenu.context_menu_div = $('__context_menu'); // cache the reference
               // register event handlers
               document.body.oncontextmenu  = ContextMenu.onContextMenu.bindAsEventListener();
               Event.observe(document, 'mousedown', ContextMenu.onMouseDownOrClick.bindAsEventListener());
               Event.observe(document, 'click', ContextMenu.onMouseDownOrClick.bindAsEventListener());
            });
         }
         ContextMenu.menus.push(this);  // add to static class list of menus, used by onContextMenu event handler
      },
      
      // -------------------------------------------------------------------
      contextElement: function(event) {
      // Returns the nearest element searching up the DOM that has the class
      // of the menu name.  Returns undefined if no objects matched  
      // -------------------------------------------------------------------
         var element = Event.element(event);
         if (!element.hasClassName(this.menu_name)) {
            element = element.up('.' + this.menu_name);
         }
         return element;
      },
      
      // --------------------------------------------------------------------
      modifyMenu: function(element) {
      // Extensions can put code here to manipulate the contents of the menu
      // to make it dynamic rather than static.
      // element: is the element in the DOM that this menu is being displayed
      //          for.  It is not necessarily the element that was clicked on
      //          (as could be in the case of nested elements).
      // -------------------------------------------------------------------
      },
      
      // -------------------------------------------------------------------
      showContextMenu: function(event) {
      // Called by the onContextMenu event handler.  If this menu is
      // to be displayed it does the following:
      //   Fills the menu div with the menu_items.
      //   Calls modifyMenu, to allow dynamic modifications
      //   Positions the menu and makes it visible
      // Returns false if it display the menu, true if it does not
      // -------------------------------------------------------------------
         var element = this.contextElement(event);
         if (!element) { return true; } // event not generated from inside an element associated with this menu.
         ContextMenu.context_menu_div.innerHTML = this.menu_items.join('');      
         this.modifyMenu(element);
         ContextMenu.context_menu_div.style.left = Event.pointerX(event) + 'px';
         ContextMenu.context_menu_div.style.top  = Event.pointerY(event) + 'px';
         ContextMenu.context_menu_div.show();
         return false;
      }
   }
});
Object.extend(
   new ContextMenu('item_menu',
      new Array(
         "This image is copyrighted by Fantography.net."
      )
   ),
   {
      modifyMenu: function(context) {
         ContextMenu.gsub(/___replace___/,context.id);
      }
   }
);

/*
document.observe( 'click', function( event )
{
	var elem = event.element();
	if ( elem.match( 'img' ) )
	{
		if(event.isRightClick(event))
		{
			
		}
	}
});
*/