/**
 * CCScript
 *  Use a css selector to find and convert an elements contents to an injected script in
 *  the page.
 *
 * options:
 *  - async: (bool)async load of injected script.  Not available on all browsers.
 *  - cssSelector: (string)the selector used as the parent of the injection.
 *
 * dependencies:
 *  - jquery
 */
(function($) {
    // Public Variables and Methods
    $.ccScript = {
        defaults: {
            singleLoad: false,
            async: false,
            cssSelector: ''
        },
        loadedScripts: {}
    };

    // Prototype Methods
    $.fn.extend({
        ccScript: function(options) {
            // build main options before element iteration
            var opts = $.extend({}, $.ccScript.defaults, options);

            // iterate and reformat each matched element
            return this.each(function() {
                var $this = $(this);

                // build element specific options if meta plugin available
                var o = $.metadata ? $.extend({}, opts, $this.metadata()) : opts;
                
                if( ($this.attr('src') || $this.attr('id')) && o.singleLoad && $.ccScript.loadedScripts[($this.attr('src') || $this.attr('id'))] ) {
                    $this.remove();
                    return;
                }

                // do our thing
                // We use document.createElement since all browsers seem to play nicely with this
                var script = document.createElement('script');
                script.type = $this.attr('script-type') || 'text/javascript';
                script.async = o.async;
                script.name = $this.attr('name');
                script.id = $this.attr('id');

                var src = $this.attr('src');
                if(src) {
                    script.src = src;
                } else {
                    script.text = $this.text();
                }

                var target = null;
                if(o.cssSelector && o.cssSelector != '') {
                    target = $(o.cssSelector);
                } else {
                    target = $this.parent();
                }

                $(target).append(script);

                if( ($this.attr('src') || $this.attr('id')) && o.singleLoad ) {
                    $.ccScript.loadedScripts[($this.attr('src') || $this.attr('id'))] = true;
                }
                
                $this.remove();


            });
        }
    });
})(jQuery);

/**
 * CCFloater
 * Float an element at a fixed position when scrolling otherwise leaves it in it's natural
 * position.
 * 
 * dependencies:
 *  - jquery
 */
(function($) {
    // Public Variables and Methods
    $.ccFloater = {
        defaults: {
            placeholderClass: ''
        },
        settings: {
            currentId: 0
        }
    };

    // Prototype Methods
    $.fn.extend({
        ccFloater: function(options) {
            // build main options before element iteration
            var opts = $.extend({}, $.ccFloater.defaults, options);

            // iterate and reformat each matched element
            return this.each(function() {
                var $this = $(this),
                isFixed = false,
                placeholderId = 'floater-' + $.ccFloater.settings.currentId++,
                $placeholder = $('<div id="' + placeholderId + '">');
                if(opts.placeholderClass) {
                    $placeholder.addClass(opts.placeholderClass);
                }
                $placeholder.insertBefore($this);
                
                var onResize, onScroll;
                
                onResize = function() {
                    // See if we have been removed from the window
                    if($this.closest('body').size() == 0) {
                        $(window).unbind('scroll', onScroll);
                        $(window).unbind('resize', onResize);
                    }
                    if(isFixed) {
                        $this.css({
                            'left': $placeholder.offset().left - parseInt($this.css('margin-left'))
                        });
                    }
                };
                
                onScroll = function() {
                    // See if we have been removed from the window
                    if($this.closest('body').size() == 0) {
                        $(window).unbind('scroll', onScroll);
                        $(window).unbind('resize', onResize);
                    }
                    if($this.offset().top - $(window).scrollTop() < 0) {
                        $placeholder.css({
                            height: $this.outerHeight(),
                            width: $this.outerWidth()
                        });
                        $this.css({
                            'top': 0,
                            'left': $placeholder.offset().left - parseInt($this.css('margin-left')),
                            'position': 'fixed'
                        });
                        isFixed = true;
                    } else if($placeholder.offset().top - $(window).scrollTop() > 0 && isFixed) {
                        $placeholder.css({
                            height: 0,
                            width: $this.outerWidth()
                        });
                        $this.css({
                            'position': 'inherit'
                        });
                        isFixed = false;
                    }
                };
                
                $(window).scroll(onScroll);
                $(window).resize(onResize);
            });
        }
    });
})(jQuery);

/**
 * CCTemplate
 *  Use a css selector to find and convert an elements contents to a jquery template.  Supports
 *  unloading when parent element is removed from document.  Optionally supports loading
 *  the template body via ajax when the element has a 'src' attribute.
 *
 * options:
 *  - name: (string)the name to assign to the template, will default to the elements id if not provided
 *
 * dependencies:
 *  - jquery
 *  - jquery-ui
 */
(function($) {
    $.widget( 'cc.ccTemplate', {
        // default options
        options: {
            name: null
        },
        _create: function() {
            if(! this.options.name ) {
                this.options.name = $(this.element).attr('id');
            }

            var tmplString = '';
            if($(this.element).attr('src')) {
                $.get($(this.element).attr('src'), null, function(data) {
                    tmplString = data;
                }, 'text');
            } else {
                tmplString = $(this.element).html().replace(/&lt;/ig, '<').replace(/&gt;/ig, '>').replace(/&apos/ig, '"');
            }
            $.template(this.options.name, tmplString);
            $(this.element).hide();
        },
        destroy: function() {
            delete $.template[this.options.name];
        },
        prependTo: function(dest, data) {
            return $.tmpl(this.options.name,data).prependTo($(dest));
        },
        appendTo: function(dest, data) {
            return $.tmpl(this.options.name,data).appendTo($(dest));
        },
        replaceInto: function(dest, data) {
            return $(dest).html($.tmpl(this.options.name,data));
        },
        replaceWith: function(dest, data) {
            return $(dest).replaceWith($.tmpl(this.options.name,data));
        },
        insertAfter: function(dest, data) {
            return $.tmpl(this.options.name,data).insertAfter($(dest));
        },
        insertBefore: function(dest, data) {
            return $.tmpl(this.options.name, data).insertBefore($(dest));
        }
    });
})(jQuery);

/**
 * CCStyle
 *  Use a css selector to find and convert an elements contents to a stylesheet.  Supports
 *  unloading when parent element is removed from document.  Optionally supports loading
 *  the style from a remote file.  It's only really a jquery ui plugin to leverage
 *  the automatic destruction methods for unloading.
 *
 * dependencies:
 *  - jquery
 *  - jquery-ui
 */
(function($) {
    $.widget( 'cc.ccStyle', {
        // default options
        options: {
            _private: {
                target: null
            }
        },
        _create: function() {
            var $element = $(this.element);

            if($element.attr('src')) {
                this.options._private.target = $('<link/>').attr({
                    rel: 'stylesheet',
                    type: 'text/css',
                    href: $element.attr('src')
                }).appendTo('head');
            } else {
                var style = $element.html().replace(/&lt;/ig, '<').replace(/&gt;/ig, '>').replace(/&apos/ig, '"');
                this.options._private.target = $('<style></style>').text(style).appendTo('head');
            }
            $(this.element).hide();
        },
        destroy: function() {
            this.options._private.target.remove();
        }
    });
})(jQuery);

/**
 * CCPaginator
 *  Use a css selector to build out a paginator with item caching.
 *
 * options:
 *  - item: (function)the function to callback directly for each paged item.
 *  - autoLoad: (bool)set to true to automatically load the first page on creation.
 *  - currentPage: (int)the page to start with or move to
 *  - pageSize: (int)the number of items to fetch with each page.
 *  - request: (function)the function to call to get more items.
 *  - params: (object)the parameters to pass with each request. page and pageSize will be appended.
 *  - itemSelector: (css string)the selector to use to find the items in the request response.
 *
 * dependencies:
 *  - jquery
 *  - jquery-ui
 *
 * events:
 *  - loadbegin
 *  - pagebegin
 *  - pageend
 *  - loadend
 *  - nomore
 *
 */
(function($) {
    $.widget( 'cc.ccPaginator', {
        // default options
        options: {
            item: function() {},

            autoLoad: true,
            currentPage: 0,
            pageSize: 10,

            request: function() {},
            params: {},
            itemSelector: '',

            pagerSelector: null,
            pagerTemplate: null,
            maxPagerItems: 10,
            numPagerEdges: 2,
            elipsis: '...',

            _private: {
                hasMore: true,
                cache: [],
                totalItems: -1,
                request: null
            }
        },

        _create: function() {
            if(this.options.autoLoad) {
                this.next();
            }
        },
        destroy: function() {
        },
        _setOption: function( key, value ) {
            this.options[ key ] = value;
            if('currentPage' == key) {
                this._loadPage();
            }
        },
        _signalPage: function(page, baseIdx) {
            this._trigger('pagebegin');
            for(i=0; i < page.length; i++) {
                this.options.item(page[i], baseIdx + i, this);
            }
            this._drawPager();

            var ui = {
                hasMore: this.options.pageSize * this.options.currentPage < this.options._private.totalItems,
                hasLess: this.options.currentPage > 1,
                pager: this
            }
            this._trigger('pageend', null, ui);
        },
        _retrievePage: function() {
            this._trigger('loadbegin');
            var self = this;
            
            self.options.params.page = self.options.currentPage;
            self.options.params.pageSize = self.options.pageSize;
            
            var params = $.extend(true, {}, self.options.params);
            
            var request = self.options._private.request = self.options.request(params, function(response) {
                if(request != self.options._private.request) {
                    return;
                }
                var page = [];
                self.options._private.totalItems = $(response).children('*[total_found]').attr('total_found') || -1;
                $(response).find(self.options.itemSelector).each(function() {
                    page.push($(this));
                });
                self.options._private.cache[self.options.currentPage] = page;
                self._signalPage(self.options._private.cache[self.options.currentPage], (self.options.currentPage - 1) * self.options.pageSize);
                self.options._private.request = null;
                self._trigger('loadend');
            });
        },
        _loadPage: function() {
            if(this.options._private.cache[this.options.currentPage]) {
                this._signalPage(this.options._private.cache[this.options.currentPage], (this.options.currentPage - 1) * this.options.pageSize);
            } else {
                this._retrievePage();
            }
        },
        hasMore: function() {
            return this.options._private.totalItems == -1 || this.options.pageSize * this.options.currentPage < this.options._private.totalItems;
        },
        previous: function() {
            --this.options.currentPage;
            if(this.options.currentPage <= 0) {
                this.options.currentPage = 1;
            }
            this._loadPage();
        },
        next: function() {
            if(!this.hasMore() || this.options._private.request) {
                return;
            }
            ++this.options.currentPage;
            this._loadPage();
        },
        reset: function() {
            this.options.currentPage = 0;
            this.options._private = {
                hasMore: true,
                cache: [],
                totalItems: -1
            }
            if(this.options._private.request) {
                this.options._private.request.abort();
                this.options._private.request = null;
            }
        },

        /* Page Nav */
        _getPageRange: function() {
            var curPage = this.options.currentPage;
            var half = Math.ceil(this.options.maxPagerItems/2);
            var pages = this.totalPages();
            var limit = pages - this.options.maxPagerItems;
            var start = curPage > half ? Math.max( Math.min( curPage - half, limit), 1) : 1;
            var end = curPage > half ? Math.min( curPage + half, pages ) : Math.min( this.options.maxPagerItems, pages );
            return [start, end];
        },
        _appendPagerItem: function(page, label) {
            var self = this;
            $(this.options.pagerTemplate).ccTemplate('appendTo', this.options.pagerSelector, {
                label: label,
                page: page,
                current: this.options.currentPage == page
            }).click(function() {
                self._setOption('currentPage', page);
                return false;
            });
        },
        _drawPager: function() {
            var pager = $(this.options.pagerSelector);
            var range = this._getPageRange();
            var numPages = this.totalPages();

            // Clear the area
            pager.empty();

            // See if we need a previous link
            if(this.options.currentPage > 1) {
                this._appendPagerItem(this.options.currentPage - 1, 'Prev');
            }
            if(range[0] > 1 && this.options.numPagerEdges > 0) {
                var end = Math.min( this.options.numPagerEdges, range[0] );
                for(i = 1; i <= end; ++i) {
                    this._appendPagerItem(i, i);
                }
                if(this.options.numPagerEdges < range[0] - 1)
                {
                    $("<span></span>").text(this.options.elipsis).appendTo(pager);
                }
            }
            for(i = range[0]; i <= range[1]; i++) {
                this._appendPagerItem(i, i);
            }
            if(range[1] < numPages) {
                if(numPages - this.options.numPagerEdges > range[1]) {
                    $("<span></span>").text(this.options.elipsis).appendTo(pager);
                }
                var start = Math.max(numPages - this.options.numPagerEdges, range[1]);
                for(i = start; i < numPages; i++) {
                    this._appendPagerItem(i, i);
                }
            }

            // Next item
            if( this.options.currentPage < numPages ) {
                this._appendPagerItem(this.options.currentPage + 1, 'Next');
            }
        },
        totalItems: function() {
            return this.options._private.totalItems;
        },
        totalPages: function() {
            return this.options._private.totalItems == -1 ? -1 : Math.ceil(this.options._private.totalItems / this.options.pageSize);
        }
    });
})(jQuery);

/**
 * CCPageLoader
 * Watch for the bottom of a list to scroll into view and autoload the next page.
 * 
 * dependencies:
 *  - jquery
 *  - ccPaginator
 */
(function($) {
    // Public Variables and Methods
    $.ccPageLoader = {
        defaults: {
            pager: '',
            triggerClass: null,
            scrollDelay: 250,
            loadingStamp: $('<div class="loader"></div>')
        },
        settings: {
            currentId: 0
        }
    };

    // Prototype Methods
    $.fn.extend({
        ccPageLoader: function(options) {
            // build main options before element iteration
            var opts = $.extend({}, $.ccPageLoader.defaults, options);

            // iterate and reformat each matched element
            return this.each(function() {
                var $this = $(this),
                isLoading = false,
                timer = null,
                didScroll = null,
                triggerId = 'loader-' + $.ccPageLoader.settings.currentId++,
                $trigger = $('<div id="' + triggerId + '">');
                
                opts.pager = opts.pager || this;
                
                if(opts.triggerClass) {
                    $trigger.addClass(opts.triggerClass);
                }
                $trigger.appendTo($this);
                
                // Listen for load events
                $(opts.pager).bind('ccpaginatorloadbegin', function() {
                    opts.loadingStamp.appendTo($trigger);
                });
                
                $(opts.pager).bind('ccpaginatorloadend', function() {
                    //$trigger.empty();
                    isLoading = false;
                    $trigger.remove().appendTo($this);
                });
                
                var onScroll = function() {
                    didScroll = true;
                }
                
                timer = setInterval(function() {
                    // See if we have been removed from the window
                    if($this.closest('body').size() == 0) {
                        $(window).unbind('scroll', onScroll);
                        window.clearInterval(timer);
                    }
                    
                    if (didScroll) {
                        didScroll = false;
                        if(isLoading || !$this.is(':visible')) {
                            return;
                        }
                        
                        var docViewTop = $(window).scrollTop(),
                        docViewBottom = docViewTop + $(window).height();
                        var elemTop = $trigger.offset().top;
                        
                        if(elemTop < docViewBottom) {
                            $(opts.pager).ccPaginator('next');
                            isLoading = true;
                        }
                    }
                }, opts.scrollDelay);
                
                $(window).scroll(onScroll);
            });
        }
    });
})(jQuery);

/**
 * CCFramework
 *  Use a css selector to initialize the entire page and rest api framework
 *
 * options:
 *
 * dependencies:
 *  - jquery
 *  - ccTemplate
 *  - ccScript
 */
(function($) {
    // Public Variables and Methods
    $.ccFramework = {
        defaults: {
            asyncAnchors: true,
            enableScripts: true,
            enableTemplates: true,
            enableStyles: true,
            cssSelectors: {
                content: '#content',
                contentWrapper: '#contentWrapper',
                ccScript: '.cc-script',
                ccTemplate: '.cc-tmpl',
                ccStyle: '.cc-style'
            },
            titlePrefix: '.\u0131I\u0131I\u0131. ClubCreate - '
        },
        settings : {},

        init: function(opts) {
            var self = this,
            o = self.settings = $.extend({}, $.ccFramework.defaults, opts);

            // Grab our anchors if need be
            if(o.asyncAnchors) {
                self._grabAnchors();
            }

            if( $.history && ! $.history.callback ) {
                $.history.init(function(url) {
                    self._loadHistory(url);
                }, {
                    unescape: '!/,?&='
                });
            }

            // Load our templates as well
            if(o.enableTemplates) {
                this._loadTemplates();
            }
            
            $(document).trigger($.Event('framework.initialized'));
        },
        _loadTemplates: function() {
            $(document).find(this.settings.cssSelectors.ccTemplate).each(function() {
                $(this).ccTemplate();
            });
        },
        _grabAnchors: function() {
            var self = this;
            $('a:not(.cc-live-url, .cc-ui)').live('click', function() {
                var $this = $(this),
                href = $this.attr('href');
                if(href && /^javascript:/.test(href)) {
                    return true;
                }
                self.loadPage(href);
                    return false;
                });
            },
            _loadHistory: function(url) {
                var self = $.ccFramework;
                /*
            if(url == '' || url == '#') {
                $(document).find(self.settings.cssSelectors.content).ccPartialPage({
                    enableTemplates: self.settings.enableTemplates,
                    enableScripts: self.settings.enableScripts,
                    enableStyles: self.settings.enableStyles,
                    cssSelectors: {
                        ccTemplate: self.settings.cssSelectors.ccTemplate,
                        ccScript: self.settings.cssSelectors.ccScript,
                        ccStyle: self.settings.cssSelectors.ccStyle
                    }
                });
                return;
            }*/
                this._loadPage(url);
            },
            _loadPage: function(url) {
                var self = $.ccFramework;

                url = url.replace(/^!/, '');
            
                // Create an event and dispatch it
                var e = $.Event('framework.willloadpage');
                e.url = url;
                $(document).trigger(e);
            
                if(e.isDefaultPrevented()) {
                    return;
                }
            
                // Allow the event to change the destination
                url = e.routed || url;

                $(self.settings.cssSelectors.contentWrapper).load(url + ' ' + self.settings.cssSelectors.content, function() {
                    $(self.settings.cssSelectors.content).ccPartialPage({
                        enableTemplates: self.settings.enableTemplates,
                        enableScripts: self.settings.enableScripts,
                        enableStyles: self.settings.enableStyles,
                        cssSelectors: {
                            ccTemplate: self.settings.cssSelectors.ccTemplate,
                            ccScript: self.settings.cssSelectors.ccScript,
                            ccStyle: self.settings.cssSelectors.ccStyle
                        },
                        pageinitialized: function(event) {
                            if($(event.target).attr('title')) {
                                self.setPageTitle($(event.target).attr('title'));
                            }
                        }
                    });
                    $('html, body').animate({
                        scrollTop:0
                    }, 'slow');
                });
                return false;
            },
            setPageTitle: function(title) {
                document.title = $.ccFramework.settings.titlePrefix + title;
            },
            loadPage: function(url) {
                if( url != '#' ) {
                    $.history.load('!' + url);
                }
            },
            reloadPage: function() {
                // Have to skirt around history plugin
                this._loadPage(this.getPage());
            },
            getPage: function() {
                var url = $.history.get();
                url = url.replace(/^!/, '');
                return url;
            },
            getQueryParam: function(param) {
                var url = $.history.get();
                if(url == '' || url == '#') {
                    url = window.location.href;
                }
                if(url.indexOf('!') == 0) {
                    url = url.substr(1);
                }
                return $.url.setUrl(url).param(param);
            },
            getUrlSegment: function(idx) {
                var url = $.history.get();
                if(url == '' || url == '#') {
                    url = window.location.href;
                }
                if(url.indexOf('!') == 0) {
                    url = url.substr(1);
                }
                return $.url.setUrl(url).segment(idx);
            }
        };
    })(jQuery);

    /**
 *  A quick and ugly plugin to scroll something into view.
 **/
    (function($) {
        // Public Variables and Methods
        $.isScrolledIntoView = function(elem) {
            var docViewTop = $(window).scrollTop();
            var docViewBottom = docViewTop + $(window).height();

            var elemTop = $(elem).offset().top;

            return ((elemTop >= docViewTop) && (elemTop <= docViewBottom));
        //&& (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
        }

        // Prototype Methods
        $.fn.extend({
            scrollIntoView: function(options) {
                return this.first().each(function() {
                    if($.isScrolledIntoView(this)) {
                        return;
                    }

                    // do our thing (really simple, could be enhanced a lot)
                    $('html, body').animate({
                        scrollTop: $(this).offset().top
                    }, 'slow');
                });
            }
        });
    })(jQuery);

    /**
 * CCPage
 *  Use a css selector to load and initialize a page.
 *
 * options:
 *
 * dependencies:
 *  - jquery
 *  - jquery-ui
 *  - ccFramework
 */
    (function($) {
        $.widget( 'cc.ccPartialPage', {
            // default options
            options: {
                enableScripts: true,
                enableTemplates: true,
                enableStyles: true,
                cssSelectors: {
                    ccScript: '.cc-script',
                    ccTemplate: '.cc-tmpl',
                    ccStyle: '.cc-style'
                }
            },
            _private: {
            },
            _create: function() {
                // Load our template
                if(this.options.enableTemplates) {
                    this._loadTemplates();
                }

                // Load our scripts
                if(this.options.enableScripts) {
                    this._loadScripts();
                }

                // Load our styles
                if(this.options.enableStyles) {
                    this._loadStyles();
                }

                var pageId = this._getPageId();
                if( window.CC && window.CC.pages[pageId] ) {
                    window.CC.pages[pageId].init(this.element);
                }

                this._trigger('pageinitialized');
            },
            destroy: function() {
                var pageId = this._getPageId();
                if( window.CC && window.CC.pages[pageId] && window.CC.pages[pageId].destroy ) {
                    window.CC.pages[pageId].destroy(this.element);
                }
            },
            _getPageId: function() {
                return this.element.attr('page') || this.element.attr('id');
            /*
            if( this.element.attr('page') ) {
                return this.element.attr('page');
            } else {
                return this.element.attr('id');
            }*/
            },
            _loadScripts: function() {
                $(this.options.cssSelectors.ccScript).ccScript();
            },
            _loadStyles: function() {
                $(this.options.cssSelectors.ccStyle).ccStyle();
            },
            _loadTemplates: function() {
                $(this.options.cssSelectors.ccTemplate).ccTemplate();
            }
        });
    })(jQuery);


    // Default page init
    (function($) {
        window.CC = window.CC || {};
        window.CC.pages = window.CC.pages || {};

        // User Management
        window.CC.auth = {
            initialized: false,
            authorized: false,
            token: null,
            username: null,
            // initialize page state / update status box
            init: function() {
                if(CC.auth.initialzied) return;

                var self = this;
                CCSocialAuth.settings.authCallback = function(socialId, msg, username) {
                    if('success' == msg) {
                        self.handleLogin(username);
                    }
                }

                // Set our document domain
                document.domain = 'clubcreate.com';

                // If we already have a token, assume we are logged in
                var token = CC.auth.getToken();
                if (token) {
                    CC.auth.authorized = true;
                    $(document).triggerHandler('authenticated', [ CC.auth.getToken(), CC.auth.getUsername() ]);
                }

                CC.auth.initialized = true;
            },
            // submit login request
            doLogin: function(email, password) {
                CCSocialAuth.authenticate2('clubcreate');
            },
            // handle login req response
            handleLogin: function(username) {
                // update cookie
                $.setCookie("username", username, 1, '.clubcreate.com');

                // Mark us as authorized
                CC.auth.authorized = true;

                $(document).triggerHandler('authenticated', [this.getToken(), username]);
            },
            // begin logout process
            doLogout: function() {
                $.deleteCookie("clubcreate", '.clubcreate.com');
                $.deleteCookie("username", '.clubcreate.com');

                CC.auth.authorized = false;

                $(document).triggerHandler('loggedout', []);
            },
            // handle unauthorization notice
            handleUnauthorized: function() {

            },
            getUsername: function() {
                return CC.auth.username || $.getCookie("username");
            },
            getToken: function() {
                return CC.auth.token || $.getCookie("clubcreate");
            }

        };

        $(document).ready(function() {
            CC.auth.init();
        });
    })(jQuery);



    // JQuery URL Parser
    // Written by Mark Perkins, mark@allmarkedup.com
    // License: http://unlicense.org/ (i.e. do what you want with it!)

    jQuery.url = function()
    {
        var segments = {};
        var parsed = {};

        /**
     * Options object. Only the URI and strictMode values can be changed via the setters below.
     */
        var options = {
            url : window.location, // default URI is the page in which the script is running
            strictMode: false, // 'loose' parsing by default
            key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], // keys available to query
            q: {
                name: "queryKey",
                parser: /(?:^|&)([^&=]*)=?([^&]*)/g
            },
            parser: {
                strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,  //less intuitive, more accurate to the specs
                loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
            }
        };

        /**
     * Deals with the parsing of the URI according to the regex above.
     * Written by Steven Levithan - see credits at top.
     */
        var parseUri = function()
        {
            str = decodeURI( options.url );

            var m = options.parser[ options.strictMode ? "strict" : "loose" ].exec( str );
            var uri = {};
            var i = 14;

            while ( i-- ) {
                uri[ options.key[i] ] = m[i] || "";
            }

            uri[ options.q.name ] = {};
            uri[ options.key[12] ].replace( options.q.parser, function ( $0, $1, $2 ) {
                if ($1) {
                    uri[options.q.name][$1] = $2;
                }
            });

            return uri;
        };

        /**
     * Returns the value of the passed in key from the parsed URI.
     *
     * @param string key The key whose value is required
     */
        var key = function( key )
        {
            if ( jQuery.isEmptyObject(parsed) )
            {
                setUp(); // if the URI has not been parsed yet then do this first...
            }
            if ( key == "base" )
            {
                if ( parsed.port !== null && parsed.port !== "" )
                {
                    return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/";
                }
                else
                {
                    return parsed.protocol+"://"+parsed.host+"/";
                }
            }

            return ( parsed[key] === "" ) ? null : parsed[key];
        };

        /**
     * Returns the value of the required query string parameter.
     *
     * @param string item The parameter whose value is required
     */
        var param = function( item )
        {
            if ( jQuery.isEmptyObject(parsed) )
            {
                setUp(); // if the URI has not been parsed yet then do this first...
            }
            return ( parsed.queryKey[item] === null ) ? null : parsed.queryKey[item];
        };

        /**
     * 'Constructor' (not really!) function.
     *  Called whenever the URI changes to kick off re-parsing of the URI and splitting it up into segments.
     */
        var setUp = function()
        {
            parsed = parseUri();

            getSegments();
        };

        /**
     * Splits up the body of the URI into segments (i.e. sections delimited by '/')
     */
        var getSegments = function()
        {
            var p = parsed.path;
            segments = []; // clear out segments array
            segments = parsed.path.length == 1 ? {} : ( p.charAt( p.length - 1 ) == "/" ? p.substring( 1, p.length - 1 ) : path = p.substring( 1 ) ).split("/");
        };

        return {

            /**
         * Sets the parsing mode - either strict or loose. Set to loose by default.
         *
         * @param string mode The mode to set the parser to. Anything apart from a value of 'strict' will set it to loose!
         */
            setMode : function( mode )
            {
                options.strictMode = mode == "strict" ? true : false;
                return this;
            },

            /**
         * Sets URI to parse if you don't want to to parse the current page's URI.
         * Calling the function with no value for newUri resets it to the current page's URI.
         *
         * @param string newUri The URI to parse.
         */
            setUrl : function( newUri )
            {
                options.url = newUri === undefined ? window.location : newUri;
                setUp();
                return this;
            },

            /**
     * Returns the value of the specified URI segment. Segments are numbered from 1 to the number of segments.
     * For example the URI http://test.com/about/company/ segment(1) would return 'about'.
     *
     * If no integer is passed into the function it returns the number of segments in the URI.
     *
     * @param int pos The position of the segment to return. Can be empty.
     */
            segment : function( pos )
            {
                if ( jQuery.isEmptyObject(parsed) )
                {
                    setUp(); // if the URI has not been parsed yet then do this first...
                }
                if ( pos === undefined )
                {
                    return segments.length;
                }
                return ( segments[pos] === "" || segments[pos] === undefined ) ? null : segments[pos];
            },

            attr : key, // provides public access to private 'key' function - see above

            param : param // provides public access to private 'param' function - see above

        };

    }();

/**
* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne brian(at)cherne(dot)net
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev])}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev])};var handleHover=function(e){var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t)}if(e.type=="mouseenter"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob)},cfg.timeout)}}};return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover)}})(jQuery);

/**
 * JavaScript Number Format v1.5.4
 * A custom JavaScript object to format numbers
 * Includes currency, commas, and decimal precision
 * 
 * http://www.mredkj.com/javascript/nfdocs.html
 */
function NumberFormat(a,b){this.VERSION="Number Format v1.5.4";this.COMMA=",";this.PERIOD=".";this.DASH="-";this.LEFT_PAREN="(";this.RIGHT_PAREN=")";this.LEFT_OUTSIDE=0;this.LEFT_INSIDE=1;this.RIGHT_INSIDE=2;this.RIGHT_OUTSIDE=3;this.LEFT_DASH=0;this.RIGHT_DASH=1;this.PARENTHESIS=2;this.NO_ROUNDING=-1;this.hasSeparators=!1;this.setNumber=setNumberNF;this.toUnformatted=toUnformattedNF;this.setInputDecimal=setInputDecimalNF;this.setSeparators=setSeparatorsNF;this.setCommas=setCommasNF;this.setNegativeFormat=
setNegativeFormatNF;this.setNegativeRed=setNegativeRedNF;this.setCurrency=setCurrencyNF;this.setCurrencyPrefix=setCurrencyPrefixNF;this.setCurrencyValue=setCurrencyValueNF;this.setCurrencyPosition=setCurrencyPositionNF;this.setPlaces=setPlacesNF;this.toFormatted=toFormattedNF;this.toPercentage=toPercentageNF;this.getOriginal=getOriginalNF;this.moveDecimalRight=moveDecimalRightNF;this.moveDecimalLeft=moveDecimalLeftNF;this.getRounded=getRoundedNF;this.preserveZeros=preserveZerosNF;this.justNumber=
justNumberNF;this.expandExponential=expandExponentialNF;this.getZeros=getZerosNF;this.moveDecimalAsString=moveDecimalAsStringNF;this.moveDecimal=moveDecimalNF;this.addSeparators=addSeparatorsNF;b==null?this.setNumber(a,this.PERIOD):this.setNumber(a,b);this.setCommas(!0);this.setNegativeFormat(this.LEFT_DASH);this.setNegativeRed(!1);this.setCurrency(!1);this.setCurrencyPrefix("$");this.setPlaces(2)}function setInputDecimalNF(a){this.inputDecimalValue=a}
function setNumberNF(a,b){b!=null&&this.setInputDecimal(b);this.numOriginal=a;this.num=this.justNumber(a)}function toUnformattedNF(){return this.num}function getOriginalNF(){return this.numOriginal}function setNegativeFormatNF(a){this.negativeFormat=a}function setNegativeRedNF(a){this.negativeRed=a}function setSeparatorsNF(a,b,c){this.hasSeparators=a;if(b==null)b=this.COMMA;if(c==null)c=this.PERIOD;this.decimalValue=b==c?c==this.PERIOD?this.COMMA:this.PERIOD:c;this.separatorValue=b}
function setCommasNF(a){this.setSeparators(a,this.COMMA,this.PERIOD)}function setCurrencyNF(a){this.hasCurrency=a}function setCurrencyValueNF(a){this.currencyValue=a}function setCurrencyPrefixNF(a){this.setCurrencyValue(a);this.setCurrencyPosition(this.LEFT_OUTSIDE)}function setCurrencyPositionNF(a){this.currencyPosition=a}function setPlacesNF(a,b){this.roundToPlaces=a!=this.NO_ROUNDING;this.truncate=b!=null&&b;this.places=a<0?0:a}
function addSeparatorsNF(a,b,c,e){a+="";var d=a.indexOf(b),b="";d!=-1&&(b=c+a.substring(d+1,a.length),a=a.substring(0,d));for(c=/(\d+)(\d{3})/;c.test(a);)a=a.replace(c,"$1"+e+"$2");return a+b}
function toFormattedNF(){var a=this.num,b;this.roundToPlaces?(a=this.getRounded(a),b=this.preserveZeros(Math.abs(a))):b=this.expandExponential(Math.abs(a));b=this.hasSeparators?this.addSeparators(b,this.PERIOD,this.decimalValue,this.separatorValue):b.replace(RegExp("\\"+this.PERIOD),this.decimalValue);var c="",e="",d="",g="",f="",k="",j="",l="",h=this.negativeFormat==this.PARENTHESIS?this.LEFT_PAREN:this.DASH,i=this.negativeFormat==this.PARENTHESIS?this.RIGHT_PAREN:this.DASH;if(this.currencyPosition==
this.LEFT_OUTSIDE){if(a<0){if(this.negativeFormat==this.LEFT_DASH||this.negativeFormat==this.PARENTHESIS)g=h;if(this.negativeFormat==this.RIGHT_DASH||this.negativeFormat==this.PARENTHESIS)f=i}if(this.hasCurrency)c=this.currencyValue}else if(this.currencyPosition==this.LEFT_INSIDE){if(a<0){if(this.negativeFormat==this.LEFT_DASH||this.negativeFormat==this.PARENTHESIS)e=h;if(this.negativeFormat==this.RIGHT_DASH||this.negativeFormat==this.PARENTHESIS)j=i}if(this.hasCurrency)d=this.currencyValue}else if(this.currencyPosition==
this.RIGHT_INSIDE){if(a<0){if(this.negativeFormat==this.LEFT_DASH||this.negativeFormat==this.PARENTHESIS)e=h;if(this.negativeFormat==this.RIGHT_DASH||this.negativeFormat==this.PARENTHESIS)j=i}if(this.hasCurrency)k=this.currencyValue}else if(this.currencyPosition==this.RIGHT_OUTSIDE){if(a<0){if(this.negativeFormat==this.LEFT_DASH||this.negativeFormat==this.PARENTHESIS)g=h;if(this.negativeFormat==this.RIGHT_DASH||this.negativeFormat==this.PARENTHESIS)f=i}if(this.hasCurrency)l=this.currencyValue}b=c+
e+d+g+b+f+k+j+l;this.negativeRed&&a<0&&(b='<font color="red">'+b+"</font>");return b}function toPercentageNF(){nNum=this.num*100;nNum=this.getRounded(nNum);return nNum+"%"}function getZerosNF(a){var b="",c;for(c=0;c<a;c++)b+="0";return b}
function expandExponentialNF(a){if(isNaN(a))return a;var b=parseFloat(a)+"",c=b.toLowerCase().indexOf("e");if(c!=-1){var e=b.toLowerCase().indexOf("+"),d=b.toLowerCase().indexOf("-",c),a=b.substring(0,c);d!=-1?(b=b.substring(d+1,b.length),a=this.moveDecimalAsString(a,!0,parseInt(b))):(e==-1&&(e=c),b=b.substring(e+1,b.length),a=this.moveDecimalAsString(a,!1,parseInt(b)));b=a}return b}function moveDecimalRightNF(a,b){var c="";return c=b==null?this.moveDecimal(a,!1):this.moveDecimal(a,!1,b)}
function moveDecimalLeftNF(a,b){var c="";return c=b==null?this.moveDecimal(a,!0):this.moveDecimal(a,!0,b)}
function moveDecimalAsStringNF(a,b,c){var e=arguments.length<3?this.places:c;if(e<=0)return a;var d=a+"",g=this.getZeros(e),f=/([0-9.]+)/;b?(d=d.replace(f,g+"$1"),d=d.replace(RegExp("(-?)([0-9]*)([0-9]{"+e+"})(\\.?)"),"$1$2.$3")):(f=f.exec(d),f!=null&&(d=d.substring(0,f.index)+f[1]+g+d.substring(f.index+f[0].length)),d=d.replace(RegExp("(-?)([0-9]*)(\\.?)([0-9]{"+e+"})"),"$1$2$4."));return d=d.replace(/\.$/,"")}
function moveDecimalNF(a,b,c){var e="",e=c==null?this.moveDecimalAsString(a,b):this.moveDecimalAsString(a,b,c);return parseFloat(e)}function getRoundedNF(a){a=this.moveDecimalRight(a);a=this.truncate?a>=0?Math.floor(a):Math.ceil(a):Math.round(a);return a=this.moveDecimalLeft(a)}
function preserveZerosNF(a){var b,a=this.expandExponential(a);if(this.places<=0)return a;b=a.indexOf(".");if(b==-1){a+=".";for(b=0;b<this.places;b++)a+="0"}else{var c=this.places-(a.length-1-b);for(b=0;b<c;b++)a+="0"}return a}
function justNumberNF(a){newVal=a+"";a=!1;newVal.indexOf("%")!=-1&&(newVal=newVal.replace(/\%/g,""),a=!0);newVal=newVal.replace(RegExp("[^\\"+this.inputDecimalValue+"\\d\\-\\+\\(\\)eE]","g"),"");var b=RegExp("["+this.inputDecimalValue+"]","g"),c=b.exec(newVal);if(c!=null){var e=newVal.substring(c.index+c[0].length);newVal=newVal.substring(0,c.index)+this.PERIOD+e.replace(b,"")}newVal.charAt(newVal.length-1)==this.DASH?(newVal=newVal.substring(0,newVal.length-1),newVal="-"+newVal):newVal.charAt(0)==
this.LEFT_PAREN&&newVal.charAt(newVal.length-1)==this.RIGHT_PAREN&&(newVal=newVal.substring(1,newVal.length-1),newVal="-"+newVal);newVal=parseFloat(newVal);isFinite(newVal)||(newVal=0);a&&(newVal=this.moveDecimalLeft(newVal,2));return newVal};
