
/****************************************************************************************
 
 * Cincinnati Children's Hospital Medica Center
 * CCHMC.js
 * CCHMC JavaScript Framework and Classes
 
 * Dependencies:
    jQuery Library: http://jquery.com/
    JavaScript OOP Class Extention (included): http://ejohn.org/blog/simple-javascript-inheritance/
 
****************************************************************************************/




/* Setup 
****************************************************************************************/

//-- Define namespace 
var CCHMC = CCHMC || {};

//-- Create debug logging mode
window.log = function(arg){
  if(this.console){console.log(arg);}
};

//-- Include Javascript Class Extention
(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}})();

/***************************************************************************************************/



/* Class: Widget - Generic class to base all widgets off of
****************************************************************************************/
CCHMC.Widget = Class.extend({
	init: function(){}
});
/* End Class: Widget
****************************************************************************************/



/* Class: Accordion
****************************************************************************************/
CCHMC.Accordion = CCHMC.Widget.extend({
    /*  Accordion Class
    *  Expand and collapse blocks of grouped content
    *  See http://ccxlabs.development.rosetta.com/cchmc/accordion-demo.php for demos and html
    *  ****************************************
    *  target (required) : selector of the accordion DOM element
    *  Options:
    *    alternate : whether or not content alternats i.e. one open at a time or freely open and close content
    *    openOnStart:  index of content you want to open by default (set to -1 to have all closed)
    *    paneClass, headerClass, showHideButtonClass, printAllButtonClass:  if you want to specify other selectors for these elements
    */

    defaults: {
        alternate: false,
        openOnStart: 0,
        print: false,
        paneClass: ".pane",
        headerClass: ".header",
        showHideButtonClass: ".show_all_btn",
        printAllButtonClass: ".print_all_btn"
    },

    init: function(target, options) {
        this._super(); //init parent class (Widget class)

        //merge user defined options with its default settings
        this.settings = $.extend({}, this.defaults, options);

        //jQuery-ify the target dom elements
        this.target = $(target);

        //if no targets found, detroy the object, and exit
        if (this.target.length == 0) {
            this.target = null;
            return false;
        }

        //reference to use inside closures
        var This = this;

        //-- Class variables
        this.contentPanes = this.target.find("> " + this.settings.paneClass); //collect all the content pane elements in the context of the target
        this.headerElements = this.target.find("> " + this.settings.headerClass); //collect all the header elements in context of the target
        this.showHideAllBtn = this.target.find("> " + this.settings.showHideButtonClass); //get the show/hide all button
        this.printAllBtn = this.target.find("> " + this.settings.printAllButtonClass); //get the print all button

        //header element click event
        this.headerElements.click(function() {
            if ($(this).hasClass("open")) {
                This.closePane($(this));
            }
            else {
                //if in alternating mode, close previously opened pane
                if (This.settings.alternate) {
                    This.collapseAll();
                }
                This.openPane($(this));
            }


            This.resolveShowHideBtn();

            return false;
        });

        //add hide/show button
        this.headerElements.append('<a href="#" onclick="return false;" class="hide_show_btn">Show</a>');


        //hide/show all button click event
        this.showHideAllBtn.click(function() {

            //if all panes open, give the button collapse all functionality
            if (This.getOpenTabs() == This.headerElements.length) {
                This.collapseAll();
                $(this).removeClass("showAll").text("Show All");
            }
            else {
                This.expandAll();
                $(this).addClass("showAll").text("Hide All");
            }

            return false;
        });

        //print all button
        this.printAllBtn.click(function() {
            var printable = [];
            This.headerElements.each(function(i) {
                printable.push($(this));
                printable.push(This.contentPanes.eq(i));
            });

            new CCHMC.PrintJob(printable);
            return false;
        });

        //if individual item print option enabled
        if (this.settings.print) {
            //create print buttons
            this.headerElements.append('<a href="#" class="print_btn">Print</a>');
            this.headerElements.find(".print_btn").click(function() {
                var printable = [];
                printable.push($(this).parent());
                printable.push($(this).parent().next());
                new CCHMC.PrintJob(printable);
                return false;
            });

        }

        //open specified content on startup
        if (this.settings.openOnStart > -1) {
            $(this.headerElements[this.settings.openOnStart]).click();
        }

        //hide show/hide all button if only one group 
        if (this.headerElements.length == 1) {
            $(this.showHideAllBtn).hide();
        }

    }, //end init

    openPane: function(header) {
        header.addClass("open");
        header.find(".hide_show_btn").addClass("hide").text("Hide");
        header.find(".print_btn").show();
        header.next().slideDown(400);
        this.resolveShowHideBtn();
    },

    closePane: function(header) {
        header.removeClass("open");
        header.find(".hide_show_btn").removeClass("hide").text("Show");
        header.find(".print_btn").hide();
        header.next().slideUp(200);
        this.resolveShowHideBtn();
    },

    expandAll: function() {
        this.contentPanes.slideDown(400);
        this.headerElements.addClass("open");
        this.headerElements.find(".hide_show_btn").addClass("hide").text("Hide");
        this.headerElements.find(".print_btn").show();
    },

    collapseAll: function() {
        this.contentPanes.slideUp(200);
        this.headerElements.removeClass("open");
        this.headerElements.find(".hide_show_btn").removeClass("hide").text("Show");
        this.headerElements.find(".print_btn").hide();
    },

    resolveShowHideBtn: function() {
        //set the state of the show/hide all button based on whats open
        if (this.getOpenTabs() == this.headerElements.length) {
            this.showHideAllBtn.removeClass("showAll").text("Hide All");
        }
        else {
            this.showHideAllBtn.addClass("showAll").text("Show All");
        }
    },

    getOpenTabs: function() {
        //returns the number content panes open
        var open = 0;
        this.headerElements.each(function(i) {
            if ($(this).hasClass("open")) {
                open++;
            }
        });
        return open;
    }

});

/* End Class: Accordion
****************************************************************************************/




/* Class: Form
****************************************************************************************/
CCHMC.Form = Class.extend({
	
	init: function(){

  	},
  	
    textInputPrompt: function(selector, prompt, promptClass) {
        /* 
         * textInputPrompt: sets/hides text input field tips
         * params:
         *   selector: string - css/jquery selector to target
         *   prompt: string - text for prompt
         *   promptClass (optional): css class for styling the input field when prompt is shown
        */
        
        var $inputEl = $(selector);
        var styleClass = promptClass == null ? "text_field_prompt" : promptClass;

        $inputEl.addClass(styleClass).val(prompt).attr("defaultValue", prompt);
        
        $inputEl.focus(function() {
            if ($inputEl.val() === prompt) {
                $inputEl.val("");
            }
            $inputEl.removeClass(styleClass);
        });
        
       $inputEl.blur(function() {
            if ($inputEl.val() === "") {
                $inputEl.val(prompt);
                $inputEl.addClass(styleClass);
            }
        });
        
    },
    
    styleSelectbox: function(selector) {
        /* 
         * styleSelectbox: styles standard html select elements
         * params:
         *   selector: string - css/jquery selector to target
        */    	
    	
    	$(selector).sSelect();
    	
    },
    
    autocomplete: function(fieldInput, categorySelect, cacheData) {
    	
		//modify jquery UI autocomplete to bold current letters searched
		$.ui.autocomplete.prototype._renderItem = function (ul, item) {
            item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
            return $("<li></li>")
                    .data("item.autocomplete", item)
                    .append("<a>" + item.label + "</a>")
                    .appendTo(ul);
        };
    	
    	if(cacheData) {
	    	//setup a data cache on client side for performance
	    	var cache = {};
	    	
	    	//clear the cache if they change the category dropdown
	    	$(categorySelect).change(function() {
	    		cache = {};
	    	});
    	}
    	
		$(fieldInput).autocomplete({
			position: {
				offset: "-5 0"
			},
			minLength: 1, //live should be 3
			source: function(request, response) {
				
				//check the cache for data
				if(cacheData) {
					if ( request.term in cache ) {
						response( cache[ request.term ] );
						return;
					}
				}
				
				//send category param from the dropdown
				request.category = $(categorySelect).val();
				
				$.ajax({
					url: "ajax-content/autocomplete.php",
					dataType: "json",
					data: request,
					success: function( data ) {
						//add results to cache
						if(cacheData){cache[ request.term ] = data;}
						
						response( data );
					}
				});
			},
			select: function(event, ui) {
				log(ui.item ? ("Selected: " + ui.item.value + " id: " + ui.item.id) : "Nothing selected");
			},
			open: function() {
				//change search bar style on autocomplete open/close
				$(".utility_navigation .search").addClass("autocompleteOn");
			},
			close:function() {
				$(".utility_navigation .search").removeClass("autocompleteOn");	
			}
		});
   

    }
    
});


/* End Class: Form
****************************************************************************************/



/* Class: FeatureSlider
****************************************************************************************/
CCHMC.FeatureSlider = CCHMC.Widget.extend({
    /* 
     * FeatureSlider: An interactive animated slider displaying featured content
     * params:
     *   el: string - css/jquery selector to target to build slider upon
     *   slideTime (optional): int - milliseconds to rotate to next content. Leave out to enable manual navigation only
    */	
	init: function(el, slideTime){
		
		this.$slider = $(el);
		
		if(this.$slider.length) {
			
			var _this = this; //to use in closures
			this.width = this.$slider.width();
			this.$slidesArr = $(".slide", this.$slider);
			this.$slideContainer = $(".slide_container", this.$slider);
			this.numSlides = this.$slidesArr.length;
			this.currentSlide = 1;
			this.timer = null;
			
			this.$prevBtn = $('<a href="#" class="slider_prev">prev</a>').appendTo(this.$slider);
			this.$nextBtn = $('<a href="#" class="slider_next">next</a>').appendTo(this.$slider);
			this.$prevBtn.click(function(){
				_this.prevSlide(); 
				return false;
			});
			this.$nextBtn.click(function(){
				_this.nextSlide(); 
				return false;
			});
	
			this.$sliderBottom = $('<div class="slider_bottom"></div>').appendTo(this.$slider);
			this.$sliderNav = $('<div class="slider_nav"></div>').appendTo(this.$sliderBottom);
			this.$sliderNavBtns = $('<div class="slider_nav_btns"></div>').appendTo(this.$sliderNav);
			for(var i=1; i<this.numSlides+1; i++) {
				this.$sliderNavBtns.append('<a href="#" class="slider_nav_btn">'+i+'</a>');
			}
			
			this.$navLinks = $(".slider_nav_btn", this.$sliderNavBtns);
			this.$navLinks.each(function(i) {
				$(this).click(function() {
					_this.gotoSlide(i+1);
					return false;
				});
			});
		
			this.$navLinks.eq(0).addClass("active");
		
		}
		
  	},
  	
  	gotoSlide: function(num) {		
  		if(this.currentSlide != num) {
	  		this.currentSlide = num;
	  		this.$slideContainer.stop().animate({left: '-' + (this.width * (this.currentSlide-1))}, 700, "swing");	
			this.$navLinks.removeClass("active").eq(this.currentSlide-1).addClass("active");
  		}
  	},
  	
  	nextSlide: function() {
  		if(this.currentSlide == this.numSlides) {
  			this.gotoSlide(1);	
  		}
  		else {
  			this.gotoSlide(this.currentSlide+1);	
  		}
  	},
  	
  	prevSlide: function() {
  		if(this.currentSlide == 1) {
  			this.gotoSlide(this.numSlides);	
  		}
  		else {
  			this.gotoSlide(this.currentSlide-1);	
  		}  		
  	}

});
/* End Class: FeatureSlider
****************************************************************************************/



/* Class: FlyoutMenu
****************************************************************************************/
CCHMC.FlyoutMenu = CCHMC.Widget.extend({
    /* 
    * FlyoutMenu: 
    * params:
    *   el: jquery selector of navigation list you want to add flyouts to
    *   showOverlay: whether or not to blackout the background on hover
    *   showSpeed: animation speed in ms
    *   showDelay: Delay on hover before showing the menu, 0 for no delay
    */

    defaults: {
        showOverlay: true,
        displayOnActive: false,
        showSpeed: 100,
        hideSpeed: 0,
        showDelay: 100,
        hideDelay: 0
    },

    open: false,

    init: function(target, options) {

        //merge user defined options with its default settings
        this.settings = $.extend({}, this.defaults, options);

        //jQuery-ify the target dom elements
        this.target = $(target);

        //if no targets found, detroy the object, and exit
        if (this.target.length == 0) {
            this.target = null;
            return false;
        }

        //reference to use inside closures
        var This = this;

        //class vars
        this.flyoutMenu = $(".flyout_menu"); //capture the menu
        this.itemRollovers = $("li:has('.flyout_menu_content')", this.target); //capture all the rollover items from the target element
        this.topLevelLinks = $("a.top_level", this.itemRollovers); //capture the main top level links
        this.flyoutTab = $(".flyout_tab"); //capture tab
        this.flyoutMenuContent = $(".flyout_menu_content"); //capture array of menu content
        this.flyoutMenu.append(this.flyoutMenuContent); //put all content into menu
        this.showTimer, this.hideTimer;  //hover delay timer

        if (this.settings.showOverlay) {
            this.overlay = $('<div class="flyout_overlay"></div>').appendTo("body"); //add the overlay div
            var overlayOffset = $(".header").position().top; //set offset of overlay so it doesnt cover navigation
            var overlayHeight = $(document).height() - overlayOffset; //set overlay height
            this.overlay.css({ opacity: 0, top: overlayOffset, height: overlayHeight }); //apply to css

            $(window).resize(function() { //re-calculate overlay size on window resize
                overlayHeight = $(document).height() - overlayOffset;
                This.overlay.css({ height: overlayHeight });
            });
        }

        //Hover functionality for each menu item
        this.itemRollovers.each(function(i) {
            //if the menu item is active and you dont want to display the menu on active items, dont add hover functions
            if (!This.settings.displayOnActive && $(This.topLevelLinks[i]).hasClass("active")) {
                return;
            }
            $(this).hover(
				function() {
				    //on mouseover, if menu is already showing, just change the content, other wise show the menu
				    if (This.open) {
				        This.changeContent($(this), i);
				    }
				    else {
				        This.showMenu($(this), i);
				    }
				},
				function() {
				    This.hideMenu($(this), i);
				}
			);
        });

    },

    showMenu: function($navItem, i) {
        var This = this;
        this.showTimer = setTimeout(function() {
            clearTimeout(This.hideTimer);
            clearTimeout(This.showTimer);
            This.changeContent($navItem, i);
            This.flyoutMenu.show();
            if (This.settings.showOverlay) {
                This.overlay.show().stop().animate({ opacity: 0.5 }, This.settings.showSpeed); //fade in overlay
            }

            This.open = true;

        }, this.settings.showDelay);

    },

    hideMenu: function($navItem, i) {
        var This = this;
        clearTimeout(this.showTimer);
        this.hideTimer = setTimeout(function() {
            clearTimeout(This.hideTimer);
            $navItem.removeClass("hover");
            This.flyoutMenu.hide(); //hide the menu
            if (This.settings.showOverlay) {
                This.overlay.stop().animate({ opacity: 0 }, This.settings.showSpeed, function() { //hide the overlay
                    $(this).hide();

                    This.open = false;

                });
            }
        }, this.settings.hideDelay);
    },

    changeContent: function($navItem, i) {
        clearTimeout(this.hideTimer);
        this.itemRollovers.removeClass("hover");
        $navItem.append(this.flyoutMenu).addClass("hover"); //add menu to this list item, add hover class
        this.flyoutTab.attr("href", this.topLevelLinks.eq(i).attr("href")); //set the tab's link to the top level link	
        this.flyoutMenuContent.hide(); //hide all content
        this.flyoutMenuContent.eq(i).show(); //show corresponding content		
    }

});
/* End Class: Flyout Menu
****************************************************************************************/



/* Class: Lightbox
****************************************************************************************/
CCHMC.Lightbox = CCHMC.Widget.extend({
    /* Custom lightbox class
    * Extends jQuery Tools Overlay plugin
    * width/height: lightbox width/height
    * overlayColor, overlayOpacity: page overlay styling
    * showSpeed, closeSpeed: animation time of opening and closing
    * type: inline, ajax (inline should have the inline content id defined in rel, ajax should have url in href)
    * onBeforeLoad: function to call before lightbox opens
    * onLoad: function to call when the lightbox is open
    * onClose: function to close when lightbox is closed
    * onAjaxLoad: function to call if ajax lightbox and when that content is loaded.
    */

    defaults: {
        width: 'auto',
        height: 'auto',
        overlayColor: '#000000',
        overlayOpacity: 0.5,
        showSpeed: 300,
        closeSpeed: 300,
        type: "inline",
        onInit: function() { },
        onBeforeLoad: function() { },
        onLoad: function() { },
        onBeforeClose: function() { },
        onClose: function() { },
        onAjaxLoad: function() { },
        skipLoad: false,
        excludeSelector: "",
        closeButton: "",
        closeOnClick: true,
        directlightbox: null,
        zIndex: 9998
    },

    trigger: null,

    init: function(trigger, options) {

        //init with null trigger for programatic boxes without trigger

        //if trigger specified and it's not found on page, exit
        if (trigger && !$(trigger).length) {
            return false;
        }

        this.trigger = trigger;

        //merge user settings with default settings
        this.settings = $.extend({}, this.defaults, options);
        var This = this; //reference for closures

        if (this.settings.type != 'show') {
            //get the lightbox skeleton already in the html and clone it for use
            this.lightbox = $('.lightbox').eq(0).clone().hide().appendTo("body");
        }
        else {
            this.lightbox = this.settings.directlightbox;
        }
        //get content insertion point
        this.contentArea = this.lightbox.find(".lightbox_content").eq(0);

        //set its height and width
        this.contentArea.width(this.settings.width).height(this.settings.height);


        //initialize the jQuery Tools overlay plugin with our settings
        this.lightbox.overlay({
            mask: {
                color: This.settings.overlayColor,
                opacity: This.settings.overlayOpacity,
                loadSpeed: This.settings.showSpeed,
                closeSpeed: This.settings.closeSpeed,
                zIndex: This.settings.zIndex
            },
            top: 'center',
            oneInstance: false,
            onBeforeLoad: function() {
                This.lightbox.show().css("position", "fixed"); //IE gets set to relative with our CSS3 plugin
                //call additional function
                This.settings.onBeforeLoad();
            },
            onLoad: function() {
                //apply iScroll for iOS devices to scroll long content in the lightbox
                if ((/iphone|ipad/gi).test(navigator.appVersion)) {
                    var iscroller = new iScroll(This.contentArea[0]);
                    //refresh the scroller when the content size changes (i.e. an accordion is opened)
                    This.contentArea.children(0).resize(function() {
                        iscroller.refresh();
                    });
                }
                This.settings.onLoad();
            },
            onBeforeClose: function() {
                This.settings.onBeforeClose();
            },
            onClose: function() {
                This.close(This.settings.onClose);
            },
            close: This.settings.closeButton,
            closeOnClick: This.settings.closeOnClick
        });

        this.settings.onInit();
        //run an each loop because the selector element may be several links, etc.		
        $(trigger).each(function(i) {
            //open the lightbox when clicking the element	
            $(this).click(function() {
                This.setUpLightbox($(this), i);
                return false;
            });
        });

        return this;

    },

    setUpLightbox: function(element, index) {
        var This = this;

        //eliminate exclusions
        $(This.settings.excludeSelector).remove();

        //if the element has a rel attribute, (inline content)
        var content = $($(element).attr("rel"));
        //if ajax, get url
        if (This.settings.type == "ajax") {
            var ajaxURL = $(element).attr("href");
        }

        //put existing content in the lightbox if inline
        if (content.length) {
            //console.log(This.settings.excludeSelector);
            This.contentArea.empty().append(content.clone());
        }
        //else if its ajax, load the page
        else if (ajaxURL) {
            //show loading indication
            This.contentArea.empty().addClass("loading");
            This.contentArea.load(ajaxURL, function() {
                //on complete
                This.contentArea.removeClass("loading");
                //call additional function
                This.settings.onAjaxLoad();
            });

        }
        else if (This.settings.type == "image") {
            var imageURL = $(element).attr("href");
            var image = $('<img />').attr('src', imageURL).addClass('image');
            //when the image downloads..
            if (!This.settings.skipLoad) {
                $(image).load(function() {
                    This.contentArea.html(image);
                    This.lightbox.data("overlay").load(); //now open the lightbox
                });
            } else {
                This.contentArea.html(image);
                This.lightbox.data("overlay").load(); //now open the lightbox
            }

            //stop rest of click function because we want to open the lightbox only when the image is done loading
            return false;
        }
        else if (This.settings.type == "iframe") {
            This.contentArea.empty().append('<iframe frameborder="0" hspace="0" wspace="0" src="' + $(element).attr("href") + '" name="DOMWindowIframe' + Math.round(Math.random() * 1000) + '" style="width:100%;height:100%;border:none;background-color:#fff;" class="OverlayIframe" ></iframe>');
            $('.OverlayIframe').load();
        }

        //open the lightbox (jquery tools api call)
        This.lightbox.data("overlay").load();
    },

    getContentArea: function() {
        if (this.contentArea)
            return this.contentArea;
        else
            return false;
    },

    open: function() {
        this.setUpLightbox(this.trigger, 0);
        this.lightbox.data("overlay").load();
    },

    close: function(callback) {
        this.lightbox.data("overlay").close();

        if (this.settings.type != 'show') {
            this.contentArea.html("");
        }
        if (callback) { callback(); }
    }


});
/* End Class: Lightbox
****************************************************************************************/





/* Class: DoctorBio
****************************************************************************************/
CCHMC.DoctorBio = CCHMC.Widget.extend({
	/* Class: DoctorBio
	 * Creates accordion for bio content
	 * Opens the Bio in a lightbox when clicking on a bio link
	 */
	
	init: function(trigger){	
		
		//create a lightbox for the bios
		var docLB = new CCHMC.Lightbox(trigger, {
			width:760,
			height:525,
			//type: "ajax",
			//onAjaxLoad: function() {
			//just doing putting the content already rendered on the page instead of ajax now
			onLoad: function() {
				var contentArea = docLB.getContentArea();
								
				//accordionize the bio content in this context
				new CCHMC.Accordion(contentArea.find(".doctor-bio-accordion"), {
					alternate: true,
					openOnStart: -1
				});
				
				//show the hidden content
				contentArea.find(".doctor_bio").show();
				
				//create a lightbox for the high res image
				/*
				var imageLinks = contentArea.find(".zoom_btn");
				var imageLB = new CCHMC.Lightbox(imageLinks, {
					type:"image",
					onBeforeLoad: function() {
						//set a higher z-index on this lightbox because there is already one open
						imageLB.lightbox.css("z-index", parseInt(docLB.lightbox.css("z-index"))+1);	
					}
				});	
				*/
			}
		});

  	} //end init
  	
});

/* End Class: Doctor Bio
****************************************************************************************/


/* Class: Slider
****************************************************************************************/
CCHMC.Slider = CCHMC.Widget.extend({


    defaults: {
        circular: true,
        prevNextBtns: false,
        navigationBtns: true,
        navigationContainer: '.nav_btns',
        onBeforeSeek: function() { },
        onSeek: function() { }
    },

    init: function(target, options) {

        this.target = $(target);
        //if element not on page, exit funtion

        if (!this.target.length) {
            return false;
        }

        //merge user settings with default settings
        this.settings = $.extend({}, this.defaults, options);
        var This = this; //reference for closures	

        //see if the module contains any custom nav buttons already. If not, create them
        this.nav = this.target.find(this.settings.navigationContainer);
        if (!this.nav.length) {
            this.nav = $('<div class="nav_btns default" />').appendTo(this.target);
        }
        else {
            //set the first one to active
            this.nav.find("a").eq(0).addClass("active");
        }

        //call the jquery tools scrollable plugin
        //make the slider on the target's inner div, the class's target is really just a container
        this.sliderAPI = this.target.find(">:first-child").scrollable({
            circular: This.settings.circular,
            onBeforeSeek: This.settings.onBeforeSeek,
            onSeek: This.settings.onSeek
        }).data("scrollable");

        //call the jquery tools navigator plugin to create the buttons if wanted
        if (this.settings.navigationBtns) {
            this.target.find(">:first-child").navigator({
                navi: this.settings.navigationContainer
            });
        }

        //if prev next buttons wanted
        if (this.settings.prevNextBtns) {
            this.prevBtn = $('<a href="#" class="prev_btn"></a>').appendTo(this.target);
            this.nextBtn = $('<a href="#" class="next_btn"></a>').appendTo(this.target);
            this.prevBtn.click(function() {
                This.sliderAPI.prev();
                return false;
            });
            this.nextBtn.click(function() {
                This.sliderAPI.next();
                return false;
            });
        }

    },

    gotoSlide: function(slideNum, speed) {
        if (this.sliderAPI) {
            this.sliderAPI.seekTo(slideNum, speed ? speed : 0);
        }
    }

});

/* End Class: Slider
****************************************************************************************/


/* Class: Carousel - extends Slider
****************************************************************************************/
CCHMC.Carousel = CCHMC.Slider.extend({
	/* Extends the slider class by adding a timed slideshow to the slider */
	
	subDefaults : { //child class needs a different "defaults" name
		slideTime: 8000,
		mediaLinkClass: '.mediaLink',
		mediaContentClass: '.mediaContent'
	},
	
	init: function(target, options){
    	
    	//merge user settings with default settings
	    var subSettings = $.extend({}, this.subDefaults, options);
    	
    	//initialize the parent class (Slider)
    	this._super(target, subSettings);
    	if(!this.target.length) {
    		return false;	
    	}
    	
		var This = this; //reference for closures
		
		this.timer = null;
														
		//add a play/pause button
		this.playPauseBtn = $('<span class="pause_btn" />').insertBefore(this.nav);
		
		//add a time indicator bar animation
		$('<div class="progressBar"><div class="innerBar"></div></div>').insertBefore(this.nav);
		this.progressBar = this.target.find(".innerBar");
		
		//pause the slide timer if manual advance via the nav buttons
		this.nav.find("a").click(function() {
			This.pause();
			return false;
		});
		
		//collect any media(videos/flash) and set them up to open in a lightbox when clicking.
		this.mediaLinks = this.target.find(this.settings.mediaLinkClass);
		if(this.mediaLinks.length) {//if any media was present..
			//initialize a reusable lightbox for media to popup in
			this.mediaLightbox = new CCHMC.Lightbox(null ,{
				onBeforeLoad: function() {
					This.pause(); //pause the carousel when opening lightbox
				},
				onClose: function() {
					This.mediaLightbox.getContentArea().empty(); //destroy media on close
				}
			});	
	
			this.mediaLinks.each(function(i) {
				//when clicking a media link...
				$(this).click(function() {
					//get its associated media content (dependent on the html structure)
					var content = $(this).parent().siblings(This.settings.mediaContentClass)[0].cloneNode(true); //clone it (needed for ie bug)
					This.mediaLightbox.getContentArea().append(content); //add it into the lightbox
					This.mediaLightbox.open(); //open lightbox
					return false;	
				});
			});
		}
		
		//start the auto scrolling
		this.play();
		
	},
	
	play: function() {
		var This = this;
		//reset and animate the progress bar
		this.progressBar.width(0).stop().animate({width:"100%"}, this.settings.slideTime, "linear");
		//apply the interval timer
		this.timer = setInterval(function(){
			This.nextSlide();
		}, this.settings.slideTime);
		//change the functionality and look of the play/pause button
		this.playPauseBtn.removeClass("playing").unbind("click").bind("click", function(){ This.pause(); });		
	},
	
	pause: function() {
		var This = this;
		this.progressBar.stop();
		clearInterval(this.timer);
		//change the functionality and look of the play/pause button
		this.playPauseBtn.addClass("playing").unbind("click").bind("click", function(){ This.play(); });			
	},
	
	nextSlide: function() {
		this.sliderAPI.next();
		this.progressBar.width(0).stop().animate({width:"100%"}, this.settings.slideTime, "linear");		
	}
	
});
/* End Class: Carousel
****************************************************************************************/



CCHMC.Spotlight = CCHMC.Widget.extend({
	defaults : {},
	
	init: function(selector, options) {
		
    	this.settings = $.extend({}, this.defaults, options);
   		this.target = $(selector);
   		
	   	if(!this.target.length) {
	   		return false;	
	   	}
	   	

	   	var navigationSliderTarget = this.target.find(".spotlight_nav_slider");
	   	
	   	//if there is a custom navigation slider of images....
	   	if(navigationSliderTarget.length) {
	   		
	   		var navigationButtons = navigationSliderTarget.find(".spotlight_nav_btn");
	   		
	   		
		   	//create a sub-slider of the navigation buttons if necessary
		   	var navigationSlider = new CCHMC.Slider(navigationSliderTarget, {
		   		navigationBtns: false,
		   		prevNextBtns: true
		   	});
	
		   	
		   	//create the main slider, with no nav buttons.
		   	var mainContentSlider = new CCHMC.Slider(this.target, {
		   		navigationBtns: false
		 	});
		   	
		   	//we will manually map the navigation slider images because it gets kind of tricky
		   	navigationButtons.each(function(i) {
		   		$(this).click(function() {
		   			navigationButtons.removeClass("active");
		   			$(this).addClass("active");
		   			mainContentSlider.gotoSlide(i, 250);
		   			return false;
		   		});
		   	});
		   	
		   	//set first one to active
		   	navigationButtons.eq(0).addClass("active");
	   	}
	   	
	   	//otherwise just add the default nav buttons
	   	else {
	   		var mainContentSlider = new CCHMC.Slider(this.target);
	   		
	   	}
	   	
	   	
	   	
	}
});

/* Class: SpotlightCarousel - extends Slider
****************************************************************************************/
CCHMC.SpotlightCarousel = CCHMC.Slider.extend({
    /* Extends the slider class by adding a timed slideshow to the slider */

    init: function(target, slideTimer, options) {

        //merge user settings with default settings
        var subSettings = $.extend({}, this.subDefaults, options);

        this._super(target, subSettings);

        var This = this; //reference for closures

        this.target.each(function(i) {
            var slider = $(this);


            var innerTarget = slider.find(">:first-child");
            var nav = slider.find(This.settings.navigationContainer);
            var timer = slideTimer;

            nav.find(This.settings.navigationTag).click(function() {
                pause();
                return false;
            });

            //start the auto scrolling
            play();

            //internal functions inside the for each because slider Class selector could be multiple elements
            function play() {
                //apply the interval timer
                timer = setInterval(function() {
                    nextSlide();
                }, slideTimer);
            }

            function pause() {
                clearInterval(timer);
            }

            function nextSlide() {
                innerTarget.data("scrollable").next();
            }


        }); //end each

    }

});
/* End Class: SpotlightCarousel
****************************************************************************************/


/* Object: Media
****************************************************************************************/

CCHMC.Media = {

    /* Class: VideoPlayer
    ****************************************************************************************/
    VideoPlayer: CCHMC.Widget.extend({

        defaults: {
            width: "100%",
            height: 400
        },

        init: function(selector, options) {

            this.settings = $.extend({}, this.defaults, options);
            this.target = $(selector);

            if (!this.target.length) {
                return false;
            }

            //set the whole widget's width so the video player and description block are the same size
            $(selector).width(this.settings.width);

            //collect flash player target, set it to span the size of the widget
            this.flashTarget = $(selector).find(".flash_video").css({
                display: "block",
                width: "100%",
                height: this.settings.height + "px"
            });

            //save the video path
            this.videoSrc = this.flashTarget.attr("href");

            this.addFlashVideoPlayer();
        },

        addFlashVideoPlayer: function() {
            var self = this;
            //create flowplayer flash video player
            var autoplay = $(this.flashTarget[0]).find('img').length > 0;
            flowplayer(this.flashTarget[0], {
                src: "/includes/cchmc2010/flash/flowplayer-3.2.5.swf",
                onFail: function() {
                    //if no flash, add html5 player
                    self.addHTML5VideoPlayer();
                },
                wmode: "opaque"
            },
				{
				    canvas: CCHMC.Media.Viewport.Video1,
				    clip: { autoPlay: autoplay, scaling: 'fit' },
				    plugins: { controls: CCHMC.Media.Skins.Video1 }
				}
			);
        },

        addHTML5VideoPlayer: function() {
            this.flashTarget.remove();
            this.html5video = $('<video controls="controls" width="100%" height="' + this.settings.height + '"><source src="' + this.videoSrc + '" type="video/mp4"/></video>').prependTo(this.target);
        },

        html5ready: function() {
            return !!document.createElement('video').canPlayType
        }
    }),

    /* Class: Audio Player
    ****************************************************************************************/
    AudioPlayer: CCHMC.Widget.extend({
        defaults: {
            width: "100%"
        },

        init: function(selector, options) {

            this.settings = $.extend({}, this.defaults, options);
            this.target = $(selector);

            if (!this.target.length) {
                return false;
            }

            //set the whole widget's width so the audio player and description block are the same size
            $(selector).width(this.settings.width);

            //collect flash player target, set it to span the size of the widget
            this.flashTarget = $(selector).find(".flash_audio").css({
                display: "block",
                width: "100%",
                height: "100%"
            });

            //save the audio path
            this.audioSrc = this.flashTarget.attr("href");

            this.addFlashAudioPlayer();
        },

        addFlashAudioPlayer: function() {
            var self = this;
            //create flowplayer flash audio player	

            flowplayer(this.flashTarget[0], {
                src: "/includes/cchmc2010/flash/flowplayer-3.2.5.swf",
                onFail: function() {
                    //if no flash, add html5 player
                    self.addHTML5AudioPlayer();
                },
                wmode: "opaque"
            },
				{
				    canvas: CCHMC.Media.Viewport.Audio1,
				    clip: { autoPlay: false },
				    plugins: { controls: CCHMC.Media.Skins.Audio1 }
				}
			);
        },

        addHTML5AudioPlayer: function() {
            this.flashTarget.remove();
            this.html5audio = $('<audio controls="controls" width="100%"><source src="' + this.audioSrc + '" type="audio/mp3"/></audio>').appendTo(this.target);
        },

        html5ready: function() {
            return !!document.createElement('audio').canPlayType
        }

    }),

    Skins: {
        // Video1 is default skin for video applications
        // UI treatments of Video1 should be nearly identical to Audio1
        //Differences are noted in comment after property value
        Video1: {
            //location of control bar
            url: 'flowplayer.controls-3.2.3.swf',

            //player size, color, and location
            bottom: 0,
            left: 0,
            height: 30,
            background: '#c8c8c8',
            backgroundGradient: [0.81, 0],
            autoHide: false,

            //set control button states
            all: false,
            play: true,
            scrubber: true,
            time: true,
            mute: true,
            fullscreen: true,

            //tool tips for controls
            tooltips: {
                buttons: true,
                pause: 'Continue playing',
                volume: null,
                fullscreen: 'View Full Screen Video'
            },
            tooltipColor: '#1176c1',
            tooltipTextColor: '#ececec',

            //sliders, buttons, icons, etc.
            buttonColor: '#9c9c9c',
            buttonOverColor: '#f89929',
            sliderBorder: '1px solid #f5f5f5',
            sliderColor: '#333333',
            scrubberHeightRatio: 0.4,
            scrubberBarHeightRatio: 0.2,
            progressGradient: 'none',
            progressColor: '#666666',
            bufferColor: '#aaaaaa',

            //elapsed/total time display
            timeFontSize: 9,
            timeSeparator: ' / ',
            timeColor: "#666666",
            durationColor: "#cc6600",
            timeBgColor: null
        },

        // Audio1 is default skin for video applications
        // UI treatments of Audio1 should be nearly identical to Audio1
        //Differences are noted in comment after property value
        Audio1: {
            //location of control bar
            url: 'flowplayer.controls-3.2.3.swf',

            //player size, color, and location
            bottom: 0,
            left: 0,
            height: 30,
            background: '#c8c8c8',
            backgroundGradient: [0.81, 0],
            autoHide: false,

            //set control button states
            all: false,
            play: true,
            scrubber: true,
            time: true,
            mute: true,
            fullscreen: false,

            //tool tips for controls
            tooltips: {
                buttons: true,
                pause: 'Continue playing',
                volume: null,
                fullscreen: null
            },
            tooltipColor: '#1176c1',
            tooltipTextColor: '#ececec',

            //sliders, buttons, icons, etc.
            buttonColor: '#9c9c9c',
            buttonOverColor: '#f89929',
            sliderBorder: '1px solid #f5f5f5',
            sliderColor: '#333333',
            scrubberHeightRatio: 0.4,
            scrubberBarHeightRatio: 0.2,
            progressGradient: 'none',
            progressColor: '#666666',
            bufferColor: '#aaaaaa',

            //elapsed/total time display
            timeFontSize: 9,
            timeSeparator: ' / ',
            timeColor: "#666666",
            durationColor: "#cc6600",
            timeBgColor: null
        }
    },

    Viewport: {
        Video1: {
            backgroundColor: '#c8c8c8',
            backgroundGradient: 'none'
        },
        Audio1: {
            backgroundColor: '#c8c8c8',
            backgroundGradient: 'none'
        }
    }

}
/* End Object: Media
****************************************************************************************/


/* Class: Finder
****************************************************************************************/
CCHMC.Finder = CCHMC.Widget.extend({
    /*  Finder Class
    *  
    *  See http://ccxlabs.development.rosetta.com/cchmc/finder.php for demos and html
    *  ****************************************
    *  target (required) : selector of the DOM element
    *  Options:
    */

    defaults: {
        startingSection: 0,
        startingTab: 0,
        navigationClass: ".finder_module_nav",
        innerTabBeforeClick: function() { }
    },

    currentSection: 0,

    init: function(target, options) {

        this.finderModules = $(target);
        //if none on page, exit
        if (!this.finderModules.length) {
            return false;
        }

        //merge user settings with default settings
        this.settings = $.extend({}, this.defaults, options);
        var This = this; //reference for closures	
        //		var AZobject = {
        //			A:"A", B:"B", C:"C", D:"D", E:"E", F:"F", G:"G", H:"H", I:"I", J:"J", K:"K", L:"L", M:"M", N:"N", O:"O", P:"P", Q:"Q", R:"R", S:"S", T:"T", U:"U", V:"V", W:"W", X:"X", Y:"Y", Z:"Z"	
        //		}

        //map the left navigation to each finder module
        this.finderTopicLinks = $(this.settings.navigationClass).find(".find_topics a");
        this.finderTopicLinks.each(function(i) {
            $(this).click(function() {
                This.gotoSection(i);
                return false;
            });
        });

        //for each finder module (3)
        this.finderModules.each(function(i) {

            //setup tabs
            var startTab = 0;

            if (i == This.settings.startingSection) {
                startTab = This.settings.startingTab;
            }

            var tabContent = $(this).find(".finder_tab_content > div");

            var api = $(this).find(".tabs").tabs(tabContent, {
                initialIndex: startTab
                //history:true //causeing problems with backend?
            }).data("tabs");
            api.onClick(function(event, index) {
                This.settings.innerTabBeforeClick(event, index);
            });
            //add A-Z tab list to each tab
            //			tabContent.each(function(i) {
            //				generateAZList($(this));
            //			});

            //setup inline search
            //            var filterForm = new CCHMC.Form();
            //            var searchField = $(this).find(".inline_search_field");
            //            filterForm.textInputPrompt(searchField, "Enter Search Term");
            //            filterForm.autocomplete(searchField, ".search_category", false);


        }); //end each

        //start on the first section (Conditions & Health Topics)
        this.gotoSection(this.settings.startingSection);


        //utility function - generates an A-Z html tab list
        function generateAZList($contentArea) {

            var listHTML = '<ul class="AZlist">';
            var contentHTML = '<div class="AZContent">';
            for (var letter in AZobject) {
                listHTML += '<li><a href="#' + letter + '">' + letter + '</a></li>';
                contentHTML += '<div class="' + letter + '"><h6>' + letter + '</h6></div>';
            }
            listHTML += '</ul>';
            contentHTML += '<div>';

            var $content = $(contentHTML).prependTo($contentArea);
            var $list = $(listHTML).prependTo($contentArea);



            $list.tabs($content.find("> div"), {
                initialIndex: 0
            });

        }

    },

    gotoSection: function(number) {
        this.currentSection = number;
        this.finderModules.hide();
        this.finderModules.eq(number).show();
        this.finderTopicLinks.removeClass("active");
        this.finderTopicLinks.eq(number).addClass("active");
    }

});

/* End Class: Finder
****************************************************************************************/




/* Class: PrintJob
****************************************************************************************/
CCHMC.PrintJob = CCHMC.Widget.extend({
	/* PrintJob Class
	 * Prints indiviual pieces of content from a module
	 * Creates a print preview window of the content
	 * width/height: print popup window width/height
	 * autoPrint:  if you want the OS print dialog to come up right away
	 */
	
	defaults : {
		width:800,
		height:600,
		autoPrint: false
	},
	
	init: function(elements, options) {
		
		this.settings = $.extend({}, this.defaults, options);
		
		//collect the content we want in the print window
		var content = "";
		$(elements).each(function() {
			content += $(this).html();
		});
	
		//collect all the stylesheets from the originating page so the styles remain when we place in the new print window
		var insertCSS = "";	
		$("link[rel='stylesheet']").each(function(i) {
			insertCSS += '<link rel="stylesheet" type="text/css" href="' + $(this).attr("href") + '" />';
		});
		
		//-- HTML template for the print window
		//Notes: Toolbar contains print and close window buttons.
		//       Hide the window contents until all the images and css load to prevent flicker.
		//       Disable clicking of anything, should just be a "print preview".
		var printTemplate = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> \n \
			<html> \n \
			<head>' + insertCSS + ' \n \
				<script type="text/javascript">function contentLoaded() {document.getElementsByTagName("body")[0].style.display="block";}</script> \n \
			</head> \n \
			<body class="print" onclick="return false;"> \n \
				<div class="toolbar"> \n \
					<button onclick="window.print()">Print</button> \n \
					<button onclick="window.close()">Close Window</button> \n \
				</div> \n \
				<div class="print_content">' +  content + '</div> \n \
			</body> \n \
			</html>';
		
		//open a new window
		var printWindow = window.open("", "print_window", "height=" + this.settings.height + ",width=" + this.settings.width + ",menubar=0,location=0,scrollbars=1,status=1,toolbar=0,resizable=1");
		//write the contents we just constructed into the window
		printWindow.document.write(printTemplate);
		printWindow.document.close();
		
		if(this.settings.autoPrint) {
			printWindow.print();
		}

	}
	
});
/* End Class: PrintJob
****************************************************************************************/


/* Class: Map
****************************************************************************************/
CCHMC.Map = CCHMC.Widget.extend({

    defaults: {
        locationListSelector: '.location_list',
        mapExpandSelector: '.map_expand_button',
        initialLat: 39.139,
        initialLong: -84.504,
        zoom: 10
    },

    id: 'jello',

    geocoder: null,

    map: null,

    markers: null,

    infoWindows: null,

    target: null,

    init: function(data, target, options) {
        var This = this;
        /*
        * data: an array of location objects
        * target: dom element to put the map into
        */

        This.settings = $.extend({}, This.defaults, options);
        This.target = target;
        //initial lat/long

        //create the map
        This.map = new google.maps.Map(This.target, {
            zoom: This.settings.zoom,
            center: new google.maps.LatLng(This.settings.initialLat, This.settings.initialLong),
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });

        //geo-coding object
        This.geocoder = new google.maps.Geocoder();

        //store the markers and info windows for use
        This.markers = {};
        This.infoWindows = {};

        //close any info windows when clicking on the map
        new google.maps.event.addListener(This.map, 'click', This.closeAllInfoWindows);


        //set up the map expansion button
        $(This.settings.mapExpandSelector).toggle(
    	function() {
    	    This.closeAllInfoWindows();
    	    $(This.settings.locationListSelector).fadeOut(100, function() {
    	        var longSize = "636px";
    	        if ($(This.target).parents('.layout_2col_landing').length > 0) {
    	            longSize = "550px";
    	        }
    	        This.resizeMap(longSize);
    	    });
    	    $(this).addClass("expanded");
    	    return false;
    	},
    	function() {
    	    This.closeAllInfoWindows();
    	    var shortSize = "450px";
    	    if ($(This.target).parents('.layout_2col_landing').length > 0) {
    	        shortSize = "400px";
    	    }
    	    This.resizeMap(shortSize, function() {
    	        $(This.settings.locationListSelector).fadeIn();
    	    });
    	    $(this).removeClass("expanded");
    	    return false;
    	});

        //initialize the location list
        if ($(This.settings.locationListSelector + ' ul').length == 0) {
            var locationList = $("<ul/>").appendTo(This.settings.locationListSelector);

            //loop over the data and add locations
            for (var i = 0; i < data.length; i++) {
                data[i].index = i; //add an index property
                This.addLocation(data[i]);
            }
        }
    },


    /* Functions
    *************************************************/

    addLocation: function(location) {
        var This = this;
        //set a full address property of the location to use elsewhere
        location.fullAddress = location.streetAddress + " " + location.extendedAddress + ", " + location.city + ", " + location.state + " " + location.zip;

        //if lat and long were specified, add the marker and info window
        if ((location.lat && location.long) && (location.lat != 0 && location.long != 0)) {
            //console.log("lat/long specified for " + location.title);                        
            var marker = This.addMarker(location);
            This.addInfoWindow(marker, location);
        }
        //otherwise, use geocoding to get lat/long from address, and add marker and info window when complete
        else {
            This.geocoder.geocode({ 'address': location.fullAddress }, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    //set the lat/long for the location object
                    location.lat = results[0].geometry.location.lat();
                    location.long = results[0].geometry.location.lng();
                    //and add marker and info window when complete
                    var marker = This.addMarker(location);
                    This.addInfoWindow(marker, location);
                }
            });
        }

        //add location to List
        var locationLink = $('<li><a href="#">' + location.title + '</a></li>').appendTo(This.settings.locationListSelector);
        //center the map on that location when clicked
        locationLink.click(function() {
            This.closeAllInfoWindows();
            This.map.panTo(new google.maps.LatLng(location.lat, location.long));
            This.map.setZoom(parseInt(location.zoom));
            This.openInfoWindow(location, This.infoWindows[location.title], This.markers[location.title]);
            return false;
        });
    },

    addMarker: function(location) {
        var This = this;
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(location.lat, location.long),
            map: This.map,
            icon: new google.maps.MarkerImage("/includes/cchmc2010/images/logoicon.gif"),
            title: location.title,
            alt: location.title
        });
        This.markers[location.title] = marker;
        return marker;
    },

    addInfoWindow: function(marker, location) {
        var This = this;
        var infoWindow = new google.maps.InfoWindow({
            content: location.content,
            maxWidth: 330
        });
        This.infoWindows[location.title] = infoWindow;
        //open info window when clicking marker
        new google.maps.event.addListener(marker, 'click', function() {
            This.openInfoWindow(location, infoWindow, marker);
        });
    },

    openInfoWindow: function(location, infoWindow, marker) {
        var This = this;
        This.closeAllInfoWindows();
        infoWindow.open(This.map, marker);
        if (location.enableRoute) { //or check if it has the form
            This.initDirectionsForm(location); //have to initialize directions form AFTER window opens
        }
    },

    initDirectionsForm: function(location) {
        var This = this;
        //add click event to go button to get directions        
        $(This.target).find(".map_directions_submit:visible").bind("click", function(e) {
            This.getDirections($(This.target).find(".map_directions_input:visible")[0].value, location.fullAddress);
            return false;
        });

        //add key listener to get directions on enter button
        $(This.target).find(".map_directions_input:visible").bind('keypress', function(e) {
            if (e.keyCode == 13) {
                This.getDirections(This.value, location.fullAddress);
                return false;
            }
        });
    },

    getDirections: function(start, destination) {
        if (start) { //basic validation - don't submit if start address is blank
            window.open("http://maps.google.com/maps?f=d&source=s_d&saddr=" + start + "&daddr=" + destination);
        }
    },

    closeAllInfoWindows: function() {
        var This = this;
        for (var i = 0; i < This.infoWindows.length; i++) {
            This.infoWindows[i].close();
        }
    },

    resizeMap: function(size, callback) {
        //var origWidth = $(target).width(); 
        var This = this;
        $(This.target).animate({ width: size }, 500, function() {
            google.maps.event.trigger(This.map, "resize");
            This.map.panTo(new google.maps.LatLng(This.settings.initialLat, This.settings.initialLong));
            if (callback) callback();
        });
    }
});

/* Map Utility Functions
*************************************************/
CCHMC.Map.Utils = {
    collectData: function(selector) {
        /*
        * collects and formats the data outputted from backend
        * selector: class of each location dom object
        */
        var data = [];
        $(selector).each(function(i) {            
            var locObj = {
                lat: $(this).find(".lat").val(),
                long: $(this).find(".long").val(),
                title: $(this).find(".title").text(),
                streetAddress: $(this).find(".street_address").text(),
                extendedAddress: $(this).find(".extended_address").text(),
                city: $(this).find(".city").text(),
                state: $(this).find(".state").text(),
                zip: $(this).find(".zip").text(),
                phone: $(this).find(".phone").text(),
                content: $(this).html(),
                enableRoute: true,
                zoom: $(this).find(".zoom").val()
            };
            data.push(locObj);
        });
        return data;
    }
}
/* End Class: Map
****************************************************************************************/

/* Class : Slideshow
****************************************************************************************/
CCHMC.Slideshow = CCHMC.Widget.extend({

    defaults: {
        thumbPanelSelector: "",
        thumbFilterSelector: ""
    },

    target: null,

    mainSlideshow: null,

    thumbSlideshow: null,

    init: function(target, options) {
        this.settings = $.extend({}, this.defaults, options);
        this.target = target;
        var This = this;


        //remove empty thumb captions
        This.filterThumbs();

        //create main slider
        This.mainSlideshow = new CCHMC.Slider(target, {
            navigationBtns: false,
            onBeforeSeek: function(event, index) {
                This.resizeMainPanel(event, index);
            }
        });

        //create thumb slider
        This.createThumbSlider();
    },

    filterThumbs: function() {
        $(this.settings.thumbPanelSelector).find(this.settings.thumbFilterSelector).remove();
    },

    createThumbSlider: function() {
        var showPrevNext = $(this.settings.thumbPanelSelector).find('.slide').length > 1;
        var thumbSlideshow = new CCHMC.Slider(this.settings.thumbPanelSelector, {
            prevNextBtns: showPrevNext
        });
    },

    setUpThumbs: function() {
        var This = this;
        $(This.settings.thumbPanelSelector).find('.slide').not('.cloned').find('.slide_item:first').addClass('current');
        $(This.settings.thumbPanelSelector).find('.slide').not('.cloned').find('img').each(function(index) {
            $(this).click(function() {
                $(This.settings.thumbPanelSelector).find('.slide_item').removeClass('current');
                $(this).parent().addClass('current');
                This.mainSlideshow.gotoSlide(index, 250);
            });
        });
    },

    setUpLightboxes: function() {
        var lightboxes = new CCHMC.Lightbox(this.target + ' a.zoom', { type: "image", skipLoad: true });
        $('.lightbox a.zoom').live('click', function() {
            return false;
        });
    },

    resizeMainPanel: function(event, index) {
        var current = $(this.target).find('.slide').not('.cloned')[index];
        var carouselContainer = $(this.target).find('.carousel_content:first');
        if (carouselContainer) {
            var currentHeight = $(carouselContainer).height();
            var newHeight = $(current).height();
            $(carouselContainer).animate({ height: newHeight }, 150);
        }
    }
});
/* End Class: Slideshow
****************************************************************************************/

/* Class : Utility 
****************************************************************************************/
CCHMC.Utility = CCHMC.Widget.extend({
    getQueryVariable: function(variable, queryString) {
        var query = "";

        if (queryString) {
            query = queryString;
        } else {
            query = window.location.search.substring(1);
        }

        var vars = query.toString().replace('&amp;', '&').split("&");
        for (var i = 0; i < vars.length; i++) {
            var pair = vars[i].split("=");
            if (pair[0] == variable) {
                return pair[1];
            }
        }
    },

    excludeQueryValues: function(oldQuery, alsoRemove) {
        var tempOldQuery = ((oldQuery.startsWith('?')) ? oldQuery.substring(1) : oldQuery).replaceAll('&amp;', '&');
        var newArray = [];
        var oldvars = tempOldQuery.split('&');
        for (var i = 0; i < oldvars.length; i++) {
            var pair = oldvars[i].split('=');
            if (!alsoRemove[pair[0]]) {
                newArray.push(new CCHMC.QueryValue(pair[0], pair[1]).convertToQuery());
            }
        }
                
        return newArray.join("&");
    },

    preloadImages: function(arrayOfImages) {
        $(arrayOfImages).each(function() {
            $('<img/>')[0].src = this;
        });
    }
});

CCHMC.QueryValue = CCHMC.Widget.extend({
    
    key: "",
    
    value: "",

    init: function(key, value) {
        this.key = key;
        this.value = value;        
    },
    
    convertToQuery: function() {
        return this.key + "=" + this.value;
    }    
});
/* End Class: Utility
****************************************************************************************/

/* String extensions
****************************************************************************************/
String.prototype.startsWith = function(str) {
    return (this.indexOf(str) === 0);
}

String.prototype.replaceAll = function(find, replace) {
    var retVal = this;
    while (retVal.indexOf(find) != -1) {
        retVal = retVal.replace(find, replace);
    }
    return retVal;
}

String.prototype.toggle = function(either, or) {
    if (this == either) {
        return or;
    }
    return either;
}
/* End String extensions
****************************************************************************************

/* JQuery extensions
****************************************************************************************/
$(document).ready(function() {
jQuery.fn.toggleAttr = function(params) {
    this.each(function() {
        var attrValue = jQuery(this).attr(params.attr).toggle(params.either, params.or);
        jQuery(this).attr(params.attr, attrValue);
    });
    return this;
   };
   $(".striped tr").live("mouseover", function() { $(this).addClass("over"); });
   $(".striped tr").live("mouseout", function() { $(this).removeClass("over"); });
   $(".striped tr:even").addClass("alt");
   //$(".striped tr").mouseover(function() { $(this).addClass("over"); }).mouseout(function() { $(this).removeClass("over"); });
   
});
/* End JQuery extensions
****************************************************************************************/

