﻿jQuery(document).ready(function() {

    //Handle all links with rel = external
    jQuery('a[rel="external"]').ExternalLinks();
    jQuery('a[rel="nofollow"]').ExternalLinks();

    //Modify the standard .NET client validation so we can have a bit more control over presentation
    ModifyASPNETValidation();

});

//Re-assigns a couple of the ASP.NET validation JS functions to provide a more flexible approach
function ModifyASPNETValidation() {
    //Hi-jack the ASP.NET error display only if required
    if (typeof (Page_ClientValidate) != "undefined") {
        ValidatorUpdateDisplay = NicerValidatorUpdateDisplay;
        AspPage_ClientValidate = Page_ClientValidate;
        Page_ClientValidate = NicerPage_ClientValidate;
    }

    //Add validation statuses to any validation controls that may be visible (i.e. visible when the page loads)
    jQuery('span.validation:visible,span.EditingFormErrorLabel:visible').each(function() {
        AddValidationStatus(jQuery(this));
    });
}

function AddValidationStatus(obj) {
    if (obj.hasClass('validation') || obj.hasClass('EditingFormErrorLabel')) {
        //We'll look for a validation container to set the status on
        var vc = obj.parents('div.validationContainer');
        if (vc.length == 0) {
            //Fall back to div.formInput
            vc = obj.parents('div.formInput');
        }
        vc.addClass('invalidInput');
    }
}

function RemoveValidationStatus(obj) {
    if (obj.hasClass('validation') || obj.hasClass('EditingFormErrorLabel')) {
        //We'll look for the validation container to remove the status
        var vc = obj.parents('div.validationContainer');
        if (vc.length == 0) {
            //Fall back to div.formInput
            vc = obj.parents('div.formInput');
        }
        vc.removeClass('invalidInput');
    }
}

//Extends the classic ASP.NET validation
function NicerValidatorUpdateDisplay(val) {
    var jQueryval = jQuery(val);
    if (val.isvalid) {
        //Hide the validation control
        jQueryval.hide();

        //Remove the validation status if there are no more validaiton controls visible
        if (jQueryval.parent().find('span.validation:visible,span.EditingFormErrorLabel:visible').length == 0) {
            RemoveValidationStatus(jQueryval);
        }
    }
    else {
        //Show the validation control
        jQueryval.show();

        //Add the validation status
        AddValidationStatus(jQueryval);
    }
}

//Extends classic ASP.NET validation to include parent element styling
function NicerPage_ClientValidate(validationGroup) {
    var valid = AspPage_ClientValidate(validationGroup);
    if (!valid) {
        //jQuery(this).parent().addClass('invalidInput');
    }
    else {
        //jQuery(this).parent().removeClass('invalidInput');
    }
    return valid;
}


function trackGAPageview(pageName) {
    if (typeof (_gaq) != 'undefined') {
        _gaq.push(['_trackPageview', pageName]);
    }
}

function trackGAEvent(category, action, label, value) {
    if (typeof (_gaq) != 'undefined') {
        _gaq.push(['_trackEvent', category, action, label, value]);
    }
}

function getQuerystringParam(key, url) {
    if (url == null) url = window.location.href;
    key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
    var qs = regex.exec(url);
    return qs == null ? '' : qs[1];
}

/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 
* Open source under the BSD License. 
* Copyright © 2008 George McGinley Smith
* All rights reserved.
*/
jQuery.easing['jswing'] = jQuery.easing['swing']; jQuery.extend(jQuery.easing, { def: 'easeOutQuad', swing: function(x, t, b, c, d) { return jQuery.easing[jQuery.easing.def](x, t, b, c, d); }, easeInQuad: function(x, t, b, c, d) { return c * (t /= d) * t + b; }, easeOutQuad: function(x, t, b, c, d) { return -c * (t /= d) * (t - 2) + b; }, easeInOutQuad: function(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b; }, easeInCubic: function(x, t, b, c, d) { return c * (t /= d) * t * t + b; }, easeOutCubic: function(x, t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; }, easeInOutCubic: function(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t + b; return c / 2 * ((t -= 2) * t * t + 2) + b; }, easeInQuart: function(x, t, b, c, d) { return c * (t /= d) * t * t * t + b; }, easeOutQuart: function(x, t, b, c, d) { return -c * ((t = t / d - 1) * t * t * t - 1) + b; }, easeInOutQuart: function(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b; return -c / 2 * ((t -= 2) * t * t * t - 2) + b; }, easeInQuint: function(x, t, b, c, d) { return c * (t /= d) * t * t * t * t + b; }, easeOutQuint: function(x, t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; }, easeInOutQuint: function(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b; return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; }, easeInSine: function(x, t, b, c, d) { return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; }, easeOutSine: function(x, t, b, c, d) { return c * Math.sin(t / d * (Math.PI / 2)) + b; }, easeInOutSine: function(x, t, b, c, d) { return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; }, easeInExpo: function(x, t, b, c, d) { return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; }, easeOutExpo: function(x, t, b, c, d) { return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; }, easeInOutExpo: function(x, t, b, c, d) { if (t == 0) return b; if (t == d) return b + c; if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b; return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; }, easeInCirc: function(x, t, b, c, d) { return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; }, easeOutCirc: function(x, t, b, c, d) { return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; }, easeInOutCirc: function(x, t, b, c, d) { if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; }, easeInElastic: function(x, t, b, c, d) {
    var s = 1.70158; var p = 0; var a = c; if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (a < Math.abs(c)) { a = c; var s = p / 4; }
    else var s = p / (2 * Math.PI) * Math.asin(c / a); return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
}, easeOutElastic: function(x, t, b, c, d) {
    var s = 1.70158; var p = 0; var a = c; if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (a < Math.abs(c)) { a = c; var s = p / 4; }
    else var s = p / (2 * Math.PI) * Math.asin(c / a); return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
}, easeInOutElastic: function(x, t, b, c, d) {
    var s = 1.70158; var p = 0; var a = c; if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5); if (a < Math.abs(c)) { a = c; var s = p / 4; }
    else var s = p / (2 * Math.PI) * Math.asin(c / a); if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
}, easeInBack: function(x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c * (t /= d) * t * ((s + 1) * t - s) + b; }, easeOutBack: function(x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; }, easeInOutBack: function(x, t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; }, easeInBounce: function(x, t, b, c, d) { return c - jQuery.easing.easeOutBounce(x, d - t, 0, c, d) + b; }, easeOutBounce: function(x, t, b, c, d) { if ((t /= d) < (1 / 2.75)) { return c * (7.5625 * t * t) + b; } else if (t < (2 / 2.75)) { return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b; } else if (t < (2.5 / 2.75)) { return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b; } else { return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b; } }, easeInOutBounce: function(x, t, b, c, d) { if (t < d / 2) return jQuery.easing.easeInBounce(x, t * 2, 0, c, d) * .5 + b; return jQuery.easing.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b; } 
});

/*
* Javascript Object Oriented Timer, version 1.0 - http://abcoder.com/javascript/core_javascript/javascript_timer
* Copyright (C) 2008 zp bappi | zpbappi (at) gmail (dot) com
* This script is distributed under the GNU Lesser General Public License (Version 3, 29 June 2007 or later).
*/
var Timer = function(millis, callback) { return this._init(millis, callback); }
Timer.prototype = { VERSION: 1.0, _init: function(millis, callback) { this._interval = 1000; this._timer = null; this._cbs = []; this._multipliers = []; this._tickCounts = []; this._canRun = []; this._stoppedThreads = 0; this._runOnce = false; this._startedAt = -1; this._pausedAt = -1; if (typeof (millis) == 'number') this._interval = millis; this.addCallback(callback); return this; }, _preset: function() { this._stoppedThreads = 0; this._startedAt = -1; this._pausedAt = -1; for (var i = 0; i < this._cbs.length; i++) { this._canRun[i] = true; this._tickCounts[i] = 0; } }, _ticks: function(initInterval) {
    var me = this; for (var i = 0; i < this._cbs.length; i++) {
        if (typeof (this._cbs[i]) == 'function' && this._canRun[i]) {
            this._tickCounts[i]++; if (this._tickCounts[i] == this._multipliers[i]) {
                this._tickCounts[i] = 0; if (this.runOnce()) { this._canRun[i] = false; this._stoppedThreads++; }
                window.setTimeout(me._cbs[i], 0);
            } 
        } 
    }
    if (this.runOnce() && this._stoppedThreads == this._cbs.length)
        this.stop(); if (typeof (initInterval) == 'number') { this.stop().start(null, true); } 
}, runOnce: function(isRunOnce) { if (typeof (isRunOnce) == 'undefined') return this._runOnce; else if (typeof (isRunOnce) == 'boolean') this._runOnce = isRunOnce; else alert("Invalid argument for runOnce(...).\n\nUsage: runOnce(true | false) /*Default value: false*/\nor, runOnce() to get status"); return this; }, interval: function(millis) { if (typeof (millis) == 'undefined') return this._interval; else if (typeof (millis) == 'number') this._interval = Math.floor(millis); return this; }, stop: function(isPausing) {
    if (this._timer) {
        if (!isPausing) this._pausedAt = -1; try { window.clearInterval(this._timer); }
        catch (ex) { }
        this._timer = null;
    }
    return this;
}, isStopped: function() { return ((this._timer == null) && !this.isPaused()); }, start: function(_initialInterval, _withoutPreset) {
    if (this.isPaused())
        return this.resume(); if (!this.isStopped())
        return this; if (!_withoutPreset)
        this._preset(); var tmpInterval = this._interval; if (typeof (_initialInterval) == 'number') tmpInterval = _initialInterval; var me = this; this._timer = window.setInterval(function() { me._ticks(_initialInterval); }, tmpInterval); this._startedAt = (new Date()).getTime(); this._startedAt -= (this._interval - tmpInterval); return this;
}, pause: function() {
    if (this._timer) { this._pausedAt = (new Date()).getTime(); this.stop(true); }
    return this;
}, isPaused: function() { return (this._pausedAt >= 0); }, resume: function() {
    if (this.isPaused()) { var tempInterval = this._interval - ((this._pausedAt - this._startedAt) % this._interval); this._pausedAt = -1; this.start(tempInterval, true); }
    return this;
}, restart: function() { return this.stop().start(); }, addCallback: function(callback, N) {
    if (typeof (callback) == 'function') {
        this._cbs.push(callback); if (typeof (N) == 'number') {
            N = Math.floor(N)
            this._multipliers.push((N < 1 ? 1 : N));
        }
        else
            this._multipliers.push(1); this._tickCounts.push(0); this._canRun.push(true);
    }
    return this;
}, clearCallbacks: function() { this._cbs.length = 0; this._multipliers.length = 0; this._canRun.length = 0; this._tickCounts.length = 0; this._stoppedThreads = 0; return this; } 
};

//See http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
jQuery.extend(jQuery.expr[':'], {
    inView: function(el) {
        var top = el.offsetTop;
        var left = el.offsetLeft;
        var width = el.offsetWidth;
        var height = el.offsetHeight;

        while (el.offsetParent) {
            el = el.offsetParent;
            top += el.offsetTop;
            left += el.offsetLeft;
        }

        return (
            top < (window.pageYOffset + window.innerHeight) &&
            left < (window.pageXOffset + window.innerWidth) &&
            (top + height) > window.pageYOffset &&
            (left + width) > window.pageXOffset
        );
    }
});

//ExternalLinks - tracking based on http://www.iqcontent.com/blog/2007/02/tracking-documents-and-external-links-in-google-analytics/
(function(jQuery) {
    jQuery.fn.extend({
        ExternalLinks: function() {
            return this.each(function() {
                if (this.tagName != 'A') {
                    return false;
                }

                var link = String(this);
                var linkHost = this.hostname;
                var siteHost = location.host;

                if (link.match(/^mailto:/i)) {
                    jQuery(this).click(function() {
                        return HandleMailToLink(this);
                    });
                }
                else if (linkHost == siteHost) {
                    var parts = link.split('?');
                    var path = parts[0];
                    if (path.match(/\.(doc|pdf|xls|ppt|zip|txt|vsd|vxd|js|css|rar|exe|wma|mov|avi|wmv|mp3|ashx)jQuery/)) {
                        ModifyTitleAttribute(this);
                        jQuery(this).click(function() {
                            return HandleDocumentLink(this);
                        });
                    }
                    else {
                        jQuery(this).click(function() {
                            return HandleInternalLink(this);
                        });
                    }
                }
                else {
                    ModifyTitleAttribute(this);
                    jQuery(this).click(function() {
                        return HandleExternalLink(this);
                    });
                }
            });

            function HandleMailToLink(anchor) {
                var email = anchor.href.substring(7);
                TrackLink('email', email);

                return true;
            }

            function HandleDocumentLink(anchor) {
                var doc = CleanURL(anchor.pathname, false);
                TrackLink('resources', doc);

                window.open(anchor.href);
                return false;
            }

            function HandleInternalLink(anchor) {
                window.open(anchor.href);
                return false;
            }

            function HandleExternalLink(anchor) {
                var pathname = (anchor.pathname.substr(0, 1) != '/'
					? anchor.pathname + '/'
					: anchor.pathname);

                var link = CleanURL(anchor.hostname + pathname, true);
                TrackLink('external', link);

                window.open(anchor.href);
                return false;
            }

            function TrackLink(type, virtualPath) {
                if (typeof (pageTracker) != 'undefined') {
                    var linkStr = CleanURL('/' + type + '/' + virtualPath, true);
                    pageTracker._trackPageview(linkStr);
                }
            }

            function CleanURL(url, end) {
                var url = url.toString();
                var urlLen = url.length;

                if (end) {
                    if (url.charAt((urlLen - 1)) == '/') {
                        url = url.substring(0, (urlLen - 1));
                    }
                }
                else {
                    if (url.charAt(0) == '/') {
                        url = url.substring(1, urlLen);
                    }
                }
                return url;
            }

            function ModifyTitleAttribute(anchor) {
                var jAnchor = jQuery(anchor);
                var title = jQuery(anchor).attr('title');
                if (title.length > 0) {
                    title += ' [opens in a new window]';
                }
                else {
                    title += 'Opens in a new window';
                }
                jAnchor.attr('title', title);
            }
        }
    });
})(jQuery);


