/**
 * EdgeOnCollege Javascript functions and classes.
 *
 * @author Derek Lei
 *
 * Copyright 2009, EdgeOnCollege, Inc.
 *
 */

/**
 * EOC utility functions.
 */
function showEl(id) {
  Effect.Appear(id, {duration: 0.1});
}

function hideEl(id) {
  Effect.Fade(id, {duration: 0.1});
}

function toggleHideShow(id) {
  var el = $(id);
  (el.style.display == 'none') ? el.appear() : el.hide();
}

/**
 * Extends Prototype/Scriptaculous libraries
 */
/* Shows an element */
Effect.BlindRight = function(element) {
  element = $(element);
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    duration: 0.5,
    scaleContent: false,
    scaleY: false,
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makeClipping().setStyle({
        width: '0px',
        height: effect.dims[0] + 'px'
      }).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping();
    }
  }, arguments[1] || { }));
};

/* Hides an element */
Effect.BlindLeft = function(element) {
  element = $(element);
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 0, Object.extend({
    duration: 0.5,
    scaleContent: false,
    scaleY: false,
    scaleMode: 'box',
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makeClipping().setStyle({
        height: effect.dims[0] + 'px'
      }).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping();
    }
  }, arguments[1] || { }));
};

/**
 * EOC Classes.
 */
var eoc = {};

/**
 * Constructor for all dropdown menus on an EdgeOnCollege page.
 *
 * @param {Array} submenuIds Set of all the submenu ids prefix to attach
 *   actions to. Prefix plus '-control' forms the id for the element that
 *   makes submenu drop down.
 */
eoc.DropDown = function(menuIds) {
  this.menuIds_ = menuIds;
  this.menus_ = [];
  for (var i=0,menu=''; menu=menuIds[i]; i++) {
    this.menus_[i] = new eoc.DropDown.Menu(menu);
  }
};

eoc.DropDown.DEBUG = false;

/**
 * Constructor for a menu control for the drop down.
 * Assumes menu controller to have targetId + '-control' as element id.
 *
 * @param {String} targetId Menu container's element id.
 */
eoc.DropDown.Menu = function(targetId) {
  this.targetId_ = targetId;
  this.controllerId_ = targetId + '-control';
  $(this.controllerId_).observe('mouseover',
      this.controlMouseOverHandler_.bind(this));
  $(this.controllerId_).observe('mouseout',
      this.controlMouseOutHandler_.bind(this));
  $(this.targetId_).observe('mouseover',
      this.controlMouseOverHandler_.bind(this));
  $(this.targetId_).observe('mouseout',
      this.controlMouseOutHandler_.bind(this));
  if (eoc.DropDown.DEBUG) {
   console.log('setup event listeners done'); 
  }
};

/**
 * Handler for menu control mouseover.
 * @private
 */
eoc.DropDown.Menu.prototype.controlMouseOverHandler_ = function() {
  if (eoc.DropDown.DEBUG) {
    console.log('mouseover handler ' + this.targetId_);
  }
  this.showMenu();
};

/**
 * Handler for menu control mouseout.
 * @private
 */
eoc.DropDown.Menu.prototype.controlMouseOutHandler_ = function() {
  if (eoc.DropDown.DEBUG) {
    console.log('mouseout handler ' + this.targetId_);
  }
  this.hideMenu();
};

/**
 * Shows submenu for a dropdown menu.
 */
eoc.DropDown.Menu.prototype.showMenu = function() {
  if (this.timer_) {
    clearTimeout(this.timer_);
  }
  showEl(this.targetId_);
};

/**
 * Hides submenu for a dropdown menu.
 */
eoc.DropDown.Menu.prototype.hideMenu = function() {
  var execute = function() {
    hideEl(this.targetId_);
  }.bind(this);
  this.timer_ = setTimeout(execute, 200);
};

/**
 * Function to be called <body> onload.
 * @param {Array} dropdowns Ids of dropdown menus to initiate.
 */
eoc.initOnLoad = function (dropdowns) {
  eoc.DropDown(dropdowns);
};

/**
 * Third party DialogBox class, slightly modified for EOC use.
 * Found on http://snippets.dzone.com/posts/show/3411
 */
eoc.DialogBox = Class.create();
Object.extend(eoc.DialogBox.prototype, {
   initialize: function(id) {
     this.createOverlay();
     this.dialog_box = $(id);
     this.dialog_box.show = this.show.bind(this);
     this.dialog_box.persistent_show = this.persistent_show.bind(this);
     this.dialog_box.hide = this.hide.bind(this);

     this.parent_element = this.dialog_box.parentNode;

     this.dialog_box.style.position = "absolute";

     var e_dims = Element.getDimensions(this.dialog_box);
     var b_dims = Element.getDimensions(this.overlay);

     this.dialog_box.style.left = ((b_dims.width/2) - (e_dims.width/2)) + 'px';
     this.dialog_box.style.top = this.getScrollTop() + ((this.winHeight() - (e_dims.width/2))/2) + 'px';
     this.dialog_box.style.zIndex = this.overlay.style.zIndex + 1;
   },

   createOverlay: function() {
     if($('dialog_overlay')) {
       this.overlay = $('dialog_overlay');
     } else {
       this.overlay = document.createElement('div');
       this.overlay.id = 'dialog_overlay';
       Object.extend(this.overlay.style, {
       	position: 'absolute',
       	top: 0,
       	left: 0,
       	zIndex: 90,
       	width: '100%',
       	height: '100%',
       	backgroundColor: '#fff',
       	display: 'none'
       });
       document.body.insertBefore(this.overlay, document.body.childNodes[0]);
     }
   },

   moveDialogBox: function(where) {
     Element.remove(this.dialog_box);
     if(where == 'back')
       this.dialog_box = this.parent_element.appendChild(this.dialog_box);
     else
       this.dialog_box = this.overlay.parentNode.insertBefore(this.dialog_box, this.overlay);
   },

   show: function() {
     this.overlay.style.height = this.bodyHeight()+'px';
     this.moveDialogBox('out');
     this.overlay.onclick = this.hide.bind(this);
     this.selectBoxes('hide');
     new Effect.Appear(this.overlay, {duration: 0.1, from: 0.0, to: 0.3});
     this.dialog_box.style.display = '';
   	 this.dialog_box.style.left = '0px';
     var e_dims = Element.getDimensions(this.dialog_box);
   	 this.dialog_box.style.left = ((this.winWidth()/2) - (e_dims.width)/2) + 'px';
     this.dialog_box.style.top = this.getScrollTop() + ((this.winHeight() - (e_dims.width/2))/2) + 'px';
   },

   getScrollTop: function() {
   	return (window.pageYOffset)?window.pageYOffset:(document.documentElement && document.documentElement.scrollTop)?document.documentElement.scrollTop:document.body.scrollTop;
   },

   persistent_show: function() {
     this.overlay.style.height = this.bodyHeight()+'px';
     this.moveDialogBox('out');
     this.selectBoxes('hide');
     new Effect.Appear(this.overlay, {duration: 0.1, from: 0.0, to: 0.3});
     this.dialog_box.style.display = '';
   	 this.dialog_box.style.left = '0px';
     var e_dims = Element.getDimensions(this.dialog_box);
   	 this.dialog_box.style.left = ((this.winWidth()/2) - (e_dims.width)/2) + 'px';
   },

   hide: function() {
     this.selectBoxes('show');
     new Effect.Fade(this.overlay, {duration: 0.1});
     this.dialog_box.style.display = 'none';
     this.moveDialogBox('back');
     $A(this.dialog_box.getElementsByTagName('input')).each(function(e){if(e.type!='submit')e.value=''});
   },

   selectBoxes: function(what) {
     $A(document.getElementsByTagName('select')).each(function(select) {
       Element[what](select);
     });
     if(what == 'hide')
       $A(this.dialog_box.getElementsByTagName('select')).each(function(select){Element.show(select)})
   },

	bodyWidth: function() { return document.body.offsetWidth || window.innerWidth || document.documentElement.clientWidth || 0; },
	bodyHeight: function() { return document.body.offsetHeight || window.innerHeight || document.documentElement.clientHeight || 0; },

  winWidth: function() {
    var viewportwidth;
    // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
    if (typeof window.innerWidth != 'undefined') {
        viewportwidth = window.innerWidth;
    } else if (typeof document.documentElement != 'undefined' &&
       typeof document.documentElement.clientWidth != 'undefined' &&
       document.documentElement.clientWidth != 0) {
     		 // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
         viewportwidth = document.documentElement.clientWidth;
    } else {
     // older versions of IE
     viewportwidth = document.getElementsByTagName('body')[0].clientWidth
    }
    return viewportwidth;
  },
  winHeight: function() { 
    var viewportheight;
    // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
    if (typeof window.innerHeight != 'undefined') {
     viewportheight = window.innerHeight
    }
    // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
    else if (typeof document.documentElement != 'undefined' &&
       typeof document.documentElement.clientHeight != 'undefined' &&
       document.documentElement.clientHeight != 0) {
         viewportheight = document.documentElement.clientHeight;
    } else {
     // older versions of IE
     viewportheight = document.getElementsByTagName('body')[0].clientHeight;
    }
    return viewportheight;
  }
});