text: /*
   * @author Ryan Johnson <http://syntacticx.com/>
   * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
   * @package LivePipe UI
   * @license MIT
   * @url http://livepipe.net/control/contextmenu
   * @require prototype.js, livepipe.js
   */
  
  /*global window, document, Prototype, Class, Event, $, $A, $R, Control, $value */
  
  if(typeof(Prototype) == "undefined") {
      throw "Control.ContextMenu requires Prototype to be loaded."; }
  if(typeof(Object.Event) == "undefined") {
      throw "Control.ContextMenu requires Object.Event to be loaded."; }
  
  Control.ContextMenu = Class.create({
      initialize: function(container,options){
          Control.ContextMenu.load();
          this.options = Object.extend({
              leftClick: false,
              disableOnShiftKey: true,
              disableOnAltKey: true,
              selectedClassName: 'selected',
              activatedClassName: 'activated',
              animation: true,
              animationCycles: 2,
              animationLength: 300,
              delayCallback: true
          },options || {});
          this.activated = false;
          this.items = this.options.items || [];
          this.container = $(container);
          this.container.observe(this.options.leftClick ? 'click' : (Prototype.Browser.Opera ? 'click' : 'contextmenu'),function(event){
              if(!Control.ContextMenu.enabled || Prototype.Browser.Opera && !event.ctrlKey) {
                  return; }
              this.open(event);
          }.bindAsEventListener(this));
      },
      open: function(event){
          if(Control.ContextMenu.current && !Control.ContextMenu.current.close()) {
              return; }
          if(this.notify('beforeOpen',event) === false) {
              return false; }
          this.buildMenu();
          if(this.items.length === 0){
              this.close(event);
              return false;
          }
          this.clicked = Event.element(event);
          Control.ContextMenu.current = this;
          Control.ContextMenu.positionContainer(event);
          Control.ContextMenu.container.show();
          if(this.notify('afterOpen',event) === false) {
              return false; }
          event.stop();
          return true;
      },
      close: function(event){
          if(event) {
              event.stop(); }
          if(this.notify('beforeClose') === false) {
              return false; }
          Control.ContextMenu.current = false;
          this.activated = false;
          Control.ContextMenu.container.removeClassName(this.options.activatedClassName);
          Control.ContextMenu.container.select('li').invoke('stopObserving');
          Control.ContextMenu.container.hide();
          Control.ContextMenu.container.update('');
          if(this.notify('afterClose') === false) {
              return false; }
          return true;
      },
      buildMenu: function(){
          var list = document.createElement('ul');
          Control.ContextMenu.container.appendChild(list);
          this.items.each(function(item){
              if(!(!item.condition || item.condition && item.condition() !== false)) {
                  return; }
              var item_container = $(document.createElement('li'));
              item_container.update($value(item.label));
              list.appendChild(item_container);
              item_container[$value(item.enabled) ? 'removeClassName' : 'addClassName']('disabled');
              item_container.observe('mousedown',function(event,item){
                  if(!$value(item.enabled)) {
                      return event.stop(); }
                  this.activated = $value(item.label);
              }.bindAsEventListener(this,item));
              item_container.observe('click',this.selectMenuItem.bindAsEventListener(this,item,item_container));
              item_container.observe('contextmenu',this.selectMenuItem.bindAsEventListener(this,item,item_container));
          }.bind(this));
      },
      addItem: function(params){
          if (!('enabled' in params)) { params.enabled = true; }
          this.items.push(params);
          return this;
      },
      destroy: function(){
          this.container.stopObserving(Prototype.Browser.Opera || this.options.leftClick ? 'click' : 'contextmenu');
          this.items = [];
      },
      selectMenuItem: function(event,item,item_container){
          if(!$value(item.enabled)) {
              return event.stop(); }
          if(!this.activated || this.activated == $value(item.label)){
              if(this.options.animation){
                  Control.ContextMenu.container.addClassName(this.options.activatedClassName);
                  $A($R(0,this.options.animationCycles * 2)).each(function(i){
                      window.setTimeout(function(){
                          item_container.toggleClassName(this.options.selectedClassName);
                      }.bind(this),i * parseInt(this.options.animationLength / (this.options.animationCycles * 2), 10));
                  }.bind(this));
                  window.setTimeout(function(){
                      if(this.close() && this.options.delayCallback) {
                          item.callback(this.clicked); }
                  }.bind(this),this.options.animationLength);
                  if(!this.options.delayCallback) {
                      item.callback(this.clicked); }
              }else if(this.close()) {
                  item.callback(this.clicked); }
          }
          event.stop();
          return false;
      }
  });
  Object.extend(Control.ContextMenu,{
      loaded: false,
      capture_all: false,
      menus: [],
      current: false,
      enabled: false,
      offset: 4,
      load: function(capture_all){
          if(Control.ContextMenu.loaded) {
              return; }
          Control.ContextMenu.loaded = true;
          if(typeof(capture_all) == 'undefined') {
              capture_all = false; }
          Control.ContextMenu.capture_all = capture_all;
          Control.ContextMenu.container = $(document.createElement('div'));
          Control.ContextMenu.container.id = 'control_contextmenu';
          Control.ContextMenu.container.style.position = 'absolute';
          Control.ContextMenu.container.style.zIndex = 99999;
          Control.ContextMenu.container.hide();
          document.body.appendChild(Control.ContextMenu.container);
          Control.ContextMenu.enable();
      },
      enable: function(){
          Control.ContextMenu.enabled = true;
          Event.observe(document.body,'click',Control.ContextMenu.onClick);
          if(Control.ContextMenu.capture_all) {
              Event.observe(document.body,'contextmenu',Control.ContextMenu.onContextMenu); }
      },
      disable: function(){
          Event.stopObserving(document.body,'click',Control.ContextMenu.onClick);
          if(Control.ContextMenu.capture_all) {
              Event.stopObserving(document.body,'contextmenu',Control.ContextMenu.onContextMenu);    }
      },
      onContextMenu: function(event){
          event.stop();
          return false;
      },
      onClick: function(){
          if(Control.ContextMenu.current) {
              Control.ContextMenu.current.close(); }
      },
      positionContainer: function(event){
          var dimensions = Control.ContextMenu.container.getDimensions();
          var top = Event.pointerY(event);
          var left = Event.pointerX(event);
          var bottom = dimensions.height + top;
          var right = dimensions.width + left;
          var viewport_dimensions = document.viewport.getDimensions();
          var viewport_scroll_offsets = document.viewport.getScrollOffsets();
          if(bottom > viewport_dimensions.height + viewport_scroll_offsets.top) {
              top -= bottom - ((viewport_dimensions.height  + viewport_scroll_offsets.top) - Control.ContextMenu.offset); }
          if(right > viewport_dimensions.width + viewport_scroll_offsets.left) {
              left -= right - ((viewport_dimensions.width + viewport_scroll_offsets.left) - Control.ContextMenu.offset); }
          Control.ContextMenu.container.setStyle({
              top: top + 'px',
              left: left + 'px'
          });
      }
  });
  Object.Event.extend(Control.ContextMenu);
  