/*

    by Chris Doyle

    Derived from Facebox 1.2 (http://famspam.com/facebox)

 */


// TODO: probably more efficient to save dialogNode/modalNode as jQuery objects instead of DOM objects
if (window.Evri == undefined) Evri = {};

Evri.ModalDialog = function (srcUrl, title, childCloseCallback, width, height) {

    // args
    this.srcUrl = srcUrl;
    this.title = title;     // was going to scrape from srcUrl TITLE, but then we couldn't show title until srcUrl loads
    this.childCloseCallback = childCloseCallback;
    this.height = height;
    this.width = width;

    // event handler postponement
    this.positioningTimeout = null;

    // DOM
    this.dialogNode = null;
    this.modalNode = null;
    this.iframe = null;
    
    // kick it off
    this.showOverlay();
    this.showDialog();
};

Evri.ModalDialog.prototype.settings = {
    opacity      : 0.5,
    minSize      : {height: 100, width: 100},
    minMargin    : 100,                             // never let modalDialog get within minMargin of browser edge
    dialogHtml   : '\
                    <div id="dialog" style="display:none;"> \
                      <div class="popup"> \
                        <table style="position:relative"> \
                          <tbody> \
                            <tr> \
                              <td class="tl"/><td class="b"/><td class="tr"/> \
                            </tr> \
                            <tr> \
                              <td class="b"/> \
                              <td class="body"> \
                                <div class="content" style="background:#FFF;position:relative;overflow:hidden;"> \
                                    <div class="header"> \
                                        <div class="title"></div> \
                                        <a class="close" title="close"/> \
                                    </div> \
                                    <div style="position:relative;margin:4px;height:100%;"> \
                                        <iframe style="height:100%;width:100%;" frameborder="0"></iframe> \
                                        <div class="iframe_overlay" style="height:100%;width:100%;background:#FFF;position:absolute;top:0px;left:0px;"> \
                                            <img src="/images/evri_loading.gif"/>\
                                        </div>\
                                    </div> \
                                </div> \
                              </td> \
                              <td class="b"/> \
                            </tr> \
                            <tr> \
                              <td class="bl"/><td class="b"/><td class="br"/> \
                            </tr> \
                          </tbody> \
                        </table> \
                      </div> \
                    </div>'
};


Evri.ModalDialog.prototype.populateIframe = function () {

    // find the iframe
    this.iframe = $(this.dialogNode).find('iframe')[0];

    // let us know when it's ready
    var modalDialog = this;
    if (this.iframe.addEventListener) {
        this.iframe.addEventListener('load', function () {modalDialog.handleIframeLoaded();}, false);
    } else if (this.iframe.attachEvent) {
        this.iframe.attachEvent('onload', function () {modalDialog.handleIframeLoaded();});
    }

    // fill it
    if (this.srcUrl.match(/\?/)) {
        this.iframe.src = this.srcUrl + '&dialog=true';
    } else {
        this.iframe.src = this.srcUrl + '?dialog=true';
    }

    // leave a hook for the iframe's document to let us know it wants to close
    Evri.ModalDialog.handleCompletedDialog = function () {
        modalDialog.close();
        if (modalDialog.childCloseCallback) modalDialog.childCloseCallback.call();
    };
};


Evri.ModalDialog.prototype.handleIframeLoaded = function () {

    if (!this.iframe) return;

    //var iwindow = this.iframe.contentWindow;
    //var params = URI.parseQueryString(window.location.hash.slice(1));  // chop the '#' off the front
    //window.location.hash = '';  // reset the hash so users don't see our hack

    // assumes the document loaded in the iframe set desiredHeight and desiredWidth on the iframe's window
    this.desiredIframeHeight = this.height || this.settings.minHeight;
    this.width  = this.width  || this.settings.minWidth;
    
    this.resize();

    $(this.dialogNode).find('.iframe_overlay').remove();    // uncover the iframe
};


Evri.ModalDialog.prototype.showDialog = function () {

    // get it in the DOM
    $('body').append(this.settings.dialogHtml);
    this.dialogNode = $('body')[0].lastChild;   // hack
    
    $(this.dialogNode).find('.title').text(this.title);
    $(this.dialogNode).find('.content').height(this.height + 'px');
    $(this.dialogNode).find('.content').width(this.width + 'px');

    // set onclick: close when user clicks on mask
    var modalDialog = this;
    $(this.dialogNode).find('.close').click(function() { modalDialog.close(); });  // pass ourselves through the closure

    // fill it

    // position it
    this.position(this.height, this.width);
    $(window).bind('resize.dialog', function(){modalDialog.handleBrowserResize();});
    $(window).bind('scroll.dialog', function(){modalDialog.handleScroll();});

    // show it
    $(this.dialogNode).fadeIn(200, function () {modalDialog.populateIframe();});
};


Evri.ModalDialog.prototype.handleBrowserResize = function () {

    /*
        we get so many resize events, if we repositiong the dialog on every one we won't get a very smooth animation.
        instead, wait until we think the user is done resizing and THEN reposition.
     */

    if (this.positioningTimeout) clearTimeout(this.positioningTimeout);

    var modalDialog = this;
    this.positioningTimeout = setTimeout(function() {modalDialog.resize();}, 250);
};


Evri.ModalDialog.prototype.handleScroll = function () {

    /*
        we get so many scroll events, if we repositiong the dialog on every one we won't get a very smooth animation.
        instead, wait until we think the user is done scrolling and THEN reposition.
     */

    if (this.positioningTimeout) clearTimeout(this.positioningTimeout);

    var modalDialog = this;
    this.positioningTimeout = setTimeout(function() {modalDialog.position();}, 250);
};


Evri.ModalDialog.prototype.resize = function () {

    var newHeight = this.height;
    var newWidth = this.width;

    // account for max/min
    var pageHeight = getPageHeight();
    if (newWidth > $(window).width() - this.settings.minMargin * 2) {
        newWidth = $(window).width() - this.settings.minMargin * 2;
    }
    if (newWidth < this.settings.minSize.width) {
        newWidth = this.settings.minSize.width;
    }
    if (newHeight > pageHeight - this.settings.minMargin * 2) {
        newHeight = pageHeight - this.settings.minMargin * 2;
    }
    if (newHeight < this.settings.minSize.height) {
        newHeight = this.settings.minSize.height;
    }


    // change it
    var modalDialog = this;
    this.position(newHeight, newWidth);

    $(this.dialogNode).find('.content').animate({height: newHeight + 'px', width: newWidth + 'px'});

    //                                          20 for header, 22 for potential scrollbars.  8 to match paddings
    $(this.iframe).animate({height: newHeight - 42 + 'px', width: newWidth - 8 + 'px'});
};


Evri.ModalDialog.prototype.position = function (resizeHeight, resizeWidth) {

    // find where it should be
    var dialogHeight = resizeHeight || $(this.dialogNode).height();
    var dialogWidth = resizeWidth || $(this.dialogNode).width();
    var scroll = getPageScroll();
    var newLeft = ($(window).width() / 2.0) - (dialogWidth / 2.0) + scroll[0];
    var newTop = (getPageHeight() / 2.0) - (dialogHeight / 2.0) + scroll[1];

    if (newTop < scroll[1]) newTop = scroll[1];
    if (newLeft < 0) newLeft = 0;

    // move it there
    var animationParms = {left: newLeft + 'px', top: newTop + 'px'}
    $(this.dialogNode).animate(animationParms);
};


Evri.ModalDialog.prototype.showOverlay = function () {
    // we'll make a new overlay each time rather than leaving it hanging around

    // make it (opacity for FF/Webkit, alpha filter for IE)
    $("body").append('<div id="modal_overlay" class="modal_overlayBG" style="display:none;opacity:' + this.settings.opacity + ';filter:alpha(opacity=' + (this.settings.opacity * 100) + ');"></div>');
    this.overlayNode = $('body')[0].lastChild;

    // close when user clicks on mask
    var modalDialog = this;
    $(this.overlayNode).click(function() { modalDialog.close(); });  // pass ourselves through the closure

    // close when user hits ESC
    $(document).bind('keydown.modal', function(e) {
          if (e.keyCode == 27) modalDialog.close();
          return true;
        });

    // show it
    $(this.overlayNode).fadeIn(200);

    return false;
};


Evri.ModalDialog.prototype.close = function () {

    // stop listening for browser events
    $(document).unbind('keydown.modal');
    $(window).unbind('resize.dialog');
    $(window).unbind('scroll.dialog');

    // this method was scoped to use this object, need to release for GC
    Evri.ModalDialog.handleCompletedDialog = null;

    this.iframe = null;

    // get rid of the modal and dialog
    var modalDialog = this; // pass ourselves through the closure
    $(this.dialogNode).fadeOut(function() {
        $(modalDialog.dialogNode).remove();
        modalDialog.dialogNode = null; // make extra sure we're not holding a reference
    });

    $(this.overlayNode).fadeOut(function() {
        $(modalDialog.overlayNode).remove();
        modalDialog.overlayNode = null; // make extra sure we're not holding a reference
    });
};



// getPageScroll() by quirksmode.com
function getPageScroll() {
  var xScroll, yScroll;
  if (self.pageYOffset) {
    yScroll = self.pageYOffset;
    xScroll = self.pageXOffset;
  } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
    yScroll = document.documentElement.scrollTop;
    xScroll = document.documentElement.scrollLeft;
  } else if (document.body) {// all other Explorers
    yScroll = document.body.scrollTop;
    xScroll = document.body.scrollLeft;
  }
  return new Array(xScroll,yScroll);
}

// Adapted by Facebox from getPageSize() by quirksmode.com
function getPageHeight() {
  var windowHeight;
  if (self.innerHeight) {	// all except Explorer
    windowHeight = self.innerHeight;
  } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
    windowHeight = document.documentElement.clientHeight;
  } else if (document.body) { // other Explorers
    windowHeight = document.body.clientHeight;
  }
  return windowHeight;
}

