/**
 * A base library for Shadowbox used as a standalone (without another base
 * library/adapter combination).
 *
 * This file is part of Shadowbox.
 *
 * Shadowbox is an online media viewer application that supports all of the
 * web's most popular media publishing formats. Shadowbox is written entirely
 * in JavaScript and CSS and is highly customizable. Using Shadowbox, website
 * authors can showcase a wide assortment of media in all major browsers without
 * navigating users away from the linking page.
 *
 * Shadowbox is released under version 3.0 of the Creative Commons Attribution-
 * Noncommercial-Share Alike license. This means that it is absolutely free
 * for personal, noncommercial use provided that you 1) make attribution to the
 * author and 2) release any derivative work under the same or a similar
 * license.
 *
 * If you wish to use Shadowbox for commercial purposes, licensing information
 * can be found at http://mjijackson.com/shadowbox/.
 *
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright   2007-2008 Michael J. I. Jackson
 * @license     http://creativecommons.org/licenses/by-nc-sa/3.0/
 * @version     SVN: $Id: shadowbox-base.js 103 2008-06-27 06:19:21Z mjijackson $
 */

// create the Shadowbox object first
var Shadowbox = {};

Shadowbox.lib = function(){

    // local style camelizing for speed
    var styleCache = {};
    var camelRe = /(-[a-z])/gi;
    var camelFn = function(m, a){
 return a.charAt(1).toUpperCase();
    };
    var toCamel = function(style){
 var camel;
 if(!(camel = styleCache[style])){
     camel = styleCache[style] = style.replace(camelRe, camelFn);
 }
 return camel;
    };

    var view = document.defaultView;
    var alphaRe = /alpha\([^\)]*\)/gi;

    /**
     * Sets the opacity of the given element to the specified level.
     *
     * @param   {HTMLElement}   el   The element
     * @param   {Number} opacity     The opacity to use
     * @return  void
     * @private
     * @static
     */
    var setOpacity = function(el, opacity){
 var s = el.style;
 if(window.ActiveXObject){ // IE
     s.zoom = 1; // give "layout"
     s.filter = (s.filter || '').replace(alphaRe, '') +
  (opacity == 1 ? '' : ' alpha(opacity=' + (opacity * 100) + ')');
 }else{
     s.opacity = opacity;
 }
    };

    return {

 adapter: 'standalone',

 /**
  * Gets the value of the style on the given element. This function
  * adapted from Ext.Element.getStyle().
  *
  * @param   {HTMLElement}   el      The DOM element
  * @param   {String} style   The name of the style (e.g. margin-top)
  * @return  {mixed}   The value of the given style
  * @public
  * @static
  */
 getStyle: function(){
     return view && view.getComputedStyle
  ? function(el, style){
      var v, cs, camel;
      if(style == 'float') style = 'cssFloat';
      if(v = el.style[style]) return v;
      if(cs = view.getComputedStyle(el, '')){
   return cs[toCamel(style)];
      }
      return null;
  }
  : function(el, style){
      var v, cs, camel;
      if(style == 'opacity'){
   if(typeof el.style.filter == 'string'){
       var m = el.style.filter.match(/alpha\(opacity=(.+)\)/i);
       if(m){
    var fv = parseFloat(m[1]);
    if(!isNaN(fv)) return (fv ? fv / 100 : 0);
       }
   }
   return 1;
      }else if(style == 'float'){
   style = 'styleFloat';
      }
      var camel = toCamel(style);
      if(v = el.style[camel]) return v;
      if(cs = el.currentStyle) return cs[camel];
      return null;
  };
 }(),

 /**
  * Sets the style on the given element to the given value. May be an
  * object to specify multiple values. This function adapted from
  * Ext.Element.setStyle().
  *
  * @param   {HTMLElement}   el      The DOM element
  * @param   {String/Object} style   The name of the style to set if a
  *      string, or an object of name =>
  *      value pairs
  * @param   {String} value   The value to set the given style to
  * @return  void
  * @public
  * @static
  */
 setStyle: function(el, style, value){
     if(typeof style == 'string'){
  var camel = toCamel(style);
  if(camel == 'opacity'){
      setOpacity(el, value);
  }else{
      el.style[camel] = value;
  }
     }else{
  for(var s in style){
      this.setStyle(el, s, style[s]);
  }
     }
 },

 /**
  * Gets a reference to the given element.
  *
  * @param   {String/HTMLElement}    el      The element to fetch
  * @return  {HTMLElement}     A reference to the element
  * @public
  * @static
  */
 get: function(el){
     return typeof el == 'string' ? document.getElementById(el) : el;
 },

 /**
  * Removes an element from the DOM.
  *
  * @param   {HTMLElement}       el      The element to remove
  * @return  void
  * @public
  * @static
  */
 remove: function(el){
     el.parentNode.removeChild(el);
 },

 /**
  * Gets the target of the given event. The event object passed will be
  * the same object that is passed to listeners registered with
  * addEvent().
  *
  * @param   {mixed}      e       The event object
  * @return  {HTMLElement}        The event's target element
  * @public
  * @static
  */
 getTarget: function(e){
     var t = e.target ? e.target : e.srcElement;
     return t.nodeType == 3 ? t.parentNode : t;
 },

 /**
  * Gets the page X/Y coordinates of the mouse event in an [x, y] array.
  * The page coordinates should be relative to the document, and not the
  * viewport. The event object provided here will be the same object that
  * is passed to listeners registered with addEvent().
  *
  * @param   {mixed}  e       The event object
  * @return  {Array}   The page X/Y coordinates
  * @public
  * @static
  */
 getPageXY: function(e){
     var x = e.pageX || (e.clientX +
  (document.documentElement.scrollLeft || document.body.scrollLeft));
     var y = e.pageY || (e.clientY +
  (document.documentElement.scrollTop || document.body.scrollTop));
     return [x, y];
 },

 /**
  * Prevents the event's default behavior. The event object here will
  * be the same object that is passed to listeners registered with
  * addEvent().
  *
  * @param   {mixed}      e       The event object
  * @return  void
  * @public
  * @static
  */
 preventDefault: function(e){
     if(e.preventDefault){
  e.preventDefault();
     }else{
  e.returnValue = false;
     }
 },

 /**
  * Gets the key code of the given event object (keydown). The event
  * object here will be the same object that is passed to listeners
  * registered with addEvent().
  *
  * @param   {mixed}  e       The event object
  * @return  {Number}  The key code of the event
  * @public
  * @static
  */
 keyCode: function(e){
     return e.which ? e.which : e.keyCode;
 },

 /**
  * Adds an event listener to the given element. It is expected that this
  * function will be passed the event as its first argument.
  *
  * @param   {HTMLElement}   el   The DOM element to listen to
  * @param   {String} name The name of the event to register
  *          (i.e. 'click', 'scroll', etc.)
  * @param   {Function}      handler     The event handler function
  * @return  void
  * @public
  * @static
  */
 addEvent: function(el, name, handler){
     if(el.addEventListener){
  el.addEventListener(name, handler, false);
     }else if(el.attachEvent){
  el.attachEvent('on' + name, handler);
     }
 },

 /**
  * Removes an event listener from the given element.
  *
  * @param   {HTMLElement}   el   The DOM element to stop listening to
  * @param   {String} name The name of the event to stop
  *          listening for (i.e. 'click')
  * @param   {Function}      handler     The event handler function
  * @return  void
  * @public
  * @static
  */
 removeEvent: function(el, name, handler){
     if(el.removeEventListener){
  el.removeEventListener(name, handler, false);
     }else if(el.detachEvent){
  el.detachEvent('on' + name, handler);
     }
 },

 /**
  * Appends an HTML fragment to the given element.
  *
  * @param   {HTMLElement}       el      The element to append to
  * @param   {String}     html    The HTML fragment to use
  * @return  void
  * @public
  * @static
  */
 append: function(el, html){
     if(el.insertAdjacentHTML){
  el.insertAdjacentHTML('BeforeEnd', html);
     }else if(el.lastChild){
  var range = el.ownerDocument.createRange();
  range.setStartAfter(el.lastChild);
  var frag = range.createContextualFragment(html);
  el.appendChild(frag);
     }else{
  el.innerHTML = html;
     }
 }

    };

}();

