﻿/*
 * Hpu Modal Dialog Scripts
 *
 * By John P. Marshall
 * Copyright (c) 2010 Zoasis Corporation
 *
 * These methods represent the client side API for modal usage in HPU web site.
 * All modals should use these APIs for consistent modal experience.
 *
 * Uses the JavaScript Module Pattern to encapsulate everything within the HpuModalDialog class.
 *
 * Dependencies: jquery.simplemodal-1.4.1.js 
 *               jquery.corner.2.11.js
 *               /images/v3/btn-close-modal.png
 *
 * See comments above each public method for information about the parameters.
 *
 * Sample Usage:
 *
 * 1. Show a modal dialog with html contents:
 * HpuModalDialog.ShowHtml( html );
 * HpuModalDialog.ShowHtml( html , width , height );
 * Note if string delimiters ' or " are required in html and not valid because html is already quoted (e.g. in onclick event) use 
 * ~~ for single quote and ~~~~ for double quote.  Not always needed since a lot of html elements attributes render fine w/o being quoted.
 *
 * 2. Show a modal dialog with a message (auto-centered):
 * HpuModalDialog.ShowMessage( message );
 * HpuModalDialog.ShowMessage( message , width , height );
 *
 * 3. Show a modal dialog with separate web page in iframe:
 * HpuModalDialog.ShowPage( "http://bluewiresystems.com" , 1000 , 300 , "auto" );
 *
 * 4. Close modal dialog programmatically:
 * HpuModalDialog.Close();
 *
 * 5. ASP.Net Code Behind (done via start up script injection which requires post-back):
 * // Now show the modal... we can pull this off without casting our master page if the page includes this directive: <%@ MasterType TypeName="BaseMasterPage" %> 
 * this.Master.ShowModalDialog( htmlMessage );
 * this.Master.ShowModalDialog( iframeUrl , height );
 * this.Master.ShowModalDialog( ModalMessageType.IFrame , url , width , height , String.Empty , String.Empty );
 *
 */



var HpuModalDialog = new function () {


    // begin "private" variables

    // Array of elements that may contain flash content that should be hidden when a 
    // modal is displayed and then displayed when the modal is being closed.  We do 
    // this since flash elements will display above our modal which isn't desired. 
    // Note that we check for the existance of the element before trying to hide/show 
    // it so if you're using flash put it in the list since if it doesn't exist on the 
    // page we showing the modal on there will be no harm done.
    var flashElementIds = ['LifeStageNav', 'Advertisement1', 'Advertisement2'];

    // Flag if we need to refresh the page on close.  Since dialog can be closed with client 
    // side close action if the modal is causing a modification to the underlying page and 
    // that page needs to be refreshed then this should be true
    var refreshOnClose = false;

    // Default options for our modal dialog.  Yes I know a style sheet may feel cleaner for 
    // some of the CSS stuff but we've had too many cases of some well intentioned developer 
    // monkeying around with the CSS and breaking our modal styles.  This way it's all 
    // here in one place with no external CSS dependencies.
    var defaultOptions = {
        autoResize: true,
        autoPosition: true,
        opacity: 60,
        overlayCss: { backgroundColor: "#000" },
        // The borderRadius CSS won't work on IE8 and below but it sure is nice compared to using an image for the border.
        // Using -moz-border-radius and -webkit-border-radius alternate css tags for browsers not yet supporting border-radius.
        // borderStyle and borderWidth combinations that look ok: solid @ 4px, ridge @ 6px
        // NOTE changes to containerCss should also be done in ShowHtml() method has option to turn off padding
        // 'behavior': 'url(/js/v3/border-radius.htc)', 
        containerCss: { backgroundColor: "#FFF", borderWidth: "4px", borderStyle: "solid", borderColor: "#67A5D1", borderRadius: "15px", '-moz-border-radius': "15px", '-webkit-border-radius': "15px", paddingTop: "20px", paddingBottom: "20px", paddingLeft: "20px", paddingRight: "20px" },
        closeHTML: "<a href='javascript:void(0);' title='Close' style='background: url(/images/v3/btn-close-modal.png) no-repeat; width:50px; height: 50px; display: block; text-indent: -9999px; line-height: 0; overflow: hidden; position: absolute; top:-32px; right:-28px; font-size: 0; cursor:pointer; z-index:9999;' />",
        // The class declared in closeClass doesn't actually exist in CSS files but is required for simplemodal to set the close click event
        closeClass: "hpu-modal-dialog-close",
        close: true,
        escClose: true,
        overlayClose: false,
        minWidth: 500,
        minHeight: 10,
        // Set height to auto in case our text is higher than our default.  Also call setPosition() 
        // so we get positioned correctly within the browser window prior to any resize events.
        onShow: function (dialog) { dialog.container.css("height", "auto"); this.setPosition(); },
        onClose: function (dialog) { HpuModalDialog.Close(); }
    };

    // After calling determineSize() these values will hold the browser window width and height so we can make 
    // some intelligent choices about how big to allow some modal dialogs to get
    var maximumWidth = 0;
    var maximumHeight = 0;

    // Most of our Show*() methods allow the user to specify suggested dimensions for the modal dialog.  Our 
    // suggestSize() method will take into account browser dimensions (via determineSize() method) and our 
    // suggestions and will adjust those suggestions to fit the reality of the current user's browser size.
    // The Show*() methods should assign the suggested dimensions to these two private variables before 
    // calling suggestSize().
    var suggestedWidth = 0;
    var suggestedHeight = 0;

    // end "private" variables



    // begin "private" methods

    // Hides each element in flashElementIds array that exists in the current document
    var hideFlash = function () {
        for (var i = 0; i < flashElementIds.length; i++) {
            if ($("#" + flashElementIds[i]).length > 0) {
                $("#" + flashElementIds[i]).hide();
            }
        }
    }

    // Shows each element in flashElementIds array that exists in the current document
    var showFlash = function () {
        for (var i = 0; i < flashElementIds.length; i++) {
            if ($("#" + flashElementIds[i]).length > 0) {
                $("#" + flashElementIds[i]).show(0);
            }
        }
    }

    // Determines the browser window width and height so we can make some intelligent 
    // Choices about modal dialog sizes that should be allowed
    var determineSize = function () {
        if (self.innerWidth) {
            maximumWidth = self.innerWidth;
            maximumHeight = self.innerHeight;
        } else if (document.documentElement && document.documentElement.clientWidth) {
            maximumWidth = document.documentElement.clientWidth;
            maximumHeight = document.documentElement.clientHeight;
        } else if (document.body) {
            maximumWidth = document.body.clientWidth;
            maximumHeight = document.body.clientHeight;
        }
    }

    // Uses suggestedWidth and suggestedHeight (hopefully set in our Show*() methods) and browser 
    // dimensions as determined by determineSize() method to calculate the suggested size that 
    // should be used for the modal dialog.
    var suggestSize = function () {

        // The Show*() method should have set suggestedWidth and suggestedHeight values but if 
        // they were not set then assign default values now.
        if (suggestedWidth == null || typeof (suggestedWidth) != "number" || suggestedWidth == 0) {
            suggestedWidth = 500;
        }
        if (suggestedHeight == null || typeof (suggestedHeight) != "number" || suggestedHeight == 0) {
            // Yes 100 is relatively short but our onShow code auto sets the height to match content for us.
            // That will not work so well for iframes, however, so don't skip passing a suggested height for iframes.
            suggestedHeight = 100;
        }

        // Determine browser size so we can be smart about how big to allow modal dialogs
        determineSize();

        // If we have a maximum width and our suggested width is within 90px of our maximum width then scale the suggested width back.
        if (maximumWidth > 0 && suggestedWidth > (maximumWidth - 90)) {
            suggestedWidth = (maximumWidth - 90);
            // Of course, we can't get crazy small here
            if (suggestedWidth < 50) {
                suggestedWidth = 50;
            }
        }

        // If we have a maximum height and our suggested height is within 60px of our maximum height then scale the suggested height back.
        if (maximumHeight > 0 && suggestedHeight > (maximumHeight - 60)) {
            suggestedHeight = (maximumHeight - 60);
            // Of course, we can't get crazy small here
            if (suggestedHeight < 20) {
                suggestedHeight = 20;
            }
        }

    }

    // end "private" methods


    // Public properties and methods are declared here
    return {

        // Public property of HTML to insert at beginning of html markup when WrapHtml flag is on
        WrapHtmlBeginningMarkup: "<div style='text-align: center; vertical-align: middle; height: 100%;'>",

        // Public property of HTML to insert at ending of html markup when WrapHtml flag is on
        WrapHtmlEndingMarkup: "</div>",


        // Shows message inside modal dialog.  Similar to ShowHtml in that it accepts html but this method 
        // wraps the html in div tags that will center the content.  Parameters are:
        // 1. html = The html to display.
        // 2. width = The modal width.  Default is 500.
        // 3. height = The modal heigth.  Default is 10 (onShow will auto adjust height to match content).
        // 4. flags = csv of flags to control modal display/behavior.  This is a shortcut method for declaring custom 
        // options where defaultOptions are mostly desired with changes specified in flags csv.  Possible 
        // values include: 
        //   a. WrapHtml - this flag wraps html in opening and closing markup which by default will center the message in the modal.
        //   b. CannotClose - this flag turns of modal close feature for cases where the dialog has buttons/links to control url 
        //      flow for things like mandatory login or registration.
        //   c. ZeroPadding - this flag removes default padding on the modal.  Html passed to the modal can include it's own padding.
        // 5. options = The modal options.  Defaults to defaultOptions.  The options minWidth and minHeight settings 
        // are set to width and height parameters (possibly adjusted if browser window is small).
        ShowMessage: function (html, width, height, flags, options) {
            if (flags == null || typeof (flags) != "string") {
                flags = "WrapHtml";
            }
            else {
                flags = flags + ",WrapHtml";
            }
            //html = "<div style='text-align: center; vertical-align: middle; height: 100%;'>" + html + "</div>";
            this.ShowHtml(html, width, height, flags, options);
        },


        // Shows HTML inside modal dialog.  Parameters are:
        // 1. html = The html to display.
        // 2. width = The modal width.  Default is 500.
        // 3. height = The modal heigth.  Default is 10 (onShow will auto adjust height to match content).
        // 4. flags = csv of flags to control modal display/behavior.  This is a shortcut method for declaring custom 
        // options where defaultOptions are mostly desired with changes specified in flags csv.  Possible 
        // values include: 
        //   a. WrapHtml - this flag wraps html in opening and closing markup which by default will center the message in the modal.
        //   b. CannotClose - this flag turns of modal close feature for cases where the dialog has buttons/links to control url 
        //      flow for things like mandatory login or registration.
        //   c. ZeroPadding - this flag removes default padding on the modal.  Html passed to the modal can include it's own padding.
        // 5. options = The modal options.  Defaults to defaultOptions.  The options minWidth and minHeight settings 
        // are set to width and height parameters (possibly adjusted if browser window is small).
        ShowHtml: function (html, width, height, flags, options) {

            // Validate input parameters
            if (width == null || typeof (width) != "number") {
                width = 500;
            }
            if (height == null || typeof (height) != "number") {
                height = 10;
            }
            if (flags == null || typeof (flags) != "string") {
                flags = "";
            }
            if (options == null) {
                options = defaultOptions;
            }

            // Note our requested width and height and see what suggestions we get
            suggestedWidth = width;
            suggestedHeight = height;
            suggestSize();

            // If we have maximum browser dimensions then set our max dialog dimensions slightly smaller
            if (maximumWidth > 0) {
                options.maxWidth = (maximumWidth - 90);
            }
            if (maximumHeight > 0) {
                options.maxHeight = (maximumHeight - 60);
            }

            // Adjust our options minimum width and height to the suggested width and height.
            if (suggestedWidth > 0) {
                options.minWidth = suggestedWidth;
            }
            else {
                options.minWidth = width;
            }
            if (suggestedHeight > 0) {
                options.minHeight = suggestedHeight;
            }
            else {
                options.minHeight = height;
            }

            // See if flag is set to trigger refresh on close and, if so, set a private far indicating this.
            if (flags.toLowerCase().indexOf("refreshonclose") >= 0) {
                refreshOnClose = true;
            }

            // See if flag is set to wrap our html in beginning and ending markup.
            if (flags.toLowerCase().indexOf("wraphtml") >= 0) {
                html = this.WrapHtmlBeginningMarkup + html + this.WrapHtmlEndingMarkup;
            }

            // See if flag is set to forbid closing of the modal dialog for cases where the dialog has 
            // buttons/links to control url flow for things like mandatory login or registration.
            if (flags.toLowerCase().indexOf("cannotclose") >= 0) {
                options.close = false;
            }

            // See if flag is set to have 0 padding
            if (flags.toLowerCase().indexOf("zeropadding") >= 0) {
                options.containerCss = { backgroundColor: "#FFF", borderWidth: "4px", borderStyle: "solid", borderColor: "#67A5D1", borderRadius: "15px", '-moz-border-radius': "15px", '-webkit-border-radius': "15px", paddingTop: "0px", paddingBottom: "0px", paddingLeft: "0px", paddingRight: "0px" };
            }

            // See if we have a template that will change our look and feel
            if (flags.toLowerCase().indexOf("template-t1") >= 0) {
                options.containerCss = { backgroundColor: "#FFF", borderWidth: "0px", borderStyle: "solid", borderColor: "White", paddingTop: "20px", paddingBottom: "20px", paddingLeft: "20px", paddingRight: "20px" };
                options.closeHTML = "<a href='javascript:void(0);' title='Close' style='background: url(/images/v3/btn-close-modal-black.png) no-repeat; width:50px; height: 50px; display: block; text-indent: -9999px; line-height: 0; overflow: hidden; position: absolute; top:-32px; right:-28px; font-size: 0; cursor:pointer; z-index:9999;' />";
            }
            if (flags.toLowerCase().indexOf("template-t2") >= 0) {
                options.containerCss = { backgroundColor: "#FFF", borderWidth: "0px", borderStyle: "solid", borderColor: "White", borderRadius: "15px", '-moz-border-radius': "15px", '-webkit-border-radius': "15px", paddingTop: "20px", paddingBottom: "20px", paddingLeft: "20px", paddingRight: "20px" };
                options.closeHTML = "<a href='javascript:void(0);' title='Close' style='background: url(/images/v3/btn-close-modal-black.png) no-repeat; width:50px; height: 50px; display: block; text-indent: -9999px; line-height: 0; overflow: hidden; position: absolute; top:-32px; right:-28px; font-size: 0; cursor:pointer; z-index:9999;' />";
            }
            if (flags.toLowerCase().indexOf("template-t3") >= 0) {
                options.containerCss = { backgroundColor: "#FFF", borderWidth: "0px", borderStyle: "solid", borderColor: "White", borderRadius: "15px", '-moz-border-radius': "15px", '-webkit-border-radius': "15px", paddingTop: "20px", paddingBottom: "20px", paddingLeft: "20px", paddingRight: "20px" };
                options.closeHTML = "<a href='javascript:void(0);' title='Close' style='background: url(/images/v3/btn-close-modal-black.png) no-repeat; width:50px; height: 50px; display: block; text-indent: -9999px; line-height: 0; overflow: hidden; position: absolute; top:-32px; right:-28px; font-size: 0; cursor:pointer; z-index:9999;' />";
            }

            // Hide flash elements that will display over our modal
            hideFlash();

            // Since this html may be embedded within other html onclick event etc. we need string delimiters other than ' and " 
            // that we can swap out now.  ' is represented by ~~ and " is represented by ~~~~ 
            html = html.replace(/~~~~/g, '"');
            html = html.replace(/~~/g, "'");

            // Show the modal
            $.modal(html, options);

            // Now make some adjustments for IE since it doesn't support rounded corners 
            // with this the corner radius is tied to the border width so it makes the 
            // borders a little larger than normal to have a more visible rounding.
            var ieBorderWidth = 6;
            var ieOffsetWidth = 0;

            // IE7
            if ($.browser.msie && $.browser.version == 7.0) {
                // Ok, this is a bit of a pain but in IE7 we have to adjust the width of our inner data div
                // and the amount we adjust it will vary based on the width of the borders and also the 
                // width of the screen which just makes this a ton of fun to do.
                // Start with our border width * 2 (left border + right border)
                ieOffsetWidth = (ieBorderWidth * 2);
                // If our container width is odd this may be a screen resolution issue so tweak by one pixel.
                var containerWidth = $('#simplemodal-container').width();
                if ((containerWidth % 2) == 1) {
                    ieOffsetWidth -= 2;
                }
                // Now make some small tweaks based on our screen width which seems to impact this for some reason
                if (screen.width >= 970 && screen.width <= 1010) {
                    // 972, 1004
                    ieOffsetWidth -= 1;
                }
                else if (screen.width >= 1200 && screen.width <= 1300) {
                    // 1239, 1280
                    ieOffsetWidth -= 1;
                }
                else if (screen.width >= 1350 && screen.width <= 1400) {
                    // 1396
                    ieOffsetWidth -= 1;
                }
                else if (screen.width >= 1500 && screen.width <= 1550) {
                    // 1536
                    ieOffsetWidth -= 1;
                }
                else if (screen.width >= 1650 && screen.width <= 1700) {
                    // 1688
                    ieOffsetWidth -= 3;
                }
                else if (screen.width >= 2000 && screen.width <= 2050) {
                    // 2021
                    ieOffsetWidth -= 1;
                }
                else if (screen.width >= 2100 && screen.width <= 2150) {
                    // 2133
                    ieOffsetWidth -= 1;
                }
                else if (screen.width >= 2250 && screen.width <= 2300) {
                    // 2293
                    ieOffsetWidth -= 2;
                }
                // Debug
                //alert("screen width: " + screen.width + "    container width: " + $('#simplemodal-container').width() + "   data width: " + $('#simplemodal-data').width());
            }
            // IE7 and IE8
            if ($.browser.msie && ($.browser.version == 7.0 || $.browser.version == 8.0)) {
                // See if flag is set to indicate we are asking for square corners and, if so, then do none of this rounding
                if (flags.toLowerCase().indexOf("iesquarecorners") >= 0) {
                    // For some reason certain content gets all jiggety-jacked with the simplemodal wrap div causing 
                    // sizing problems, unwanted scroll bars, etc. it's all more trouble than its worth so if we were 
                    // told ieSquareCorners as one of our flags then don't do any border adjustments.
                }
                else {
                    // Now adjust the data div width based on our IE7 calculated offset (see IE7-only code above)
                    if (ieOffsetWidth > 0) {
                        $('#simplemodal-data').width($('#simplemodal-container').width() - ieOffsetWidth);
                    }
                    // Round our container corners
                    $('#simplemodal-container').corner("cc:#666666 sc:#67A5D1 " + ieBorderWidth.toString() + "px");
                    // Add left and right borders to match what we have via rounding the top and bottom
                    $('#simplemodal-data').css('margin', '-20px -20px -20px -20px')
                                    .css('padding', '20px 20px 20px 20px')
                                    .css('border-left-style', 'solid').css('border-left-width', ieBorderWidth.toString() + 'px').css('border-left-color', '#67A5D1')
                                    .css('border-right-style', 'solid').css('border-right-width', ieBorderWidth.toString() + 'px').css('border-right-color', '#67A5D1');
                }
            }

        },


        // Shows URL inside iframe in modal dialog.  Parameters are:
        // 1. url = The url to display.
        // 2. width = The modal width.  The iframe width will default to this -5.  Default is 600.
        // 3. height = The modal heigth.  The iframe height will default to this -5.  Default is 300.
        // 4. scroll = The iframe scrolling setting.  Options are: yes, no, auto.  Default (and recommended value) is auto.
        // 5. flags = csv of flags to control modal display/behavior.  This is a shortcut method for declaring custom 
        // options where defaultOptions are mostly desired with changes specified in flags csv.  Possible 
        // values include: 
        //   a. WrapHtml - this flag wraps html in opening and closing markup which by default will center the message in the modal.
        //   b. CannotClose - this flag turns of modal close feature for cases where the dialog has buttons/links to control url 
        //      flow for things like mandatory login or registration.
        //   c. ZeroPadding - this flag removes default padding on the modal.  Html passed to the modal can include it's own padding.
        // 6. options = The modal options.  Defaults to defaultOptions.  The options minWidth and minHeight settings 
        // are set to width and height parameters (possibly adjusted if browser window is small).
        ShowPage: function (url, width, height, scroll, flags, options) {

            // Validate input parameters
            if (width == null || typeof (width) != "number") {
                width = 600;
            }
            if (height == null || typeof (height) != "number") {
                height = 300;
            }
            if (scroll == null || typeof (scroll) != "string" || (scroll != "yes" && scroll != "no" && scroll != "auto")) {
                scroll = "auto";
            }
            if (options == null) {
                options = defaultOptions;
            }

            // We end up calling ShowHtml() which will handle suggested dimensions but we do it here anyway because 
            // we need those dimensions for building our iframe tag which is passed into ShowHtml().

            // Note our requested width and height and see what suggestions we get
            suggestedWidth = width;
            suggestedHeight = height;
            suggestSize();

            // If we just lowered the suggested width or height below our requested width or height then turn 
            // scrolling to auto since we won't be showing the content in it's requested dimensions
            if (suggestedWidth < width || suggestedHeight < height) {
                scroll = "auto";
            }

            // Build the html for displaying our iframe using our suggested dimensions
            var html = '<iframe src="' + url + '" height="' + (suggestedHeight - 5).toString() +
                        '" width="' + (suggestedWidth - 5).toString() + '" scrolling="' + scroll + '" frameborder="0" />';

            // Now pass into ShowHtml() method for display
            this.ShowHtml(html, suggestedWidth, suggestedHeight, flags, options);

        },


        // Closes the modal dialog
        Close: function () {
            // Close the modal dialog
            $.modal.close();
            // Show flash elements that we hid when we displayed the modal
            showFlash();
            // If we asked to have our page refreshed then do that now
            if (refreshOnClose) {
                location.reload(true);
            }
        }


    };

} (); 
// The parens here cause the anonymous function to execute and return the object so public properties and methods are ready to use

