/**
 * @fileoverview frozTabs plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-04-28
 */

( function( $ ) {
    /**
     * Strict mark-up required
     * Places contents in tabs
     * @namespace frozTabs
     * @requires jQuery 1.2.6 and above / jQuery scrollTo / jqueryhashchange / frozTabs.css
     * @example jQuery( "#id-of-block-that-contains-links and contents" ).frozTabs
     * @return {jQuery Object}
     */
    jQuery.fn.frozTabs = function( options ) {
        var opts                     = jQuery.extend( {}, jQuery.fn.frozTabs.defaults, options );
        jQuery.fn.frozTabs.opts      = opts;
        var $this                    = jQuery( this );
        
        var storeData = function(set){
            var contentArray = new Array();
            var heightArray = new Array();

            jQuery('.' + opts.tabContainerClass, set).children('div').each( function(){
                contentArray.push('#' + jQuery(this).attr('id'));
                heightArray.push(jQuery(this).outerHeight(true));
            })
            
            set.data('contentArray', contentArray)
               .data('heightArray', heightArray)
               .data('contentLength', contentArray.length);
            
            return set;
        }
        
        var setupTabs = function(set){
        
            var tabs = new Array();
            var links = new Array();

            if ( opts.slider !== null ){
                jQuery('.' + opts.tabContainerClass, set).wrapInner(jQuery('<div class="' + opts.slider + '"></div>'));
                set.data('slider', jQuery('.' + opts.tabContainerClass, set).children())
                jQuery('.' + opts.tabContainerClass, set).children('div').children('div').each( function(){
                    tabs.push(jQuery(this));
                })
                set.data('slider').css({
                    overflow: 'hidden',
                    display: 'block',
                    position: 'relative'
                });
            } else {
                jQuery('.' + opts.tabContainerClass, set).children('div').each( function(){
                    tabs.push(jQuery(this).css({position: 'absolute'}).hide());
                })
            }
            
            jQuery('.' + opts.linkContainerClass, set).children('li').children('a').each( function(){
                links.push(jQuery(this));
            })
            
            set.data('tabs', tabs);
            set.data('links', links);
            
            setStarter(set);
            
            return set;
        }
        
        var setStarter = function(set){
            var finalIndex = 0;
            
            if ( opts.hashing === true ){
                var loc = checkHash();
                for ( index in set.data('contentArray') ){
                    if ( set.data('contentArray')[index] === loc ){
                        finalIndex = index;
                        break;
                    }
                }
            jQuery(window).data('tabhashclicked', false);
            } else {
                for( index in set.data('tabs') ){
                    if ( index == opts.selected ){
                        finalIndex = index;
                        break;
                    }
                }
            }
            
			activate(set, finalIndex);
            set.data('activeTabCount', finalIndex );
            var height = getContentHeight(set, finalIndex)
            
            if ( opts.slider !== null ){
                var top = getContentTop(set, finalIndex);
                jQuery('.' + opts.tabContainerClass, set).css({height: height + 'px'});
                set.data('slider').css({top: top + 'px'})
            } else {
            	showContent(set, finalIndex, height);
//                set.data('tabs')[finalIndex].show();
            }
            
            handleAutoScroll(set);
        }
        
        var activate = function(set, finalIndex){
        	for ( index in set.data('links') ){
        		set.data('links')[index].closest('li').removeClass(opts.activeClass);
        	}
        	
        	for ( index in set.data('tabs') ){
        		set.data('tabs')[index].removeClass(opts.activeClass);
        	}
        	
        	var baseIndex = opts.tabZIndexBase;
        	var liCount = set.data('links').length;
        	
        	set.data('links')[finalIndex].closest('li').addClass(opts.activeClass);
        	set.data('tabs')[finalIndex].addClass(opts.activeClass);
        	
        }
        
        var handleAutoScroll = function(set){
        	if (opts.autoScroll === true){
    	        jQuery.scrollTo(('#' + set.attr('id')), opts.autoScrollSpeed);   //scroll to tab
    	    } else if (opts.autoScroll === false){
    	        jQuery.scrollTo('body', opts.autoScrollSpeed);   //scroll to body
    	    } else {
    	        if (opts.autoScroll !== null){
    	            jQuery.scrollTo(opts.autoScroll, opts.autoScrollSpeed);  //scroll to specified element
    	        }
    	    } 
        }
        
        var checkHash = function(){
            if ( (jQuery.browser.msie === true) && (jQuery.browser.version === '7.0') ) {
            	var tabParam = window.location.toString().substring(window.location.toString().indexOf('#'));
            } else {
            	var tabParam = window.location.hash;
            }

            return tabParam;
        }
        
        var getContentHeight = function(set, index){
            
            return set.data('heightArray')[index];
        }
        
        var getContentTop = function(set, index){
            
            var finalTop = 0;
            
            for ( count in set.data('heightArray') ){
                if ( !(count > (index - 1)) ){
                    finalTop += set.data('heightArray')[count];
                }
            }
            
            return -(finalTop);            
        }
        
        var setupBehavior = function(set){
        	
        	for ( linkCount in set.data('links') ){
		        set.data('links')[linkCount].closest('li').click( function(){
		        	if ( !jQuery(this).hasClass(opts.activeClass) ){

				        var href = jQuery(this).children('a').attr('href');
				        var finalCount = 0;
				        
				        for ( count in set.data('contentArray') ){
				            if ( set.data('contentArray')[count] === href ){
				                finalCount = count;
				                break;
				            }
				        }
				            
			            var height = getContentHeight(set, finalCount);
				        if ( opts.slider !== null ){
				            var top = getContentTop(set, finalCount);
				            slideContent(set, height, top);
				        } else if ( opts.tabFade === true ){
				            fadeContent(set, finalCount, height);
				        } else {
				            showContent(set, finalCount, height);
				        }
				        
						activate(set, finalCount);
				        set.data('activeTabCount', finalCount );
				            
				        if ( opts.hashing === true ){
				        	jQuery(window).data('tabhashclicked', true);
				            updateHash(set, finalCount, href);
				        }
				        
		            }
		            return false;
		        })
            }
            return set;
        }
        
        var slideContent = function(set, height, top){
            jQuery('.' + opts.tabContainerClass, set).stop( false, true )
               .animate({height: height + 'px'}, opts.easingDuration, opts.slideEasing );
               
            set.data('slider').stop( false, true )
               .animate({top: top + 'px'}, opts.easingDuration, opts.slideEasing);
        }
        
        var fadeContent = function(set, finalCount, height){
            jQuery('.' + opts.tabContainerClass, set).stop( false, true )
               .animate({height: height + 'px'}, opts.easingDuration, opts.slideEasing );
            set.data('tabs')[set.data('activeTabCount')].stop( false, true ).fadeOut(opts.fadeTime);
            set.data('tabs')[finalCount].stop( false, true ).fadeIn(opts.fadeTime);
        }
        
        var showContent = function(set, finalCount, height){
            jQuery('.' + opts.tabContainerClass, set).stop( false, true )
               .css({height: height + 'px'});
            set.data('tabs')[set.data('activeTabCount')].stop( false, true ).hide();
            set.data('tabs')[finalCount].stop( false, true ).show();
        }
        
        var setupLinks = function(set){
        	var linkHead = jQuery('ul.' + opts.linkContainerClass, set);
        	var baseIndex = opts.tabZIndexBase;
        	var liCount = linkHead.children('li').length;

        	if ( opts.roundCorner === true ){
        		linkHead.addClass(opts.roundCornerClass)
        	}
        	
        	if ( opts.alignReverse === true ){
        		linkHead.addClass(opts.alignRightClass)
        		alignListRight(set, linkHead, liCount);
        	} 
        	
        	if ( opts.tabRightPos > 0 ){
        		linkHead.addClass(opts.alignRightClass)
        		alignListRight(set, linkHead, liCount);
        		
        		for ( index in set.data('links') ){
        			var parentLi = set.data('links')[index].closest('li');
        			parentLi.css({
        				zIndex: (baseIndex + (liCount - index)), 
        				left: (opts.tabRightPos * (liCount - index - 1))
        			});
        		}
        	
        	} else if ( opts.tabLeftPos > 0 ){
        		for ( index in set.data('links') ){
        			var parentLi = set.data('links')[index].closest('li');
        			parentLi.css({zIndex: (baseIndex + (liCount - index)), left: -(index * opts.tabLeftPos) + 'px'});
        		}
        	}
        
        	return set;
        }
        
        var alignListRight = function(set, linkHead, liCount){
        	var linkArray = new Array();
        	var dataLinks = new Array();
        	
        	linkHead.children('li').each( function(){
        		var clone = jQuery(this).clone(); 
        		
        		if ((jQuery.browser.msie === true) && (jQuery.browser.version === '7.0')){
		    		clone.children('a').attr('href', 
		    			clone.children('a').attr('href').slice(clone.children('a').attr('href').indexOf('#'))
		    		)
        		}	
        		
        		if (jQuery(this).nextAll().length === 0){
        			linkArray.push(clone);
        			dataLinks.push(clone.children('a'))
        			for ( ctr = 0; ctr < liCount; ctr++){
        				jQuery(this).after(linkArray[ctr]);
        			}
        			jQuery(this).remove();
        		} else {     	
        			linkArray.push(clone);
        			dataLinks.push(clone.children('a'))
        			jQuery(this).remove();
        		}
        	});      
        	
        	set.data('links', dataLinks);  
        }
        
        var updateHash = function(set, finalCount, href){
        	
        	var target = set.data('tabs')[finalCount]
        	var temp = target.attr('id');
        	
        	target.attr('id', '');
        
            if((jQuery.browser.msie === true) && (jQuery.browser.version === '7.0')){
		    	window.location = window.location.toString().substring(0, window.location.toString().indexOf('#')) + href;
		    } else {
            	window.location.hash = href;
		    }
		    
		    target.attr('id', temp);
		    
        }
        
        var handleHashchange = function(set){
        	if ( jQuery(window).data('tabhashclicked') === false ){
        		var href = checkHash();
        		var finalCount = null;
        		for ( index in set.data('contentArray') ){
        			if ( href === set.data('contentArray')[index] ){
        				finalCount = index;
        			}
        		}
        		
        		if ( finalCount !== null ){
        			set.data('links')[finalCount].trigger('click');
        			jQuery(window).data('tabhashclicked', false);
        		}
        	} else {
        		jQuery(window).data('tabhashclicked', false);
        	}
        }
        
        if ( $this.length > 0 ){
//            jQuery(window).load( function(){
            	
            	$this.each( function(){
            	    var set = storeData(jQuery(this));
            	    set = setupTabs(set);
            	    set = setupLinks(set);
            	    set = setupBehavior(set);
		        
		    	    jQuery(window).bind( 'hashchange', function(event) {
						if ( opts.hashing === true ){
							handleHashchange(set);	
						}
		        	})
			    });
            	
//            });
        }
         
	 	return $this;
    };
    
    /** 
     * Sends a message to the console
     * @private
     */
    var _debug = function( message ) {
        if ( true === jQuery.fn.frozTabs.opts.debug ) {
            console.log( message );
        }
    };
	    
    jQuery.fn.frozTabs.defaults =   {
    selected: 0,
	slider: null,
	slideEasing: 'easeInOutExpo',
	easingDuration: 'slow',
    roundCorner: false,
    tabZIndexBase: 1,
    tabLeftPos: 0,
    tabRightPos: 0,
    alignReverse: false, 					//should be true if links are aligned to the right but tabRightPos=0
    activeClass: 'froz-tab-active',
    alignRightClass: 'froz-tab-link-right',
    roundCornerClass: 'froz-tab-link-round',
    linkContainerClass: 'link-container',
    tabContainerClass: 'tab-container',     //div containing contents
    tabFade: true,
    fadeTime: 400,
    hashing: true,                          //determines if hash is used and updated along with tab usage
    autoScrollSpeed: 0,
    autoScroll: null                        //true: page auto-scrolls to tab
                                            //false: page auto scrolls to body
                                            //null: page does not autoscroll
                                            //if selectors are declared here, page auto-scrolls to declared element
    };          

} )(jQuery);
/**
 * @fileoverview frozInputModeler plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-09-27
 */
 
( function( $ ) {
    /**
     * all parameters
     * <ul> passes must have ID
     * all content banners must have the same dimensions
     * When thumbnails are clicked, contents slide over accordingly
     * @namespace frozInputModeler Plugin Namespace
     * @requires jQuery 1.2.6 and above / jquery mousewheel
     * @example jQuery( "#id-of-list-that-contains-contents" ).frozInputModeler
     * @return {jQuery Object}
     */
    jQuery.fn.frozInputModeler = function( options ) {
        var opts                            = jQuery.extend( {}, jQuery.fn.frozInputModeler.defaults, options );
        jQuery.fn.frozInputModeler.opts      = opts;
        var $this                           = jQuery( this );
        
        var disableSelect = function(doc){
            if ( jQuery.browser.msie === true ){
                doc.onselectstart = function(){
                    return false;
                }
            } else if ( jQuery.browser.mozilla === true ){
                if ( jQuery(doc).find('body').length < 1 ){
                    doc.style.MozUserSelect = 'none';
                } else {
                    doc.body.style.MozUserSelect = 'none';
                }
            } else if ( jQuery.browser.webkit === true ){
                if ( jQuery(doc).find('body').length < 1 ){
                    doc.style.WebkitUserSelect = 'none';
                } else {
                    doc.body.style.WebkitUserSelect = 'none';
                }
            }
        }
        
        var enableSelect = function(doc){
            if ( jQuery.browser.msie === true ){
                doc.onselectstart = null;
            } else if ( jQuery.browser.mozilla === true ){
                doc.body.style.MozUserSelect = null;
            } else if ( jQuery.browser.webkit === true ){
                doc.body.style.WebkitUserSelect = null;
            }
        }
        
        var initializeInputs = function(form){
            
            var modelArray = new Array();
            var count = form.find(opts.inputRoot).length + 1;
            
            jQuery('select', form).each( function(){
                if ( opts.renderSelect === true ){
                
                    jQuery(this).closest(opts.inputRoot).css({position: 'relative', zIndex: opts.baseIndex + count})
                    
                    var model = renderSelectModel(jQuery(this));
                    
                    modelArray.push(model);
                    count -= 1;
                    
                    jQuery(this).attr('tabIndex', -1);
                    model.attr('tabIndex', 0);
                    
                    jQuery(this).focusin( function(){
                        model.focus();
                    })
                }
            })
            
            return modelArray;
        }
        
                
        var renderSelectModel = function(input){
        
            var selectModel = createModel(input, opts.selectModelClass);

            var options = createSelectOptions(input.find('option'), selectModel, input);

            selectModel.append(options.css({position: 'absolute',
                                            top: parseInt(input.outerHeight(true)) + opts.selectOptionsTopAdjust,
                                            left: 0}));
            
            if ( jQuery.browser.msie === true ){
                input.fadeTo(1, 0.01).after(selectModel);
            } else {
                input.after(selectModel.fadeTo(1, 0.01)).fadeTo(1, 0.01, function(){
                    selectModel.fadeTo(1,1);
                });
            }
            
            return selectModel;
        }
        
        var createModel = function(input, className){
            var height = input.outerHeight(true);
            var width = input.outerWidth(true);
            var position = input.position();
            
            var inputModel = jQuery('<div id="' + input.attr('id') + '-model" class="' + className + '"></div>');
            inputModel.css({position: 'absolute'})
                      .animate({top: position.top, left: position.left}, 1)
            
            if ( opts.setDimensions === true ){
                inputModel.css({height: height, width: width}) 
            }
            
            
            return inputModel;
        }
        
        var createSelectOptions = function(options, model, input){
            var optList = jQuery('<ul class="' + opts.selectOptionsClass + '"></ul>');
            optList.wrap('<div class="' + opts.selectOptionsWrapperClass + '"></div>')

            var initText = null;
            
            if ( parseInt(opts.selectOptionHeight) > 0 ){
                var optionHeight = opts.selectOptionHeight + 'px';
            } else {
                var optionHeight = model.css('height');
            }
            
            options.each( function(){
                optList.append('<li>' + jQuery(this).text() + '</li>')

                if ( (jQuery(this).attr('value') == '') && (opts.allowBlankValue === false) ){
                    optList.children('li:last').data('value', jQuery(this).text());
                } else {
                    optList.children('li:last').data('value', jQuery(this).attr('value'));
                }
                
                if ( initText === null ){
                    initText = jQuery(this).text();
                }

                if ( jQuery(this).attr('selected') === true ){
                    initText = jQuery(this).text();
                }
            })
                
            optList.css({top: '0px', position: 'relative'}).closest('div.' + opts.selectOptionsWrapperClass).hide();
            optList.data('modelshowamount', opts.selectOptionsShowAmount);
            
            if ( opts.setDimensions === true ){
                optList.children().css({height: optionHeight})
            }
            
            model.prepend('<span class="' + opts.modelTextClass + '"></span>')
                 .find('span.' + opts.modelTextClass).text(initText)
            
            if ( opts.selectScrollBar !== null ){
            
                if ( (optList.data('modelshowamount') >= optList.children('li').length) || 
                     (optList.data('modelshowamount') < 1) ){
                    var listHeight = 'auto';
                } else {
                    optList.closest('div.' + opts.selectOptionsWrapperClass).addClass(opts.selectWithScrollClass);
                    var listHeight = parseInt(optionHeight) * optList.data('modelshowamount');
                    createScrollBar(optList, listHeight);
                }
                
                optList.wrap('<div class="' + opts.selectUlWrapperClass + '"></div>')
                if ( opts.setDimensions === true ){
                    optList.width(parseInt(model.css('width')))
                           .closest('div.' + opts.selectUlWrapperClass)
                           .css({height: listHeight,
                                 width: parseInt(model.css('width'))
                                })
                }
            }

            return optList.closest('div.' + opts.selectOptionsWrapperClass);
        }
        
        var createScrollBar = function(list, listHeight){
            var scroll = jQuery('<div class="' + opts.selectScrollBar + '"></div>');
            scroll.append('<div class="' + opts.selectScrollUpClass + '">&uarr;</div>')
                  .append('<div class="' + opts.selectScrollMarkerClass + '"></div>')
                  .append('<div class="' + opts.selectScrollDownClass + '">&darr;</div>')
                  .height(listHeight)
                  .children('div').css({position: 'absolute', left: '0px'});
            
            scroll.children('div.' + opts.selectScrollMarkerClass)
                  .css({top: (opts.selectScrollButtonHeight) + 'px', 
                        height: ((listHeight - (2 * opts.selectScrollButtonHeight)) * 
                                (list.data('modelshowamount')/list.children('li').length)) + 'px'
                        })
                  .data('minscroll', opts.selectScrollButtonHeight)
                  .data('maxscroll', listHeight - (opts.selectScrollButtonHeight) - 
                                     parseInt(scroll.children('div.' + opts.selectScrollMarkerClass).css('height')))
                  
            scroll.children('div.' + opts.selectScrollDownClass)
                  .css({top: (listHeight - opts.selectScrollButtonHeight) + 'px'});
            
            list.after(scroll);
        }
        
        var setValue = function(model, li){
            model.find('span.' + opts.modelTextClass).text(li.text());
            model.prev(':input').val(li.data('value'));
        }
        
        var closeOptions = function(options){
            options.closest('div.' + opts.selectOptionsWrapperClass).removeClass(opts.selectShownOptionsClass).hide()
                   .closest('div.' + opts.selectModelClass).removeClass(opts.selectActiveModelClass);
        }
        
        var deselectForm = function(count, models){
            for ( index in models){
                if ( index != count){
                    closeOptions(models[index].find('ul.' + opts.selectOptionsClass));
                }
            }
        }
        
        var setupSelectBehavior = function(model, count, models){
            var options = model.find('ul.' + opts.selectOptionsClass);
            model.focusout( function(){
                closeOptions(options);
                jQuery(this).data('clickonly', false);
            }).focusin( function(){
                deselectForm(count, models)
                options.closest('div.' + opts.selectOptionsWrapperClass).addClass(opts.selectShownOptionsClass).show();
                jQuery(this).addClass(opts.selectActiveModelClass);
                jQuery(this).data('clickonly', false);
            }).keydown( function(event){
                if (event.keyCode == '38'){  //up
                    selectUp(options);
                    if ( !options.closest('div.' + opts.selectOptionsWrapperClass).hasClass(opts.selectShownOptionsClass) ){
                        options.find('li.' + opts.selectActiveListClass).trigger('click')
                    }
                    return false;
                } else if (event.keyCode == '40') {        //down
                    selectDown(options);
                    if ( !options.closest('div.' + opts.selectOptionsWrapperClass).hasClass(opts.selectShownOptionsClass) ){
                        options.find('li.' + opts.selectActiveListClass).trigger('click')
                    }
                    return false;
                } else if (event.keyCode == '13'){
                    options.find('li.' + opts.selectActiveListClass).trigger('click')
                    deselectForm(count, models)
                    closeOptions(options);
                    return false;
                } else if (event.keyCode == '27'){
                    closeOptions(options);
                }
            }).click( function(){
                if ( jQuery(this).data('clickonly') === true ){
                    if ( jQuery(this).find('div.' + opts.selectOptionsWrapperClass).hasClass(opts.selectShownOptionsClass) ){
                        closeOptions(options);
                    } else {
                        deselectForm(count, models)
                        options.closest('div.' + opts.selectOptionsWrapperClass).addClass(opts.selectShownOptionsClass).show();
                        jQuery(this).addClass(opts.selectActiveModelClass);
                    }
                } else {
                    jQuery(this).data('clickonly', true)
                }
            }).mousewheel( function(event, delta){
                if ( options.closest('div.' + opts.selectOptionsWrapperClass).hasClass(opts.selectShownOptionsClass) ){
                    var diff = Math.abs(delta);
                    var counter = 0
                    jQuery(document).data('scrollOnly', true);
                    
                    while ( counter < diff ){            
                        if ( delta > 0 ){
                            handleKey(jQuery(this), event, delta);
                        } else {
                            handleKey(jQuery(this), event, delta);
                        }
                        
                        counter += 1;
                    }
                    
                    return false;
                }
            })
            
            options.children('li').click( function(){
                renderListInactive(options);
                jQuery(this).addClass(opts.selectActiveListClass);
                setValue(model, jQuery(this));
                closeOptions(options);
                model.data('clickonly', false);
            }).mouseenter( function(){
                if ( jQuery(document).data('scrollOnly') === false){
                    renderListInactive(options);
                    jQuery(this).addClass(opts.selectActiveListClass);
                }
            });
            
            model.find('div.' + opts.selectScrollBar).children('div').click( function(event){
                
                if ( jQuery(this).hasClass(opts.selectScrollUpClass) ){
                    jQuery(this).data('scrollStart', parseInt(event.pageY));
                    handleKey(model, event, 1);
                } else if ( jQuery(this).hasClass(opts.selectScrollDownClass) ){
                    jQuery(this).data('scrollStart', parseInt(event.pageY));
                    handleKey(model, event, -1);
                }
                
                model.data('clickonly', true);
                return false;
            })
            
            model.find('div.' + opts.selectScrollBar).children('div.' + opts.selectScrollMarkerClass).each( function(){
                jQuery(this).data('baseScrollStart', null);
                jQuery(this).data('baseScrollEnd', null);
            }).mousedown( function(e){
                jQuery(this).addClass(opts.selectActiveScrollerClass);
                jQuery(document).data('modelScroll', jQuery(this))
                disableSelect(document);
                
                if ( jQuery(this).data('baseScrollStart') === null ){
                    jQuery(this).data('baseScrollStart', parseInt(e.pageY));
                    jQuery(this).data('baseScrollEnd', parseInt(e.pageY) + jQuery(this).data('maxscroll'));
                }
                
                jQuery(this).data('scrollStart', parseInt(e.pageY));
            })
            
            jQuery(document).mouseup( function(){
                if ( jQuery(document).data('modelScroll') !== null ){
                    jQuery(document).data('modelScroll').removeClass(opts.selectActiveScrollerClass);
                }
                
                jQuery(document).data('modelScroll', null);
                enableSelect(document);
            })
        }
        
        var handleKey = function(model, event, delta){
            var marker = model.find('div.' + opts.selectScrollMarkerClass);
            
            dragMarker(marker, -(delta * opts.scrollMultiplier), event);            
        }
        
        var handleDrag = function(marker, event){
            var diff = event.pageY - marker.data('scrollStart');

            if (!((event.pageY < marker.data('baseScrollStart') && (diff > 0)) ) && 
                !((event.pageY > marker.data('baseScrollEnd') && (diff < 0)) ) ){
                dragMarker(marker, diff, event);
            }
        }
        
        var dragMarker = function(marker, diff, event){
            
            var newTop = parseInt(marker.css('top')) + diff;
            
            if (newTop > marker.data('maxscroll')){
                newTop = marker.data('maxscroll')
            } else if (newTop < marker.data('minscroll')){
                newTop = marker.data('minscroll')
            }

            marker.css({top: newTop + 'px'});

            marker.data('scrollStart', parseInt(event.pageY) );
            setForScroll(marker, diff, newTop);
        }
        
        var setForScroll = function(marker, diff, newTop){
            list = marker.closest('div.' + opts.selectOptionsWrapperClass).find('ul.' + opts.selectOptionsClass);
            
            var detect = (newTop - marker.data('minscroll')) / (marker.data('maxscroll') - marker.data('minscroll'));

            if ( diff > 0 ){
                var direction = 'bottom';
            } else {
                var direction = 'top';
            }
            
            scrollPage(list, 0, direction, detect)
        }
        
        var scrollPage = function(list, count, align, detect){
            var scrollTop = parseInt(list.css('top'));
            var wrapperHeight = list.closest('div.' + opts.selectOptionsWrapperClass).innerHeight();
            var liHeight = list.children('li:first').outerHeight(true);
            var liCount = list.children('li').length;
            var maxTop = liHeight * (liCount - list.data('modelshowamount'));
            var activePoint = 0;

            if ( detect === false ){
                if ( count === null ){
                    if ( list.children('li.' + opts.selectActiveListClass).length < 1 ){
                        count = 0;
                    } else {
                        count = list.children('li.' + opts.selectActiveListClass).prevAll().length;
                    }
                }
            
                var startPoint = Math.abs(scrollTop);
                var endPoint = startPoint + wrapperHeight - liHeight;
                activePoint = count * liHeight;
                
                if ( !((startPoint <= activePoint) && (activePoint < endPoint)) ){
                
                    if ( align === 'bottom' ){
                        activePoint -= ((list.data('modelshowamount') - 1) * liHeight);
                    }
                    
                    if ( activePoint > maxTop ){
                        activePoint = maxTop;
                    } else if ( activePoint < 0 ){
                        activePoint += ((list.data('modelshowamount') - 1) * liHeight);
                    }
                    
                    list.stop(false, true).animate({top: '-' + activePoint + 'px'}, opts.selectScrollSpeed);
                    scrollMarker(list, activePoint, liHeight, liCount, count);
                    
                }
            } else {
                count = Math.floor((liCount - list.data('modelshowamount')) * detect);
                activePoint = count * liHeight;
                list.stop(false, true).animate({top: '-' + activePoint + 'px'}, opts.selectScrollSpeed);
            }
            
            
        }
        
        var scrollMarker = function(list, activePoint, liHeight, liCount, count){
            var scrollButton = list.closest('div.' + opts.selectOptionsWrapperClass)
                                   .find('div.' + opts.selectScrollMarkerClass);
            
            var scrollMin = scrollButton.data('minscroll');
            var scrollMax = scrollButton.data('maxscroll');
            var scrollInc = (scrollMax - scrollMin) / (liCount - list.data('modelshowamount'));
            
            var topAdjust = scrollMin + (scrollInc * (activePoint / liHeight));
            
            if ( topAdjust > scrollMax ){
                topAdjust = scrollMax;
            } else if ( topAdjust < scrollMin ){
                topAdjust = scrollMin;
            }            

            scrollButton.stop(false, true).animate({top: topAdjust + 'px'}, opts.selectScrollSpeed);
        }
        
        var selectUp = function(list){
            var activeList = list.find('li.' + opts.selectActiveListClass);
            var count = 0;

            renderListInactive(list);
            
            if ( !(activeList.length < 1) ){
                count = activeList.prevAll().length - 1;
                list.children('li:eq(' + count + ')').addClass(opts.selectActiveListClass)
            } else {
                count = -1;
            }
            
            var direction = 'top';
            
            if ( count < 0 ){
                count = -1;
            } else {
                scrollPage(list, count, direction, false);
            }
            
        }
        
        var selectDown = function(list){
            var activeList = list.find('li.' + opts.selectActiveListClass);
            var count = 0;
            
            renderListInactive(list);
            
            if ( !(activeList.length < 1) ){
                count = activeList.prevAll().length + 1;
            }
            
            var direction = 'bottom';
            
            if ( count > (list.children('li').length - 1) ){
                count = list.children('li').length - 1;
            } else {
                scrollPage(list, count, direction, false);
            }
            
            list.children('li:eq(' + count + ')').addClass(opts.selectActiveListClass)
            
        }

        var renderListInactive = function(list){
            list.children().removeClass(opts.selectActiveListClass);
        }
        
        var setupBehavior = function(models){
            
            var menuList = new Array();
            
            for ( index in models){
                if ( models[index].hasClass(opts.selectModelClass) ){
                    setupSelectBehavior(models[index], index, models)
                    menuList.push(models[index].find('div.' + opts.selectOptionsWrapperClass));
                    disableSelect(models[index][0]);
                    jQuery(document).data('scrollOnly', false);
                }
            }
            
        }
        
        if ( $this.length > 0 ){
        
            jQuery(document).data('modelScroll', null).data('scrollOnly', false);
            
            if ( $this.is('form') ){ 
                
                $this.addClass(opts.modelFormClass);
                
                var modelList = initializeInputs(jQuery(this));            
                
                setupBehavior(modelList);
            
            } else {
                if ( $this.is('select') ){
                    if ( opts.renderSelect === true ){
                        $this.closest('form').addClass(opts.modelFormClass);                     
                        
                        $this.closest(opts.inputRoot).css({position: 'relative', zIndex: opts.baseIndex})
                        
                        var model = renderSelectModel($this);
                        
                        $this.attr('tabIndex', -1);
                        model.attr('tabIndex', 0);
                        
                        jQuery(this).focusin( function(){
                            model.focus();
                        })
                        
                        
                        var modelList = new Array();
                        modelList.push(model)
                        
                        setupBehavior(modelList);
                    }
                }
            }
            
            if ( jQuery.browser.mozilla === true ){ 
                window.onblur = function(){
                    for ( index in modelList ){
                        modelList[index].trigger('blur');
                    };
                };
            }
            
            jQuery(document).mousemove( function(e){
                if ( jQuery(document).data('modelScroll') !== null ){
                    handleDrag(jQuery(document).data('modelScroll'), e);
                }
                jQuery(document).data('scrollOnly', false);
            })
        }
        
        
        return $this;
    };

    /** 
     * Sends a message to the console
     * @private
     */
    var _debug = function( message ) {
        if ( true === jQuery.fn.frozInputModeler.opts.debug ) {
            console.log( message );
        }
    };
    
    jQuery.fn.frozInputModeler.defaults =   {
        setDimensions: true,
        modelFormClass: 'froz-model-form',        
        modelTextClass: 'model-text',
        baseIndex: 1,
        inputRoot: 'li',
        allowBlankValue: false,
        
        renderSelect: true,
        
        selectModelClass: 'select-model',
        selectOptionsClass: 'select-options',
        selectOptionsWrapperClass: 'select-options-wrapper',
        selectUlWrapperClass: 'select-ul-wrapper',
        selectOptionsShowAmount: 5,
        selectShownOptionsClass: 'shown',
        selectOptionsTopAdjust: 0,
        selectWithScrollClass: 'with-scrollbar',
        selectScrollBar: 'select-model-scroll',
        selectScrollUpClass: 'select-scroll-up',
        selectScrollDownClass: 'select-scroll-down',
        selectScrollMarkerClass: 'select-scroll-marker',
        selectOptionHeight: 0,
        selectScrollButtonHeight: 13,
        selectActiveModelClass: 'active-model',
        selectActiveListClass: 'active-option',
        selectActiveScrollerClass: 'active-scroll',
        selectScrollSpeed: 0,
        scrollMultiplier: 5
    };
} )(jQuery);
/**
 * @fileoverview frozCarousel plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-07-04
 */
 
( function( $ ) {
    /**
     * <ul> passes must have ID
     * @namespace frozCarousel Plugin Namespace
     * @requires jQuery 1.2.6 and above / jQuery Easing / jquery Timer
     * @example jQuery( "#id-of-DIV-that-contains-UL-that-contains-LIs" ).frozCarousel();
     * @return {jQuery Object}
     */
    jQuery.fn.frozCarousel = function( options ) {
        var opts                            = jQuery.extend( {}, jQuery.fn.frozCarousel.defaults, options );
        jQuery.fn.frozCarousel.opts      = opts;
        var $this                           = jQuery( this );
        
        var setupList = function(list, head){
            list.wrap('<div class="' + opts.wrapper + '" id="' + head.attr('id') + '-list-wrapper"></div>');
            list.data('wrapper', list.parent());
            var liCount = list.children('li').length;
            
            list.data('maxCount', (liCount - opts.showAmount))
                .data('range', opts.showAmount)
                .data('currentCount', opts.start);
            
            var adjust = 0;
            if ( opts.vertical === true ){
                list.children('li').each( function(){
                    if ( jQuery(this).outerWidth() > adjust ){
                        adjust = jQuery(this).outerWidth();
                    }
                })
            } else {
                list.children('li').each( function(){
                    if ( jQuery(this).outerHeight() > adjust ){
                        adjust = jQuery(this).outerHeight();
                    }
                })
            }
            
            setupDimensions(list, list.children('li:first'), liCount, adjust);
            
            return head;
        }
        
        var setupDimensions = function(list, sample, count, adjust){
            var wrapper = list.data('wrapper');

            if ( opts.vertical === true ){
                list.css({
                    height: (sample.outerHeight(true) * count) + 'px',
                    width: adjust + 'px'
                })

                wrapper.css({
                    height: (sample.outerHeight(true) * opts.showAmount) + 'px',
                    width: adjust + 'px'
                })
            } else {
                list.css({
                    height: adjust + 'px',
                    width: (sample.outerWidth(true) * count) + 'px'
                })

                wrapper.css({
                    height: adjust + 'px',
                    width: (sample.outerWidth(true) * opts.showAmount) + 'px'
                })
            }
        }
        
        var setupControls = function(head){
            var controls = null;
        
            if ( opts.controls === 'top' ){
                head.addClass(opts.topControlClass);
                controls = createTopControls(head); 
            
                if ( controls !== null ){
                    head.prepend(controls);
                }   
                        
            } else if ( (opts.controls === 'side') || (opts.controls === 'wrap') ){
                if (opts.controls === 'side'){
                    head.addClass(opts.sideControlClass);
                } else {
                    head.addClass(opts.wrapControlClass);
                }
                
                controls = createSideControls(head)
                
                if ( controls !== null ){
                    head.prepend(controls[0]);
                    head.prepend(controls[1]);
                    head.append(controls[2]);
                }   
                
                controls = head.find('div.' + opts.controlDivClass);
                
            }
            
            if ( controls !== null ){
                setupBehavior(controls, head, opts.slideTime, opts.easing);
                
                if ( opts.autohideControls === true ){
                    controls.addClass(opts.hideControlClass);
                }
                
            }
            
            return head;
        }
        
        var setupBehavior = function(controls, head, slideTime, easing){
            var prev = controls.find('a.' + opts.prevClass)
            var counter = controls.find('div.' + opts.counterClass);
            var next = controls.find('a.' + opts.nextClass)
            var list = head.find('ul.' + opts.carouselList);
            
            if ( counter.length === 1){
                counter.data('default', opts.counter).data('rangeTerm', opts.rangeCounterTerm);
            }
            
            setStarter(list, list.data('currentCount'), counter);
            
            if ( prev.length === 1 ){
                prev.click( function(){
                    deActivateList(list)
                    slidePrev(list, counter, slideTime, easing);
                    return false;
                })
            }
            
            if ( next.length === 1 ){
                next.click( function(){
                    deActivateList(list)
                    slideNext(list, counter, slideTime, easing);
                    return false;
                })
            }
        }
        
        var activateList = function(list, current){
            list.children('li:eq(' + current + ')').addClass(opts.activeClass);
            if ( opts.loop === false ){
                disableButtons(list, current, list.data('maxCount'));
            }
        }
        
        var deActivateList = function(list){
            list.children('li').removeClass(opts.activeClass);
            if ( opts.loop === false ){
                enableButtons(list);
            }
        }
        
        var disableButtons = function(list, current, maxCount){
            var head = list.closest('div.' + opts.identifier);
            if ( current <= 0 ){
                head.find('a.' + opts.prevClass).addClass(opts.disabledControlClass)
            } else if ( current >= list.data('maxCount') ) {
                head.find('a.' + opts.nextClass).addClass(opts.disabledControlClass)
            }
        }
        
        var enableButtons = function(list){
            var controls = list.closest('div.' + opts.identifier).find('div.' + opts.controlDivClass + ' > a');
            controls.removeClass(opts.disabledControlClass);
        }
        
        var setStarter = function(list, current, counter){
            var liCount = list.children('li').length;
            
            if ( opts.vertical === true ){
                var increment = list.children('li:first').outerHeight(true);
                var distance = current * increment;
                list.stop(false, true).css({top: distance + 'px'});
            } else {
                var increment = list.children('li:first').outerWidth(true);
                var distance = current * increment;
                list.stop(false, true).css({left: distance + 'px'});
            }
            
            if ( counter.length === 1 ){
                updateCounter(liCount, list, counter);
            }
            
            activateList(list, current);
        }
        
        var slidePrev = function(list, counter, slideTime, easing){
            var liCount = list.children('li').length;
            var count = list.data('currentCount');
            var maxCount = list.data('maxCount');
            
            if ( (count - 1) >= 0 ){
                list.data('currentCount', (count - 1))
            
                if ( opts.vertical === true ){
                    var increment = list.children('li:first').outerHeight(true);
                    list.stop(false, true).animate({top: '+=' + increment + 'px'}, slideTime, easing);
                } else {
                    var increment = list.children('li:first').outerWidth(true);
                    list.stop(false, true).animate({left: '+=' + increment + 'px'}, slideTime, easing);
                }
            } else {
                if ( opts.loop === true ){
                    list.data('currentCount', list.data('maxCount'))
                    
                    if ( opts.vertical === true ){
                        var increment = list.children('li:first').outerHeight(true);
                        list.stop(false, true).animate({top: -((list.data('maxCount')) *increment) + 'px'}, slideTime,easing);
                    } else {
                        var increment = list.children('li:first').outerWidth(true);
                        list.stop(false, true).animate({left: -((list.data('maxCount')) *increment) + 'px'}, slideTime,easing);
                    }
                }
            }
            
            activateList(list, list.data('currentCount'));
            if ( counter.length === 1 ){
                updateCounter(liCount, list, counter);
            }
        }
        
        var slideNext = function(list, counter, slideTime, easing){
            var liCount = list.children('li').length;
            var count = list.data('currentCount');
            var maxCount = list.data('maxCount');
            
            if ( (count + 1) <= maxCount ){
                list.data('currentCount', (count + 1))
            
                if ( opts.vertical === true ){
                    var increment = list.children('li:first').outerHeight(true);
                    list.stop(false, true).animate({top: '-=' + increment + 'px'}, slideTime, easing);
                } else {
                    var increment = list.children('li:first').outerWidth(true);
                    list.stop(false, true).animate({left: '-=' + increment + 'px'}, slideTime, easing);
                }
            } else {
                if ( opts.loop === true ){
                    list.data('currentCount', 0)
                    
                    if ( opts.vertical === true ){
                        var increment = list.children('li:first').outerHeight(true);
                        list.stop(false, true).animate({top: '0px'}, slideTime, easing);
                    } else {
                        var increment = list.children('li:first').outerWidth(true);
                        list.stop(false, true).animate({left: '0px'}, slideTime, easing);
                    }
                }
            }
            
            activateList(list, list.data('currentCount'));
            if ( counter.length === 1 ){
                updateCounter(liCount, list, counter);
            }
        }
        
        var updateCounter = function(liCount, list, counter){
            if ( !(list.data('range') > 1) ){
                counter.text((list.data('currentCount') + 1) + counter.data('default') + liCount);
            } else {
                counter.text((list.data('currentCount') + 1) + counter.data('rangeTerm') + 
                                (list.data('currentCount') + list.data('range')) + 
                                counter.data('default') + liCount);
            }
        }
        
        var createTopControls = function(head){
            var controlDiv = createBeforeControl();
            if ( opts.prev !== null ){
                controlDiv.append(createPrevControl())
            }
            if ( opts.counter !== null ){
                controlDiv.append(createCounterControl())
            }
            if ( opts.next !== null ){
                controlDiv.append(createNextControl())
            }
            
            return controlDiv;
        }
        
        var createSideControls = function(head){
            var controlBeforeDiv = createBeforeControl();
            var controlMidDiv = createMidControl();
            var controlAfterDiv = createAfterControl();
            
            if ( opts.prev !== null ){
                controlBeforeDiv.append(createPrevControl())
            }
            if ( opts.counter !== null ){
                controlMidDiv.append(createCounterControl())
            }
            if ( opts.next !== null ){
                controlAfterDiv.append(createNextControl())
            }
            
            var controlDiv = new Array(controlBeforeDiv, controlMidDiv, controlAfterDiv);
            
            return controlDiv;
        }
        
        var createPrevControl = function(){
            return jQuery('<a href="#" class="' + opts.prevClass +'">' + opts.prev + '</a>')
        }
        
        var createCounterControl = function(){
            return jQuery('<div class="' + opts.counterClass +'">' + opts.counter + '</div>')
        }
        
        var createNextControl = function(){
            return jQuery('<a href="#" class="' + opts.nextClass +'">' + opts.next + '</a>')
        }
        
        var createBeforeControl = function(){
            return jQuery('<div class="' + opts.prependControlClass + ' ' + opts.controlDivClass + '"></div>');
        }
        
        var createMidControl = function(){
            return jQuery('<div class="' + opts.prependMidControlClass + ' ' + opts.controlDivClass + '"></div>');
        }
        
        var createAfterControl = function(){
            return jQuery('<div class="' + opts.appendControlClass + ' ' + opts.controlDivClass + '"></div>');
        }
        
        var setAutoSlide = function(head){
            mainTimer = jQuery.timer( head.data('autoSlide'), function( timer ) { 
                head.find('a.' + opts.nextClass).trigger('click');
            });
            
            head.data('carouselTimer', mainTimer);
            return head;
        }
        
        var setHoverHold = function(head){
            head.mouseenter( function(){
                head.data('carouselTimer').stop();
            }).mouseleave( function(){
                setAutoSlide(head);
            })
        }
        
        var setupAutohide = function(controls){
            var fadeTime = opts.controlFadeTime;
            var fadeOpacity = opts.controlFadeOpacity;
            var showOpacity = opts.controlShowOpacity;
            
            controls.fadeTo(0, opts.controlFadeOpacity)
                    .mouseenter( function(){
                        controls.stop(false, false).fadeTo(fadeTime, showOpacity);
                    }).mouseleave( function(){
                        controls.stop(false, false).fadeTo(fadeTime, fadeOpacity);
                    })
        }
        
        var openFancybox = function(target){
        
            var data = target.data('fancyboxData');
            var type = target.data('fancyboxType');
        
            if ( type === 'image' ){
                jQuery.fancybox({
                    content: data
	        	})
            }        
        }
        
        var setupLinks = function(links){
            links.each( function(){
                jQuery(this).data('fancyboxData', null)
            }).click( function(){
                if ( jQuery(this).data('fancyboxData') === null ){
                    var href = jQuery(this).attr('href');
                    if ( href.slice(href.lastIndexOf('.')).match('(.jpg)|(.gif)|(.png)$') !== null){
                        var image = new Image();
                        image.src = href;
                        jQuery(this).data('fancyboxData', image);
                        jQuery(this).data('fancyboxType', 'image');
                        openFancybox(jQuery(this));
                        return false;
                    }
                } else {
                    openFancybox(jQuery(this));
                    return false;
                }
            })
        }
        
        if ( $this.length > 0 ){
            $this.each( function(){
                var head = setupList(jQuery(this).find('ul.' + opts.carouselList), jQuery(this));  
                head.addClass(opts.identifier);
                head = setupControls(head);
                                
                if ( opts.autohideControls === true ){
                    setupAutohide(head.find('div.' + opts.hideControlClass))                    
                }
                
                if ( opts.autoSlide > 0 ){
                    head.data('autoSlide', opts.autoSlide)
                        .data('slideTime', opts.slideTime)
                        .data('easing', opts.easing);
                    head = setAutoSlide(head);
                    
                    if ( opts.hoverHold === true ){
                        setHoverHold(head);
                    }
                }
                
                var links = head.find('ul.' + opts.carouselList).find('a');
                
                if ( links.length > 0 ){
                    if ( opts.enableFancyBox === true ){
                        setupLinks(links);                
                    }
                }
                
            })
        }
        
        return $this;
    };

    /** 
     * Sends a message to the console
     * @private
     */
    var _debug = function( message ) {
        if ( true === jQuery.fn.frozCarousel.opts.debug ) {
            console.log( message );
        }
    };
    
    jQuery.fn.frozCarousel.defaults =   {
        identifier: 'froz-carousel-main',                        //unique id to be used for carousel objects
        carouselList: 'froz-carousel-list',
        wrapper: 'froz-carousel-wrapper',
        vertical: false,                                //if true, contents slide vertically
        showAmount: 1,                                  //amount of elements to be shown in slider display
        controls: 'top',                                // top, bottom, side(left and right) or wrap(top and bottom)
        activeClass: 'froz-carousel-active',                //class assigned to active image
        disabledControlClass: 'froz-carousel-disabled',                //class assigned to active image
        topControlClass: 'controls-top',
        sideControlClass: 'controls-side',
        wrapControlClass: 'controls-wrap',
        controlDivClass: 'froz-carousel-controls',      //class given to control elements
        prependControlClass: 'precontrol',
        prependMidControlClass: 'midcontrol',
        appendControlClass: 'postcontrol',
        prevClass: 'froz-carousel-prev',
        counterClass: 'froz-carousel-counter',
        nextClass: 'froz-carousel-next',
        prev: "Previous",                               //previous button display. can be replaced with html element
        counter: ' of ',                                   //image counter separator. if null, no counter is displayed
        next: 'Next',                                   //next button display. can be replaced with html element
        rangeCounterTerm: ' to ',
        start: 0,                                       //starter slide
        slideTime: 500,                                 //sliding duration
        easing: 'easeInOutExpo',                        //sliding easing animation
        autoSlide: 0,                                   //speed of auto slide. slider does not auto-slide if === 0
        hoverHold: true,                                //if true, auto-slide stops when mouse hovers over slider
        loop: true,                                     //determines if slide goes through other end if end of slide is reached
        autohideControls: false,
        hideControlClass: 'froz-carousel-auto-hide',
        controlShowOpacity: 1,
        controlFadeOpacity: 0.01,
        controlFadeTime: 300,
        enableFancyBox: true
        
//        btnActiveClass: 'froz-carousel-active-button',      //class assigned to active control button
//        widthAdjust: 0,                                 //custom width length added to slider element
//        heightAdjust: 0,                                //custom height length added to slider element
//        setCss: true,                                   //if true, positioning is automtically set for controls and main DIV
//        controlHide: 0,                                 //if > 0, sets duration of opacity lowering animation upon mouse hover
//        indivHide: 0,                                   //same as controlhide, except animations are separated per button
//        hideOpacity: 0.01,                              //opacity of hidden control elements
//        showOpacity: 1,                                 //opactiy of displayed control elements
//        controlOverlap: 0,                              //if > 0, determines amount of px that controls overlap slider
//                                                        //works only for control === side || control === wrap
                                                        
        
    };
} )(jQuery);
/**
 *
 * Date picker
 * Author: Stefan Petre www.eyecon.ro
 * 
 * Dual licensed under the MIT and GPL licenses
 * 
 */
(function ($) {
	var DatePicker = function () {
		var	ids = {},
			views = {
				years: 'datepickerViewYears',
				moths: 'datepickerViewMonths',
				days: 'datepickerViewDays'
			},
			tpl = {
				wrapper: '<div class="datepicker"><div class="datepickerBorderT" /><div class="datepickerBorderB" /><div class="datepickerBorderL" /><div class="datepickerBorderR" /><div class="datepickerBorderTL" /><div class="datepickerBorderTR" /><div class="datepickerBorderBL" /><div class="datepickerBorderBR" /><div class="datepickerContainer"><table cellspacing="0" cellpadding="0"><tbody><tr></tr></tbody></table></div></div>',
				head: [
					'<td>',
					'<table cellspacing="0" cellpadding="0">',
						'<thead>',
							'<tr>',
								'<th class="datepickerGoPrev"><a href="#"><span><%=prev%></span></a></th>',
								'<th colspan="6" class="datepickerMonth"><a href="#"><span></span></a></th>',
								'<th class="datepickerGoNext"><a href="#"><span><%=next%></span></a></th>',
							'</tr>',
							'<tr class="datepickerDoW">',
								'<th><span><%=week%></span></th>',
								'<th><span><%=day1%></span></th>',
								'<th><span><%=day2%></span></th>',
								'<th><span><%=day3%></span></th>',
								'<th><span><%=day4%></span></th>',
								'<th><span><%=day5%></span></th>',
								'<th><span><%=day6%></span></th>',
								'<th><span><%=day7%></span></th>',
							'</tr>',
						'</thead>',
					'</table></td>'
				],
				space : '<td class="datepickerSpace"><div></div></td>',
				days: [
					'<tbody class="datepickerDays">',
						'<tr>',
							'<th class="datepickerWeek"><a href="#"><span><%=weeks[0].week%></span></a></th>',
							'<td class="<%=weeks[0].days[0].classname%>"><a href="#"><span><%=weeks[0].days[0].text%></span></a></td>',
							'<td class="<%=weeks[0].days[1].classname%>"><a href="#"><span><%=weeks[0].days[1].text%></span></a></td>',
							'<td class="<%=weeks[0].days[2].classname%>"><a href="#"><span><%=weeks[0].days[2].text%></span></a></td>',
							'<td class="<%=weeks[0].days[3].classname%>"><a href="#"><span><%=weeks[0].days[3].text%></span></a></td>',
							'<td class="<%=weeks[0].days[4].classname%>"><a href="#"><span><%=weeks[0].days[4].text%></span></a></td>',
							'<td class="<%=weeks[0].days[5].classname%>"><a href="#"><span><%=weeks[0].days[5].text%></span></a></td>',
							'<td class="<%=weeks[0].days[6].classname%>"><a href="#"><span><%=weeks[0].days[6].text%></span></a></td>',
						'</tr>',
						'<tr>',
							'<th class="datepickerWeek"><a href="#"><span><%=weeks[1].week%></span></a></th>',
							'<td class="<%=weeks[1].days[0].classname%>"><a href="#"><span><%=weeks[1].days[0].text%></span></a></td>',
							'<td class="<%=weeks[1].days[1].classname%>"><a href="#"><span><%=weeks[1].days[1].text%></span></a></td>',
							'<td class="<%=weeks[1].days[2].classname%>"><a href="#"><span><%=weeks[1].days[2].text%></span></a></td>',
							'<td class="<%=weeks[1].days[3].classname%>"><a href="#"><span><%=weeks[1].days[3].text%></span></a></td>',
							'<td class="<%=weeks[1].days[4].classname%>"><a href="#"><span><%=weeks[1].days[4].text%></span></a></td>',
							'<td class="<%=weeks[1].days[5].classname%>"><a href="#"><span><%=weeks[1].days[5].text%></span></a></td>',
							'<td class="<%=weeks[1].days[6].classname%>"><a href="#"><span><%=weeks[1].days[6].text%></span></a></td>',
						'</tr>',
						'<tr>',
							'<th class="datepickerWeek"><a href="#"><span><%=weeks[2].week%></span></a></th>',
							'<td class="<%=weeks[2].days[0].classname%>"><a href="#"><span><%=weeks[2].days[0].text%></span></a></td>',
							'<td class="<%=weeks[2].days[1].classname%>"><a href="#"><span><%=weeks[2].days[1].text%></span></a></td>',
							'<td class="<%=weeks[2].days[2].classname%>"><a href="#"><span><%=weeks[2].days[2].text%></span></a></td>',
							'<td class="<%=weeks[2].days[3].classname%>"><a href="#"><span><%=weeks[2].days[3].text%></span></a></td>',
							'<td class="<%=weeks[2].days[4].classname%>"><a href="#"><span><%=weeks[2].days[4].text%></span></a></td>',
							'<td class="<%=weeks[2].days[5].classname%>"><a href="#"><span><%=weeks[2].days[5].text%></span></a></td>',
							'<td class="<%=weeks[2].days[6].classname%>"><a href="#"><span><%=weeks[2].days[6].text%></span></a></td>',
						'</tr>',
						'<tr>',
							'<th class="datepickerWeek"><a href="#"><span><%=weeks[3].week%></span></a></th>',
							'<td class="<%=weeks[3].days[0].classname%>"><a href="#"><span><%=weeks[3].days[0].text%></span></a></td>',
							'<td class="<%=weeks[3].days[1].classname%>"><a href="#"><span><%=weeks[3].days[1].text%></span></a></td>',
							'<td class="<%=weeks[3].days[2].classname%>"><a href="#"><span><%=weeks[3].days[2].text%></span></a></td>',
							'<td class="<%=weeks[3].days[3].classname%>"><a href="#"><span><%=weeks[3].days[3].text%></span></a></td>',
							'<td class="<%=weeks[3].days[4].classname%>"><a href="#"><span><%=weeks[3].days[4].text%></span></a></td>',
							'<td class="<%=weeks[3].days[5].classname%>"><a href="#"><span><%=weeks[3].days[5].text%></span></a></td>',
							'<td class="<%=weeks[3].days[6].classname%>"><a href="#"><span><%=weeks[3].days[6].text%></span></a></td>',
						'</tr>',
						'<tr>',
							'<th class="datepickerWeek"><a href="#"><span><%=weeks[4].week%></span></a></th>',
							'<td class="<%=weeks[4].days[0].classname%>"><a href="#"><span><%=weeks[4].days[0].text%></span></a></td>',
							'<td class="<%=weeks[4].days[1].classname%>"><a href="#"><span><%=weeks[4].days[1].text%></span></a></td>',
							'<td class="<%=weeks[4].days[2].classname%>"><a href="#"><span><%=weeks[4].days[2].text%></span></a></td>',
							'<td class="<%=weeks[4].days[3].classname%>"><a href="#"><span><%=weeks[4].days[3].text%></span></a></td>',
							'<td class="<%=weeks[4].days[4].classname%>"><a href="#"><span><%=weeks[4].days[4].text%></span></a></td>',
							'<td class="<%=weeks[4].days[5].classname%>"><a href="#"><span><%=weeks[4].days[5].text%></span></a></td>',
							'<td class="<%=weeks[4].days[6].classname%>"><a href="#"><span><%=weeks[4].days[6].text%></span></a></td>',
						'</tr>',
						'<tr>',
							'<th class="datepickerWeek"><a href="#"><span><%=weeks[5].week%></span></a></th>',
							'<td class="<%=weeks[5].days[0].classname%>"><a href="#"><span><%=weeks[5].days[0].text%></span></a></td>',
							'<td class="<%=weeks[5].days[1].classname%>"><a href="#"><span><%=weeks[5].days[1].text%></span></a></td>',
							'<td class="<%=weeks[5].days[2].classname%>"><a href="#"><span><%=weeks[5].days[2].text%></span></a></td>',
							'<td class="<%=weeks[5].days[3].classname%>"><a href="#"><span><%=weeks[5].days[3].text%></span></a></td>',
							'<td class="<%=weeks[5].days[4].classname%>"><a href="#"><span><%=weeks[5].days[4].text%></span></a></td>',
							'<td class="<%=weeks[5].days[5].classname%>"><a href="#"><span><%=weeks[5].days[5].text%></span></a></td>',
							'<td class="<%=weeks[5].days[6].classname%>"><a href="#"><span><%=weeks[5].days[6].text%></span></a></td>',
						'</tr>',
					'</tbody>'
				],
				months: [
					'<tbody class="<%=className%>">',
						'<tr>',
							'<td colspan="2"><a href="#"><span><%=data[0]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[1]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[2]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[3]%></span></a></td>',
						'</tr>',
						'<tr>',
							'<td colspan="2"><a href="#"><span><%=data[4]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[5]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[6]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[7]%></span></a></td>',
						'</tr>',
						'<tr>',
							'<td colspan="2"><a href="#"><span><%=data[8]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[9]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[10]%></span></a></td>',
							'<td colspan="2"><a href="#"><span><%=data[11]%></span></a></td>',
						'</tr>',
					'</tbody>'
				]
			},
			defaults = {
				flat: false,
				starts: 1,
				prev: '&#9664;',
				next: '&#9654;',
				lastSel: false,
				mode: 'single',
				view: 'days',
				calendars: 1,
				format: 'Y-m-d',
				position: 'bottom',
				eventName: 'click',
				onRender: function(){return {};},
				onChange: function(){return true;},
				onShow: function(){return true;},
				onBeforeShow: function(){return true;},
				onHide: function(){return true;},
				locale: {
					days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
					daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
					daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
					months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
					monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
					weekMin: 'wk'
				}
			},
			fill = function(el) {
				var options = $(el).data('datepicker');
				var cal = $(el);
				var currentCal = Math.floor(options.calendars/2), date, data, dow, month, cnt = 0, week, days, indic, indic2, html, tblCal;
				cal.find('td>table tbody').remove();
				for (var i = 0; i < options.calendars; i++) {
					date = new Date(options.current);
					date.addMonths(-currentCal + i);
					tblCal = cal.find('table').eq(i+1);
					switch (tblCal[0].className) {
						case 'datepickerViewDays':
							dow = formatDate(date, 'B, Y');
							break;
						case 'datepickerViewMonths':
							dow = date.getFullYear();
							break;
						case 'datepickerViewYears':
							dow = (date.getFullYear()-6) + ' - ' + (date.getFullYear()+5);
							break;
					} 
					tblCal.find('thead tr:first th:eq(1) span').text(dow);
					dow = date.getFullYear()-6;
					data = {
						data: [],
						className: 'datepickerYears'
					}
					for ( var j = 0; j < 12; j++) {
						data.data.push(dow + j);
					}
					html = tmpl(tpl.months.join(''), data);
					date.setDate(1);
					data = {weeks:[], test: 10};
					month = date.getMonth();
					var dow = (date.getDay() - options.starts) % 7;
					date.addDays(-(dow + (dow < 0 ? 7 : 0)));
					week = -1;
					cnt = 0;
					while (cnt < 42) {
						indic = parseInt(cnt/7,10);
						indic2 = cnt%7;
						if (!data.weeks[indic]) {
							week = date.getWeekNumber();
							data.weeks[indic] = {
								week: week,
								days: []
							};
						}
						data.weeks[indic].days[indic2] = {
							text: date.getDate(),
							classname: []
						};
						if (month != date.getMonth()) {
							data.weeks[indic].days[indic2].classname.push('datepickerNotInMonth');
						}
						if (date.getDay() == 0) {
							data.weeks[indic].days[indic2].classname.push('datepickerSunday');
						}
						if (date.getDay() == 6) {
							data.weeks[indic].days[indic2].classname.push('datepickerSaturday');
						}
						var fromUser = options.onRender(date);
						var val = date.valueOf();
						if (fromUser.selected || options.date == val || $.inArray(val, options.date) > -1 || (options.mode == 'range' && val >= options.date[0] && val <= options.date[1])) {
							data.weeks[indic].days[indic2].classname.push('datepickerSelected');
						}
						if (fromUser.disabled) {
							data.weeks[indic].days[indic2].classname.push('datepickerDisabled');
						}
						if (fromUser.className) {
							data.weeks[indic].days[indic2].classname.push(fromUser.className);
						}
						if (fromUser.className2) {
							data.weeks[indic].days[indic2].classname.push(fromUser.className2);
						}
						data.weeks[indic].days[indic2].classname = data.weeks[indic].days[indic2].classname.join(' ');
						cnt++;
						date.addDays(1);
					}
					html = tmpl(tpl.days.join(''), data) + html;
					data = {
						data: options.locale.monthsShort,
						className: 'datepickerMonths'
					};
					html = tmpl(tpl.months.join(''), data) + html;
					tblCal.append(html);
				}
			},
			parseDate = function (date, format) {
				if (date.constructor == Date) {
					return new Date(date);
				}
				var parts = date.split(/\W+/);
				var against = format.split(/\W+/), d, m, y, h, min, now = new Date();
				for (var i = 0; i < parts.length; i++) {
					switch (against[i]) {
						case 'd':
						case 'e':
							d = parseInt(parts[i],10);
							break;
						case 'm':
							m = parseInt(parts[i], 10)-1;
							break;
						case 'Y':
						case 'y':
							y = parseInt(parts[i], 10);
							y += y > 100 ? 0 : (y < 29 ? 2000 : 1900);
							break;
						case 'H':
						case 'I':
						case 'k':
						case 'l':
							h = parseInt(parts[i], 10);
							break;
						case 'P':
						case 'p':
							if (/pm/i.test(parts[i]) && h < 12) {
								h += 12;
							} else if (/am/i.test(parts[i]) && h >= 12) {
								h -= 12;
							}
							break;
						case 'M':
							min = parseInt(parts[i], 10);
							break;
					}
				}
				return new Date(
					y === undefined ? now.getFullYear() : y,
					m === undefined ? now.getMonth() : m,
					d === undefined ? now.getDate() : d,
					h === undefined ? now.getHours() : h,
					min === undefined ? now.getMinutes() : min,
					0
				);
			},
			formatDate = function(date, format) {
				var m = date.getMonth();
				var d = date.getDate();
				var y = date.getFullYear();
				var wn = date.getWeekNumber();
				var w = date.getDay();
				var s = {};
				var hr = date.getHours();
				var pm = (hr >= 12);
				var ir = (pm) ? (hr - 12) : hr;
				var dy = date.getDayOfYear();
				if (ir == 0) {
					ir = 12;
				}
				var min = date.getMinutes();
				var sec = date.getSeconds();
				var parts = format.split(''), part;
				for ( var i = 0; i < parts.length; i++ ) {
					part = parts[i];
					switch (parts[i]) {
						case 'a':
							part = date.getDayName();
							break;
						case 'A':
							part = date.getDayName(true);
							break;
						case 'b':
							part = date.getMonthName();
							break;
						case 'B':
							part = date.getMonthName(true);
							break;
						case 'C':
							part = 1 + Math.floor(y / 100);
							break;
						case 'd':
							part = (d < 10) ? ("0" + d) : d;
							break;
						case 'e':
							part = d;
							break;
						case 'H':
							part = (hr < 10) ? ("0" + hr) : hr;
							break;
						case 'I':
							part = (ir < 10) ? ("0" + ir) : ir;
							break;
						case 'j':
							part = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy;
							break;
						case 'k':
							part = hr;
							break;
						case 'l':
							part = ir;
							break;
						case 'm':
							part = (m < 9) ? ("0" + (1+m)) : (1+m);
							break;
						case 'M':
							part = (min < 10) ? ("0" + min) : min;
							break;
						case 'p':
						case 'P':
							part = pm ? "PM" : "AM";
							break;
						case 's':
							part = Math.floor(date.getTime() / 1000);
							break;
						case 'S':
							part = (sec < 10) ? ("0" + sec) : sec;
							break;
						case 'u':
							part = w + 1;
							break;
						case 'w':
							part = w;
							break;
						case 'y':
							part = ('' + y).substr(2, 2);
							break;
						case 'Y':
							part = y;
							break;
					}
					parts[i] = part;
				}
				return parts.join('');
			},
			extendDate = function(options) {
				if (Date.prototype.tempDate) {
					return;
				}
				Date.prototype.tempDate = null;
				Date.prototype.months = options.months;
				Date.prototype.monthsShort = options.monthsShort;
				Date.prototype.days = options.days;
				Date.prototype.daysShort = options.daysShort;
				Date.prototype.getMonthName = function(fullName) {
					return this[fullName ? 'months' : 'monthsShort'][this.getMonth()];
				};
				Date.prototype.getDayName = function(fullName) {
					return this[fullName ? 'days' : 'daysShort'][this.getDay()];
				};
				Date.prototype.addDays = function (n) {
					this.setDate(this.getDate() + n);
					this.tempDate = this.getDate();
				};
				Date.prototype.addMonths = function (n) {
					if (this.tempDate == null) {
						this.tempDate = this.getDate();
					}
					this.setDate(1);
					this.setMonth(this.getMonth() + n);
					this.setDate(Math.min(this.tempDate, this.getMaxDays()));
				};
				Date.prototype.addYears = function (n) {
					if (this.tempDate == null) {
						this.tempDate = this.getDate();
					}
					this.setDate(1);
					this.setFullYear(this.getFullYear() + n);
					this.setDate(Math.min(this.tempDate, this.getMaxDays()));
				};
				Date.prototype.getMaxDays = function() {
					var tmpDate = new Date(Date.parse(this)),
						d = 28, m;
					m = tmpDate.getMonth();
					d = 28;
					while (tmpDate.getMonth() == m) {
						d ++;
						tmpDate.setDate(d);
					}
					return d - 1;
				};
				Date.prototype.getFirstDay = function() {
					var tmpDate = new Date(Date.parse(this));
					tmpDate.setDate(1);
					return tmpDate.getDay();
				};
				Date.prototype.getWeekNumber = function() {
					var tempDate = new Date(this);
					tempDate.setDate(tempDate.getDate() - (tempDate.getDay() + 6) % 7 + 3);
					var dms = tempDate.valueOf();
					tempDate.setMonth(0);
					tempDate.setDate(4);
					return Math.round((dms - tempDate.valueOf()) / (604800000)) + 1;
				};
				Date.prototype.getDayOfYear = function() {
					var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
					var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
					var time = now - then;
					return Math.floor(time / 24*60*60*1000);
				};
			},
			layout = function (el) {
				var options = $(el).data('datepicker');
				var cal = $('#' + options.id);
				if (!options.extraHeight) {
					var divs = $(el).find('div');
					options.extraHeight = divs.get(0).offsetHeight + divs.get(1).offsetHeight;
					options.extraWidth = divs.get(2).offsetWidth + divs.get(3).offsetWidth;
				}
				var tbl = cal.find('table:first').get(0);
				var width = tbl.offsetWidth;
				var height = tbl.offsetHeight;
				cal.css({
					width: width + options.extraWidth + 'px',
					height: height + options.extraHeight + 'px'
				}).find('div.datepickerContainer').css({
					width: width + 'px',
					height: height + 'px'
				});
			},
			click = function(ev) {
				if ($(ev.target).is('span')) {
					ev.target = ev.target.parentNode;
				}
				var el = $(ev.target);
				if (el.is('a')) {
					ev.target.blur();
					if (el.hasClass('datepickerDisabled')) {
						return false;
					}
					var options = $(this).data('datepicker');
					var parentEl = el.parent();
					var tblEl = parentEl.parent().parent().parent();
					var tblIndex = $('table', this).index(tblEl.get(0)) - 1;
					var tmp = new Date(options.current);
					var changed = false;
					var fillIt = false;
					if (parentEl.is('th')) {
						if (parentEl.hasClass('datepickerWeek') && options.mode == 'range' && !parentEl.next().hasClass('datepickerDisabled')) {
							var val = parseInt(parentEl.next().text(), 10);
							tmp.addMonths(tblIndex - Math.floor(options.calendars/2));
							if (parentEl.next().hasClass('datepickerNotInMonth')) {
								tmp.addMonths(val > 15 ? -1 : 1);
							}
							tmp.setDate(val);
							options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
							tmp.setHours(23,59,59,0);
							tmp.addDays(6);
							options.date[1] = tmp.valueOf();
							fillIt = true;
							changed = true;
							options.lastSel = false;
						} else if (parentEl.hasClass('datepickerMonth')) {
							tmp.addMonths(tblIndex - Math.floor(options.calendars/2));
							switch (tblEl.get(0).className) {
								case 'datepickerViewDays':
									tblEl.get(0).className = 'datepickerViewMonths';
									el.find('span').text(tmp.getFullYear());
									break;
								case 'datepickerViewMonths':
									tblEl.get(0).className = 'datepickerViewYears';
									el.find('span').text((tmp.getFullYear()-6) + ' - ' + (tmp.getFullYear()+5));
									break;
								case 'datepickerViewYears':
									tblEl.get(0).className = 'datepickerViewDays';
									el.find('span').text(formatDate(tmp, 'B, Y'));
									break;
							}
						} else if (parentEl.parent().parent().is('thead')) {
							switch (tblEl.get(0).className) {
								case 'datepickerViewDays':
									options.current.addMonths(parentEl.hasClass('datepickerGoPrev') ? -1 : 1);
									break;
								case 'datepickerViewMonths':
									options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -1 : 1);
									break;
								case 'datepickerViewYears':
									options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -12 : 12);
									break;
							}
							fillIt = true;
						}
					} else if (parentEl.is('td') && !parentEl.hasClass('datepickerDisabled')) {
						switch (tblEl.get(0).className) {
							case 'datepickerViewMonths':
								options.current.setMonth(tblEl.find('tbody.datepickerMonths td').index(parentEl));
								options.current.setFullYear(parseInt(tblEl.find('thead th.datepickerMonth span').text(), 10));
								options.current.addMonths(Math.floor(options.calendars/2) - tblIndex);
								tblEl.get(0).className = 'datepickerViewDays';
								break;
							case 'datepickerViewYears':
								options.current.setFullYear(parseInt(el.text(), 10));
								tblEl.get(0).className = 'datepickerViewMonths';
								break;
							default:
								var val = parseInt(el.text(), 10);
								tmp.addMonths(tblIndex - Math.floor(options.calendars/2));
								if (parentEl.hasClass('datepickerNotInMonth')) {
									tmp.addMonths(val > 15 ? -1 : 1);
								}
								tmp.setDate(val);
								switch (options.mode) {
									case 'multiple':
										val = (tmp.setHours(0,0,0,0)).valueOf();
										if ($.inArray(val, options.date) > -1) {
											$.each(options.date, function(nr, dat){
												if (dat == val) {
													options.date.splice(nr,1);
													return false;
												}
											});
										} else {
											options.date.push(val);
										}
										break;
									case 'range':
										if (!options.lastSel) {
											options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
										}
										val = (tmp.setHours(23,59,59,0)).valueOf();
										if (val < options.date[0]) {
											options.date[1] = options.date[0] + 86399000;
											options.date[0] = val - 86399000;
										} else {
											options.date[1] = val;
										}
										options.lastSel = !options.lastSel;
										break;
									default:
										options.date = tmp.valueOf();
										break;
								}
								break;
						}
						fillIt = true;
						changed = true;
					}
					if (fillIt) {
						fill(this);
					}
					if (changed) {
						options.onChange.apply(this, prepareDate(options));
					}
				}
				return false;
			},
			prepareDate = function (options) {
				var tmp;
				if (options.mode == 'single') {
					tmp = new Date(options.date);
					return [formatDate(tmp, options.format), tmp, options.el];
				} else {
					tmp = [[],[], options.el];
					$.each(options.date, function(nr, val){
						var date = new Date(val);
						tmp[0].push(formatDate(date, options.format));
						tmp[1].push(date);
					});
					return tmp;
				}
			},
			getViewport = function () {
				var m = document.compatMode == 'CSS1Compat';
				return {
					l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
					t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
					w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
					h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
				};
			},
			isChildOf = function(parentEl, el, container) {
				if (parentEl == el) {
					return true;
				}
				if (parentEl.contains) {
					return parentEl.contains(el);
				}
				if ( parentEl.compareDocumentPosition ) {
					return !!(parentEl.compareDocumentPosition(el) & 16);
				}
				var prEl = el.parentNode;
				while(prEl && prEl != container) {
					if (prEl == parentEl)
						return true;
					prEl = prEl.parentNode;
				}
				return false;
			},
			show = function (ev) {
				var cal = $('#' + $(this).data('datepickerId'));
				if (!cal.is(':visible')) {
					var calEl = cal.get(0);
					fill(calEl);
					var options = cal.data('datepicker');
					options.onBeforeShow.apply(this, [cal.get(0)]);
					var pos = $(this).offset();
					var viewPort = getViewport();
					var top = pos.top;
					var left = pos.left;
					var oldDisplay = $.curCSS(calEl, 'display');
					cal.css({
						visibility: 'hidden',
						display: 'block'
					});
					layout(calEl);
					switch (options.position){
						case 'top':
							top -= calEl.offsetHeight;
							break;
						case 'left':
							left -= calEl.offsetWidth;
							break;
						case 'right':
							left += this.offsetWidth;
							break;
						case 'bottom':
							top += this.offsetHeight;
							break;
					}
					if (top + calEl.offsetHeight > viewPort.t + viewPort.h) {
						top = pos.top  - calEl.offsetHeight;
					}
					if (top < viewPort.t) {
						top = pos.top + this.offsetHeight + calEl.offsetHeight;
					}
					if (left + calEl.offsetWidth > viewPort.l + viewPort.w) {
						left = pos.left - calEl.offsetWidth;
					}
					if (left < viewPort.l) {
						left = pos.left + this.offsetWidth
					}
					cal.css({
						visibility: 'visible',
						display: 'block',
						top: top + 'px',
						left: left + 'px'
					});
					if (options.onShow.apply(this, [cal.get(0)]) != false) {
						cal.show();
					}
					$(document).bind('mousedown', {cal: cal, trigger: this}, hide);
				}
				return false;
			},
			hide = function (ev) {
				if (ev.target != ev.data.trigger && !isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
					if (ev.data.cal.data('datepicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
						ev.data.cal.hide();
					}
					$(document).unbind('mousedown', hide);
				}
			};
		return {
			init: function(options){
				options = $.extend({}, defaults, options||{});
				extendDate(options.locale);
				options.calendars = Math.max(1, parseInt(options.calendars,10)||1);
				options.mode = /single|multiple|range/.test(options.mode) ? options.mode : 'single';
				return this.each(function(){
					if (!$(this).data('datepicker')) {
						options.el = this;
						if (options.date.constructor == String) {
							options.date = parseDate(options.date, options.format);
							options.date.setHours(0,0,0,0);
						}
						if (options.mode != 'single') {
							if (options.date.constructor != Array) {
								options.date = [options.date.valueOf()];
								if (options.mode == 'range') {
									options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf());
								}
							} else {
								for (var i = 0; i < options.date.length; i++) {
									options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf();
								}
								if (options.mode == 'range') {
									options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf();
								}
							}
						} else {
							options.date = options.date.valueOf();
						}
						if (!options.current) {
							options.current = new Date();
						} else {
							options.current = parseDate(options.current, options.format);
						} 
						options.current.setDate(1);
						options.current.setHours(0,0,0,0);
						var id = 'datepicker_' + parseInt(Math.random() * 1000), cnt;
						options.id = id;
						$(this).data('datepickerId', options.id);
						var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options);
						if (options.className) {
							cal.addClass(options.className);
						}
						var html = '';
						for (var i = 0; i < options.calendars; i++) {
							cnt = options.starts;
							if (i > 0) {
								html += tpl.space;
							}
							html += tmpl(tpl.head.join(''), {
									week: options.locale.weekMin,
									prev: options.prev,
									next: options.next,
									day1: options.locale.daysMin[(cnt++)%7],
									day2: options.locale.daysMin[(cnt++)%7],
									day3: options.locale.daysMin[(cnt++)%7],
									day4: options.locale.daysMin[(cnt++)%7],
									day5: options.locale.daysMin[(cnt++)%7],
									day6: options.locale.daysMin[(cnt++)%7],
									day7: options.locale.daysMin[(cnt++)%7]
								});
						}
						cal
							.find('tr:first').append(html)
								.find('table').addClass(views[options.view]);
						fill(cal.get(0));
						if (options.flat) {
							cal.appendTo(this).show().css('position', 'relative');
							layout(cal.get(0));
						} else {
							cal.appendTo(document.body);
							$(this).bind(options.eventName, show);
						}
					}
				});
			},
			showPicker: function() {
				return this.each( function () {
					if ($(this).data('datepickerId')) {
						show.apply(this);
					}
				});
			},
			hidePicker: function() {
				return this.each( function () {
					if ($(this).data('datepickerId')) {
						$('#' + $(this).data('datepickerId')).hide();
					}
				});
			},
			setDate: function(date, shiftTo){
				return this.each(function(){
					if ($(this).data('datepickerId')) {
						var cal = $('#' + $(this).data('datepickerId'));
						var options = cal.data('datepicker');
						options.date = date;
						if (options.date.constructor == String) {
							options.date = parseDate(options.date, options.format);
							options.date.setHours(0,0,0,0);
						}
						if (options.mode != 'single') {
							if (options.date.constructor != Array) {
								options.date = [options.date.valueOf()];
								if (options.mode == 'range') {
									options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf());
								}
							} else {
								for (var i = 0; i < options.date.length; i++) {
									options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf();
								}
								if (options.mode == 'range') {
									options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf();
								}
							}
						} else {
							options.date = options.date.valueOf();
						}
						if (shiftTo) {
							options.current = new Date (options.mode != 'single' ? options.date[0] : options.date);
						}
						fill(cal.get(0));
					}
				});
			},
			getDate: function(formated) {
				if (this.size() > 0) {
					return prepareDate($('#' + $(this).data('datepickerId')).data('datepicker'))[formated ? 0 : 1];
				}
			},
			clear: function(){
				return this.each(function(){
					if ($(this).data('datepickerId')) {
						var cal = $('#' + $(this).data('datepickerId'));
						var options = cal.data('datepicker');
						if (options.mode != 'single') {
							options.date = [];
							fill(cal.get(0));
						}
					}
				});
			},
			fixLayout: function(){
				return this.each(function(){
					if ($(this).data('datepickerId')) {
						var cal = $('#' + $(this).data('datepickerId'));
						var options = cal.data('datepicker');
						if (options.flat) {
							layout(cal.get(0));
						}
					}
				});
			}
		};
	}();
	$.fn.extend({
		DatePicker: DatePicker.init,
		DatePickerHide: DatePicker.hidePicker,
		DatePickerShow: DatePicker.showPicker,
		DatePickerSetDate: DatePicker.setDate,
		DatePickerGetDate: DatePicker.getDate,
		DatePickerClear: DatePicker.clear,
		DatePickerLayout: DatePicker.fixLayout
	});
})(jQuery);

(function(){
  var cache = {};
 
  this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] ||
        tmpl(document.getElementById(str).innerHTML) :
     
      // Generate a reusable function that will serve as a template
      // generator (and which will be cached).
      new Function("obj",
        "var p=[],print=function(){p.push.apply(p,arguments);};" +
       
        // Introduce the data as local variables using with(){}
        "with(obj){p.push('" +
       
        // Convert the template into pure JavaScript
        str
          .replace(/[\r\t\n]/g, " ")
          .split("<%").join("\t")
          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
          .replace(/\t=(.*?)%>/g, "',$1,'")
          .split("\t").join("');")
          .split("%>").join("p.push('")
          .split("\r").join("\\'")
      + "');}return p.join('');");
   
    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
})();
/*
 * jCal calendar multi-day and multi-month datepicker plugin for jQuery
 *	version 0.3.7
 * Author: Jim Palmer
 * Released under MIT license.
 */
(function($) {
	$.fn.jCal = function (opt) {
		$.jCal(this, opt);
		return this;
	};
	$.jCal = function (target, opt) {
		opt = $.extend({
			day:			new Date(),									// date to drive first cal
			days:			1,											// default number of days user can select
			showMonths:		1,											// how many side-by-side months to show
			monthSelect:	false,										// show selectable month and year ranges via animated comboboxen
			dCheck:			function (day) { return 'day'; },			// handler for checking if single date is valid or not - returns class to add to day cell
			callback:		function (day, days) { return true; },		// callback function for click on date
			drawBack:		function () { return true; },				// callback function for month being drawn
			selectedBG:		'rgb(0, 143, 214)',							// default bgcolor for selected date cell
			defaultBG:		'rgb(255, 255, 255)',						// default bgcolor for unselected date cell
			dayOffset:		0,											// 0=week start with sunday, 1=week starts with monday
			scrollSpeed:	150,										// default .animate() speed used
			forceWeek:		false,										// true=force selection at start of week, false=select days out from selected day
			dow:			['S', 'M', 'T', 'W', 'T', 'F', 'S'],		// days of week - change this to reflect your dayOffset
			ml:				['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
			ms:				['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
			_target:		target										// target DOM element - no need to set extend this variable
		}, opt);
		opt.day = new Date(opt.day.getFullYear(), opt.day.getMonth(), 1);
		if ( !$(opt._target).data('days') ) $(opt._target).data('days', opt.days);
		$(target).stop().empty();
		for (var sm=0; sm < opt.showMonths; sm++)
			$(target).append('<div class="jCalMo"></div>');
		opt.cID = 'c' + $('.jCalMo').length;
		$('.jCalMo', target).each(
			function (ind) {
				drawCalControl($(this), $.extend( {}, opt, { 'ind':ind, 
						'day':new Date( new Date( opt.day.getTime() ).setMonth( new Date( opt.day.getTime() ).getMonth() + ind ) ) }
					));
				drawCal($(this), $.extend( {}, opt, { 'ind':ind, 
						'day':new Date( new Date( opt.day.getTime() ).setMonth( new Date( opt.day.getTime() ).getMonth() + ind ) ) }
					));
			});
		if ( $(opt._target).data('day') && $(opt._target).data('days') ) 
			reSelectDates(target, $(opt._target).data('day'), $(opt._target).data('days'), opt);
		if ( typeof opt.drawBack == 'function' ) opt.drawBack();
	};
	function drawCalControl (target, opt) {
		$(target).append(
			'<div class="jCal">' + 
					( (opt.ind == 0) ? '<div class="left" />' : '' ) + 
					'<div class="month">' + 
						'<span class="monthYear">' + opt.day.getFullYear() + '</span>' +
						'<span class="monthName">' + opt.ml[opt.day.getMonth()] + '</span>' +
					'</div>' +
					( (opt.ind == ( opt.showMonths - 1 )) ? '<div class="right" />' : '' ) +
			'</div>');
		if ( opt.monthSelect )
			$(target).find('.jCal .monthName, .jCal .monthYear')
				.bind('mouseover', $.extend( {}, opt ),
					function (e) { 
						$(this).removeClass('monthYearHover').removeClass('monthNameHover');
						if ( $('.jCalMask', e.data._target).length == 0 ) $(this).addClass( $(this).attr('class') + 'Hover' );
					})
				.bind('mouseout', function () { $(this).removeClass('monthYearHover').removeClass('monthNameHover'); })
				.bind('click', $.extend( {}, opt ),
					function (e) {
						$(e.data._target).stop();
						$('.jCalMo .monthSelector, .jCalMo .monthSelectorShadow').remove();
						var monthName = $(this).hasClass('monthName'),
							pad = Math.max( parseInt($(this).css('padding-left')), parseInt($(this).css('padding-left'))) || 2, 
							calcTop = ( $(this).position().top - ( ( monthName ? e.data.day.getMonth() : 2 ) * ( $(this).height() + 0 ) ) );
						calcTop = calcTop > 0 ? calcTop : 0;
						var topDiff = $(this).position().top - calcTop;
						$('<div class="monthSelectorShadow" style="' +
							'top:' + $(e.data._target).position().top + 'px; ' +
							'left:' + $(e.data._target).position().left + 'px; ' +
							'width:' + ( $(e.data._target).width() + ( parseInt($(e.data._target).css('paddingLeft')) || 0 ) + ( parseInt($(e.data._target).css('paddingRight')) || 0 ) ) + 'px; ' +
							'height:' + ( $(e.data._target).height() + ( parseInt($(e.data._target).css('paddingTop')) || 0 ) + ( parseInt($(e.data._target).css('paddingBottom')) || 0 ) ) + 'px;">' +
						'</div>')
							.css('opacity',0.01).appendTo( $(this).parent() );
						$('<div class="monthSelector" style="' +
							'top:' + calcTop + 'px; ' +
							'left:' + ( $(this).position().left ) + 'px; ' +
							'width:' + ( $(this).width() + ( pad * 2 ) ) + 'px;">' +
						'</div>')
							.css('opacity',0).appendTo( $(this).parent() );
						for (var di = ( monthName ? 0 : -2 ), dd = ( monthName ? 12 : 3 ); di < dd; di++)
							$(this).clone().removeClass('monthYearHover').removeClass('monthNameHover').addClass('monthSelect')
								.attr( 'id', monthName ? (di + 1) + '_1_' + e.data.day.getFullYear() : (e.data.day.getMonth() + 1) + '_1_' + (e.data.day.getFullYear() + di) )
								.html( monthName ? e.data.ml[di] : ( e.data.day.getFullYear() + di ) )
								.css( 'top', ( $(this).height() * di ) ).appendTo( $(this).parent().find('.monthSelector') );
						var moSel = $(this).parent().find('.monthSelector').get(0), diffOff = $(moSel).height() - ( $(moSel).height() - topDiff );
						$(moSel)
							.css('clip','rect(' + diffOff + 'px ' + ( $(this).width() + ( pad * 2 ) ) + 'px '+ diffOff + 'px 0px)')
							.animate({'opacity':.92,'clip':'rect(0px ' + ( $(this).width() + ( pad * 2 ) ) + 'px ' + $(moSel).height() + 'px 0px)'}, e.data.scrollSpeed, function () {
									$(this).parent().find('.monthSelectorShadow').bind('mouseover click', function () { $(this).parent().find('.monthSelector').remove(); $(this).remove(); });
								})
							.parent().find('.monthSelectorShadow').animate({'opacity':.1}, e.data.scrollSpeed);
						$('.jCalMo .monthSelect', e.data._target).bind('mouseover mouseout click', $.extend( {}, e.data ), 
							function (e) {
								if ( e.type == 'click' )
									$(e.data._target).jCal( $.extend(e.data, {day:new Date($(this).attr('id').replace(/_/g, '/'))}) );
								else
									$(this).toggleClass('monthSelectHover');
							});
						if ( typeof opt.drawBack == 'function' ) opt.drawBack();
					});
		$(target).find('.jCal .left').bind('click', $.extend( {}, opt ),
			function (e) {
				if ($('.jCalMask', e.data._target).length > 0) return false;
				$(e.data._target).stop();
				var mD = { w:0, h:0 };
				$('.jCalMo', e.data._target).each( function () { 
						mD.w += $(this).width() + parseInt($(this).css('padding-left')) + parseInt($(this).css('padding-right')); 
						var cH = $(this).height() + parseInt($(this).css('padding-top')) + parseInt($(this).css('padding-bottom')); 
						mD.h = ((cH > mD.h) ? cH : mD.h);
					} );
				$(e.data._target).prepend('<div class="jCalMo"></div>');
				e.data.day = new Date( $('div[id*=' + e.data.cID + 'd_]:first', e.data._target).attr('id').replace(e.data.cID + 'd_', '').replace(/_/g, '/') );
				e.data.day.setDate(1);
				e.data.day.setMonth( e.data.day.getMonth() - 1 );
				drawCalControl($('.jCalMo:first', e.data._target), e.data);
				drawCal($('.jCalMo:first', e.data._target), e.data);
				if (e.data.showMonths > 1) {
					$('.right', e.data._target).clone(true).appendTo( $('.jCalMo:eq(1) .jCal', e.data._target) );
					$('.left:last, .right:last', e.data._target).remove();
				}
				$(e.data._target).append('<div class="jCalSpace" style="width:'+mD.w+'px; height:'+mD.h+'px;"></div>');
				$('.jCalMo', e.data._target).wrapAll(
					'<div class="jCalMask" style="clip:rect(0px '+mD.w+'px '+mD.h+'px 0px); width:'+ ( mD.w + ( mD.w / e.data.showMonths ) ) +'px; height:'+mD.h+'px;">' + 
						'<div class="jCalMove"></div>' +
					'</div>');
				$('.jCalMove', e.data._target).css('margin-left', ( ( mD.w / e.data.showMonths ) * -1 ) + 'px').css('opacity', 0.5).animate({ marginLeft:'0px' }, e.data.scrollSpeed,
					function () {
						$(this).children('.jCalMo:not(:last)').appendTo( $(e.data._target) );
						$('.jCalSpace, .jCalMask', e.data._target).empty().remove();
						if ( $(e.data._target).data('day') ) 
							reSelectDates(e.data._target, $(e.data._target).data('day'), $(e.data._target).data('days'), e.data);
						if ( typeof opt.drawBack == 'function' ) 
							opt.drawBack();
					});
			});
		$(target).find('.jCal .right').bind('click', $.extend( {}, opt ),
			function (e) {
				if ($('.jCalMask', e.data._target).length > 0) return false;
				$(e.data._target).stop();
				var mD = { w:0, h:0 };
				$('.jCalMo', e.data._target).each( function () { 
						mD.w += $(this).width() + parseInt($(this).css('padding-left')) + parseInt($(this).css('padding-right')); 
						var cH = $(this).height() + parseInt($(this).css('padding-top')) + parseInt($(this).css('padding-bottom')); 
						mD.h = ((cH > mD.h) ? cH : mD.h);
					} );
				$(e.data._target).append('<div class="jCalMo"></div>');
				e.data.day = new Date( $('div[id^=' + e.data.cID + 'd_]:last', e.data._target).attr('id').replace(e.data.cID + 'd_', '').replace(/_/g, '/') );
				e.data.day.setDate(1);
				e.data.day.setMonth( e.data.day.getMonth() + 1 );
				drawCalControl($('.jCalMo:last', e.data._target), e.data);
				drawCal($('.jCalMo:last', e.data._target), e.data);
				if (e.data.showMonths > 1) {
					$('.left', e.data._target).clone(true).prependTo( $('.jCalMo:eq(1) .jCal', e.data._target) );
					$('.left:first, .right:first', e.data._target).remove();
				}
				$(e.data._target).append('<div class="jCalSpace" style="width:'+mD.w+'px; height:'+mD.h+'px;"></div>');
				$('.jCalMo', e.data._target).wrapAll(
					'<div class="jCalMask" style="clip:rect(0px '+mD.w+'px '+mD.h+'px 0px); width:'+ ( mD.w + ( mD.w / e.data.showMonths ) ) +'px; height:'+mD.h+'px;">' + 
						'<div class="jCalMove"></div>' +
					'</div>');
				$('.jCalMove', e.data._target).css('opacity', 0.5).animate({ marginLeft:( ( mD.w / e.data.showMonths ) * -1 ) + 'px' }, e.data.scrollSpeed,
					function () {
						$(this).children('.jCalMo:not(:first)').appendTo( $(e.data._target) );
						$('.jCalSpace, .jCalMask', e.data._target).empty().remove();
						if ( $(e.data._target).data('day') ) 
							reSelectDates(e.data._target, $(e.data._target).data('day'), $(e.data._target).data('days'), e.data);
						$(this).children('.jCalMo:not(:first)').removeClass('');
						if ( typeof opt.drawBack == 'function' )
							opt.drawBack();
					});
			});
	};	
	function reSelectDates (target, day, days, opt) {
		var fDay = new Date(day.getTime());
		var sDay = new Date(day.getTime());
		for (var fC = false, di = 0, dC = days; di < dC; di++) {
			var dF = $(target).find('div[id*=d_' + (sDay.getMonth() + 1) + '_' + sDay.getDate() + '_' + sDay.getFullYear() + ']');
			if ( dF.length > 0 ) {
				dF.stop().addClass('selectedDay');
				fC = true;
			}
			sDay.setDate( sDay.getDate() + 1 );
		}
		if ( fC && typeof opt.callback == 'function' ) opt.callback( day, days );
	};
	function drawCal (target, opt) {
		for (var ds=0, length=opt.dow.length; ds < length; ds++)
			$(target).append('<div class="dow">' + opt.dow[ds] + '</div>');
		var fd = new Date( new Date( opt.day.getTime() ).setDate(1) );
		var ldlm = new Date( new Date( fd.getTime() ).setDate(0) );
		var ld = new Date( new Date( new Date( fd.getTime() ).setMonth( fd.getMonth() + 1 ) ).setDate(0) );
		var copt = {fd:fd.getDay(), lld:ldlm.getDate(), ld:ld.getDate()};
		var offsetDayStart = ( ( copt.fd < opt.dayOffset ) ? ( opt.dayOffset - 7 ) : 1 );
		var offsetDayEnd = ( ( ld.getDay() < opt.dayOffset ) ? ( 7 - ld.getDay() ) : ld.getDay() );
		for ( var d = offsetDayStart, dE = ( copt.fd + copt.ld + ( 7 - offsetDayEnd ) ); d < dE; d++)
			$(target).append(
				(( d <= ( copt.fd - opt.dayOffset ) ) ? 
					'<div id="' + opt.cID + 'd' + d + '" class="pday">' + ( copt.lld - ( ( copt.fd - opt.dayOffset ) - d ) ) + '</div>' 
					: ( ( d > ( ( copt.fd - opt.dayOffset ) + copt.ld ) ) ?
						'<div id="' + opt.cID + 'd' + d + '" class="aday">' + ( d - ( ( copt.fd - opt.dayOffset ) + copt.ld ) ) + '</div>' 
						: '<div id="' + opt.cID + 'd_' + (fd.getMonth() + 1) + '_' + ( d - ( copt.fd - opt.dayOffset ) ) + '_' + fd.getFullYear() + '" class="' +
							( opt.dCheck( new Date( (new Date( fd.getTime() )).setDate( d - ( copt.fd - opt.dayOffset ) ) ) ) || 'invday' ) +
							'">' + ( d - ( copt.fd - opt.dayOffset ) )  + '</div>'
					) 
				)
			);
		$(target).find('div[id^=' + opt.cID + 'd]:first, div[id^=' + opt.cID + 'd]:nth-child(7n+2)').before( '<br style="clear:both;" />' );
		$(target).find('div[id^=' + opt.cID + 'd_]:not(.invday)').bind("mouseover mouseout click", $.extend( {}, opt ),
			function(e){
					if ($('.jCalMask', e.data._target).length > 0) return false;
					var osDate = new Date ( $(this).attr('id').replace(/c[0-9]{1,}d_([0-9]{1,2})_([0-9]{1,2})_([0-9]{4})/, '$1/$2/$3') );
					if (e.data.forceWeek) osDate.setDate( osDate.getDate() + (e.data.dayOffset - osDate.getDay()) );
					var sDate = new Date ( osDate.getTime() );
					if (e.type == 'click')
						$('div[id*=d_]', e.data._target).stop().removeClass('selectedDay').removeClass('overDay');
					for (var di = 0, ds = $(e.data._target).data('days'); di < ds; di++) {
						var currDay = $(e.data._target).find('#' + e.data.cID + 'd_' + ( sDate.getMonth() + 1 ) + '_' + sDate.getDate() + '_' + sDate.getFullYear());
						if ( currDay.length == 0 || $(currDay).hasClass('invday') ) break;
						if ( e.type == 'mouseover' )		$(currDay).addClass('overDay');
						else if ( e.type == 'mouseout' )	$(currDay).stop().removeClass('overDay');
						else if ( e.type == 'click' )		$(currDay).stop().addClass('selectedDay');
						sDate.setDate( sDate.getDate() + 1 );
					}
					if (e.type == 'click') {
						e.data.day = osDate;
						if ( e.data.callback( osDate, di, this ) )
							$(e.data._target).data('day', e.data.day).data('days', di);
					}
			});
	};
	
})(jQuery);
/**
 * @fileoverview frozCrossSlider plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-04-28
 */
 
( function( $ ) {
    /**
     * all parameters
     * <ul> passes must have ID
     * all content banners must have the same dimensions
     * When thumbnails are clicked, contents slide over accordingly
     * @namespace frozCrossSlider Plugin Namespace
     * @requires jQuery 1.2.6 and above / jQuery Easing / jquery.color
     * @example jQuery( "#id-of-list-that-contains-contents" ).frozCrossSlider
     * @return {jQuery Object}
     */
    jQuery.fn.frozCrossSlider = function( options, images ) {
        var opts                            = jQuery.extend( {}, jQuery.fn.frozCrossSlider.defaults, options );
        jQuery.fn.frozCrossSlider.opts      = opts;
        var $this                           = jQuery( this );
        
        var setLoader = function(head, loc){
            var loader = jQuery('<img src="' + loc + '"/>');
            loader.addClass(opts.loaderClass).hide();
            head.append(loader).data('loader', loader);
            
            return head;
        }
        
        var showLoader = function(head){
            head.data('loader').show();
        }
        
        var hideLoader = function(head){
            head.data('loader').hide();
        }
        
        var setShow = function(head, index){
            if ( !isNaN(head.data('currentIndex')) && (head.data('currentIndex') !== null) ){
                head.data('currentIndex', index);

                var initSrc = head.data('images')[index].src;
                
                if ( head.data('timer') !== null ){
                    head.data('timer').stop();
                }
                
                if ( typeof(head.data('image-' + index)) == 'undefined' ){
                
                    if ( head.data('showLoaderInBetween') === true ){
                        showLoader(head);
                    }
                    
                    jQuery.ajax({
                        url: initSrc,
                        dataType: 'string',
                        success: function(data){
                            var img = jQuery('<img src="' + initSrc + '" class="' + head.data('imgClass') + '" />');
                            replaceImageNew(head, img, index);
                        },
                        error: function(XMLHttpRequest, textStatus, errorThrown){
                            if ( (jQuery.browser.msie === true) && (XMLHttpRequest.status == '200') ){
                                var img = jQuery('<img src="' + initSrc + '" class="' + head.data('imgClass') + '" />');
                                replaceImageNew(head, img, index);
                            } else {
                                head.data('onAjaxError')(XMLHttpRequest, textStatus, errorThrown);
                                if ( head.data('timer') !== null ){
                                    head.data('timer').reset(head.data('sleep'));
                                }
                            }
                        }
                    })
                } else {
                    replaceImage(head, head.data('image-' + index), index);
                }
            }
        }
        
        var replaceImage = function(head, image, index){
        
            if ( typeof(head.data('onShow')) == 'function' ){
                head.data('onShow')(head, image, index);
            }
                
            if ( head.data('timer') !== null ){
                head.data('timer').reset(head.data('sleep'));
            }
            
            if ( head.data('noReplace') !== true ){
                if ( head.find('img.' + head.data('imgClass')).length > 0 ){
                    head.find('img.' + head.data('imgClass')).stop(false, true).fadeOut(head.data('fade'));
                }
            
                head.append(image.stop(false, true).fadeIn(head.data('fade')));
            }
        }
        
        var replaceImageNew = function(head, image, index){

            image.load(function(){
                jQuery(this).hide();
                hideLoader(head);
                
                replaceImage(head, jQuery(this), index);
                
                if ( head.data('storeImages') === true ){
                    head.data('image-' + index, jQuery(this), index);
                }
            })
        }
        
        var preloadImages = function(head, starter, sleep){
            head.data('currentIndex', null)
        
            for ( index in head.data('images') ){
                var src = head.data('images')[index].src;
                var img = jQuery('<img src="' + src + '" class="' + head.data('imgClass') + '" />');
                img.addClass(opts.imgLoadingClass)
                head.append(img.hide())
                head.data('image-' + index, img, index);
                
                if ( (parseInt(index) + 1) == head.data('images').length ){
                    img.load( function(){
                        head.data('currentIndex', (starter - 1))
                        hideLoader(head);
                        
                        if ( parseInt(sleep) > 0 ){
                            setAutoSlide(head);
                            if (opts.hoverHold === true){
                                setHoverHold();
                            }
                        } else {
                            setShow(head, starter);
                        }
                    })
                }
            }
            
            return head;
        }
        
        var setAutoSlide = function(head){
            
            var mainTimer = jQuery.timer( head.data('sleep'), function( timer ) { 
                if ( !isNaN(head.data('currentIndex')) ){
                    var maxLength = head.data('length');
                    var index = (parseInt(head.data('currentIndex')) + 1);
                    
                    if ( index >= maxLength ){
                        index = 0;
                    }
                    
                    setShow(head, index);
                }
            });
            
            head.data('timer', mainTimer);
            return head;
        }
        
        var setHoverHold = function(head){
            head.hover( function(){
                head.data('timer').stop();
            }, function(){
                head.data('timer').reset(head.data('sleep'));
            });
        }
        
        if ( $this.length > 0 ){
        
            $this.each( function(){
                var head = jQuery(this).addClass(opts.enableClass)
                           .data('images', images)
                           .data('length', images.length)
                           .data('imgClass', opts.mainImageClass)
                           .data('fade', opts.fade)
                           .data('showLoaderInBetween', opts.showLoaderInBetween)
                           .data('storeImages', opts.storeImages)
                           .data('onAjaxError', opts.onAjaxError)
                           .data('onHide', opts.onHide)
                           .data('onShow', opts.onShow);
            
                if ( typeof(opts.loader) == 'string' ){
                    head = setLoader(head, opts.loader);
                    showLoader(head);
                }         
                
                head.data('currentIndex', opts.startIndex)
                head.data('timer', null);
                
                if ( opts.preload === true ){
                    head = preloadImages(head, opts.startIndex, opts.sleep);
                }
                
                if ( parseInt(opts.sleep) > 0 ){
                    head.data('currentIndex', parseInt(head.data('currentIndex')) - 1);
                    head.data('sleep', opts.sleep);
                    var head = setAutoSlide(head);
                    
                    if (opts.hoverHold === true){
                        setHoverHold(head);
                    }
                } else {
                    setShow(head, opts.startIndex);   
                }
            })          
        
        }
                
        return $this;
    };

    /** 
     * Sends a message to the console
     * @private
     */
    var _debug = function( message ) {
        if ( true === jQuery.fn.frozCrossSlider.opts.debug ) {
            console.log( message );
        }
    };
    
    jQuery.fn.frozCrossSlider.defaults =   {
        enableClass: 'froz-cross-slide-enable',
        mainImageClass: 'froz-cross-main',
        sleep: 5,
        hoverHold: true,
        fade: 1,
        startIndex: 0,
        storeImages: true,
        ajax: true,
        preload: false,
        showLoaderInBetween: false,
        loaderClass: 'froz-cross-slide-loader',
        imgLoadingClass: 'froz-cross-image-loading',
        
        onHide: function(head){
            return false;
        },
        onShow: function(head, image, index){
            return false;
        },
        onAjaxError: function(XMLHttpRequest, textStatus, errorThrown){
            console.log(textStatus);
            return false;
        }
    };
} )(jQuery);
/**
 * @fileoverview frozAlbumGallery plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-04-28
 */
 
( function( $ ) {
    /**
     * all parameters
     * <ul> passes must have ID
     * all content banners must have the same dimensions
     * When thumbnails are clicked, contents slide over accordingly
     * @namespace frozAlbumGallery Plugin Namespace
     * @requires jQuery 1.4.2 and above / jQuery Easing / jquery gallerific(new) / jQuery fancybox
     * @example jQuery( "#id-of-list-that-contains-contents" ).frozAlbumGallery
     * @return {jQuery Object}
     */
    jQuery.fn.frozAlbumGallery = function( options ) {
        var opts                            = jQuery.extend( {}, jQuery.fn.frozAlbumGallery.defaults, options );
        jQuery.fn.frozAlbumGallery.opts      = opts;
        var $this                           = jQuery( this );
		
        var setupClick = function(){		
            $this.children('li').children('a').click( function(){
            	changeHash(jQuery(this).parent('li').attr('id'));
            	var count = null
                var container = detectContainer(jQuery(this).closest('li'));
            	var href = jQuery(this).attr('href');
            	jQuery.fancybox.showActivity();
            	jQuery.ajax({
            	    url: href,
            	    success: function(data){
            	    	appendData(container, data);
//            	    	gallerify(container);
            	    	container.frozGallerify();
            	    	jQuery.fancybox({
            	    		content: container.show(),
            	    		overlayOpacity: 0.9,
//            	    		centerOnScroll: true,
            	    		autoDimensions: true,
            	    		speedIn: 100,
            	    		speedOut: 100,
            	    		onClosed: function(){
            	    			container.hide();
            	    		}
            	    	})
            	    }
            	})  
            	
            	return false;
            })
		
		}
		
		var defineDimensions = function(container){
			var height = container.outerHeight(true);
			var width = container.outerWidth(true);
			container.css({height: height, width: width})
		}
		
		var appendData = function(container, data){
			if ( container.contents().length < 1 ){
				container.append(data);
			}
		}
		
		var detectContainer = function(list){
		    var container = jQuery(list).find('div.' + opts.containerClass);
		    
		    if ( container.length < 1 ){
		    	list.append('<div class="' + opts.containerClass + '"></div>');
		    	container = jQuery('.' + opts.containerClass, list)
		    	.hide();
		    }
		    
		    return container;
		}
		
		var changeHash = function(hash){
			
			if((jQuery.browser.msie === true) && (jQuery.browser.version === '7.0')){
        		window.location = window.location.toString().substring(0, window.location.toString().indexOf('#')) +'#'+hash;
            } else {
            	window.location.hash = '#' + hash;
            }
            
		}
		
		var detectHash = function(){
		
            if((jQuery.browser.msie === true) && (jQuery.browser.version === '7.0')){
            	if ( window.location.toString().indexOf('#') < 0 ){
            		var hash = '';
            	} else {
            		var hash = window.location.toString().substring(window.location.toString().indexOf('#'));
            	}
            } else {
            	var hash = window.location.hash;
            }
            
            if ( !(hash == '') ){
            	jQuery(hash, $this).find('a:first').trigger('click');
            }
		}
		
		var setupHashBehavior = function(){
			jQuery(window).bind( 'hashchange', function(e) {
                detectHash();
            });  
		}
		
		if ( $this.length > 0 ){
		    
		    setupClick();
		    
		    detectHash();
		    
		    setupHashBehavior();
		
		}
		
		
        return $this;
    };

    /** 
     * Sends a message to the console
     * @private
     */
    var _debug = function( message ) {
        if ( true === jQuery.fn.frozAlbumGallery.opts.debug ) {
            console.log( message );
        }
    };
    
    jQuery.fn.frozAlbumGallery.defaults =   {
    	containerClass: 'album-ajax-content-container',
    	fadeTime: 500,
    	
    	galleryContainerClass: 'froz-gallery-initialized',
        mainGalleryClass: 'froz-album-gallery',
        thumbnailsId: 'thumbs',
        navigationId: 'gallery',
        controlsId: 'controls',
        slideshowContainer: 'slideshow-container',
        captionId: 'caption',
        loadingId: 'loading',
        slideshowId: 'slideshow',
        captionClass: 'caption',
        downloadClass: 'download',
        imageTitleClass: 'image-title',
        imageDescClass: 'image-desc',
        
        hashPrefix: 'album-'
    };
} )(jQuery);
/**
 * @fileoverview frozGallerify plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-04-28
 */
 
( function( $ ) {
    /**
     * all parameters
     * <ul> passes must have ID
     * all content banners must have the same dimensions
     * When thumbnails are clicked, contents slide over accordingly
     * @namespace frozGallerify Plugin Namespace
     * @requires jQuery 1.4.2 and above / jQuery Easing / jquery gallerific(new) / jQuery prettyphoto
     * @example jQuery( "#id-of-list-that-contains-contents" ).frozGallerify
     * @return {jQuery Object}
     */
    jQuery.fn.frozGallerify = function( options ) {
        var opts                            = jQuery.extend( {}, jQuery.fn.frozGallerify.defaults, options );
        jQuery.fn.frozGallerify.opts      = opts;
        var $this                           = jQuery( this );
		
		var container = $this;
		
		if ( container.hasClass(opts.galleryContainerClass) ){
			
		} else {
			var list = container.find('ul:first');
			galleryArray =  new Array(opts.thumbnailsId,            //0
	                                  opts.navigationId,            //1
	                                  opts.controlsId,              //2
	                                  opts.slideshowContainer,      //3
	                                  opts.captionId,               //4
	                                  opts.loadingId,               //5    
	                                  opts.slideshowId,             //6
	                                  opts.captionClass,            //7
	                                  opts.downloadClass,           //8
	                                  opts.imageTitleClass,         //9
	                                  opts.imageDescClass           //10
	                                  );           
	                             
	        list.addClass('thumbs').css({listStyleType: 'none'}).wrap('<div id="' + galleryArray[0] + '"></div>')
	            .children('li').children('a').addClass('thumb');
	            
	        var slideDiv = list.parent();
	        
	        slideDiv.wrap('<div class="' + opts.mainGalleryClass + '"></div>')
	        slideDiv.before('<div id="' + galleryArray[1] + '"></div>');
	        
	        var slideSibling = slideDiv.prev();
	        
	        slideSibling.append('<div id="' + galleryArray[2] + '"></div>');
	        slideSibling.append('<div id="' + galleryArray[3] + '"></div>');
	        slideSibling.append('<div id="' + galleryArray[4] + '"></div>');
	        slideSibling.children('#' + galleryArray[3]).append('<div id="' + galleryArray[5] + '"></div>');
	        slideSibling.children('#' + galleryArray[3]).append('<div id="' + galleryArray[6] + '"></div>');
	            
	        list.children().each( function(){
//                var href = jQuery(this).children('a').attr('href');
	            jQuery(this).children('.' + galleryArray[7]).append('<div class="' + galleryArray[8] + '"></div>')
															.append('<div class="' + galleryArray[9] + '"></div>')
															.append('<div class="' + galleryArray[10] + '"></div>');
//                jQuery('.' + galleryArray[8], this).append('<a href="' + href + '"></a>');
	        })
	        
	        for ( index in galleryArray ){
	            jQuery('#' + galleryArray[index]).addClass(galleryArray[index]);
	            galleryArray[index] = '#' + galleryArray[index];
	        }
	        
	        var presentSlide = null;
	        
	        list.parent().galleriffic({
				delay:                     2500,
				numThumbs:                 9,
				preloadAhead:              10,
				enableTopPager:            true,
				enableBottomPager:         false,
				maxPagesToShow:            7,
				imageContainerSel:         slideSibling.children('#' + galleryArray[3]).children('#' + galleryArray[6]),
				controlsContainerSel:      slideSibling.children('#' + galleryArray[2]),
				captionContainerSel:       slideSibling.children('#' + galleryArray[4]),
				loadingContainerSel:       slideSibling.children('#' + galleryArray[3]).children('#' + galleryArray[5]),
				renderSSControls:          true,
				renderNavControls:         true,
				playLinkText:              'Play Slideshow',
				pauseLinkText:             'Pause Slideshow',
				prevLinkText:              '&lsaquo; Prev',
				nextLinkText:              'Next &rsaquo;',
				nextPageLinkText:          'Next Page',
				prevPageLinkText:          'Previous Page',
				enableHistory:             false,
				autoStart:                 false,
				syncTransitions:           true,
				defaultTransitionDuration: 900
				,
				onSlideChange: function(prevIndex, nextIndex){
	        		jQuery('span', list.parent().parent().find('div#' + opts.slideshowId)).css({position: 'absolute'});
	        		if ( jQuery('div#' + opts.captionId, list.parent().parent()).children() > 1 ){
	        			jQuery('div#' + opts.captionId, list.parent().parent()).children(':last-child').prevAll().remove();
	        		}
				}
				,
				onTransitionOut: function(previousSlide, previousCaption, isSync, transitionOutCallback){
					if ( jQuery.browser.webkit === true ){
						previousSlide.remove();
					}
					previousSlide.fadeTo(opts.fadeTime, 0.0, transitionOutCallback);
				
					if (previousCaption)
						previousCaption.remove();
				}
				,
				onTransitionIn: function(newSlide, newCaption, isSync){
								
					if ( presentSlide !== jQuery('img', newSlide).attr('src') ){				
						newSlide.fadeTo(opts.fadeTime, 1.0);
					} else {
						newSlide.fadeTo(1, 1.0);
					}
				
					if (newCaption) {
						newCaption.fadeTo(opts.fadeTime, 1.0);
					}
				
					presentSlide = jQuery('img', newSlide).attr('src');
				}
				,
				onPageTransitionIn: function(){
					list.parent().fadeIn(opts.fadeTime)
				}
	        });
	        
	        container.addClass(opts.galleryContainerClass);
		
			var defineDimensions = function(container){
				var height = container.outerHeight(true);
				var width = container.outerWidth(true);
				container.css({height: height, width: width})
			}

	        defineDimensions(container)
	        
	    }
		
        return $this;
    };

    /** 
     * Sends a message to the console
     * @private
     */
    var _debug = function( message ) {
        if ( true === jQuery.fn.frozGallerify.opts.debug ) {
            console.log( message );
        }
    };
    
    jQuery.fn.frozGallerify.defaults =   {
    	fadeTime: 500,
    	
    	galleryContainerClass: 'froz-gallery-initialized',
        mainGalleryClass: 'froz-album-gallery',
        thumbnailsId: 'thumbs',
        navigationId: 'gallery',
        controlsId: 'controls',
        slideshowContainer: 'slideshow-container',
        captionId: 'caption',
        loadingId: 'loading',
        slideshowId: 'slideshow',
        captionClass: 'caption',
        downloadClass: 'download',
        imageTitleClass: 'image-title',
        imageDescClass: 'image-desc'
    };
} )(jQuery);
/**
 * @fileoverview frozPortfolio plugin
 * @author Lawrence Natividad
 * @copyright Copyright ( c ) 2010 Frozynart Designs
 * @license Licensed under MIT ( http://www.frozynart.com/license/mit )
 * @version: 1.0 2010-04-28
 */
 
( function( $ ) {
    /**
     * all parameters
     * <ul> passes must have ID
     * all content banners must have the same dimensions
     * When thumbnails are clicked, contents slide over accordingly
     * @namespace frozPortfolio Plugin Namespace
     * @requires jQuery 1.2.6 and above / jQuery Easing / jquery.color
     * @example jQuery( "#id-of-list-that-contains-contents" ).frozPortfolio
     * @return {jQuery Object}
     */
    jQuery.fn.frozImageEffectsInit = function( imgArray, options, change ) {
        var opts                            = jQuery.extend( {}, jQuery.fn.frozImageEffectsInit.defaults, options );
        jQuery.fn.frozImageEffectsInit.opts      = opts;
        var $this                           = jQuery( this );
        
        var initialize = function(imgArray, opts){
            var panelArray = [];

            if ( typeof(imgArray) == 'object'){
                for ( index in imgArray ){
                    
                    if ( typeof(imgArray[index]) == 'string' ){
                        var imgName = imgArray[index];
                        var image = jQuery('<img src="' + imgName + '"/>');
                    } else if ( imgArray[index].is('img') ){
                        var image = imgArray[index];
                        var imgName = image.attr('src');
                    }

                    var panelIsStored = false;
                    
                    if ( (typeof(jQuery(document).data(opts.documentStorageName)) == 'object') && (opts.forceNew !== true) ){
                        if ( typeof(jQuery(document).data(opts.documentStorageName).data(imgName)) == 'object' ){
                            var panel = jQuery(document).data(opts.documentStorageName).data(imgName);
                            panelIsStored = true;
                        }
                    }

                    if ( panelIsStored !== true ){
                        var panel = jQuery('<div class="' + opts.panelClass + '"></div>');
                        panel.data('setOpts', opts);
                        
                        var imageDims = getImageDims(image);
                        
                        if ( imageDims[0] > 0 ){
                            panel = createPanel(image, opts, panel);
                            panel = setupEffectPos(panel, opts)
                            panel.addClass(opts.readyClass).data('image', image).trigger('load');
                        } else {
                            image.load( {currentName: imgName, opts: opts, panel: panel}, function(event){
                                createPanel(jQuery(this), event.data.opts, event.data.panel);
                                setupEffectPos(event.data.panel, opts)
                                event.data.panel.addClass(event.data.opts.readyClass).data('image', jQuery(this)).trigger('load');
                            })
                        }
                    }

                    panelArray.push(panel);
                    
                }
            }

            return panelArray;
            
        }
        
        var getImageDims = function(image){

            var dimIdentifier = image.clone();
            var imPos = dimIdentifier.css('position');
            var imVis = dimIdentifier.css('visibility');
            
            jQuery('body').append(dimIdentifier.css({
                position: 'absolute', visibility: 'hidden'
            }))
            
            var width = dimIdentifier.width();
            var height = dimIdentifier.height();
            
            dimIdentifier.css({ position: imPos, visibility: imVis }).remove();
            
            return [width, height];
        }
        
        var setupEffectPos = function(panel, opts){
            if ( opts.orientation === 'vertical' ){
                panel = setupVertEffectPos(panel, opts)
            } else if ( opts.orientation === 'horizontal' ){
                panel = setupHoriEffectPos(panel, opts)
            } else if ( opts.orientation === 'bricks' ){
                panel = setupBrickEffectPos(panel, opts)
            }
            
            
            return panel;
        }
        
        var setupBrickEffectPos = function(panel, opts){    //fade, center, sunrise, sunshine, arrowLeft, arrowRight, diagonal
            if ( (opts.effect === 'fade') || 
                 (opts.effect === 'center') ||
                 (opts.effect === 'sunrise')  ||
                 (opts.effect === 'sunshine') ||
                 (opts.effect === 'arrowRight') ||
                 (opts.effect === 'arrowLeft') ){
                panel.find('div.' + opts.blockClass).fadeTo(0, 0).each( function(){
                    jQuery(this).data('animSpecs')[2] = 0;
                })
            } else if (opts.effect === 'diagonal'){
                panel.find('div.' + opts.blockClass).css({
                    left: '-' + panel.data('width') + 'px'
                }).each( function(){
                    jQuery(this).data('animSpecs')[0] = '-' + panel.data('width');
                })
            } else {
                console.log('Square bricks do not support this effect: ' + opts.effect)
            }
            
            return panel;
        }
        
        var setupHoriEffectPos = function(panel, opts){     //fade, blinds, curtain, teeth, slideRight, arrowRight, slideLeft, arrowLeft, roll, float
        
            if ( opts.effect === 'fade' ){
                panel.children('div.' + opts.blockClass).fadeTo(0, 0).each( function(){
                    jQuery(this).data('animSpecs')[2] = 0;
                })
            } else if ( opts.effect === 'blinds' ){
                panel.children('div.' + opts.blockClass).data('finalHeight', 0).css({height: '0px'});
            } else if ( opts.effect === 'curtain' ){
                panel.children('div.' + opts.blockClass).each( function(){
                    if ( (jQuery(this).index() + 0.5 ) < (panel.data('blockCount') / 2) ){
                        jQuery(this).css({ top: '-' + panel.data('blockHeight') + 'px', left: '0px' })
                                    .data('animSpecs')[1] = '-' + panel.data('blockHeight');
                    } else {
                        jQuery(this).css({ top: panel.data('height') + 'px', left: '0px' })
                                    .data('animSpecs')[1] = panel.data('height');
                    }
                    
                });
            } else if ( opts.effect === 'teeth' ){
                panel.children('div.' + opts.blockClass).each( function(){
                    if ( (jQuery(this).index() % 2) > 0 ){
                        jQuery(this).css({ left: '-' + panel.data('width') + 'px'})
                                    .data('animSpecs')[0] = '-' + panel.data('width');
                    } else {
                        jQuery(this).css({ left: panel.data('width') + 'px'})
                                    .data('animSpecs')[0] = panel.data('width');
                    }
                
                });
            } else if ( (opts.effect === 'slideRight') ||
                        (opts.effect === 'arrowRight') ){
                panel.children('div.' + opts.blockClass)
                .css({ left: '-' + panel.data('width') + 'px'})
                .each( function(){
                    jQuery(this).data('animSpecs')[0] = '-' + panel.data('width');
                })
            } else if ( (opts.effect === 'slideLeft') ||
                        (opts.effect === 'arrowLeft') ){
                panel.children('div.' + opts.blockClass)
                .css({ left: panel.data('width') + 'px'})
                .each( function(){
                    jQuery(this).data('animSpecs')[0] = panel.data('width');
                })
            } else if ( (opts.effect === 'roll') || (opts.effect === 'float') ){
                panel.children('div.' + opts.blockClass)
                .css({top: '-' + panel.data('blockHeight') + 'px'})
                .each( function(){
                    jQuery(this).data('animSpecs')[1] = '-' + panel.data('blockHeight');
                })
            } else {
                console.log('Horizontal blocks do not support this effect: ' + opts.effect)
            }
            
            return panel;
        }        
        
        var setupVertEffectPos = function(panel, opts){  

            if ( opts.effect === 'fade' ){
                panel.children('div.' + opts.blockClass).fadeTo(0, 0).each( function(){
                    jQuery(this).data('animSpecs')[2] = 0;
                })
            } else if (opts.effect === 'blinds'){
                panel.children('div.' + opts.blockClass).data('finalWidth', 0).css({width: '0px'});
            } else if ( opts.effect === 'curtain' ){
                panel.children('div.' + opts.blockClass).each( function(){
                    if ( (jQuery(this).index() + 0.5 ) < (panel.data('blockCount') / 2) ){
                        jQuery(this).css({ left: '-' + panel.data('blockWidth') + 'px', top: '0px' })
                                    .data('animSpecs')[0] = '-' + panel.data('blockWidth');
                    } else {
                        jQuery(this).css({ left: panel.data('width') + 'px', top: '0px' })
                                    .data('animSpecs')[0] = panel.data('width');
                    }
                    
                });
            } else if ( opts.effect === 'teeth' ){
                panel.children('div.' + opts.blockClass).each( function(){
                    if ( (jQuery(this).index() % 2) > 0 ){
                        jQuery(this).css({ top: '-' + panel.data('blockHeight') + 'px'})
                                    .data('animSpecs')[1] = '-' + panel.data('blockHeight');
                    } else {
                        jQuery(this).css({ top: panel.data('blockHeight') + 'px'})
                                    .data('animSpecs')[1] = panel.data('blockHeight');
                    }
                
                });
            } else if ( (opts.effect === 'drop') ||
                        (opts.effect === 'arrowDown') ){
                panel.children('div.' + opts.blockClass)
                .css({ top: '-' + panel.data('blockHeight') + 'px'})
                .each( function(){
                    jQuery(this).data('animSpecs')[1] = '-' + panel.data('blockHeight');
                })
            } else if ( (opts.effect === 'rise') ||
                        (opts.effect === 'arrowUp') ){
                panel.children('div.' + opts.blockClass)
                .css({ top: panel.data('blockHeight') + 'px'})
                .each( function(){
                    jQuery(this).data('animSpecs')[1] = panel.data('blockHeight');
                })
            } else if ( (opts.effect === 'roll') || (opts.effect === 'float') ){
                panel.children('div.' + opts.blockClass)
                .css({left: '-' + panel.data('blockWidth') + 'px'})
                .each( function(){
                    jQuery(this).data('animSpecs')[0] = '-' + panel.data('blockWidth');
                })
            } else {
                console.log('Vertical blocks do not support this effect: ' + opts.effect)
            }
            
            return panel;
        }        
                
        var createPanel = function(image, opts, panel){

            var imageDims = getImageDims(image);
            var width = imageDims[0];
            var height = imageDims[1];
                        
            panel.css({
                position: 'absolute',
                width: width + 'px',
                height: height + 'px',
                zIndex: opts.baseIndex,
                overflow: 'hidden'
            })

            if ( opts.orientation === 'vertical' ) {
                panel = createVerticalBlocks(panel, opts, image, width, height);
            } else if (opts.orientation === 'horizontal') {
                panel = createHorizontalBlocks(panel, opts, image, width, height);
            } else if ( opts.orientation === 'bricks' ){
                panel = createBrickBlocks(panel, opts, image, width, height)
            }
            
            return panel;
        }
        
        var createBrickBlocks = function(panel, opts, image, width, height){
            
            var block = jQuery('<div class="' + opts.blockClass + '"></div>');
            var strip = jQuery('<div class="' + opts.blockClass + '-strip"></div>');
            
            var blockWidth = Math.ceil(parseInt(width) / parseInt(opts.blockCount));
            var blockHeight = blockWidth;
            
            strip.css({
                height: height + 'px',
                width: blockWidth + 'px',
                position: 'absolute'
            })
            
            block.css({
                height: blockHeight + 'px',
                width: blockWidth + 'px',
                position: 'absolute',
                backgroundImage: 'url(' + image.attr('src') + ')'
            })
            
            var brickCtr = 0;
            
            for ( i = 0; i < parseInt(opts.blockCount); i++){
                var tempStrip = strip.clone();
                
                for ( o = 0; o < (height / blockHeight); o++){
                    var tempBlock = block.clone();
                    brickCtr ++;
                    
                    if ( o === 0 ){
                        tempBlock.addClass('top-brick');
                    }
                    
                    var bgPos = '-' + (blockWidth * i) + 'px -' + (blockHeight * o) + 'px';
                    tempBlock.data('defSpecs', [0, (blockHeight * o), opts.efOpacity])
                             .data('animSpecs', [0, (blockHeight * o), opts.efOpacity]);
                    tempStrip.append(tempBlock.css({ backgroundPosition: bgPos, 
                                                     left: '0px', 
                                                     top: (blockHeight * o) + 'px' 
                                                }));
                }
                
                tempStrip.data('defSpecs', [(blockWidth * i), 0, opts.efOpacity])
                         .data('animSpecs', [(blockWidth * i), 0, opts.efOpacity])
                         .css({left: (blockWidth * i) + 'px'})
                panel.append(tempStrip);
            }
            
            
            panel.data('effect', opts.effect)
                 .data('orientation', opts.orientation)
                 .data('width', width)
                 .data('height', height)
                 .data('blockWidth', blockWidth)
                 .data('blockHeight', height)
                 .data('blockCount', opts.blockCount)
                 .data('baseIndex', opts.baseIndex)
                 .data('brickCount', brickCtr)
                 
            return panel;
        }
        
        var createVerticalBlocks = function(panel, opts, image, width, height){
            
            var block = jQuery('<div class="' + opts.blockClass + '"></div>');
            var blockWidth = Math.ceil(parseInt(width) / parseInt(opts.blockCount));

            block.css({
                height: height + 'px',
                width: blockWidth + 'px',
                position: 'absolute',
                backgroundImage: 'url(' + image.attr('src') + ')'
            })
            
            for ( i = 0; i < parseInt(opts.blockCount); i++ ){
                var tempBlock = block.clone();
                var bgPos = '-' + (blockWidth * i) + 'px 0px';
                tempBlock.data('defSpecs', [(blockWidth * i), 0, opts.efOpacity])
                         .data('animSpecs', [(blockWidth * i), 0, opts.efOpacity]);
                panel.append(tempBlock.css({ backgroundPosition: bgPos, left: (blockWidth * i) + 'px', top: '0px' }));
            }
            
            panel.data('effect', opts.effect)
                 .data('orientation', opts.orientation)
                 .data('width', width)
                 .data('height', height)
                 .data('blockWidth', blockWidth)
                 .data('blockHeight', height)
                 .data('blockCount', opts.blockCount)
                 .data('baseIndex', opts.baseIndex)
            
            return panel;
        }
        
        var createHorizontalBlocks = function(panel, opts, image, width, height){
        
            var block = jQuery('<div class="' + opts.blockClass + '"></div>');
            var blockHeight = Math.ceil(parseInt(height) / parseInt(opts.blockCount));

            block.css({
                height: blockHeight + 'px',
                width: width + 'px',
                position: 'absolute',
                backgroundImage: 'url(' + image.attr('src') + ')'
            })
            
            for ( i = 0; i < parseInt(opts.blockCount); i++ ){
                var tempBlock = block.clone();
                var bgPos = '0px -' + (blockHeight * i) + 'px';
                tempBlock.data('defSpecs', [0, (blockHeight * i), opts.efOpacity])
                         .data('animSpecs', [0, (blockHeight * i), opts.efOpacity]);
                panel.append(tempBlock.css({ backgroundPosition: bgPos, left: '0px', top: (blockHeight * i) + 'px' }));
            }

            panel.data('effect', opts.effect)
                 .data('orientation', opts.orientation)
                 .data('width', width)
                 .data('height', height)
                 .data('blockWidth', width)
                 .data('blockHeight', blockHeight)
                 .data('blockCount', opts.blockCount)
                 .data('baseIndex', opts.baseIndex)
            
            return panel;
        }
        
        if ( $this.length > 0 ){

            if ( change === true ){
                var panel = imgArray[0];
                panel.children().remove();
                var temp = createPanel(panel.data('image'), opts, panel);
                var panelArray = [setupEffectPos(temp, opts)];
            } else {
                var panelArray = initialize(imgArray, opts);
            }
            
            if ( !(typeof(jQuery(document).data(opts.documentStorageName)) == 'object') ){
                jQuery(document).data(opts.documentStorageName, jQuery('<div></div>'));
            }
            
            for ( index in panelArray ){
                if ( typeof(imgArray[index]) == 'string' ){
                    var tempKey = imgArray[index];
                } else if ( jQuery(imgArray[index]).is('img') ){
                    var tempKey = imgArray[index].attr('src');
                } else {
                    var tempKey = index;
                }
                
                var tempVal = panelArray[index]; 

                jQuery(document).data(opts.documentStorageName).data(tempKey, tempVal);
            }
            
        }

        return panelArray;
    };
    
    
    
    
    
    
    
    
    
    
    
    jQuery.fn.frozImageEffectsShow = function( img, options, inward ) {
        var opts = jQuery.extend( {}, jQuery.fn.frozImageEffectsInit.defaults, options );
        jQuery.fn.frozImageEffectsInit.opts = opts;
        var $this                           = jQuery( this );
        
        var animate = function(panel, opts, goIn){
        
            if ( goIn === true ){
                $this.append(panel.css({left: '0px', top: '0px'}));
            }

            if ( opts.panelOffset !== null ){
                panel.offset(opts.panelOffset);
            }
            
            if ( opts.panelOffsetLeft !== null ){
                var offsetLeft = opts.panelOffsetLeft;
            } else {
                var offsetLeft = 0;
            }
            
            if ( opts.panelOffsetTop !== null ){
                var offsetTop = opts.panelOffsetTop;
            } else {
                var offsetTop = 0;
            }
            
            panel.animate({left: '+=' + offsetLeft + 'px', top: '+=' + offsetTop + 'px'}, 0);
            
            if ( typeof(opts.onAnimStart) == 'function' ){
                opts.onAnimStart(panel, opts, goIn);
            }
            
            var lastBlock = null;
            
            if ( (panel.data('orientation') === 'horizontal') || (panel.data('orientation') === 'vertical') ){
                lastBlock = animateNormal(panel, opts, goIn)
            } else if ( panel.data('orientation') === 'bricks' ){
                lastBlock = animateBricks(panel, opts, goIn);
            }
            
            if ( (typeof(lastBlock) == 'object') && (typeof(opts.onAnimEnd) == 'function') ){
                lastBlock.queue( function(){
                    opts.onAnimEnd(panel, opts, goIn);
                    jQuery(this).dequeue();
                });
            }
            
        }
        
        var animateBricks = function(panel, opts, goIn){

            if ( goIn === true ){
                var specName = 'defSpecs';
            } else {
                var specName = 'animSpecs';
            }
            
            var lastBlockIndex = 0;
            var lastBlock = null;
            
            panel.children('div.' + opts.blockClass + '-strip').each( function(){
                
                var strip = jQuery(this);        
                var stripCount = jQuery(this).index();
                var stripChildCount = jQuery(this).children('div.' + opts.blockClass).length;
                var stripValue = (stripCount * stripChildCount)
            
                jQuery(this).children('div.' + opts.blockClass).each( function(){
                    var varX = jQuery(this).data(specName)[0] + 'px';
                    var varY = jQuery(this).data(specName)[1] + 'px';
                    var varO = jQuery(this).data(specName)[2];

                    var animWidth = jQuery(this).data('finalWidth');
                    var animHeight = jQuery(this).data('finalHeight');
                    var finalIndex = null;
                    var count = jQuery(this).index() + stripValue;

                    if ( goIn === true ){
                        var finalWidth = panel.data('blockWidth');
                        var finalHeight = panel.data('blockHeight');
                    } else {
                        var finalWidth = animWidth;
                        var finalHeight = animHeight;
                    }
                    
                    if ( (panel.data('effect') === 'center') ||
                         (panel.data('effect') === 'sunrise') ||
                         (panel.data('effect') === 'sunshine') ){
                        
                        if ( panel.data('effect') === 'center' ){
                            var stripMiddle = (parseInt(panel.data('blockCount'))) / 2;
                            var brickMiddle = (stripChildCount - 1) / 2;
                            var stripDistance = Math.abs(stripCount - stripMiddle);
                            var brickDistance = Math.abs(jQuery(this).index() - brickMiddle) * opts.brickAngle;
                        } else if ( panel.data('effect') === 'sunrise' ){
                            var stripMiddle = (parseInt(panel.data('blockCount'))) / 2;
                            var stripDistance = Math.abs(stripCount - stripMiddle);
                            var brickDistance = (Math.abs(jQuery(this).index() - stripChildCount) - 1)  * opts.brickAngle;
                        } else if ( panel.data('effect') === 'sunshine' ){
                            var stripMiddle = (parseInt(panel.data('blockCount'))) / 2;
                            var stripDistance = Math.abs(stripCount - stripMiddle);
                            var brickDistance = jQuery(this).index() * opts.brickAngle;
                        }
                        
                        count = Math.floor(stripDistance + brickDistance);
                        
                        if ( opts.reverseAnim === true ){
                            count = stripChildCount - count - 1;
                        }
                        
                    } else if ( panel.data('effect') === 'diagonal' ){
                        
                        count = (stripChildCount - jQuery(this).index()) + 
                                (panel.data('blockCount') - stripCount) - 1;

                        if ( opts.reverseAnim === true ){
                            count = jQuery(this).index() + stripCount - 1;
                        }
                        
                    } else {
                    
                        if ( panel.data('effect') === 'arrowRight' ){
                            var brickMiddle = (stripChildCount - 1) / 2;
                            var brickDistance = Math.abs(jQuery(this).index() - brickMiddle) * opts.brickAngle;
                            
                            count = (brickDistance + stripCount);
                            
                        } else if ( panel.data('effect') === 'arrowLeft' ){
                            var brickMiddle = (stripChildCount - 1) / 2;
                            var brickDistance = Math.abs(jQuery(this).index() - brickMiddle) * opts.brickAngle;
                            
                            count =  Math.floor(brickDistance + (panel.data('blockCount') - stripCount - 1) );
                            
                        }

                        if ( opts.reverseAnim === true ){
                            count = panel.data('blockCount') - count - 1;
                        }
                    }
                    
                    if ( count > lastBlockIndex ){
                        lastBlock = jQuery(this);
                    }
                    
                    var delay = opts.efDelay * count;

                    jQuery(this).stop(false, true)
                    .delay(delay)
                    .animate({
                        left: varX,
                        top: varY
                    }, {duration: opts.efTime, easing: opts.efEasing})
                    .fadeTo(opts.efTime, varO, opts.efEasing);

//                    if ( (typeof(animWidth) == 'string') || (typeof(animWidth) == 'number') ){
//                        jQuery(this).animate({width: finalWidth + 'px'}, 
//                                             {duration: opts.efTime, easing: opts.efEasing});
//                    }
//                    
//                    if ( (typeof(animHeight) == 'string') || (typeof(animHeight) == 'number') ){
//                        jQuery(this).animate({height: finalHeight + 'px'}, 
//                                             {duration: opts.efTime, easing: opts.efEasing});
//                    }
                    
                    if ( typeof(finalIndex) == 'number' ){
                        jQuery(this).css({zIndex: finalIndex});
                    }
                })
            });
            
            return lastBlock;
        }
        
        
        var animateNormal = function(panel, opts, goIn){
            
            if ( goIn === true ){
                var specName = 'defSpecs';
            } else {
                var specName = 'animSpecs';
            }
            
            var lastBlockIndex = 0;
            var lastBlock = null;

            panel.children('div.' + opts.blockClass).each( function(){
                var varX = jQuery(this).data(specName)[0] + 'px';
                var varY = jQuery(this).data(specName)[1] + 'px';
                var varO = jQuery(this).data(specName)[2];

                var animWidth = jQuery(this).data('finalWidth');
                var animHeight = jQuery(this).data('finalHeight');
                var finalIndex = null;
                var count = jQuery(this).index();
                
                if ( goIn === true ){
                    var finalWidth = panel.data('blockWidth');
                    var finalHeight = panel.data('blockHeight');
                } else {
                    var finalWidth = animWidth;
                    var finalHeight = animHeight;
                }

                if ( (panel.data('effect') === 'arrowDown') || 
                     (panel.data('effect') === 'arrowUp') || 
                     (panel.data('effect') === 'arrowRight') || 
                     (panel.data('effect') === 'arrowLeft') ){
                    count = Math.floor(Math.abs(((panel.data('blockCount') - 1) / 2) - jQuery(this).index()));
                    
                    if ( opts.reverseAnim === true ){
                        count = ((panel.data('blockCount') - 1) / 2) - count;
                    }
                } else {
                
                    if ( opts.reverseAnim === true ){
                        count = panel.data('blockCount') - count - 1;
                    }
                }
    
                if ( panel.data('effect') === 'curtain' ){
                    var half = parseInt(panel.data('blockCount')) / 2;
                    count = panel.data('blockCount') - Math.abs(Math.floor(half - jQuery(this).index()));
                    finalIndex = panel.data('baseIndex') * Math.abs(Math.floor(half - jQuery(this).index()));
                } else if ( panel.data('effect') === 'roll' ){
                    if ( goIn === false ){
                        finalIndex = count;
                    } else {
                        finalIndex = panel.data('blockCount') - 1 - count;
                    }
                }
                 
                if ( count > lastBlockIndex ){
                    lastBlock = jQuery(this);
                }

                var delay = opts.efDelay * count;

                jQuery(this).stop(false, true)
                .delay(delay)
                .animate({
                    left: varX,
                    top: varY
                }, {duration: opts.efTime, easing: opts.efEasing})
                .fadeTo(opts.efTime, varO, opts.efEasing);

                if ( (typeof(animWidth) == 'string') || (typeof(animWidth) == 'number') ){
                    jQuery(this).animate({width: finalWidth + 'px'}, 
                                         {duration: opts.efTime, easing: opts.efEasing});
                }
                
                if ( (typeof(animHeight) == 'string') || (typeof(animHeight) == 'number') ){
                    jQuery(this).animate({height: finalHeight + 'px'}, 
                                         {duration: opts.efTime, easing: opts.efEasing});
                }
                
                if ( typeof(finalIndex) == 'number' ){
                    jQuery(this).css({zIndex: finalIndex});
                }
            })
            
            return lastBlock;
        }
        
        var checkPanel = function(panel, opts){
            if ( typeof(options) == 'object' ){
                if ( ((opts.orientation !== panel.data('orientation')) && (typeof(options.orientation) == 'string')) ||
                     ((opts.effect !== panel.data('effect')) && (typeof(options.effect) == 'string')) ){

                    if ( typeof(options.orientation) == 'string' ){
                        var tempOr = options.orientation;
                    } else {
                        var tempOr = panel.data('orientation')
                    }
                    
                    if ( typeof(options.effect) == 'string' ){
                        var tempEf = options.effect;
                    } else {
                        var tempEf = panel.data('effect')
                    }
                    
                    panelArray = jQuery(document).frozImageEffectsInit([panel], {orientation: tempOr, effect: tempEf}, true);
                    panel = panelArray[0];
                }
            }   

            return panel;
        }
        
        var getPanel = function(img){

            if ( typeof($this.is) == 'function' ){
                if ( $this.hasClass(opts.readyClass) ){
                    return $this; 
                }
            }

            if ( typeof(img) == 'string' ){
                var temp = jQuery(document).frozImageEffectsInit([img], opts);
                return temp[0];
            } else if ( typeof(img.is) == 'function' ){
                if ( img.hasClass(opts.readyClass) ){
                    return img;
                } else if ( img.is('img') ){
                    var temp = jQuery(document).frozImageEffectsInit([img], opts);
                    return temp[0];
                } else {
                    console.log('Image panel not ready');
                    return null;
                }
            }
            
            return null;
        }
        
        var panel = null;

        if ( $this.length > 0 ){
            panel = getPanel(img);
            
            if ( (typeof(panel) == 'object') && (panel != null) ){
            
                if ( typeof(panel.data('setOpts')) == 'object' ){
                    opts = jQuery.extend( {}, panel.data('setOpts'), options );
                }

                if ( typeof(inward) == 'boolean' ){
                    var animType = inward;
                } else {
                    var animType = true;
                }
                
                if ( panel.hasClass(opts.readyClass) ){
                    panel = checkPanel(panel, opts);
                    animate(panel, opts, animType);
                } else {
                    panel.load( function(){
                        panel = checkPanel(jQuery(this), opts);
                        animate(panel, opts, animType);
                    })
                }
            
            }
            
        }

        if ( typeof(panel) == 'object' ){
            return panel;
alert('panel')
        } else {
            return null;
alert('null')
        }
        
    };
    
    
    
    
    
    
    
    jQuery.fn.frozImageEffectsHide = function( flashHide, options ) {
        var $this                           = jQuery( this );
    
        if ( ($this.length === 1) && (typeof($this.is) == 'function') ){
            var panel = $this;
            
            if ( (typeof(panel.data('setOpts')) == 'object') ||
                 (panel.is('img')) ){
                 
                if ( panel.is('img') ){
                    var opts = jQuery.extend( {}, jQuery.fn.frozImageEffectsInit.defaults, options );
                } else {
                    var opts = jQuery.extend( {}, panel.data('setOpts'), options );
                    opts = jQuery.extend( {}, opts, options );
                }
                
                jQuery.fn.frozImageEffectsInit.opts = opts;

                if ( panel.hasClass(opts.readyClass) ){
                    
                    if ( typeof(flashHide) == 'boolean' ){
                        if ( flashHide === true ){
                            opts.efDelay = 0;
                            opts.efTime = 0;
                        }
                    }

                    jQuery('body').frozImageEffectsShow(panel, 
                        {efDelay: opts.efDelay, 
                         efTime: opts.efTime,
                         reverseAnim: !(opts.reverseAnim)
                        }, 
                        false)
                }
            }
        
        }
    
        return $this;
        
    };
    
    jQuery.fn.frozImageEffectsInit.defaults =   {
        panelClass: 'froz-imgeffect-panel',
        blockClass: 'froz-imgeffect-block',
        readyClass: 'initialized',
        documentStorageName: 'frozImageEffectsStorage',
        forceNew: false,
        
        baseIndex: 100,
        orientation: 'vertical',
        blockCount: '10',
        effect: 'fade',         //vertical: fade, blinds, curtain, teeth, slideDown, roll, float, spring, door
        
        //for frozImageEffectsShow
        efTime: 500,
        efDelay: 200,
        efEasing: 'jswing',
        efOpacity: 1,
        reverseAnim: false, 
        brickAngle: 1,      //for brick orientation only
        
        panelOffset: null,      //jQuery offset object
        panelOffsetLeft: null,
        panelOffsetTop: null,
         
        onAnimStart: null,  //function(panel, opts, show)
        onAnimEnd: null     //function(panel, opts, show)
    };
} )(jQuery);





/**
 * jQuery Galleriffic plugin
 *
 * Copyright (c) 2008 Trent Foley (http://trentacular.com)
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Much thanks to primary contributer Ponticlaro (http://www.ponticlaro.com)
 */
;(function($) {
	// Globally keep track of all images by their unique hash.  Each item is an image data object.
	var allImages = {};
	var imageCounter = 0;

	// Galleriffic static class
	$.galleriffic = {
		version: '2.0.1',

		// Strips invalid characters and any leading # characters
		normalizeHash: function(hash) {
			return hash.replace(/^.*#/, '').replace(/\?.*$/, '');
		},

		getImage: function(hash) {
			if (!hash)
				return undefined;

			hash = $.galleriffic.normalizeHash(hash);
			return allImages[hash];
		},

		// Global function that looks up an image by its hash and displays the image.
		// Returns false when an image is not found for the specified hash.
		// @param {String} hash This is the unique hash value assigned to an image.
		gotoImage: function(hash) {
			var imageData = $.galleriffic.getImage(hash);
			if (!imageData)
				return false;

			var gallery = imageData.gallery;
			gallery.gotoImage(imageData);
			
			return true;
		},

		// Removes an image from its respective gallery by its hash.
		// Returns false when an image is not found for the specified hash or the
		// specified owner gallery does match the located images gallery.
		// @param {String} hash This is the unique hash value assigned to an image.
		// @param {Object} ownerGallery (Optional) When supplied, the located images
		// gallery is verified to be the same as the specified owning gallery before
		// performing the remove operation.
		removeImageByHash: function(hash, ownerGallery) {
			var imageData = $.galleriffic.getImage(hash);
			if (!imageData)
				return false;

			var gallery = imageData.gallery;
			if (ownerGallery && ownerGallery != gallery)
				return false;

			return gallery.removeImageByIndex(imageData.index);
		}
	};

	var defaults = {
		delay:                     3000,
		numThumbs:                 20,
		preloadAhead:              40, // Set to -1 to preload all images
		enableTopPager:            false,
		enableBottomPager:         true,
		maxPagesToShow:            7,
		imageContainerSel:         '',
		captionContainerSel:       '',
		controlsContainerSel:      '',
		loadingContainerSel:       '',
		renderSSControls:          true,
		renderNavControls:         true,
		playLinkText:              'Play',
		pauseLinkText:             'Pause',
		prevLinkText:              'Previous',
		nextLinkText:              'Next',
		nextPageLinkText:          'Next &rsaquo;',
		prevPageLinkText:          '&lsaquo; Prev',
		enableHistory:             false,
		enableKeyboardNavigation:  true,
		autoStart:                 false,
		syncTransitions:           false,
		defaultTransitionDuration: 1000,
		onSlideChange:             undefined, // accepts a delegate like such: function(prevIndex, nextIndex) { ... }
		onTransitionOut:           undefined, // accepts a delegate like such: function(slide, caption, isSync, callback) { ... }
		onTransitionIn:            undefined, // accepts a delegate like such: function(slide, caption, isSync) { ... }
		onPageTransitionOut:       undefined, // accepts a delegate like such: function(callback) { ... }
		onPageTransitionIn:        undefined, // accepts a delegate like such: function() { ... }
		onImageAdded:              undefined, // accepts a delegate like such: function(imageData, $li) { ... }
		onImageRemoved:            undefined  // accepts a delegate like such: function(imageData, $li) { ... }
	};

	// Primary Galleriffic initialization function that should be called on the thumbnail container.
	$.fn.galleriffic = function(settings) {
		//  Extend Gallery Object
		$.extend(this, {
			// Returns the version of the script
			version: $.galleriffic.version,

			// Current state of the slideshow
			isSlideshowRunning: false,
			slideshowTimeout: undefined,

			// This function is attached to the click event of generated hyperlinks within the gallery
			clickHandler: function(e, link) {
				this.pause();

				if (!this.enableHistory) {
					// The href attribute holds the unique hash for an image
					var hash = $.galleriffic.normalizeHash($(link).attr('href'));
					$.galleriffic.gotoImage(hash);
					e.preventDefault();
				}
			},

			// Appends an image to the end of the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
			appendImage: function(listItem) {
				this.addImage(listItem, false, false);
				return this;
			},

			// Inserts an image into the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
			// @param {Integer} position The index within the gallery where the item shouold be added.
			insertImage: function(listItem, position) {
				this.addImage(listItem, false, true, position);
				return this;
			},

			// Adds an image to the gallery and optionally inserts/appends it to the DOM (thumbExists)
			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
			// @param {Boolean} thumbExists Specifies whether the thumbnail already exists in the DOM or if it needs to be added.
			// @param {Boolean} insert Specifies whether the the image is appended to the end or inserted into the gallery.
			// @param {Integer} position The index within the gallery where the item shouold be added.
			addImage: function(listItem, thumbExists, insert, position) {
				var $li = ( typeof listItem === "string" ) ? $(listItem) : listItem;				
				var $aThumb = $li.find('a.thumb');
				var slideUrl = $aThumb.attr('href');
				var title = $aThumb.attr('title');
				var $caption = $li.find('.caption').remove();
				var hash = $aThumb.attr('name');

				// Increment the image counter
				imageCounter++;

				// Autogenerate a hash value if none is present or if it is a duplicate
				if (!hash || allImages[''+hash]) {
					hash = imageCounter;
				}

				// Set position to end when not specified
				if (!insert)
					position = this.data.length;
				
				var imageData = {
					title:title,
					slideUrl:slideUrl,
					caption:$caption,
					hash:hash,
					gallery:this,
					index:position
				};

				// Add the imageData to this gallery's array of images
				if (insert) {
					this.data.splice(position, 0, imageData);

					// Reset index value on all imageData objects
					this.updateIndices(position);
				}
				else {
					this.data.push(imageData);
				}

				var gallery = this;

				// Add the element to the DOM
				if (!thumbExists) {
					// Update thumbs passing in addition post transition out handler
					this.updateThumbs(function() {
						var $thumbsUl = gallery.find('ul.thumbs');
						if (insert)
							$thumbsUl.children(':eq('+position+')').before($li);
						else
							$thumbsUl.append($li);
						
						if (gallery.onImageAdded)
							gallery.onImageAdded(imageData, $li);
					});
				}

				// Register the image globally
				allImages[''+hash] = imageData;

				// Setup attributes and click handler
				$aThumb.attr('rel', 'history')
					.attr('href', '#'+hash)
					.removeAttr('name')
					.click(function(e) {
						gallery.clickHandler(e, this);
					});
				return this;
			},

			// Removes an image from the gallery based on its index.
			// Returns false when the index is out of range.
			removeImageByIndex: function(index) {
				if (index < 0 || index >= this.data.length)
					return false;
				
				var imageData = this.data[index];
				if (!imageData)
					return false;
				
				this.removeImage(imageData);
				
				return true;
			},

			// Convenience method that simply calls the global removeImageByHash method.
			removeImageByHash: function(hash) {
				return $.galleriffic.removeImageByHash(hash, this);
			},

			// Removes an image from the gallery.
			removeImage: function(imageData) {
				var index = imageData.index;
				
				// Remove the image from the gallery data array
				this.data.splice(index, 1);
				
				// Remove the global registration
				delete allImages[''+imageData.hash];
				
				// Remove the image's list item from the DOM
				this.updateThumbs(function() {
					var $li = gallery.find('ul.thumbs')
						.children(':eq('+index+')')
						.remove();

					if (gallery.onImageRemoved)
						gallery.onImageRemoved(imageData, $li);
				});

				// Update each image objects index value
				this.updateIndices(index);

				return this;
			},

			// Updates the index values of the each of the images in the gallery after the specified index
			updateIndices: function(startIndex) {
				for (i = startIndex; i < this.data.length; i++) {
					this.data[i].index = i;
				}
				
				return this;
			},

			// Scraped the thumbnail container for thumbs and adds each to the gallery
			initializeThumbs: function() {
				this.data = [];
				var gallery = this;

				this.find('ul.thumbs > li').each(function(i) {
					gallery.addImage($(this), true, false);
				});

				return this;
			},

			isPreloadComplete: false,

			// Initalizes the image preloader
			preloadInit: function() {
				if (this.preloadAhead == 0) return this;
				
				this.preloadStartIndex = this.currentImage.index;
				var nextIndex = this.getNextIndex(this.preloadStartIndex);
				return this.preloadRecursive(this.preloadStartIndex, nextIndex);
			},

			// Changes the location in the gallery the preloader should work
			// @param {Integer} index The index of the image where the preloader should restart at.
			preloadRelocate: function(index) {
				// By changing this startIndex, the current preload script will restart
				this.preloadStartIndex = index;
				return this;
			},

			// Recursive function that performs the image preloading
			// @param {Integer} startIndex The index of the first image the current preloader started on.
			// @param {Integer} currentIndex The index of the current image to preload.
			preloadRecursive: function(startIndex, currentIndex) {
				// Check if startIndex has been relocated
				if (startIndex != this.preloadStartIndex) {
					var nextIndex = this.getNextIndex(this.preloadStartIndex);
					return this.preloadRecursive(this.preloadStartIndex, nextIndex);
				}

				var gallery = this;

				// Now check for preloadAhead count
				var preloadCount = currentIndex - startIndex;
				if (preloadCount < 0)
					preloadCount = this.data.length-1-startIndex+currentIndex;
				if (this.preloadAhead >= 0 && preloadCount > this.preloadAhead) {
					// Do this in order to keep checking for relocated start index
					setTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);
					return this;
				}

				var imageData = this.data[currentIndex];
				if (!imageData)
					return this;

				// If already loaded, continue
				if (imageData.image)
					return this.preloadNext(startIndex, currentIndex); 
				
				// Preload the image
				var image = new Image();
				
				image.onload = function() {
					imageData.image = this;
					gallery.preloadNext(startIndex, currentIndex);
				};

				image.alt = imageData.title;
				image.src = imageData.slideUrl;

				return this;
			},
			
			// Called by preloadRecursive in order to preload the next image after the previous has loaded.
			// @param {Integer} startIndex The index of the first image the current preloader started on.
			// @param {Integer} currentIndex The index of the current image to preload.
			preloadNext: function(startIndex, currentIndex) {
				var nextIndex = this.getNextIndex(currentIndex);
				if (nextIndex == startIndex) {
					this.isPreloadComplete = true;
				} else {
					// Use setTimeout to free up thread
					var gallery = this;
					setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);
				}

				return this;
			},

			// Safe way to get the next image index relative to the current image.
			// If the current image is the last, returns 0
			getNextIndex: function(index) {
				var nextIndex = index+1;
				if (nextIndex >= this.data.length)
					nextIndex = 0;
				return nextIndex;
			},

			// Safe way to get the previous image index relative to the current image.
			// If the current image is the first, return the index of the last image in the gallery.
			getPrevIndex: function(index) {
				var prevIndex = index-1;
				if (prevIndex < 0)
					prevIndex = this.data.length-1;
				return prevIndex;
			},

			// Pauses the slideshow
			pause: function() {
				this.isSlideshowRunning = false;
				if (this.slideshowTimeout) {
					clearTimeout(this.slideshowTimeout);
					this.slideshowTimeout = undefined;
				}

				if (this.$controlsContainer) {
					this.$controlsContainer
						.find('div.ss-controls a').removeClass().addClass('play')
						.attr('title', this.playLinkText)
						.attr('href', '#play')
						.html(this.playLinkText);
				}
				
				return this;
			},

			// Plays the slideshow
			play: function() {
				this.isSlideshowRunning = true;

				if (this.$controlsContainer) {
					this.$controlsContainer
						.find('div.ss-controls a').removeClass().addClass('pause')
						.attr('title', this.pauseLinkText)
						.attr('href', '#pause')
						.html(this.pauseLinkText);
				}

				if (!this.slideshowTimeout) {
					var gallery = this;
					this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
				}

				return this;
			},

			// Toggles the state of the slideshow (playing/paused)
			toggleSlideshow: function() {
				if (this.isSlideshowRunning)
					this.pause();
				else
					this.play();

				return this;
			},

			// Advances the slideshow to the next image and delegates navigation to the
			// history plugin when history is enabled
			// enableHistory is true
			ssAdvance: function() {
				if (this.isSlideshowRunning)
					this.next(true);

				return this;
			},

			// Advances the gallery to the next image.
			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.  
			next: function(dontPause, bypassHistory) {
				this.gotoIndex(this.getNextIndex(this.currentImage.index), dontPause, bypassHistory);
				return this;
			},

			// Navigates to the previous image in the gallery.
			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
			previous: function(dontPause, bypassHistory) {
				this.gotoIndex(this.getPrevIndex(this.currentImage.index), dontPause, bypassHistory);
				return this;
			},

			// Navigates to the next page in the gallery.
			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
			nextPage: function(dontPause, bypassHistory) {
				var page = this.getCurrentPage();
				var lastPage = this.getNumPages() - 1;
				if (page < lastPage) {
					var startIndex = page * this.numThumbs;
					var nextPage = startIndex + this.numThumbs;
					this.gotoIndex(nextPage, dontPause, bypassHistory);
				}

				return this;
			},

			// Navigates to the previous page in the gallery.
			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
			previousPage: function(dontPause, bypassHistory) {
				var page = this.getCurrentPage();
				if (page > 0) {
					var startIndex = page * this.numThumbs;
					var prevPage = startIndex - this.numThumbs;				
					this.gotoIndex(prevPage, dontPause, bypassHistory);
				}
				
				return this;
			},

			// Navigates to the image at the specified index in the gallery
			// @param {Integer} index The index of the image in the gallery to display.
			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
			gotoIndex: function(index, dontPause, bypassHistory) {
				if (!dontPause)
					this.pause();
				
				if (index < 0) index = 0;
				else if (index >= this.data.length) index = this.data.length-1;
				
				var imageData = this.data[index];
				
				if (!bypassHistory && this.enableHistory)
					$.historyLoad(String(imageData.hash));  // At the moment, historyLoad only accepts string arguments
				else
					this.gotoImage(imageData);

				return this;
			},

			// This function is garaunteed to be called anytime a gallery slide changes.
			// @param {Object} imageData An object holding the image metadata of the image to navigate to.
			gotoImage: function(imageData) {
				var index = imageData.index;

				if (this.onSlideChange)
					this.onSlideChange(this.currentImage.index, index);
				
				this.currentImage = imageData;
				this.preloadRelocate(index);
				
				this.refresh();
				
				return this;
			},

			// Returns the default transition duration value.  The value is halved when not
			// performing a synchronized transition.
			// @param {Boolean} isSync Specifies whether the transitions are synchronized.
			getDefaultTransitionDuration: function(isSync) {
				if (isSync)
					return this.defaultTransitionDuration;
				return this.defaultTransitionDuration / 2;
			},

			// Rebuilds the slideshow image and controls and performs transitions
			refresh: function() {
				var imageData = this.currentImage;
				if (!imageData)
					return this;

				var index = imageData.index;

				// Update Controls
				if (this.$controlsContainer) {
					this.$controlsContainer
						.find('div.nav-controls a.prev').attr('href', '#'+this.data[this.getPrevIndex(index)].hash).end()
						.find('div.nav-controls a.next').attr('href', '#'+this.data[this.getNextIndex(index)].hash);
				}

				var previousSlide = this.$imageContainer.find('span.current').addClass('previous').removeClass('current');
				var previousCaption = 0;

				if (this.$captionContainer) {
					previousCaption = this.$captionContainer.find('span.current').addClass('previous').removeClass('current');
				}

				// Perform transitions simultaneously if syncTransitions is true and the next image is already preloaded
				var isSync = this.syncTransitions && imageData.image;

				// Flag we are transitioning
				var isTransitioning = true;
				var gallery = this;

				var transitionOutCallback = function() {
					// Flag that the transition has completed
					isTransitioning = false;

					// Remove the old slide
					previousSlide.remove();

					// Remove old caption
					if (previousCaption)
						previousCaption.remove();

					if (!isSync) {
						if (imageData.image && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
							gallery.buildImage(imageData, isSync);
						} else {
							// Show loading container
							if (gallery.$loadingContainer) {
								gallery.$loadingContainer.show();
							}
						}
					}
				};

				if (previousSlide.length == 0) {
					// For the first slide, the previous slide will be empty, so we will call the callback immediately
					transitionOutCallback();
				} else {
					if (this.onTransitionOut) {
						this.onTransitionOut(previousSlide, previousCaption, isSync, transitionOutCallback);
					} else {
						previousSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0, transitionOutCallback);
						if (previousCaption)
							previousCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0);
					}
				}

				// Go ahead and begin transitioning in of next image
				if (isSync)
					this.buildImage(imageData, isSync);

				if (!imageData.image) {
					var image = new Image();
					
					// Wire up mainImage onload event
					image.onload = function() {
						imageData.image = this;

						// Only build image if the out transition has completed and we are still on the same image hash
						if (!isTransitioning && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
							gallery.buildImage(imageData, isSync);
						}
					};

					// set alt and src
					image.alt = imageData.title;
					image.src = imageData.slideUrl;
				}

				// This causes the preloader (if still running) to relocate out from the currentIndex
				this.relocatePreload = true;

				return this.syncThumbs();
			},

			// Called by the refresh method after the previous image has been transitioned out or at the same time
			// as the out transition when performing a synchronous transition.
			// @param {Object} imageData An object holding the image metadata of the image to build.
			// @param {Boolean} isSync Specifies whether the transitions are synchronized.
			buildImage: function(imageData, isSync) {
				var gallery = this;
				var nextIndex = this.getNextIndex(imageData.index);

				// Construct new hidden span for the image
				var newSlide = this.$imageContainer
					.append('<span class="image-wrapper current"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+imageData.title+'">&nbsp;</a></span>')
					.find('span.current').css('opacity', '0');
				
				newSlide.find('a')
					.append(imageData.image)
					.click(function(e) {
						gallery.clickHandler(e, this);
					});
				
				var newCaption = 0;
				if (this.$captionContainer) {
					// Construct new hidden caption for the image
					newCaption = this.$captionContainer
						.append('<span class="image-caption current"></span>')
						.find('span.current').css('opacity', '0')
						.append(imageData.caption);
				}

				// Hide the loading conatiner
				if (this.$loadingContainer) {
					this.$loadingContainer.hide();
				}

				// Transition in the new image
				if (this.onTransitionIn) {
					this.onTransitionIn(newSlide, newCaption, isSync);
				} else {
					newSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
					if (newCaption)
						newCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
				}
				
				if (this.isSlideshowRunning) {
					if (this.slideshowTimeout)
						clearTimeout(this.slideshowTimeout);

					this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
				}

				return this;
			},

			// Returns the current page index that should be shown for the currentImage
			getCurrentPage: function() {
				return Math.floor(this.currentImage.index / this.numThumbs);
			},

			// Applies the selected class to the current image's corresponding thumbnail.
			// Also checks if the current page has changed and updates the displayed page of thumbnails if necessary.
			syncThumbs: function() {
				var page = this.getCurrentPage();
				if (page != this.displayedPage)
					this.updateThumbs();

				// Remove existing selected class and add selected class to new thumb
				var $thumbs = this.find('ul.thumbs').children();
				$thumbs.filter('.selected').removeClass('selected');
				$thumbs.eq(this.currentImage.index).addClass('selected');

				return this;
			},

			// Performs transitions on the thumbnails container and updates the set of
			// thumbnails that are to be displayed and the navigation controls.
			// @param {Delegate} postTransitionOutHandler An optional delegate that is called after
			// the thumbnails container has transitioned out and before the thumbnails are rebuilt.
			updateThumbs: function(postTransitionOutHandler) {
				var gallery = this;
				var transitionOutCallback = function() {
					// Call the Post-transition Out Handler
					if (postTransitionOutHandler)
						postTransitionOutHandler();
					
					gallery.rebuildThumbs();

					// Transition In the thumbsContainer
					if (gallery.onPageTransitionIn)
						gallery.onPageTransitionIn();
					else
						gallery.show();
				};

				// Transition Out the thumbsContainer
				if (this.onPageTransitionOut) {
					this.onPageTransitionOut(transitionOutCallback);
				} else {
					this.hide();
					transitionOutCallback();
				}

				return this;
			},

			// Updates the set of thumbnails that are to be displayed and the navigation controls.
			rebuildThumbs: function() {
				var needsPagination = this.data.length > this.numThumbs;

				// Rebuild top pager
				if (this.enableTopPager) {
					var $topPager = this.find('div.top');
					if ($topPager.length == 0)
						$topPager = this.prepend('<div class="top pagination"></div>').find('div.top');
					else
						$topPager.empty();

					if (needsPagination)
						this.buildPager($topPager);
				}

				// Rebuild bottom pager
				if (this.enableBottomPager) {
					var $bottomPager = this.find('div.bottom');
					if ($bottomPager.length == 0)
						$bottomPager = this.append('<div class="bottom pagination"></div>').find('div.bottom');
					else
						$bottomPager.empty();

					if (needsPagination)
						this.buildPager($bottomPager);
				}

				var page = this.getCurrentPage();
				var startIndex = page*this.numThumbs;
				var stopIndex = startIndex+this.numThumbs-1;
				if (stopIndex >= this.data.length)
					stopIndex = this.data.length-1;

				// Show/Hide thumbs
				var $thumbsUl = this.find('ul.thumbs');
				$thumbsUl.find('li').each(function(i) {
					var $li = $(this);
					if (i >= startIndex && i <= stopIndex) {
						$li.show();
					} else {
						$li.hide();
					}
				});

				this.displayedPage = page;

				// Remove the noscript class from the thumbs container ul
				$thumbsUl.removeClass('noscript');
				
				return this;
			},

			// Returns the total number of pages required to display all the thumbnails.
			getNumPages: function() {
				return Math.ceil(this.data.length/this.numThumbs);
			},

			// Rebuilds the pager control in the specified matched element.
			// @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
			buildPager: function(pager) {
				var gallery = this;
				var numPages = this.getNumPages();
				var page = this.getCurrentPage();
				var startIndex = page * this.numThumbs;
				var pagesRemaining = this.maxPagesToShow - 1;
				
				var pageNum = page - Math.floor((this.maxPagesToShow - 1) / 2) + 1;
				if (pageNum > 0) {
					var remainingPageCount = numPages - pageNum;
					if (remainingPageCount < pagesRemaining) {
						pageNum = pageNum - (pagesRemaining - remainingPageCount);
					}
				}

				if (pageNum < 0) {
					pageNum = 0;
				}

				// Prev Page Link
				if (page > 0) {
					var prevPage = startIndex - this.numThumbs;
					pager.append('<a rel="history" href="#'+this.data[prevPage].hash+'" title="'+this.prevPageLinkText+'">'+this.prevPageLinkText+'</a>');
				}

				// Create First Page link if needed
				if (pageNum > 0) {
					this.buildPageLink(pager, 0, numPages);
					if (pageNum > 1)
						pager.append('<span class="ellipsis">&hellip;</span>');
					
					pagesRemaining--;
				}

				// Page Index Links
				while (pagesRemaining > 0) {
					this.buildPageLink(pager, pageNum, numPages);
					pagesRemaining--;
					pageNum++;
				}

				// Create Last Page link if needed
				if (pageNum < numPages) {
					var lastPageNum = numPages - 1;
					if (pageNum < lastPageNum)
						pager.append('<span class="ellipsis">&hellip;</span>');

					this.buildPageLink(pager, lastPageNum, numPages);
				}

				// Next Page Link
				var nextPage = startIndex + this.numThumbs;
				if (nextPage < this.data.length) {
					pager.append('<a rel="history" href="#'+this.data[nextPage].hash+'" title="'+this.nextPageLinkText+'">'+this.nextPageLinkText+'</a>');
				}

				pager.find('a').click(function(e) {
					gallery.clickHandler(e, this);
				});

				return this;
			},

			// Builds a single page link within a pager.  This function is called by buildPager
			// @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
			// @param {Integer} pageNum The page number of the page link to build.
			// @param {Integer} numPages The total number of pages required to display all thumbnails.
			buildPageLink: function(pager, pageNum, numPages) {
				var pageLabel = pageNum + 1;
				var currentPage = this.getCurrentPage();
				if (pageNum == currentPage)
					pager.append('<span class="current">'+pageLabel+'</span>');
				else if (pageNum < numPages) {
					var imageIndex = pageNum*this.numThumbs;
					pager.append('<a rel="history" href="#'+this.data[imageIndex].hash+'" title="'+pageLabel+'">'+pageLabel+'</a>');
				}
				
				return this;
			}
		});

		// Now initialize the gallery
		$.extend(this, defaults, settings);
		
		// Verify the history plugin is available
		if (this.enableHistory && !$.historyInit)
			this.enableHistory = false;
		
		// Select containers
		if (this.imageContainerSel) this.$imageContainer = $(this.imageContainerSel);
		if (this.captionContainerSel) this.$captionContainer = $(this.captionContainerSel);
		if (this.loadingContainerSel) this.$loadingContainer = $(this.loadingContainerSel);

		// Initialize the thumbails
		this.initializeThumbs();
		
		if (this.maxPagesToShow < 3)
			this.maxPagesToShow = 3;

		this.displayedPage = -1;
		this.currentImage = this.data[0];
		var gallery = this;

		// Hide the loadingContainer
		if (this.$loadingContainer)
			this.$loadingContainer.hide();

		// Setup controls
		if (this.controlsContainerSel) {
			this.$controlsContainer = $(this.controlsContainerSel).empty();
			
			if (this.renderSSControls) {
				if (this.autoStart) {
					this.$controlsContainer
						.append('<div class="ss-controls"><a href="#pause" class="pause" title="'+this.pauseLinkText+'">'+this.pauseLinkText+'</a></div>');
				} else {
					this.$controlsContainer
						.append('<div class="ss-controls"><a href="#play" class="play" title="'+this.playLinkText+'">'+this.playLinkText+'</a></div>');
				}

				this.$controlsContainer.find('div.ss-controls a')
					.click(function(e) {
						gallery.toggleSlideshow();
						e.preventDefault();
						return false;
					});
			}
		
			if (this.renderNavControls) {
				this.$controlsContainer
					.append('<div class="nav-controls"><a class="prev" rel="history" title="'+this.prevLinkText+'">'+this.prevLinkText+'</a><a class="next" rel="history" title="'+this.nextLinkText+'">'+this.nextLinkText+'</a></div>')
					.find('div.nav-controls a')
					.click(function(e) {
						gallery.clickHandler(e, this);
					});
			}
		}

		var initFirstImage = !this.enableHistory || !location.hash;
		if (this.enableHistory && location.hash) {
			var hash = $.galleriffic.normalizeHash(location.hash);
			var imageData = allImages[hash];
			if (!imageData)
				initFirstImage = true;
		}

		// Setup gallery to show the first image
		if (initFirstImage)
			this.gotoIndex(0, false, true);

		// Setup Keyboard Navigation
		if (this.enableKeyboardNavigation) {
			$(document).keydown(function(e) {
				var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
				switch(key) {
					case 32: // space
						gallery.next();
						e.preventDefault();
						break;
					case 33: // Page Up
						gallery.previousPage();
						e.preventDefault();
						break;
					case 34: // Page Down
						gallery.nextPage();
						e.preventDefault();
						break;
					case 35: // End
						gallery.gotoIndex(gallery.data.length-1);
						e.preventDefault();
						break;
					case 36: // Home
						gallery.gotoIndex(0);
						e.preventDefault();
						break;
					case 37: // left arrow
						gallery.previous();
						e.preventDefault();
						break;
					case 39: // right arrow
						gallery.next();
						e.preventDefault();
						break;
				}
			});
		}

		// Auto start the slideshow
		if (this.autoStart)
			this.play();

		// Kickoff Image Preloader after 1 second
		setTimeout(function() { gallery.preloadInit(); }, 1000);

		return this;
	};
})(jQuery);


jQuery(document).ready( function() {
    jQuery(window).load( function(){
        jQuery('#tabs').frozTabs({slider: 'froz-tabs-slider', tabLeftPos: 1});

        jQuery('form.froz-model-enable').frozInputModeler({
            selectOptionsShowAmount: 5,
            selectScrollButtonHeight: 21,
            selectOptionHeight: 30
        }).find('input.check-btn').val('');
        
        jQuery('div.froz-carousel-enable').frozCarousel({
            showAmount: 3,
            controls: 'side',
            counter: null,
            loop: false
        })
        
        jQuery('#photo-gallery').frozAlbumGallery();
    })
    
    
    if ( jQuery('#main-booking-form').length > 0 ){
        
        var headForm = jQuery('#main-booking-form');
        
        var appendZero = function(num){
            num = String(num)
            if (num.length === 1){
                num = '0' + num;
            }
            
            return num;
        }
               
        var createDateInput = function(label){
            var input = jQuery('<li class="js-date fake-input-' + label + '"><label>Check-' + label + 
                               ' date</label><input type="text" class="fake-input" readonly="readonly"/></li>');
            
            return input;
        }
        
        var getFormattedDate = function(date){
            var formattedDate = appendZero(date.getMonth() + 1) + '/' + 
                                appendZero(date.getDate()) + '/' + date.getFullYear();

            return formattedDate;
        }
        
        var updateInput = function(target, date, flag){
            formatDate = getFormattedDate(date);
            
            target.data('date', date.valueOf());
            target.find('input.fake-input').val(formatDate);
            
            if ( flag === 'in' ){
            
            } else if ( flag === 'out' ){
            
            }
            
            jQuery('#main-booking-day' + flag, headForm).find('select').val(date.getDate());
            jQuery('#main-booking-month' + flag, headForm).find('select').val(date.getMonth() + 1);
            jQuery('#main-booking-year' + flag, headForm).find('select').val(date.getFullYear());
            
            return formatDate;
        }
        
        var updateNights = function(nightSpan, outDate, inDate){
            var nightsVal = Math.floor((outDate - inDate) / (86400000));

            if ( parseInt(nightsVal) == 1 ){            
                nightSpan.text(nightsVal + ' Night');
            } else if ( parseInt(nightsVal) > 0 ){
                nightSpan.text(nightsVal + ' Nights');
            }

            return nightsVal;
        }
        
        var getNewDate = function(date, delta){
            var newTime = date.valueOf() + (86400000 * delta);
            var newDate = new Date();
            newDate.setTime(newTime);

            return newDate;
        }
        
        var transferErrors = function(){
        
            var inErrorList = jQuery('#main-booking-dayin', headForm).find('ul.errors');
            var outErrorList = jQuery('#main-booking-dayout', headForm).find('ul.errors');
            var newInList = jQuery('<ul class="errors"></ul>');
            var newOutList = jQuery('<ul class="errors"></ul>');
            
            if ( inErrorList.length > 0 ){
                var inError = inErrorList.children('li');
                
                if ( inError.length > 0 ){
                    inError.each( function(){
                        newInList.append('<li>' + jQuery(this).text() + '</li>');
                    })
                    
                    jQuery('li.fake-input-in', headForm).append(newInList);
                }
            }
            
            if ( outErrorList.length > 0 ){
                var outError = outErrorList.children('li');
                
                if ( outError.length > 0 ){
                    outError.each( function(){
                        newOutList.append('<li>' + jQuery(this).text() + '</li>');
                    })
                    
                    jQuery('li.fake-input-out', headForm).append(newOutList);
                }
            }
                        
        }
        
        var removeWeek = function(picker){
            if ( picker.find('tr.datepickerDoW > th').length == 16 ){
                picker.find('th.datepickerMonth').attr('colspan', 5);
                picker.find('tr.datepickerDoW > th:eq(0)').remove();
                picker.find('tr.datepickerDoW > th:eq(7)').remove();
                removeExtra(picker);
            }
        }
        
        var removeExtra = function(picker){
            picker.find('th.datepickerGoNext:first').find('a:first').remove();
            picker.find('th.datepickerGoPrev:eq(1)').find('a:first').remove();
        }
        
        jQuery('#main-booking-form').each( function(){
            
            var fromInput = createDateInput('in');
            var dayIn = jQuery('#main-booking-dayin', this).find('select').val();
            var monthIn = jQuery('#main-booking-monthin', this).find('select').val();
            var yearIn = jQuery('#main-booking-yearin', this).find('select').val();
            jQuery('#main-booking-dayin', this).before(fromInput);
            
            var toInput = createDateInput('out');
            var nightSpan = jQuery('<span id="nights-display"></span>');
            var dayOut = jQuery('#main-booking-dayout', this).find('select').val();
            var monthOut = jQuery('#main-booking-monthout', this).find('select').val();
            var yearOut = jQuery('#main-booking-yearout', this).find('select').val();
            jQuery('#main-booking-dayout', this).before(toInput.append(nightSpan));
            
            jQuery('li.replace-input', this).css({position: 'absolute'}).fadeTo(0, 0.01);

            var mainDate = new Date();
            fromInput.data('today', mainDate.valueOf());
            var formattedMain = getFormattedDate(mainDate);
            
            var inDate = new Date(yearIn, (monthIn - 1), dayIn);
            var formattedIn = updateInput(fromInput, inDate, 'in');

            var outDate = new Date(yearOut, (monthOut - 1), dayOut);
            var formattedOut = updateInput(toInput, outDate, 'out');
            
            headForm.data('nights', updateNights(nightSpan, outDate, inDate));
            
            transferErrors();
            
            var startDateClass = 'start-date';
            var endDateClass = 'end-date';
            
            var dateFlagFrom = false;
            var dateFlagTo = false;
            fromInput.data('picker', null).data('adjusted', false).data('maxDate', 0);
            toInput.data('picker', null).data('adjusted', false).data('maxDate', 0).data('falseStart', false);
            
            toInput.find('input.fake-input').DatePicker({
                date: formattedOut,
                current: inDate,
                format: 'm/d/Y',
                mode: 'single',
                calendars: 2,
                position: 'top',
                onShow: function(picker){
                    if ( toInput.data('picker') == null ){
                        toInput.data('picker', jQuery(picker));
                    }

                    if ( toInput.data('falseStart') == true ){
                        jQuery(picker).find('th.datepickerGoNext:eq(1)').find('a:first').click();
                        toInput.data('falseStart', false);  
                    }
                    
                },
                onChange: function(formatted, dates){
                    updateInput(toInput, dates, 'out');
                    var date = new Date();
                    date.setTime(fromInput.data('date'));
                    headForm.data('nights', updateNights(nightSpan, dates, date));
                    toInput.find('input.fake-input').DatePickerHide();
                },
                onRender: function(date){
                    if ( toInput.data('picker') != null ){
                        toInput.data('picker').find('td.datepickerNotInMonth').removeClass('datepickerSelected')
                                                                              .addClass('datepickerDisabled');
                        removeWeek(toInput.data('picker'));

                        if ( date.getDate() === 15 ){
                            if ( toInput.data('adjusted') === false ){
                                var temp = new Date(fromInput.data('today'));
                                var today = new Date(temp.getFullYear(), temp.getMonth(), 1);
                                var maxDate = new Date(today.valueOf() + (2629743830 * 9));
                                
                                var maxReserveDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), 64);
                                var outDate = maxReserveDate.setDate(1) - 86400000;
                                var inDate = outDate - 86400000;
                                fromInput.data('maxDate', new Date(inDate));
                                toInput.data('maxDate', new Date(outDate));
                                                   
                                if ( (date.valueOf() < inDate) && (maxDate.valueOf() > date.valueOf()) ){
                                    toInput.data('falseStart', true);
                                }
                                
                                if ( maxDate.valueOf() < date.valueOf() ){
                                    toInput.data('falseStart', false);
                                }
                                var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
                                
                                if ( ((date.getMonth() == today.getMonth()) && (date.getFullYear() == today.getFullYear())) || 
                                     (firstDay.valueOf() <= fromInput.data('date')) ) {
                                    toInput.data('picker').find('th.datepickerGoPrev').find('a:first')
                                        .addClass('cal-nav-disabled');
                                } else {
                                    toInput.data('picker').find('th.datepickerGoPrev').find('a:first')
                                        .removeClass('cal-nav-disabled');
                                }
                                
                                if ( (date.getMonth() == maxDate.getMonth()) && (date.getFullYear() == maxDate.getFullYear())){
                                    toInput.data('picker').find('th.datepickerGoNext').find('a:first')
                                        .addClass('cal-nav-disabled');
                                } else {
                                    toInput.data('picker').find('th.datepickerGoNext').find('a:first')
                                        .removeClass('cal-nav-disabled');
                                }
                                
                                toInput.data('adjusted', true);
                            } else {
                                toInput.data('adjusted', false);
                            }
                        }
                        
                    }

                    return {
                        disabled: ( (date.valueOf() <= fromInput.data('date')) || (date.valueOf() > toInput.data('maxDate')) ),
                        selected: ((date.valueOf() >= fromInput.data('date')) && (date.valueOf() <= toInput.data('date'))),
                        className: (date.valueOf() == fromInput.data('date')) ? startDateClass : false,
                        className2: (date.valueOf() == toInput.data('date')) ? endDateClass : false

                    }
                },
                onHide: function(){
                    toInput.find('input:first').DatePickerHide();
                    var exDate = new Date();
                    exDate.setTime(toInput.data('date'));
                    toInput.find('input:first').DatePickerSetDate(exDate.valueOf(), true);
                }
            });
            
            fromInput.find('input.fake-input').DatePicker({
                date: formattedIn,
                current: inDate,
                format: 'm/d/Y',
                mode: 'single',
                calendars: 2,
                position: 'top',
                onShow: function(picker){
                    if ( dateFlagFrom === false){
                        jQuery(picker).find('th.datepickerGoNext:eq(1)').find('a:first').click();  
                        dateFlagFrom = true;
                    }
                     
                    if ( fromInput.data('picker') === null ){
                        fromInput.data('picker', jQuery(picker));
                    }
                },
                onChange: function(formatted, dates){
                    if ( dates > fromInput.data('maxDate') ){
                        dates = fromInput.data('maxDate');
                    }
                    
                    updateInput(fromInput, dates, 'in');
                    var date = getNewDate(dates, headForm.data('nights'));

                    if ( date > toInput.data('maxDate') ){
                        date = toInput.data('maxDate');
                        headForm.data('nights', updateNights(nightSpan, date, dates) );
                    }

                    updateInput(toInput, date, 'out');
                    toInput.find('input.fake-input').DatePickerSetDate(date, true);
                    fromInput.find('input.fake-input').DatePickerHide();
                },
                onRender: function(date){
                    if ( fromInput.data('picker') != null ){
                        fromInput.data('picker').find('td.datepickerNotInMonth').removeClass('datepickerSelected')
                                                                                .addClass('datepickerDisabled');
                        removeWeek(fromInput.data('picker'));

                        if ( date.getDate() === 15 ){
                            if ( fromInput.data('adjusted') === false ){
                                var temp = new Date(fromInput.data('today'));
                                var today = new Date(temp.getFullYear(), temp.getMonth(), temp.getDate());
                                var maxDate = new Date(today.valueOf() + (2629743830 * 9));
                                
                                if ( (date.getMonth() == today.getMonth()) && (date.getFullYear() == today.getFullYear()) ){
                                    fromInput.data('picker').find('th.datepickerGoPrev').find('a:first')
                                        .addClass('cal-nav-disabled');
                                } else {
                                    fromInput.data('picker').find('th.datepickerGoPrev').find('a:first')
                                        .removeClass('cal-nav-disabled');
                                }
                                
                                if ( (date.getMonth() == maxDate.getMonth()) && (date.getFullYear() == maxDate.getFullYear())){
                                    fromInput.data('picker').find('th.datepickerGoNext').find('a:first')
                                        .addClass('cal-nav-disabled');
                                } else {
                                    fromInput.data('picker').find('th.datepickerGoNext').find('a:first')
                                        .removeClass('cal-nav-disabled');
                                }
                                
                                fromInput.data('adjusted', true);
                            } else {
                                fromInput.data('adjusted', false);
                            }
                        }
                    }
                    
                    return {
                        disabled: ( (date.valueOf() < fromInput.data('today')) || 
                                    (date.valueOf() > fromInput.data('maxDate')) ),
                        selected: ((date.valueOf() >= fromInput.data('date')) && (date.valueOf() <= toInput.data('date'))),
                        className: (date.valueOf() == fromInput.data('date')) ? startDateClass : false,
                        className2: (date.valueOf() == toInput.data('date')) ? endDateClass : false
                    }
                }
            })
            
            fromInput.find('input.fake-input').DatePickerShow().DatePickerHide();
            toInput.find('input.fake-input').DatePickerShow().DatePickerHide();
            
            var calendars = jQuery('div.datepicker', jQuery('body'));
            
            jQuery(calendars[0]).find('div.datepickerContainer')
                .prepend('<div class="cal-title">Check-out date <a href="#" class="cal-close">Close</a> </div>')
                .find('a.cal-close').click( function(){ toInput.find('input.fake-input').DatePickerHide(); });
            jQuery(calendars[1]).find('div.datepickerContainer')
                .prepend('<div class="cal-title">Check-in date <a href="#" class="cal-close">Close</a> </div>')
                .find('a.cal-close').click( function(){ fromInput.find('input.fake-input').DatePickerHide(); });
            
            calendars.find('th.datepickerMonth').find('a').click( function(){
                return false;
            })
            
        }).submit( function(){
            jQuery('li.replace-input', headForm).find('select').each( function(){
//                console.log(jQuery(this).val());
            });
            
            jQuery(this).ajaxSubmit({
                dataType: 'json',
                success: function(data){
                    if ( data.success == false ){
                    
                        headForm.find('fieldset > ol > li > ul.errors').remove();
                        var phoneTarget = jQuery('#phone_txt-otherDigits')
                    
                        for ( error in data.errors ){
                            
                            headForm.find('fieldset > ol > li').each( function(){
                            
                                if ( error == 'phone_txt' ){
                                    var comparator = 'phone_txt[areaCode]';
                                } else {
                                    var comparator = error;
                                }

                                if ( jQuery(this).find(':input:first').attr('name') == comparator ){
                                
                                    var errorList = jQuery('<ul class="errors"></ul>');
                                    jQuery(this).append(errorList);
                                    
                                    for ( index in data.errors[error] ){
                                        errorList.append('<li>' + data.errors[error][index] + '</li>');
                                    }
                                        
                                }
                            })
                            
                        }
                        
                        transferErrors();
                        
                        jQuery('img.captcha-img', headForm).replaceWith(data.captchaImg);
                        
                    } else {
                        var completeMessage = data.msg; 
                        headForm.closest('div.col-2').find('h3.complete-message').addClass('form-success').text(data.msg)
                                                                                 .siblings('div').remove();
                    }
                    
                }
            });
            
            return false;
            
        })
    }
    
    if (jQuery( '#header-image' ).length > 0) {
//        jQuery( '#header-image' ).crossSlider({
//            sleep: 5,
//            fade: 1
//        },[
//            { src: BASE_URL + "/img/ui/header-image/1.jpg" },
//            { src: BASE_URL + "/img/ui/header-image/2.jpg" },
//            { src: BASE_URL + "/img/ui/header-image/3.jpg" },
//            { src: BASE_URL + "/img/ui/header-image/4.jpg" },
//            { src: BASE_URL + "/img/ui/header-image/5.jpg" }
//           
//        ]);

        var headerImageArray = [
            { src: BASE_URL + "/img/ui/header-image/1.jpg" },
            { src: BASE_URL + "/img/ui/header-image/2.jpg" },
            { src: BASE_URL + "/img/ui/header-image/3.jpg" },
            { src: BASE_URL + "/img/ui/header-image/4.jpg" },
            { src: BASE_URL + "/img/ui/header-image/5.jpg" }
        ]

        jQuery( '#header-image' ).frozCrossSlider({
            sleep: 5000,
            fade: 0,
            loader: BASE_URL + '/img/loading16.gif',
            onShow: function(head, image, index){
                head.data('noReplace', true).frozImageEffectsShow(
                    image,
                {
                    baseIndex: 1000,
                    blockCount: 15,
                    orientation: 'bricks',
                    effect: 'center',
                    efDelay: 50,
                    efTime: 500,
                    onAnimEnd: function(panel, opts, goIn){
                        if ( goIn === true ){
                            head.find('img').hide();
                            head.append(image.show());
                            panel.frozImageEffectsHide(true).detach();
                        }
                    }
                });
            }
        }, headerImageArray);


    }
    //jQuery('#slideshowHolder').jqFancyTransitions({ width: 672, height: 304, effect: 'curtain' });
});


jQuery('.rounded').corners();
    jQuery(function(){
            jQuery( '#loopedSlider' ).loopedSlider({
                /*autoHeight: 500*/
                containerClick: false
            });
            
            
            
            jQuery("a[rel^='prettyPhoto']").prettyPhoto({
                animationSpeed: 'normal', /* fast/slow/normal */
                padding: 30, /* padding for each side of the picture */
                opacity: 0.1, /* Value betwee 0 and 1 */
                showTitle: true, /* true/false */
                allowresize: true, /* true/false */
                counter_separator_label: '/', /* The separator for the gallery counter 1 "of" 2 */
                theme: 'light_rounded', /* light_rounded / dark_rounded / light_square / dark_square / dark_blue_square */
                callback: function(){}
            });
        });

