/**
 * papaya objects for jQuery
 * lightbox
 *
 * @copyright 2002-2007 by papaya Software GmbH - All rights reserved.
 * @link http://www.papaya-cms.com/
 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU General Public License, version 2
 *
 * You can redistribute and/or modify this script under the terms of the GNU General Public
 * License (GPL) version 2, provided that the copyright and license notes, including these
 * lines, remain unmodified. papaya is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.
 *
 * @package papaya
 * @author Michael van Engelshoven <engelshoven@papaya-cms.com>
 * @version $Id$
 */


/**
 * Displays the selected div as a lightbox. The show event is basicly bound on the click event
 * of an anchor. Also the close event is bound to an anchor in the lightbox. Its possible to add
 * more than one open/close triggers to your lightbox. The show/hide event can triggered manually
 * from any javascript.
 *
 * @name papayaLightbox
 * @param hash settings             A hash of options
 * @option integer zIndex           The z-index for the overlay div
 * @option bool repositionLightbox  Actualize the position (top,left,position) of the lightbox
 * @option integer overlayOpacity   The opacity value for the overlay (0-100)
 * @option integer fadeTime         The time to fade the overlay (milliseconds)
 * @option integer slideTime        The time to slide down the ligboxed Element
 * @option string overlayClass      The class name of the overlay div
 * @option string activeOverlay     Class name of the active overlay element
 * @option expr closeTrigger        This elements click event will display the lightbox
 * @option expr openTrigger         The trigger which open the lightbox
 * @option bool closeOnClick        The lightbox will be closed when the overlay gets clicked
 * @option bool closeOnEsc          The lightbox will be close when esc-kex is pressed
 * @option function onShow          Callback function that is triggered before the lightbox displays
 *                                  It must return true to display the lightbox
 * @option function onHide          Callback function that is called, before the lightbox hides
 *                                  It must return true to hide the lightbox
 * @option function afterShow       Callback function which is triggered after the show animation has finished
 * @option function afterHide       Callback function which is triggered after the hide animation has finished
 */

jQuery.papayaLightbox = {
  init: function(settings) {
    //The jquery objects that contain our lightboxed elements.
    var cContainers = this;
    // define defaults and override with options, if available
    // by extending the default settings, we don't modify the argument
    settings = jQuery.extend({
      zIndex: 3000,
      repositionLightbox: true,
      overlayOpacity: 50,
      fadeTime: 150,
      slideTime: 300,
      overlayClass: 'lightboxOverlay',
      activeOverlayClass: 'activeOverlay',
      closeTrigger: '.lightboxCloseTrigger',
      openTrigger: '.lightboxOpenTrigger',
      closeOnClick: true,
      closeOnEsc: true,
      onShow: false,
      onHide: false,
      afterShow: false,
      afterHide: false
    }, settings);

    jQuery.papayaLightbox.initOverlay(settings);

    //Loop through the jquery objects (these are the elements that contain our items to collapse).
    return cContainers.each(function(){

      //This current dom element an its triggers
      var jDomElem = this;

      // Write settings to Lightboxed domElement
      jDomElem.lightboxSettings = settings;
      jDomElem.lightboxActive = false;

      // Put the lightboxed element above the overlay
      jQuery(jDomElem).css({zIndex: settings.zIndex +1});

      // If set the reposition flag, site the lightbox
      if(settings.repositionLightbox)
        jQuery.papayaLightbox.reposiontLightbox(jDomElem);

      // modify trigger events
      jQuery(jDomElem).addOpenTrigger(settings.openTrigger);
      jQuery(jDomElem).addCloseTrigger(settings.closeTrigger);

      // add close function to click on overlay and ESC-Press
      if(settings.closeOnClick) {
        jQuery("." + settings.overlayClass).click(function() {
          jQuery(jDomElem).closeLightbox();
        });
      }
      if(settings.closeOnEsc) {
        if(window.event) {
          jQuery("body", document).keyup( function(jEvtElem) {
            jQuery.papayaLightbox.keyPressed(jEvtElem, jDomElem);
          });
        } else {
          jQuery(document).keyup( function(jEvtElem) {
            jQuery.papayaLightbox.keyPressed(jEvtElem, jDomElem);
          });
        }
      }
    });
  },

  addOpenTrigger: function(openTrigger) {
    //The jquery objects that contain our lightboxed elements.
    var cContainers = this;
    return cContainers.each( function() {
      var jDomElem = this;
      jQuery(openTrigger).click(function() {
        jQuery(jDomElem).openLightbox();
        return false;
      });
    });
  },

  addCloseTrigger: function(closeTrigger) {
    //The jquery objects that contain our lightboxed elements.
    var cContainers = this;
    // walk throug all matched elements
    return cContainers.each( function() {
      var jDomElem = this;
      // and modify click event
      jQuery(closeTrigger).click(function() {
        jQuery(jDomElem).closeLightbox();
        return false;
      });
    });
  },

  show: function(jDomElem) {
    if(jDomElem.lightboxActive == false) {
      // the lightbox setting far the actual element
      var settings = jDomElem.lightboxSettings;
      // all sizes of the page
      var pageSize = jQuery.papayaUtils.getSize();
      // If IE show iframe to hide active-x elements
      if (jQuery.browser.msie) {
        jQuery('#ImageBoxIframe')
          .css ('height', Math.max(pageSize.iheight,pageSize.height) + 'px')
          .css ('width', Math.max(pageSize.iwidth,pageSize.width) + 'px')
          .show();
        // When Document is scrolled, the overlay must be repositioned
        jQuery(window).bind("scroll", function() {
          jQuery.papayaLightbox.resizeOverlay();
        });
      }
      // set the overlay to fullpage ...
      jQuery("." + settings.overlayClass).each( function() {
        var overlayObj = this;
        jQuery(overlayObj).css({
          zIndex: settings.zIndex,
          position: 'absolute',
          top: 0,
          left: 0,
          height: Math.max(pageSize.iheight, pageSize.height),
          width: Math.max(pageSize.iwidth, pageSize.width)
        })
        // ... and fade it in
        .fadeIn(settings.fadeTime,function(){
        // After the fade, scroll the lightbox
          var bodySize = jQuery.papayaLightbox.reposiontLightbox(jDomElem);
          jQuery(jDomElem).slideDown(settings.slideTime, function() {
            jDomElem.lightboxActive = true;
            // if an afterSHow event exits, call it
            if(jDomElem.lightboxSettings.afterShow) {
              jDomElem.lightboxSettings.afterShow();
            }
          });
        })
        .addClass("activeOverlay");
        // Resize the overlay, if window resized
        $(window).resize( function() {
          jQuery.papayaLightbox.resizeOverlay();
        });
        overlayObj.lightboxCount++;
      });
    }
  },

  hide: function(jDomElem) {
    if(jDomElem.lightboxActive == true) {
      // the lightbox setting far the actual element
      var settings = jDomElem.lightboxSettings;
      // hide the lightbox
      jQuery(jDomElem).hide();
      jDomElem.lightboxActive = false;
      // fade out the overlay
      jQuery("." + settings.overlayClass).each(function() {
        var overlayObj = this;
        overlayObj.lightboxCount--;
        if(overlayObj.lightboxCount <= 0) {
          jQuery(overlayObj).fadeOut(settings.fadeTime, function() {
            // The IE6 iframe must be hidden
            if (jQuery.browser.msie) {
              jQuery('#ImageBoxIframe')
                .hide();
              // unbind repositioning of overlay
              jQuery(window).unbind("scroll");
            }
            // If an afterHide event exits, call it
            if(jDomElem.lightboxSettings.afterHide) {
              jDomElem.lightboxSettings.afterHide();
            }
          })
          .removeClass("activeOverlay");
          // Unbind resize event (resizeOverlay) from window
          $(window).unbind("resize");
        } else {
          // If an afterHide event exits, call it
          if(jDomElem.lightboxSettings.afterHide) {
              jDomElem.lightboxSettings.afterHide();
          }
        }
      });
    }
  },

  openLightbox: function(settings) {
    //The jquery objects that contain our lightboxed elements.
    var cContainers = this;
    // walk throug all matched elements
    return cContainers.each( function() {
      var jDomElem = this;
      // If this Lightbox not initialized, initialize it
      if(!jDomElem.lightboxSettings) {
        jQuery(jDomElem).papayaLightbox(settings);
      }
      // if an onShow callback function exists
      if(jDomElem.lightboxSettings.onShow) {
        if(jDomElem.lightboxSettings.onShow()) {
          // and if it return true, show box
          jQuery.papayaLightbox.show(jDomElem);
        }
      } else {
        // Show the box.....
        jQuery.papayaLightbox.show(jDomElem);
      }
    });
  },

  closeLightbox: function() {
    //The jquery objects that contain our lightboxed elements.
    var cContainers = this;
    // walk throug all matched elements
    return cContainers.each( function() {
      var jDomElem = this;
      // if an onHide callback function exists
      if(jDomElem.lightboxSettings.onHide) {
        if(jDomElem.lightboxSettings.onHide()) {
          // and if it return true, hide box
          jQuery.papayaLightbox.hide(jDomElem);
        }
      } else {
        // Hide the box.....
        jQuery.papayaLightbox.hide(jDomElem);
      }
    });
  },

  reposiontLightbox: function(jDomElem) {
    jQuery(jDomElem).css({
      position: "absolute",
      left: "-9999px",
      top: "0px",
      display: "block"
    }).appendTo("body");
    var elemSize = jQuery.papayaUtils.getSize(jDomElem);
    var bodySize = jQuery.papayaUtils.getSize(jQuery('body'));
    jQuery(jDomElem).css({
      position: "absolute",
      left: "50%",
      top: (bodySize.top+50) + 'px',
      marginLeft: 0-(elemSize.width/2),
      display: "none"
    });
  },

  initOverlay: function(settings) {
    // If no overlay exists...
    if(jQuery("." + settings.overlayClass).length == 0) {
      // .. add overlay to begin of document body
      var overlayObj = jQuery("<div>").addClass(settings.overlayClass).css({
          opacity: settings.overlayOpacity/100,
          display: 'none'});
      jQuery("body").prepend(overlayObj);

      // select matched overlay(s)
      jQuery("." + settings.overlayClass).each( function() {
        var jDomElem = this;
        jDomElem.lightboxCount = 0;
      });
    }
    if (jQuery.browser.msie) {
      iframe = document.createElement('iframe');
      jQuery(iframe)
        .attr(
          {
            id      : 'ImageBoxIframe',
            src     : 'javascript:false;',
            frameborder : 'no',
            scrolling : 'no'
          }
        )
        .css (
          {
            display   : 'none',
            position  : 'absolute',
            top     : '0',
            left    : '0',
            filter    : 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'
          }
        );
      jQuery('body').append(iframe);
    }
  },

  resizeOverlay: function() {
    // check for IE 6 or lower
    if(jQuery.browser.msie && jQuery.browser.version < 7.0) {
      // get page size
      var pageSize = jQuery.papayaUtils.getSize()
      // set the overlay to fullpage ...
      jQuery(".activeOverlay").css({
        display: 'block',
        position: 'absolute',
        top: pageSize.top,
        left: pageSize.left,
        height: pageSize.iheight,
        width: pageSize.iwidth
      });
    } else {
      jQuery(".activeOverlay").css({
        position: 'fixed',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%'
      });
    }

  },

  keyPressed: function (jEvtElem, jDomElem) {
    // is lightbox active???
    if(jDomElem.lightboxActive) {
      // get keycode
      var keyCode = jEvtElem.charCode || jEvtElem.keyCode || -1;
      switch (keyCode) {
        //escape
        case 27:
          jQuery(jDomElem).closeLightbox();
        break;
      }
    }
  },

  /**
   * getSize from Interface Elements for jQuery
   * http://interface.eyecon.ro
   *
   * Copyright (c) 2006 Stefan Petre
   * Dual licensed under the MIT and GPL licenses.
   */
  getSize : function (jDomElem){
    // set all data default to 0
    var top=0;
    var left=0;
    var width=0;
    var height=0;
    var iwidth=0;
    var iheight=0;
    if (jDomElem && jDomElem.nodeName.toLowerCase() != 'body') {
      // Its some Element
      top = jDomElem.scrollTop;
      left = jDomElem.scrollLeft;
      width = jDomElem.scrollWidth;
      height = jDomElem.scrollHeight;
    } else  {
      // Its the size of the page
      if (document.documentElement) {
        top = document.documentElement.scrollTop;
        left = document.documentElement.scrollLeft;
        width = document.documentElement.scrollWidth;
        height = document.documentElement.scrollHeight;
      } else if (document.body) {
        top = document.body.scrollTop;
        left = document.body.scrollLeft;
        width = document.body.scrollWidth;
        height = document.body.scrollHeight;
      }
      iwidth = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
      iheight = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
    }
    return { top: top, left: left, width: width, height: height, iwidth: iwidth, iheight: iheight };
  }
}

jQuery.fn.extend ({
  papayaLightbox: jQuery.papayaLightbox.init,

  /**
   * The lightbox can be opened manual via javascript. In this case no open trigger
   * is neccessary.
   *
   * @name openLightbox
   * @param settings hash Settings to configure this Lightbox
   * @example $('#dialog_window').openLightbox();
   * @type jQuery
   * @package Plugins/Papaya
   */
  openLightbox: jQuery.papayaLightbox.openLightbox,

  /**
   * The lightbox can be closed by javascript, too!
   *
   * @name closeLightbox
   * @example $('#dialog_window').closeLightbox();
   * @type jQuery
   * @package Plugins/Papaya
   */
  closeLightbox: jQuery.papayaLightbox.closeLightbox,

  /**
   * You can bind multiple triggers to open the lightbox
   *
   * @name addOpenTrigger
   * @example $('#dialog_window').addOpenTrigger('.newButton');
   * @type jQuery
   * package Plugins/Papaya
   */
  addOpenTrigger: jQuery.papayaLightbox.addOpenTrigger,

  /**
   * You can also bind multiple triggers to close the lightbox
   * This Trigger must be a child element of the lightbox. Other
   * elements are beyond the Overlay and cant be clicked.
   *
   * @name addCloseTrigger
   * @example $('#dialog_window').addCloseTrigger('.anotherButton');
   * @type jQuery
   * package Plugins/Papaya
   */
  addCloseTrigger: jQuery.papayaLightbox.addCloseTrigger
});


/**
 * This Function displays a lightbox with your Message. The user can press
 * two different buttons, After the click, a callback function is called and
 * the window will be closed.
 *
 * @name hobnoxMsgBox
 * @param hash settings             A hash of options
 * @option string className         Class name of the created element
 * @option string title             This text is displayed in header of the messagebox
 * @option string text              The text for the message box
 * @option string confirmCaption    Caption for the confirm button
 * @option string cancelCaption     Caption for the cancel button
 * @option function afterConfirm    Callback function which is triggered after the confirm button was pressed
 * @option function afterCancel     Callback function which is triggered after the cancel button was pressed
 */
function hobnoxMsgBox(settings) {
  // set default values
  settings = jQuery.extend({
    className: "lightbox",
    title: "hobnox message box",
    text: "",
    confirmCaption: "OK",
    cancelCaption: false,
    afterConfirm: false,
    afterCancel: false
  }, settings);

  // create box
  var jDomElem = jQuery("<div>").addClass(settings.className).addClass("hobnoxMsgBox");
  // add title and text
  jQuery("<h1>").html(settings.title).appendTo(jDomElem);
  jQuery("<p>").addClass("instruction").html(settings.text).appendTo(jDomElem);
  jQuery("<div>").addClass("actionButtons").appendTo(jDomElem);

  // add ok buttuon with call of callback function
  jQuery("<button>").text(settings.confirmCaption).click(function () {
    if(settings.afterConfirm) settings.afterConfirm(jDomElem);
    // Close Lightbox, remove created elements
    jQuery(".hobnoxMsgBox").closeLightbox().remove();
  })
  .appendTo(jQuery(".actionButtons", jDomElem));

  // If cancel button defined, add em!
  if(settings.cancelCaption) {
    jQuery("<button>").text(settings.cancelCaption).click(function () {
      if(settings.afterCancel) settings.afterCancel(jDomElem);
      // Close Lightbox, remove created elements
      jQuery(".hobnoxMsgBox").closeLightbox().remove();
    })
    .appendTo(jQuery(".actionButtons", jDomElem));
  }

  // Write box to html and open it!
  jQuery("body").append(jDomElem);
  jQuery(".hobnoxMsgBox").openLightbox({
    closeOnEsc: false,
    closeOnClick: false
  });
}
