﻿
/**
  * MSML.modal 
  * 
  * @description
  * Microsoft Live Messenger Portal modal layer
  
  * 
  * @copyright       Neue Digitale / Razorfish 
  * @author          martin.krause@neue-digitale.de
  * @version         1.0
  *
  * @revision        $Revision$
  * @lastmodified    $Date$
  *
  * @jslint			    2009-01-28
  *
  */

MSLM.modal = {

    __version: 1.0, // class version 
    __class: 'MSLM.modal', // class name

    // set default options
    _oDefaults: {

        sClassLoading: 'loading',
        sIDLayerModalOverlay: '#MSLM_modal_overlay',

        // define layer types 
        /**
        * // identifier
        * games: {
        * 		boolNonIeOnly: true, // should appear on non-ie user agents 
        * 		sClassAnchor: ' #content .MSLM_show_modal_games', // jquery selector for adding the event 
        * 		sClassLayer: '.MSLM_modal_games' // classname for the element to show - id is blocked by the iss
        * },
        **/
        oTypes: {
            games: {
                boolNonIeOnly: true,
                sClassAnchor: ' #content .MSLM_show_modal_games',
                sClassLayer: '.MSLM_modal_games'
            },
            applications: {
                boolNonIeOnly: true,
                sClassAnchor: ' #content .MSLM_show_modal_application',
                sClassLayer: '.MSLM_modal_application'
            },
            addContact: {
                boolNonIeOnly: true,
                sClassAnchor: '  #content .MSLM_show_modal_addcontact',
                sClassLayer: '.MSLM_modal_addcontact'
            },
            MSNVersion: {
                boolNonIeOnly: true,
                sClassAnchor: '  #content .MSLM_modal_show_msnversion',
                sClassLayer: '.MSLM_modal_msnversion'
            },
            buddyScout: {
                boolNonIeOnly: false,
                sClassAnchor: '  #content .MSLM_show_modal_buddyscouts',
                sClassLayer: '.MSLM_modal_bodyscouts'
            },
            buddyScoutChat: {
                boolNonIeOnly: false,
                sClassAnchor: '  #content .MSLM_show_modal_buddyscouts_chat',
                sClassLayer: '.MSLM_modal_bodyscouts_chat'
            },
            requestScout: {
                boolNonIeOnly: false,
                sClassAnchor: '.jModal_showRequestScout',
                sClassLayer: '.MSLM_modal_requestScout'
            }
        }
    },

    // status flag
    _isOpen: false,

    // set vars
    _$elIframe: null,
    _$elModal: null,
    _$elLayer: null,


    /**
    * Setup
    * @param {String} [sTitle], title
    * @return {Void}
    */
    _setUp: function(oOptions) {
        var _scope = MSLM.modal;
        // merge options and defaults
        _scope._oOpt = jQuery.extend({}, _scope._oDefaults, oOptions);
        _scope._oDefaults = null;
        // add events 
        _scope._addEvents();
        // set html references
        _scope._getReferences();
    },

    /**
    * Add events 
    * @return {Void}
    */
    _addEvents: function() {
        // add events on links using global options
        for (var _sKey in MSLM.modal._oOpt.oTypes) {
            var _oThisType = MSLM.modal._oOpt.oTypes[_sKey];
            // this kind of layer should be shown if we're dealing with non explorer agents
            if (_oThisType.boolNonIeOnly && jQuery.browser.msie) { continue; }
            // get all anchors, 
            jQuery(_oThisType.sClassAnchor)
				.unbind('click.modalShow')
            // pass layerelement to show as event.data.$elLayer 
				.bind('click.modalShow', { $elLayer: jQuery(_oThisType.sClassLayer).eq(0) }, MSLM.modal.show);
        }

        // add ajax callback
        jQuery(document)
			.unbind('ajaxLoadComplete', MSLM.modal.onAjaxLoadComplete)
			.bind('ajaxLoadComplete', MSLM.modal.onAjaxLoadComplete);

        // add event for hiding layer
        jQuery('.modal .close a')
			.unbind('click.modalClose', MSLM.modal.close)
			.bind('click.modalClose', MSLM.modal.close);

        jQuery('.modal .closelink')
			.unbind('click.modalClose', MSLM.modal.close)
			.bind('click.modalClose', MSLM.modal.close);
    },


    /**
    * Create HTML references
    * @return {Void}
    */
    _getReferences: function() {
        // store modal layer
        MSLM.modal._$elModal = jQuery(MSLM.modal._oOpt.sIDLayerModalOverlay)
        // set opacity, due to ie
									.css('opacity', '0.5');

    },

    /**
    * Fix Internet Explorer 6 by creates an <iframe> 
    * to prevent <select>s bleeding throught.
    * @return {Void}
    */
    _setIe6Fix: function() {
        // just msie6
        if (jQuery.browser.msie && parseInt(jQuery.browser.version) == 6) {
            // cache  scope
            var _scope = MSLM.modal;
            // create a new iframe if necessary
            if (!_scope._$elIframe) {
                // get current dimensions
                _scope._oDim = MSLM.modal._getDimensions();
                _scope._$elIframe = jQuery('<iframe src="javascript:false;"/>')
					.css({
					    display: 'none',
					    opacity: 0,
					    position: 'fixed',
					    height: _scope._oDim.height,
					    width: _scope._oDim.width,
					    zIndex: 200001,
					    top: 0,
					    left: 0
					})
					.insertBefore(_scope._$elModal);
                _scope._$elModal.css('position', 'absolute');
            }
            // show iframe
            _scope._$elIframe.show();


        }
    },

    /**
    * Hides iframe
    * @return {Void}
    */
    _unsetIe6Fix: function() {
        if (this._$elIframe) {
            this._$elIframe.hide();
        }
    },

    /**
    * Getter for _isOpen: returns boolean indicating current layer status opened / closed
    * @return {Bool}
    */
    isOpen: function() {
        return MSLM.modal._isOpen;
    },


    /**
    * Calculates dimensions
    * @return {Object} {height, width}
    */
    _getDimensions: function() {
        var _iWidth = jQuery('body').outerWidth();
        return {
            // height: get body height and add the wrapper offsetTop due to navigation position: absolute
            height: jQuery('body').outerHeight() + jQuery('#wrapper').offset().top,
            // min-width for calculating layer position equals wrapper width
            width: (_iWidth > 972) ? _iWidth : 972
        };
    },


    //    showRequestScout: function(event) {
    //		if (MSLM.modal._$elLayer) {
    //			 return false;
    //		}
    //		MSLM.modal._$elLayer = jQuery(MSLM.modal._oOpt.sIDLayerRequestScout)
    //		MSLM.modal.show(event);
    //		return false;
    //    },
    //    
    //    showAdvice: function(event) {
    //		if (MSLM.modal._$elLayer) {
    //			 return false;
    //		}
    //		MSLM.modal._$elLayer = jQuery(MSLM.modal._oOpt.sIDLayerAdvice)
    //		MSLM.modal.show(event);
    //		return false;
    //    },


    /**
    * Shows layer by using event.data.$elLayer to determine element to show
    * @see _doShow
    * @return {Boolean}
    */
    show: function(event) {
        // stop event
        event.stopPropagation();
        // get element from event 
        var _$element = jQuery(event.target) || jQuery(event);
        // exit if there's already an open layer or no element being passed 
        if (MSLM.modal.isOpen() || !event.data.$elLayer || !event.data.$elLayer.size()) {
            return false;
        }
        // store element to show
        MSLM.modal._$elLayer = event.data.$elLayer;
        // actually show element
        MSLM.modal._doShow();
        return false;
    },


    /**
    * Shows layer by passing the layer's class name 
    * @see _doShow
    * @return {Boolean}
    */
    showByClass: function(sClass) {
        // exit if there's already an open layer or no element being passed 
        if (MSLM.modal.isOpen() || !sClass || !jQuery(sClass).eq(0).size()) {
            return false;
        }
        // store element to show by using getElementByClassName. Reduce results to the first match 
        MSLM.modal._$elLayer = jQuery(sClass).eq(0);
        // actually show element
        MSLM.modal._doShow();
        return false;
    },

    /**
    * Actually shows layer
    * @return {Void}
    */
    _doShow: function() {
        MSLM.modal._isOpen = true;
        // create iframe
        MSLM.modal._setIe6Fix();
        // set iframe && modal dimensions
        MSLM.modal.setMiscDimensions();
        // set layer position
        MSLM.modal.setLayerPosition({ type: 'initial' });
        // add resize eventlistener
        if (!jQuery.browser.msie || (jQuery.browser.msie && jQuery.browser.version.indexOf('6.') == -1)) {
            jQuery(window).bind('resize.modalLayerPosition', { type: 'resize' }, MSLM.modal.setLayerPosition);
        }
        // no animation due to png-fade-bug

        if (jQuery.browser.msie) {

            MSLM.modal._$elModal.show();
            MSLM.modal._$elLayer.show();
        }
        // show by fading elements
        else {

            MSLM.modal._$elModal.fadeIn('fast');
            MSLM.modal._$elLayer.fadeIn('fast');
        }

    },

    _pause: function(millis) {
        var date = new Date();
        var curDate = null;

        do { curDate = new Date(); }
        while (curDate - date < millis);
    },

    /**
    * Close currently opened layer
    * @return {Boolean}
    */
    close: function(event) {
        // stop event
        event.stopPropagation();
        // close element
        MSLM.modal._doClose();
        return false;
    },

    /**
    * Close currently opened layer
    * @return {Void}
    */
    _doClose: function() {
        // remove iframe
        MSLM.modal._unsetIe6Fix();
        // no animation due to png-fade-bug
        if (jQuery.browser.msie) {
            MSLM.modal._$elModal.hide();
            MSLM.modal._$elLayer.hide();
            // trigger callback
            MSLM.modal.onCompleteClose();
        }
        // fade out 
        else {
            MSLM.modal._$elModal.fadeOut('fast');
            MSLM.modal._$elLayer.fadeOut('fast', MSLM.modal.onCompleteClose);
        }
        // remove eventlistener
        jQuery(window).unbind('resize.modalLayerPosition');
        // clear element reference
        MSLM.modal._$elLayer = null;
        MSLM.modal._isOpen = false;
    },

    /**
    * OnCloseComplete Callback being triggered after the element ist gone 
    * @return {Void}
    */
    onCompleteClose: function() {
        if (MSLM.load.contentInto.storedHTMLNodes && MSLM.load.contentInto.storedHTMLId) {
            window.setTimeout(MSLM.modal.restoreOriginalContent, 500);
        }
    },

    /**
    * Restores original content after closingthe layer if this should be necessary.
    * @return {Void}
    */
    restoreOriginalContent: function() {
        // restore HTML
        jQuery('#' + MSLM.load.contentInto.storedHTMLId).replaceWith(MSLM.load.contentInto.storedHTMLNodes);
        // reset input-elements 
        jQuery('#' + MSLM.load.contentInto.storedHTMLId).find(':input').val('');
        // clear references
        MSLM.load.contentInto.storedHTMLId = null;
        MSLM.load.contentInto.storedHTMLNodes = null;
    },


    /**
    * Sets layer position according to wrapper/window dimensions 
    * @param {String}, Type: 'initial' || 'resize'
    * @return {Void}
    */
    setLayerPosition: function() {

        // cache wrapper element
        var _$elWrapper = jQuery('#wrapper');

        switch (arguments[0].type) {

            // on open        
            case 'initial':
                // get window element
                var _$elWindow = jQuery(window);
                // set layer position: top / left centering the layer inside the viewport
                MSLM.modal._$elLayer.css({
                    left: ((_$elWrapper.position().left + (_$elWrapper.outerWidth() / 2)) - (MSLM.modal._$elLayer.outerWidth() / 2)) + 'px',
                    top: ((_$elWindow.scrollTop() + (_$elWindow.height() / 2)) - (MSLM.modal._$elLayer.outerHeight() / 2)) + 'px'
                });
                break;

            // on resize       
            case 'resize':
                // set layer postition: left, keeping the layer centered above the content-wrapper "#wrapper"
                MSLM.modal._$elLayer.css({
                    left: ((_$elWrapper.position().left + (_$elWrapper.outerWidth() / 2)) - (MSLM.modal._$elLayer.outerWidth() / 2)) + 'px'
                });
                break;
        }

        // set modal overlay / iframe dimensions
        MSLM.modal.setMiscDimensions();

    },

    /**
    * Set modal overlay and iframe position
    * @return {Void}
    */
    setMiscDimensions: function() {
        // cache scop
        var _scope = MSLM.modal;
        // get current dimensions
        _scope._oDim = MSLM.modal._getDimensions();
        // set modal overlay dimensions to span the whole page
        _scope._$elModal.css({
            height: _scope._oDim.height,
            width: _scope._oDim.width
        });
        // set iframe dimensions if necessary
        if (_scope._$elIframe) {
            _scope._$elIframe.css({
                height: _scope._oDim.height,
                width: _scope._oDim.width
            });
        }
    },


    /**
    * Custom event: onAjaxLoadComplete callback
    * @return {Void}
    */
    onAjaxLoadComplete: function() {
        //		console.log('[MSLM.load] onAjaxLoadComplete: ', arguments);
        MSLM.modal._addEvents();
    },

    /**
    * Constructor
    * @param {Object} [oOptions]
    * @constructor
    */
    initialize: function(oOptions) {
        // fake singleton
        if (this._oOpt) {
            return this;
        }
        // setup 
        this._setUp(oOptions);
        // fake singleton
        return this;
    }
};

// initialize onDOMReady
jQuery(function() {
	MSLM.modal.initialize();


});
