﻿/**
 * DOM-related utilities which build on the YUI DOM module.
 */

WOL.util.Dom = {
   /**
    * Given an element and two class names, determines which class name the element
    * actually has and replaces it with the other. Throws an exception if neither
    * class name is present on the element, or if something is passed to it which is
    * not an <code>HTMLElement</code>.
    *
    * @param {HTMLElement|String} elem An element reference or string id of an element
    * @param {String} classA One of the two class names.
    * @param {String} classB The other class name.
    */
   toggleClass: function(elem, classA, classB) {
      if(typeof(elem) == 'string') {
         elem = document.getElementById(elem);
      };
      if(!elem ||
         (!Dom.hasClass(elem, classA) && !Dom.hasClass(elem, classB))) {
         var errMsg = 'Element ' + elem + ' has neither ' + classA + ' nor ' + classB + ' as a class name';
         throw new Error(errMsg);
      };
      var newClass = Dom.hasClass(elem, classA) ? classB : classA;
      var oldClass = (newClass == classA) ? classB : classA;
      Dom.replaceClass(elem, oldClass, newClass);
   },
   
   /**
    * Given an element, switches it to <code>display: none</code> if it currently has
    * <code>display: block</code>, and vice-versa.
    * @param {String|HTMLElement} elem The element, either its string <id> or the element
    * itself.
    */
   toggleDisplay: function(elem) {
      if(typeof(elem) == 'string') {
         elem = document.getElementById(elem);
      };
      var newDisplay = (Dom.getStyle(elem, 'display') == 'block') ? 'none' : 'block';
      Dom.setStyle(elem, 'display', newDisplay);
   },

   /**
    * Given a YUI AJAX response object, parses its <code>responseText</code> into a
    * JSON object and returns it.
    * @param {Response} o The response object.
    * @type Object
    */
   parseJSONResponse: function(o) {
      var json_obj = eval( '(' + o.responseText + ')' );
      return json_obj;
   }
};
/**
 * @class
 * <p>popupMenu handles menus which need to pop up and display lists of links
 * to other pages (for example, the search box needs to pop out with "advanced
 * search", etc.</p>
 *
 * <p>It expects a containing element of some sort, which has within it:</p>
 *
 * <ul>
 * <li>A link with <code>class</code> "menu", and its <code>href</code> pointing
 * to the <code>id</code> of the list representing the pop-up menu.</li>
 * <li>A <code>ul</code> whose <code>id</code> corresponds to the <code>href</code>
 * of the link which pops up the menu, and whose <code>li</code>s are the links in
 * the menu.</li>
 * </ul>
 *
 * @constructor
 * @param {String} id The <code>id</code> of the containing element.
 * @param {String} offClass A CSS class, assumed to be present on the menu
 * <code>ul</code> by default, which hides the menu.
 * @param {String} onClass A CSS class which, when set on the menu <code>ul</code>,
 * will make it visible.
 */
WOL.widget.popupMenu = function(id, offClass, onClass) {
   
   /**
    * The containing element.
    * @type HTMLElement
    */
   this.container = document.getElementById(id);
   
   /**
    * The link which shows/hides the menu.
    * @type HTMLAnchorElement
    */
   this.triggerLink = Dom.getElementsByClassName('menu-button', 'a', this.container)[0];
   
   /**
    * The <code>ul</code> representing the menu.
    * @type HTMLULElement
    */
   this.menu = document.getElementById(this.triggerLink.href.split('#')[1]);
   
   /**
    * The CSS class which will hide the menu.
    * @type String
    */
   this.offClass = offClass;
   
   /**
    * The CSS class which will show the menu.
    * @type String
    */
   this.onClass = onClass;
   
   Evt.addListener(this.triggerLink, 'click', this.toggleMenu, this);
   Evt.addListener(document.body, 'click', this.resetMenu, this);
};

/**
 * Toggles the display of the menu on or off.
 * @param {Event} e The mouse click triggering the toggle.
 * @param {String} instance The instance of popupMenu in use.
 */
WOL.widget.popupMenu.prototype.toggleMenu = function(e, instance) {
   Evt.preventDefault(e);
   WOL.util.Dom.toggleClass(instance.menu, instance.offClass, instance.onClass);
   WOL.util.Dom.toggleClass(instance.triggerLink, 'menu-button-on', 'menu-button');
};

/**
 * Hides the menu when a click registers anywhere other than in it or
 * on its triggering link.
 * @param {Event} e The mouse click triggering this.
 * @param {String} instance The instance of popupMenu in use.
 */
WOL.widget.popupMenu.prototype.resetMenu = function(e, instance) {
   var target = Evt.getTarget(e);
   if(target.nodeType == 3) {
      target = target.parentNode;
   };
   if(!Dom.isAncestor(instance.container, target)) {
      if(Dom.hasClass(instance.menu, instance.onClass)) {
         Dom.replaceClass(instance.menu, instance.onClass, instance.offClass);
      };
      if(Dom.hasClass(instance.triggerLink, 'menu-button-on')) {
         Dom.replaceClass(instance.triggerLink, 'menu-button-on', 'menu-button');
      };
   };
};