jQuery.fn.fadeToggle = function(speed, easing, callback) {
    return this.animate({opacity: 'toggle'}, speed, easing, callback);
};

jQuery.fn.slideFadeToggle = function(speed, easing, callback) {
    return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
};

//requires wrapper for content, i.e. var $box = $('#box').wrap('<div id="box-outer"></div>');
jQuery.fn.blindToggle = function(speed, easing, callback) {
    var h = this.height() + parseInt(this.css('paddingTop')) + parseInt(this.css('paddingBottom'));
    return this.animate({marginTop: parseInt(this.css('marginTop')) < 0 ? 0 : -h}, speed, easing, callback);
};

//helper function to check for elements that are hidden bc of their parent.
//default jQuery :hidden doesn't report hidden on a child elemenet if it is hidden due to inheritance from an anscestor element.
//jQuery.extend(jQuery.expr[ ":" ], {reallyvisible : "!(jQuery(a).is(':hidden') || jQuery(a).parents(':hidden').length)" });

//fixes jQuery ie7 reported as ie6 sometimes bug
//http://dev.jquery.com/ticket/3169
jQuery.browser.version = jQuery.browser.msie && /msie 7\.0/i.test(navigator.userAgent) ? "7.0" : jQuery.browser.version;


function NVGX() {
    var version = '2.1';
    return version;
}

NVGX.common = {
    enterKeyCode: 13,
    ctrlKeyCode: 17,
    escKeyCode: 27,
    ctrlDown: false,
    btnWaitingOriginalText: '',
    options: {
        isPopup: false
    },
    start: function () {
        if (NVGX.common.options.isPopup) NVGX.media.initPopups();
        NVGX.common.initToolTips();
        NVGX.common.initLinkBehaviors();
        NVGX.common.initFormBehaviors();
        NVGX.common.initTopNavState();
        NVGX.common.imageLinkable();
        NVGX.common.launchPrintDialog();
        NVGX.common.tableStripe();       
        //going away someday
        NVGX.error.start();
    },
    popNewWindow: function(url, title) {
        var win = window.open(url, title, "width=" + window.height + ",height=" + window.height + ",toolbar=yes,fullscreen=yes,location=yes,status=yes,scrollbars=yes,resizable=yes");
        if (win) {
            if (window.focus) {
                win.focus();
            }
        }
        else {
            alert("We have detected that an attempt to launch a popup window was unsuccessful.  Please be sure you allow popups in your browser for Navigenics.com");
        }
    },
    initNoCache: function() {
        $('.nocache').attr('autocomplete', 'off'); //put the 'nocache' on credit card fields and other fields that shouldn't cache the user input, doesn't work for all browsers
    },
    //make an inline image have a hover state, original image needs class of 'has-hover' to activate, uploaded hover image should have '-hover' appeneded to the end of the file name
    preloadHovers: function() {
        if (jQuery.browser.msie) {
            var originalImages = $('.hoverable-img').find('img.has-hover');
            var hoverSrc = [];

            $(originalImages).each(function(i) {
                hoverSrc.push(originalImages.eq(i).attr('src').split('.').join('-hover.'));
                originalImages.eq(i).after('<img class="hover-image" src="" alt="" />');
            });

            var hoverImages = $('.hoverable-img').find('img.hover-image');

            $(hoverImages).each(function(i) {
                $(this).attr('src', hoverSrc[i]);
            });

        } else {
            var originalImages = $('.hoverable-img').find('img.has-hover');
            var hoverImages = [];

            $(originalImages).each(function(i) {
                hoverImages.push(originalImages.eq(i).attr('src').split('.').join('-hover.'));
            });

            $(hoverImages).each(function(i) {
                $('<img />').attr('src', hoverImages[i]).addClass('hover-image').load(function() {
                    originalImages.eq(i).after($(this));
                });
            });
        }
    },

    //Standard table striping, if you want to stripe a table that has class standard, add the class: striped
    tableStripe: function() {
        $('table.standard.striped tr:even').addClass('even');
    },

    //processing button indicator, currently assumes button tag with left-right spans in it.
    initButtonWait: function() { //simple waiting... or processing button so people stop trying to click it when page takes a while to load.
        // disabled attr state was removed bc it breaks checkout wizard, instead put a css disabled version with greyed out button at some point since disabled isn't reliable across browsers anyway.
        var waitingButton = $('button.button-wait');
        waitingButton.click(function() {
            var waitingButtonTextSpan = $(this).children().children();
            NVGX.common.btnWaitingOriginalText = waitingButtonTextSpan.html();
            waitingButtonTextSpan.html('Processing...');
            $(this).css('cursor', 'pointer');
            waitingButtonTextSpan.addClass('waiting');
        });
    },
    //for ajax forms that don't refresh...
    removeButtonWait: function() {
        var waitingButtonSpan = $('span.waiting');
        if (waitingButtonSpan.length && NVGX.common.btnWaitingOriginalText != '') {
            waitingButtonSpan.html(NVGX.common.btnWaitingOriginalText);
            waitingButtonSpan.removeClass('waiting');
        }
    },

    //make an entire div become a clickable link by adding the class = "clickable". Will take on the href of the link in the div that has the class = "wholediv-clickable"
    clickableDiv: function() {
        NVGX.common.initCtrlKeyDownListener();
        //put this clickable class on the div you want to click
        var clickables = $('.clickable');
        if (clickables.length) {

            //put wholediv-clickable on the link you want use
            divHeights = [];
            divWidths = [];

            clickables.each(function(i) {
                divHeights.push($(this).height());
                divWidths.push($(this).width());
            });

            clickables.click(function() {
                if (NVGX.common.ctrlDown) {
                    NVGX.common.ctrlDown = false;
                    NVGX.common.popNewWindow($(this).find('a.wholediv-clickable').attr('href'), 'Navigenics');
                } else {
                    window.location.href = $(this).find('a.wholediv-clickable').attr('href');
                }
            });

            clickables.hover(
                function() {
                    $(this).addClass('hover');
                },
                function() {
                    $(this).removeClass('hover');
                }
            );
        }
    },
    initCtrlKeyDownListener: function() {
        $(document).keydown(function(event) {
            if (event.keyCode == NVGX.common.ctrlKeyCode) {
                NVGX.common.ctrlDown = true;
            }
        });

        $(document).keyup(function(event) {
            if (event.keyCode == NVGX.common.ctrlKeyCode) {
                NVGX.common.ctrlDown = false;
            }
        });
    },
    initBlockDoubleSubmit: function() {
        var formSubmitted = false;
        $('.block-double-submit').bind('submit', function(event) {
            if (!formSubmitted)
                formSubmitted = true;
            else
                event.preventDefault(); //stop submission if already submitted
        });
    },
    isIE6: function() { //helper function for determining IE6.
        return ($.browser.msie && (parseInt($.browser.version,10) <= 6));
    },
    isMac: function() {
        return (!!navigator.platform) && (navigator.platform.indexOf('Mac') !== -1);    
    },
    isFF3: function() {
        return ($.browser.mozilla && parseFloat($.browser.version) >= 1.9);
    },
    ie6LogoFix: function() {
        if (NVGX.common.isIE6()) {
            $('#header').find('img').attr('src', '/static/images/visitor/logo-print.gif');
        }
    },
    initHealthConditionsSelect: function() {
        $("select.conditionSelect").change(function() {
            $("form.selectSubmit").submit();
        });
    },
    launchPrintDialog: function() {
        $('.print-dialog').click(function() {
            window.print();
        });
    },
    simpleHideShow: function() {
        $('.hide-show-action').click(function() {
            $('.hide-show').toggle('fast', function() {
                $(document).bind('click', function(e) {
                    var clicked = $(e.target); // get the element clicked
                    if (clicked.is(":not('.hide-show')") || clicked.parents().is(":not('.hide-show')")) {
                        $('.hide-show').hide();
                    }
                });
            });
        });
        $('.hide-show-action').hover(function() {
            $(this).addClass('hover');
        },
        function() {
            $(this).removeClass('hover');
        });

    },
    hoverList: function() {
        $('.hover-list').find('li').hover(
            function() {
                $(this).addClass('hover');
            },
            function() {
                $(this).removeClass('hover');
            }
        );
    },
    imageLinkable: function() {
        if ($('.image-linkable').length) {
            var imgLinkable = $('.image-linkable img');
            imgLinkable.css('cursor', 'pointer');
            imgLinkable.click(function() {
                var container = $(this).parent();
                window.location = container.find('a.more').attr('href');
            });

            $('.image-linkable h2').hover(function() {
                $(this).addClass("hover");
            }, function() {
                $(this).removeClass("hover");
            });

            $('.image-linkable h3').hover(function() {
                $(this).addClass("hover");
            }, function() {
                $(this).removeClass("hover");
            });

            $('.image-linkable h2').click(function() {
                var container = $(this).parent();
                if (container.find('a').hasClass('newwindow')) {
                    window.open(container.find('a.more').attr('href'));
                    return false;
                } else {
                    window.location = container.find('a.more').attr('href');
                }
            });

            $('.image-linkable h3').click(function() {
                var container = $(this).parent();

                if (container.find('a').hasClass('newwindow')) {
                    window.open(container.find('a.more').attr('href'));
                    return false;
                } else {
                    window.location = container.find('a.more').attr('href');
                }
            });
        }
    },
    hoverImageSwap: function (element, startImage, hoverImage) {
        $(element).hover(
            function() {
                if ($(this).find('img').length >= 1) {
                    $(this).find('img')[0].src = hoverImage;
                }
            },
            function() {
                if ($(this).find('img').length >= 1) {
                    $(this).find('img')[0].src = startImage;
                }
            }
        );
    },
    newsletterSubmit: function() {
        if ($('.newsletter .email').attr('value') == 'email address') {
            $('.newsletter .email').attr('value', '');
        }
    },
    //this should be generalized, currently just the newsletter gets this
    initDefaultInputText: function(inputJQueryEl, defaultText) {
        inputJQueryEl.css('color', '#999'); //not adding a class becasue the ajax removes all classes added by js
        inputJQueryEl.attr('value', defaultText);
        inputJQueryEl.focus(function() {
            $(this).attr('value', '');
            inputJQueryEl.css('color', '#333');
        });
    },
    /*
     * Load a lightbox with jquery object content with options passed to the function.
     * options - can contain any of the modal plugin settings as well as custom ones:
     * {modal:true} //block any of the default escape mechanisms like escape key and mouse click. false by default.
     */
    loadLightBox: function(jqueryObject, options) {
        //navigenics defaults if no options passed below.  entire list included for reference.
        $.extend($.modal.defaults, {
            opacity: (options != undefined && options.opacity != undefined) ? options.opacity : 50,
            overlayId: (options != undefined && options.overlayId != undefined) ? options.overlayId : 'lightbox-overlay',
            overlayCss: (options != undefined && options.overlayCss != undefined) ? options.overlayCss : {},
            containerId: (options != undefined && options.containerId != undefined) ? options.containerId : 'lightbox-container',
            containerCss: (options != undefined && options.containerCss != undefined) ? options.containerCss : {position:'absolute'},
            dataCss: (options != undefined && options.dataCss != undefined) ? options.dataCss : {},
            zIndex: (options != undefined && options.zIndex != undefined) ? options.zIndex : 1000,
            close: (options != undefined && options.close != undefined) ? options.close : false,
            closeHTML: (options != undefined && options.closeHTML != undefined) ? options.closeHTML : '<a class="lightbox-close "title="Close">Close</a>',
            closeClass: (options != undefined && options.closeClass != undefined) ? options.closeClass : 'lightbox-close',
            position: (options != undefined && options.position != undefined) ? options.position : null,
            persist: (options != undefined && options.persist != undefined) ? options.persist : true, //needed for now to block ie error on subsequent loads
            onOpen: (options != undefined && options.onOpen != undefined) ? options.onOpen : null,
            onShow: (options != undefined && options != undefined).onShow ? options.onShow : null,
            onClose: (options != undefined && options.onClose != undefined) ? options.onClose : null,
            containerCssPositioning: (options != undefined && options.containerCssPositioning != undefined) ? options.containerCssPositioning : 'absolute' //default is to not scroll contents with page
        });

        jqueryObject.modal(); //setup the lightbox with global defaults set above, note plugin already has iframe method for ie6

        //setup bg click unload
        if (options != undefined && !options.modal) {
            var overlay = $('#' + $.modal.defaults.overlayId);

            overlay.click(function() {
                NVGX.common.unloadLightBox();
            });

            //setup global esc key to exit lightbox
            $(document).keydown(function(e) {
                if (e.which == NVGX.common.escKeyCode) {  // escape, close box
                    NVGX.common.unloadLightBox();
                }
            });
        }
    },
    unloadLightBox: function() {
        $.modal.close();
    },
    initDelayLightboxClose: function() { //function to delay the closing after a lightbox
        $('form.delay-lightbox-close').submit(function() {
            setTimeout(function () { NVGX.common.unloadLightBox();NVGX.common.initPrintReportOptions();}, 5000);            
            return true;
        });
    },
    initIE6ButtonHovers: function() {
        $('button').hover(
            function(){ $(this).addClass('btn-hover'); },
            function(){ $(this).removeClass('btn-hover');
        });

    },
    initFormBehaviors: function() { //set focus on first form element but not if user already clicked and started typing.
        NVGX.common.initNoCache();

        if ($('form').length) {

            var errors = $('.hasError').length;
            var fieldFocused = false;

            //allow force focus for forms with hidden but visible inputs like checkout :)
            var focusElement = $('.focus-first:first');
            if (!focusElement.length) { //if no focus-element identified, grab the first textfield
                focusElement = $("input[type='text']:visible:enabled:first").not('.skip-focus');  //might need to revisit later for textareas or other elements that are first in the form...
            }

            if (focusElement.length) {
                focusElement.focus(function() {
                    fieldFocused = true;
                });

                if (!errors && !fieldFocused) {
                    focusElement.focus();
                }
            }

            NVGX.common.initDefaultButtonClick();
            NVGX.common.initBlockDoubleSubmit();
        }

        NVGX.common.initButtonWait(); //this one doesnt need a form can be any button
    },
    initLoginPopupBehaviors: function() {
        //focus field, clear error message on unload, and set default submit button instead of cancel.
        var fieldFocused = false;
        var focusElement = $('.login-focus:first');

        focusElement.focus(function() {
            fieldFocused = true;
        });

        if (!fieldFocused) focusElement.focus();
        var loginInputs = $('form.login-form *');
        loginInputs.children().filter('input').attr('value', '');
        $('.feedbackPanel').hide();
        NVGX.common.defaultSubmitButtonClick(loginInputs);
    },
    initDefaultButtonClick: function() { //requires class of 'default-submit' for the submit button you want to tie to the enter key.
        if ($('form .default-submit').length) {
            var visibleFormInputs = $('form:visible *'); //skip any hidden forms, i.e inline or whatever content.
            NVGX.common.defaultSubmitButtonClick(visibleFormInputs);
        }
    },
    defaultSubmitButtonClick: function(jQueryFormElement) { //submit default button for enter button for child elements of a specific element
        var formListenerInputs = jQueryFormElement.children().filter('input').not('.skip-default-submit'); //only capture input enter keys for now and skip any that should be
        var elementToFire = jQueryFormElement.filter('.default-submit'); //use the default-submit button within the form in question.
        NVGX.common.registerKeyAction(formListenerInputs, elementToFire, 'enter');
    },
    registerKeyAction: function(listenerElements, elementToFire, key) { //helper function for any keypress activities
        var lastKeyPressCode;
        if (key == 'enter') var keyCode = NVGX.common.enterKeyCode; //only enter key for now, add more later as needed.

        listenerElements.keypress(function (e) {
            if ((e.which && e.which == keyCode) || (e.keyCode && e.keyCode == keyCode)) {
                if (!($.browser.mozilla && (lastKeyPressCode == 38 /* up */ || lastKeyPressCode == 40 /* down */))) //for firefox ignore arrow keys for autofill choices...
                    elementToFire.click();
                return false;
            }

            lastKeyPressCode = e.keyCode; //firefox/mozilla keycode
        });
    },
    initTextAreaLimit: function() {
        $('textarea').each(function() {
            NVGX.common.setTextAreaLimit($(this), 255);
        });
    },
    setTextAreaLimit: function(el, limit) {
        if (!limit) limit = 255;
        el.keypress(function () {
            if (($(this).val().length > limit)) $(this).val(($(this).val()).substring(0, limit));
        });
        el.keyup(function () {
            if (($(this).val().length > limit)) $(this).val(($(this).val()).substring(0, limit));
        });
    },
    initNewsTicker:function() {
        var newsItems = $('#news');
        if(newsItems.length) {
            newsItems.cycle({delay:2000, sync:0, pause:1});             
        }
    },
    /* use this for arrow driven expando stuff */
    initExpandingContent: function () {
        var toggleLink = $('.toggle-link');
        toggleLink.click(function() {
            $('.toggle-slide-content').slideFadeToggle('slow', function() {
                //$('.toggle-content').toggle(); //had to remove the toggle function has bugs with jquery 1.3 and IE8
                $('.toggle-content').each( function() {
                    if($(this).css('display') === 'none') {
                        $(this).css('display','inline');
                    }
                    else {
                        $(this).css('display','none');                        
                    }
                });

                toggleLink.toggleClass("toggle-link-down"); //flip the arrow to point open or closed
            });

            return false;
        });
    },
    initExpandingChoices:function() {
        /**
         * This function prepares a page to hide/show related content on click events.
         *
         * Minimally, this function looks for elements tagged with the class 'topic' and adjusts the visibility of
         * other elements tagged with 'topic-content' upon clicking.  Additionally, this function can also optionally make
         * visible a second element tagged with the class 'topic-related-content', to do so the corresponding topic
         * must also be tagged with 'topic-related'.
         *
         * If 'topic' is used on a form component (e.g. radio input), this function will also take into consideration
         * the 'checked' value of the component, and adjust the initial visibilty of the related content accordingly.
         *
         * This method makes a distinct assumption that all elements tagged as 'topics' are in one to one
         * correspondance with their associated 'topic-content' and optionally their 'topic-related-content'.
         * In particular this means that you will need to have topic-content's even for topics that don't have any subcontent.
         * For example:
         *   <input class"topic" name="A"/>
         *   <input class"topic topic-related" name="B"/>
         *   <div class="topic-content">Expanded content for A</div>
         *   <input class"topic" name="C"/>
         *   <div class="topic-content">Expanded content for B</div>
         *   <div class="topic-content hidden">Hidden content for C</div>
         *   <div class="topic-related-content hidden">Topic-related content for B</div>
         *
         * As the above example illustrates, The correspondances between 'topic'/'topic-content' and
         * 'topic-related'/'topic-related-content' are seperate.
         *
         * The 'topic-content' need not appear after their corresponding 'topic' in the document, but must appear in
         * same relative order (if topic A comes before topic B, then topic A's content must come before topic B's
         * content).  The same holds true for elements tagged with the 'topic-related-content' class.
         *
         * Currently this function is used for the Scripps and Sempra qualifications pages.
         */
        var topics = $('.topic');

        // content that should appear when the topic is clicked / checked
        var infos = $('.topic-content');
        var otherInfos = $('.topic-related-content');

        // this is where the assumption 1-1 correspondance between topics and contents is made
        topics.each(function(idx) {
            var info = infos.eq(idx);
            var otherInfo = otherInfos.eq(idx);

            $(this).click(function() {
                if (!info.is(":visible")) {
                    infos.hide();
                    otherInfos.hide();

                    if ($(this).hasClass('topic-related')) {
                        otherInfo.fadeIn("normal");
                    }
                    info.fadeIn("normal");
                }
            });

            /* Initial display cases (first render, and after form submits):
             *   if the topic is selected, show its corresponding topic-content and
             *   optionally any topic-related-contents */
            if ($(this).is(':checked')) {
                info.show();
                if ($(this).hasClass('topic-related')) {
                    otherInfo.show();
                }
            }
        });
    },
    initRelatedContent: function() { //made in a hurry for qualcomm only // (wpaoli) And modified in a hurry for same :-)
        var related = $('.related');
        var unRelated = $('.un-related');

        $('.reset-related').click(function() {
            related.find('input').attr('checked', 'checked');
            unRelated.show();
        });

        $('.set-related').click(function() {
            related.find('input').attr('checked', 'checked');
            related.find('input').removeAttr('disabled');
            unRelated.hide();
        });
    },
    /**
     * CAUTION. This method removes all alt or title values and displays them as a tooltips. If run-twice,
     * net result will be that first time all alt, title values will be removed and converted to tooltips and then the second time,
     * since there are no alt or title values left to use, all tooltips will be removed.
     */
    initToolTips: function() {

        var filter = function(index) { return $(this).attr('alt') || $(this).attr('title'); } //Filter out any elements that
                                                                                              //Dont have a title or alt attribute defined.
        var tooltips = $('.has-info-tip').filter(filter);

        if(tooltips.length) {
            tooltips.tooltip({ //this already has bgiframe detection in it.
                track: false,
                showURL: false,
                showBody: "::",
                delay: 0,
                extraClass: "info-tip",
                opacity: 0.95
            });    
        }
    },
    initLinkBehaviors: function() {
        $("a.newwindow").attr('target', '_blank');
        // this is for the inline informed consent page which for some reason is putting extra spans in
        $("a span.newwindow").parent().attr('target', '_blank');
        $("a.external").attr('target', '_blank'); // even though XHTML Strict doesn't want 'target', DOM 2.0 says it's ok
        $("a.blog").attr('target', 'blog');

        //if ie use an inline img instead bc css version doesnt do well when wrapped
        if ($.browser.msie) {
            var extImg = $('<img alt="View in another browser window" src="/static/images/common/external.gif" />').css('marginLeft', '3px');
            var pdfImg = $('<img alt="View Adobe Acrobat Reader PDF document" src="/static/images/common/pdf_icon.png" />').css({
                marginLeft:"3px",
                marginTop:"3px",
                marginBottom:"-3px"
            });

            $("a.external,a.pdf").not('.noimg')
                    .filter('.external').append(extImg).end()
                    .filter('.pdf').append(pdfImg).end()
                    .removeClass('external')
                    .removeClass('pdf');
        }
    },
    initPrintReportOptions: function () {
        var selectAllEnabledWrapper = $('.conditionSelectsEnabled'); //wrapper to disable/enable everything in it rather than each el one by one.
        var selectAllDisabledWrapper = $('.conditionSelectsDisabled');
        var checkboxes = $('.checkbox');
        var allRadio = $('.allConditions');

        $('.selectAllConditionsLink').click(function() {
            checkboxes.attr('checked', 'checked');
            return false;
        });

        $('.deselectAllConditionsLink').click(function() {
            checkboxes.attr('checked', '');
            return false;
        });

        var disableConditionSelects = function() {
            selectAllEnabledWrapper.removeClass('visible');
            selectAllEnabledWrapper.addClass('invisible');
            selectAllDisabledWrapper.removeClass('invisible');
            selectAllDisabledWrapper.addClass('visible');
        };

        var enableConditionSelects = function() {
            selectAllEnabledWrapper.removeClass('invisible');
            selectAllEnabledWrapper.addClass('visible');
            selectAllDisabledWrapper.removeClass('visible');
            selectAllDisabledWrapper.addClass('invisible');
        };

        allRadio.click(function() {
            checkboxes.attr('disabled', 'disabled').attr('checked', 'checked').next().addClass('disabled');
            disableConditionSelects();
        });

        $('.elevatedConditions').click(function() {
            $('.elevated').attr('disabled', 'disabled').attr('checked', 'checked').next().removeClass('disabled');
            $('.normal').attr('disabled', 'disabled').attr('checked', '').next().addClass('disabled');
            disableConditionSelects();
        });

        $('.chooseConditions').click(function() {
            checkboxes.attr('disabled', '').next().removeClass('disabled');
            enableConditionSelects();
        });

        //on load set default choices and update indicator
        allRadio.attr('checked', 'checked');
        checkboxes.attr('checked', 'checked').attr('disabled', 'disabled').next().addClass('disabled');
    },
    strengthInit: function()
    {
        var inputs = $('input.measured');
        var focusedOnce = false;

        if (inputs.length) {
            var container = $('<div id="pwStrength" class="strengthWidget"><h4 id="pwHead">Password strength</h4><p id="pwStatus" class="strengthStatus"></p><div id="pwMeter" class="strengthMeter"><div id="pwMeterLevel"></div></div></div>');
            container.appendTo("body").hide();

            container.stat = $('#pwStatus');
            container.meterLevel = $('#pwMeterLevel');

            inputs.focus(function() {
                //if it has an error lets not fire on first focus (either form load or user initiated) so they can start typing and see the error message.
                if (($(this).val().length) && (!($(this).hasClass('hasError') && !focusedOnce))) {
                    NVGX.common.strengthRender($(this), container);
                    container.fadeIn('normal');
                }
                focusedOnce = true;
            }).blur(function() {
                container.fadeOut('fast', 0);
            }).keyup(function() {
                if ($(this).val().length) { //only show if there is at least one char in there
                    container.fadeIn('normal');
                    NVGX.common.strengthRender($(this), container);
                }
                else {
                    container.fadeOut('fast', 0);
                }
            });

            if ($.fn.bgiframe) {
                container.bgiframe(); //fix ie6 z-index issues over scrollbars and select dropdowns
            }
        }
    },
    strengthRender: function(el, container) {
        var levels = ['#cccccc', '#ff0000', '#ff5f5f', '#399800', '#4dcd00', '#56e500'];
        var desc = ["Very Weak", "Weak", "Moderate", "Good", "Better", "Strong"];

        var score = NVGX.common.strengthMetric(el.val());

        container.meterLevel.css({
            'width':(2 * score) + 'em',
            'height':'1em', /* shouldnt be needed but is... */
            'background': levels[score]
        });

        container.stat.html(desc[score]);

        var offset = el.offset();
        container.css({
            'left': offset.left,
            'top': offset.top + el.height() + 6
        });
    },
    strengthMetric: function(value) {
        if (!value) return 0;
        var score = 0;
        if (value.length > 6) score++;
        if (value.length > 12) score++;
        if (value.match(/\d+/)) score++;
        if (value.match(/[a-z]/) && value.match(/[A-Z]/)) score++;
        if (value.match(/.[!,@,#,$,%,^,&,*,?,_,~,-,(,)]/))    score++;
        return score;
    },
    initTopNavState: function() {
        $('.top-nav a').click(function() {
            $(this).parent().addClass('clicked');
        });

        if(NVGX.common.isIE6()) {
            document.execCommand("BackgroundImageCache", false, true); //stops bg image flickering for ie6 sitewide
            NVGX.common.initIE6ButtonHovers(); //ie6 doesn't fire button hovers in css so need to do it using a css class        
        }

        NVGX.common.initTopNavFadeHover();        
    },

    initTopNavFadeHover: function() {
        var innerDiv;
        var button;

        $('ul.top-nav li a.nav-link').removeClass('nav-link'); //remove css hook for hover so it doesn't overwrite js

        $('.top-nav li').hover(function(){
            button = $(this);
            button.stop();
            if(!button.hasClass('clicked') || $('ul.top-nav li.clicked').count() <= 0) {
                if(!button.hasClass('order-now')) { //ignore order now bc opacity 0 will flash white behind it.
                    if(!button.hasClass('active')) {

                        innerDiv = button.find('.nav-inner-bg:not(:animated)'); //we need an absolutely positioned element in the li so the a doesn't inherit the opacity transition, similar to lightboxes

                        if(!innerDiv || !innerDiv.length) { //don't keep recreating dom elements, also needed to check for innerDiv for ie6
                            innerDiv = $('<div class="nav-inner-bg"></div>');

                            if(NVGX.common.isFF3() && NVGX.common.isMac()) { //had to bump width slightly for about us page for mac ff3 only...
                                innerDiv.css({height:button.height()+'px',width:(button.width() + .1)+'px'});
                            }
                            else {
                                innerDiv.css({height:button.height()+'px',width:button.width()+'px'});
                            }

                            button.append(innerDiv);
                        }

                        innerDiv.css({opacity:0,display:'block'}).animate({opacity:1},300);
                        button.find('a:not(:animated)').animate({color:"#ffffff"},50); //uses color plugin to avoid flicker of text
                    }
                    else {
                        button.find('a').addClass('nav-link'); //leave default no fade for actives
                    }
                }
                else { //order now button slightly different due to non-transparent starting state of a tag.

                    innerDiv = button.find('.nav-ordernow-inner-bg:not(:animated)'); //we need an absolutely positioned element in the li so the a doesn't inherit the opacity transition, similar to lightboxes

                    if(!innerDiv || !innerDiv.length) { //don't keep recreating dom elements
                        innerDiv = $('<div class="nav-ordernow-inner-bg"></div>');

                        innerDiv.css({height:button.height()+'px',width:button.width()+'px'});
                        button.append(innerDiv);
                    }

                    innerDiv.css({opacity:0,display:'block'}).animate({opacity:1},'fast');
                }
            }
        }, function() {
            button = $(this);
            button.stop();

            if(!button.hasClass('clicked')) {
                if(!button.hasClass('order-now')) {
                    if(!button.hasClass('active') && !(button.hasClass('clicked'))) { //keep the active states and selected color after click.

                        if(innerDiv && innerDiv.length) {
                            innerDiv.hide();
                        }
                        button.find('a').animate({color:"#444444"},1); //color plugin uses animate to stop instead of css.
                    }

                }
                else { //order now button mouseout
                    if(innerDiv && innerDiv.length) {
                        innerDiv.hide();
                    }
                }
            }
        });
    },

    simpleFadeOut: function(el) {
        $(el).fadeOut('fast');
    },

    simpleFadeIn: function(el) {
        $(el).fadeIn('fast');
    }


};

/* going away for redesign when error messages are changed to be handled by wicket instead of js, remove after conversion */
NVGX.error = {  //please make the js error functionality go away its all a big hack :(
    start: function() {
        var errs = $('.hasError');
        errs.not(".error-applied").each(function() {
            var emsg = $('<span class="error-message"></span>');
            emsg.html(!!$(this).attr('title') ? $(this).attr('title') : 'Complete this field');
            $(this).attr('title', '');

            if (this.tagName.toLowerCase() != 'fieldset' && $.inArray(['input', 'textarea', 'select'], this.tagName)) {
                $(this).after(emsg);
            }
            else {
                if ($(this).children().filter('.required').length) {
                    $(this).children().filter('.required').append(emsg);
                }
                else {
                    $(this).append(emsg);
                }
            }
            $(this).addClass("error-applied");
        });

        if (!!errs.length) {
            if (!errs.eq(0).is(':disabled')) {
                errs.eq(0).focus();
            }
        }
    }
};


NVGX.media = {
    initPopups: function() { //TODO properly convert this function to jquery and resize a popup based on it's contents size automatically
        //window.resizeBy(500, $(window).height());
    }
};

NVGX.pathways = {
    start: function(linkId) {
        var pathwaysTop = '15%';
        var options = {
            position:[pathwaysTop, ''],
            closeClass:'close',
            persist:false
        };

        if ($('#home')) {
            NVGX.common.loadLightBox($('.popup-container-wrap'), options);
        }

        var id_length = linkId.indexOf("-item");

        if (id_length > 0) {
            var id = linkId.substring(0, id_length);

            NVGX.pathways.initPathways(id);
            $('.previous').hide();
        }

        $('.previous').css('display', 'none');
        $('.previous').hide();
    },
    initPathways: function(pathwayId) {
        $('.pathway').css('visibility', 'hidden');

        var panels = $('#' + pathwayId + '-slider .content');
        var container = $('#' + pathwayId + '-slider .scrollContainer');
        var scroll = $('#' + pathwayId + '-slider .scroll');

        $('#' + pathwayId).css({'display':'block', 'visibility':'hidden'});

        //if .pagination has stuff in it then use it, otherwise, used .thumbnail-pagination
        if ($('#' + pathwayId + ' .pagination').length > 0) {
            var pagination_class = '.pagination';
        }

        if ($('#' + pathwayId + ' .thumbnail-pagination').length > 0) {
            var pagination_class = '.thumbnail-pagination';
        }

        el = $('#' + pathwayId + '-slider ' + pagination_class).find('a:first').get(0);

        var scrollOptions = {
            target: scroll,
            items: panels,
            navigation: pagination_class + ' a',
            prev: '.large-button.previous',
            next: '.large-button.next',
            axis: 'xy',
            duration: 300,
            easing: 'swing',
            onAfter: NVGX.pathways.trigger
        };

        //onload
        if ($('#' + pathwayId + ' .pathway').hasClass('image-left')) {
            $('#' + pathwayId + ' .column-first').find('img').hide();
            $('#' + pathwayId + ' .column-first').find('img').eq(0).addClass('on');
            $('#' + pathwayId + ' .column-first').find('img').eq(0).show();
        }

        $('.next').hide();
        $('.next').fadeIn('slow');

        container.css('width', panels[0].offsetWidth * panels.length);

        //Call to the serialScroll plugin:
        $('#' + pathwayId + '-slider').serialScroll(scrollOptions);

        //to deal with the ff3 issue of using the back button or refeshing and having the same slide that you left return. This will force the first frame
        $('#' + pathwayId + '-slider').localScroll(scrollOptions);

        //scrollOptions.duration = 1;
        $.localScroll.hash(scrollOptions);

        //If there is an image in the first column(on left), put the bg on behind the controls
        if ($('#' + pathwayId + ' .content:first .column-first').find('img').length > 0) {
            $('#' + pathwayId + ' .page-controls-bg').show();
            $('#' + pathwayId + ' .page-controls').addClass('over-image');
        } else {
            $('#' + pathwayId + ' .page-controls-bg').hide();
        }

        //events
        $('#' + pathwayId + ' ' + pagination_class + ' a').click(NVGX.pathways.selectPage);

        //Events for the image swaps, currently using the number at the end of the id string (eg: page-1) Java is working with those being numbers, so, Might as wll use that. Ideal would be to use the index array num opf the image list.
        $('#' + pathwayId + ' ' + pagination_class + ' a').click(function() {
            var prevSlide = this.hash;
            var prevSlideNum = prevSlide.split('-')[prevSlide.split('-').length - 1];
            NVGX.pathways.stopAndRestartFlash(prevSlideNum, pathwayId);
        });

        $('.next').click(function() {
            var prevSlide = el.hash;
            var prevSlideNum = prevSlide.split('-')[prevSlide.split('-').length - 1];

            NVGX.pathways.stopAndRestartFlash(prevSlideNum, pathwayId);
            NVGX.pathways.stopAndRestartFlash(parseInt(prevSlideNum) + 1, pathwayId);
        });

        $('.previous').click(function() {

            var prevSlide = el.hash;
            var prevSlideNum = prevSlide.split('-')[prevSlide.split('-').length - 1];

            NVGX.pathways.stopAndRestartFlash(prevSlideNum, pathwayId);
            NVGX.pathways.stopAndRestartFlash(parseInt(prevSlideNum) - 1, pathwayId);
        });

        $('.pathway').css('visibility', 'visible');
        $('#' + pathwayId).css({'visibility':'visible'});

        $('.thumbnail-pagination a:first').trigger('click');
        $('#' + pathwayId + ' a:first').trigger('click');

    },
    selectPage:function() {

        //Are we on the last panel? fade the next button
        var pathwaySlideName = this.hash.substring(1);
        var pathwayId = pathwaySlideName.substring(0, pathwaySlideName.indexOf('-page-'));
        var slideNum = this.hash.split('-')[this.hash.split('-').length - 1];

        var slideLength = $('#' + pathwayId + ' .content').length;
        //if .pagination has stuff in it then use it, otherwise, used .thumbnail-pagination
        if ($('#' + pathwayId + ' .pagination').length > 0) {
            var pagination_class = '.pagination';
        }

        if ($('#' + pathwayId + ' .thumbnail-pagination').length > 0) {
            var pagination_class = '.thumbnail-pagination';
        }

        if (slideNum == slideLength) {
            $('.next').fadeOut('fast');
        }

        if (slideNum == 1) {
            $('.previous').fadeOut('fast');
        } else {
            $('.previous').fadeIn('slow');
        }

        //Add the active class to the link to change the button state on pagination nav
        $('#' + pathwayId + ' ' + pagination_class + ' a').removeClass('active');
        $(this).addClass('active');
    },
    trigger:function(data) {
        var pathwayId = data.id.substring(0, data.id.indexOf('-page'));

        //if .pagination has stuff in it then use it, otherwise, used .thumbnail-pagination
        if ($('#' + pathwayId + ' .pagination').length > 0) {
            var pagination_class = '.pagination';
        }

        if ($('#' + pathwayId + ' .thumbnail-pagination').length > 0) {
            var pagination_class = '.thumbnail-pagination';
        }

        el = $('#' + pathwayId + '-slider ' + pagination_class).find('a[href$="' + data.id + '"]').get(0);

        NVGX.pathways.selectPage.call(el);

        if ($('#' + pathwayId + ' .column-first').find('img').length == 1) {
            if ($.browser.msie) {
                $('#' + pathwayId + ' .page-controls-bg').slideDown('fast');
            } else {
                $('#' + pathwayId + ' .page-controls-bg').fadeIn('fast');
            }
            $('#' + pathwayId + ' .page-controls').addClass('over-image');
        }

        //if this is not the last panel, fade back in the next button
        if ($('#' + pathwayId + ' .content:last').attr('id') != data.id) {
            $('#' + pathwayId + ' .next:hidden').fadeIn('fast');
        }
    },
    stopAndRestartFlash:function(pageId, pathwayId) {
        $('#' + pathwayId + '-page-' + pageId + ' object').each(function() {
            var movieID = $(this).attr("id");
            $("#" + movieID).get(0).restartMovie(); //call function defined in flash external interface to restart the movie
        });

        $('#' + pathwayId + '-page-' + pageId + ' embed').each(function() {
            var movieID = $(this).attr("id");
            $("#" + movieID).get(0).restartMovie(); //call function defined in flash external interface to restart the movie
        });
    }
};

NVGX.accordion = {
    start: function() {
        //inject the letters Q and A if there is an id of "q-and-a'
        $('#q-and-a dt').prepend('<span class="question">Q<span>:</span></span>');
        $('#q-and-a dd').prepend('<span class="answer">A<span>:</span></span>');

        $('.collapse-all').hide();
        $('.accordion dl').hide();
        $('.accordion .accordion-section').hide();

        $('.accordion h2').hover(
                function() {
                    if (!$(this).hasClass('selected')) {
                        $(this).addClass('hover');
                    }
                },
                function() {
                    $(this).removeClass('hover');
                }
                );

        $('.accordion h2').click(function() {
            var nextSection = $(this).next();
            var visibleDiv = $('.accordion .accordion-section:visible');

            if ($('.accordion').hasClass('all-expanded')) {   //this means all-expanded is on
                $(this).toggleClass('selected');
                if ($('.accordion .accordion-section:visible').length == 1) {
                    $('.collapse-all').hide();
                    $('.expand-all').show();
                }

                nextSection.slideToggle('fast');
                return;
            } else {
                $('.accordion h2').removeClass('selected');
                $(this).toggleClass('selected');
            }

            $('.accordion').removeClass('all-expanded');

            nextSection.slideToggle('fast');

            if (visibleDiv.length) {
                visibleDiv.slideUp('fast', function() {
                    if ($('.accordion .accordion-section:visible').length == 0) {
                        $('.collapse-all').hide();
                        $('.expand-all').show();

                        if (!$(this).hasClass('selected')) {
                            $('.accordion h2').not($(this)).removeClass('selected');
                        }

                    }
                });
            }
        });

        $('.expand-all').click(function() {
            $('.accordion .accordion-section').slideDown('fast', function() {
                $('.expand-all').hide();
                $('.collapse-all').show();
            });

            $('.accordion h2').addClass('selected');
            $('.accordion').addClass('all-expanded');
        });

        $('.collapse-all').click(function() {
            $('.accordion .accordion-section').slideUp('fast', function() {
                if ($('.accordion .accordion-section:visible').length == 1) {
                    $('.collapse-all').hide();
                } else {
                    $('.expand-all').show();
                }
            });

            $('.accordion h2').removeClass('selected');
            $('.accordion').removeClass('all-expanded');

        });

        $('.accordian-controls').hover(
            function() {
                $(this).addClass('hover');
                $(this).css('cursor', 'pointer');
            },
            function() {
                $(this).removeClass('hover');
            }
        );
    }
};

$(document).ready(function() {
    window.setTimeout(function() { //help with jquery safari domready loading issues http://dev.jquery.com/ticket/4187
        NVGX.common.start();
    }, 1);
});

