﻿(function ($) {
    $.setValue = function (id, value) {
        var ele = $(id);
        var options = $(id + ' option');
        var size = options.size();

        // Remove the current selected option
        var selected = $(id + ' option[selected="selected"]');
        if (selected) selected.removeAttr('selected');

        for (var i = 0; i < size; i++) {
            var option = options.eq(i);

            if (option.html() == value) {
                option.attr('selected', 'selected');
                break;
            }
        }
    };

})(jQuery);

function redirect(href) { window.location = href; }

jQuery.fn.isValidEmail = function () {
    var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;

    return reg.test(this.val());
};

jQuery.fn.getHref = function () { return this.attr('href'); }
jQuery.fn.getId = function () { return this.attr('id'); }

jQuery.fn.isChecked = function () {
    return this.attr('checked') == true;
};

jQuery.fn.addEmailValidator = function () {
    this.parent().append("<div class=\"email-validator\" title=\"E-mails should be in the form name@address.com and may contain underscores (_), dashes (-) and periods (.)\"></div>");
    jQuery('.email-validator', this.parent()).tooltip({ effect: 'fade' });

    this.keyup(function () {    
        if (jQuery(this).isValidEmail()) jQuery('.email-validator', jQuery(this).parent()).removeClass("invalid").addClass("valid");
        else jQuery('.email-validator', jQuery(this).parent()).removeClass("valid").addClass("invalid");
    });
};

function randomize(min, max) {
    return Math.floor(Math.random() * (max + 1 - min)) + min;
}

/*
Used for setting persistent data values through jQuery
*/
jQuery.fn.setDataValue = function (key, value) {
    //jQuery.data(jQuery(this)[0], key, value);
    this.data(key, value);
}

/*
Used for getting persistent data values through jQuery
*/
jQuery.fn.getDataValue = function (key) {
    //return jQuery.data(jQuery(this)[0], key);
    return this.data(key);
}

jQuery.fn.centerList = function () {
    var offset = 1;
    if ($.browser.webkit) offset = 25;
    jQuery(this).each(function () {

        jQuery(this).css('display', 'table').css('width', $(this).width() + offset).css('margin-left', 'auto').css('margin-right', 'auto');
    });
}

/*
* ###########################################################################
* Name: Reveal
* Description: Oranizes a group of elements into a slideUp/slideDown reveal
* type of grouping where links will toggle their siblings.
* ###########################################################################
*/
jQuery.fn.reveal = function () {
    $(this).toggle(
        function (event) {
            event.preventDefault();
            $(this).html('&laquo; Hide');

            $('.reveal', $(this).parentsUntil('div').parent()).slideDown();
        },
        function (event) {
            event.preventDefault();
            $(this).html('Show More &raquo;');

            $('.reveal', $(this).parentsUntil('div').parent()).slideUp();
        }
    );

    $(this).each(function () {
            $('.reveal', $(this).parentsUntil('div').parent()).slideUp();
    });
}

/*
* ###########################################################################
* Name: SlideList
* Description: Groups a set of elements by applying slide out functionality
* to the constituent panels.
* ###########################################################################
*/
jQuery.fn.slideList = function (options) {
    var controller = new slideListController(this, options);

    this.setDataValue('slide-controller', controller);

    controller.initialize();
}

function slideListController(element, options) {
    this.target = element;
    this.options = options;
    this.container = '.slide';
    this.panel = 'p';
    this.header = 'h4';
    this.slideTime = 250;
}

slideListController.prototype.initialize = function () {
    if (this.options != undefined && this.options != null) {
        if (this.options.container != undefined) this.container = this.options.container;
        if (this.options.header != undefined) this.header = this.options.header;
        if (this.options.panel != undefined) this.panel = this.options.panel;
        if (this.options.slideTime != undefined) this.slideTime = this.options.slideTime;
    }

    var scope = this;
    jQuery(this.container, jQuery(this.target)).each(function () {
        var containerElement = this;
        jQuery(scope.panel, this).hide();
        jQuery(scope.header, this).click(function () { scope.switchTo(containerElement); });
    });
};

slideListController.prototype.switchTo = function (containerElement) {
    jQuery(this.container + '.Selected ' + this.panel, this.target).slideUp(this.slideTime)
    jQuery(this.container + '.Selected', this.target).removeClass('Selected');

    jQuery(containerElement).addClass('Selected');
    jQuery(this.panel, containerElement).slideDown(this.slideTime);
};

/*
* ###########################################################################
* Name: TabGroup
* Description: Groups a set of elements by applying tab functionality
* ###########################################################################
*/
jQuery.fn.tabGroup = function (options) {
    var controller = new tabGroupController(this, options);

    this.setDataValue('tab-controller', controller);

    controller.initialize();
}

function tabGroupController(element, options) {
    this.target = element;
    this.options = options;
    this.container = '.tab';
    this.header = 'h4'
    this.callback = null;
}

tabGroupController.prototype.initialize = function () {
    if (this.options != undefined && this.options != null) {
        if (this.options.container != undefined) this.container = this.options.container;
        if (this.options.header != undefined) this.header = this.options.header;
        if (this.options.callback != undefined) this.callback = this.options.callback;
    }

    var html = '<ul class="tab-controls">';
    var scope = this;
    jQuery(this.container, this.target).each(function () {
        var h = jQuery(scope.header, jQuery(this));

        if (h != undefined) {
            html += '<li><a href="#">' + h.html() + '</a></li>';
        }

        if (jQuery(this).index() > 0) jQuery(this).hide();
    });

    html += '</ul>';

    jQuery(this.target).prepend(html);

    jQuery('ul.tab-controls a', this.target).click(function (event) { scope.onClick(event, this); });

    this.switchTo(jQuery(this.container, this.target).first());
};

tabGroupController.prototype.onClick = function (event, anchor) {
    event.preventDefault();

    var searchString = jQuery(anchor).html();

    var scope = this;
    jQuery(this.container, this.target).each(function () {
        var current = jQuery(scope.header, jQuery(this)).first();
        if (current.html() == searchString) {
            scope.switchTo(this);
        }
    });
};

tabGroupController.prototype.switchTo = function (tabElement) {
    var scope = this;

    jQuery(this.container + '.Selected', this.target).removeClass('Selected').hide();
    jQuery('ul.tab-controls li.Selected', this.target).removeClass('Selected');

    var _tab = jQuery(tabElement);
    _tab.show().addClass('Selected');

    jQuery('ul.tab-controls li', this.target).each(function () {
        if (jQuery('a', jQuery(this)).html() == jQuery(scope.header, tabElement).html()) {
            jQuery(this).addClass('Selected');
        }
    });

    if (scope.callback != null) {
        scope.callback(jQuery(scope.header, _tab).html());
    }
};

/*
 * ###########################################################################
 * Name: Fader
 * Description: Provides basic fading functionality for a list of elements.
 * ###########################################################################
 */
jQuery.fn.fader = function (options) {
    // Get the existing controller
    var controller = this.getDataValue(this, 'controller');

    // stop existing controller
    if (controller != undefined) controller.stop();

    // Create the new controller
    controller = new faderController(this, options);

    // Add the value to persistent storage
    this.setDataValue('controller', controller);

    // Gentleman, START YOUR ENGINES!!!!
    controller.start();

    return controller;
}

function faderController(element, options) {
    this.target = element;
    this.options = options;
    this.timeout = 8000;
    this.fadeTime = 800;
    this.fadeDelay = 600;
    this.timer = null;
    this.current = 0;
    this.addControls = true;
    this.callback = null;

    /* Fields used managing controls clicks out of sync */
    this.queuedIndex = null;
}

faderController.prototype.pause = function () {
    // Kill the existing timer to make sure it doesn't
    // continue on.
    clearTimeout(this.timer);
    this.timer = null;
};

faderController.prototype.start = function () {
    // Load up options if we can
    if (this.options != undefined) {
        if (this.options.timeout != undefined) this.timeout = this.options.timeout;
        if (this.options.fadeTime != undefined) this.fadeTime = this.options.fadeTime;
        if (this.options.fadeDelay != undefined) this.fadeDelay = this.options.fadeDelay;
        if (this.options.addControls != undefined) this.addControls = this.options.addControls;
        if (this.options.callback != undefined) this.callback = this.options.callback;
    }

    // The way this works is by setting a timeout for when the next fade
    // should occur. At the end of the next fade, we will recreate
    // the timeout. This keeps things consistent.
    var scope = this;
    this.timer = setTimeout(function () { scope.update(); }, this.timeout);

    // Hide all elements except for the first
    jQuery('ul.fader > li', this.target).each(function () {
        if (jQuery(this).index() > 0) jQuery(this).hide(0);
    });

    if (this.addControls) {
        var controlsHtml = '<ul class="fader-controls">';

        jQuery('ul.fader > li', this.target).each(function () {
            controlsHtml += '<li><a href="#">' + (jQuery(this).index() + 1).toString() + '</a></li>';
        });

        controlsHtml += '</ul>';

        jQuery(this.target).append(controlsHtml);
    }

    jQuery('.fader-controls li:eq(0)').addClass('Selected');
    jQuery('.fader-controls li a').click(function (event) {
        event.preventDefault();
        scope.selectPanel(jQuery(this).parent().index());
    });
};

faderController.prototype.update = function () {
    // Kill the existing timer to make sure it doesn't
    // continue on.
    clearTimeout(this.timer);
    this.timer = null;

    // Fade out the existing element
    jQuery('ul.fader > li:eq(' + this.current + ')', this.target).fadeOut(this.fadeTime);
    jQuery('.fader-controls li.Selected', this.target).removeClass('Selected');

    // Update the index!
    this.current = this.current + 1;

    // Verify that we haven't gone out of bounds and reset if we have.
    var liCount = jQuery('ul.fader > li', this.target).size();
    if (this.current == liCount) this.current = 0;

    // Setup the fade and recreation of the timeout
    var scope = this;
    jQuery('ul.fader > li:eq(' + this.current + ')', this.target)
        .delay(this.fadeDelay)
        .fadeIn(this.fadeTime, function () { scope.updateDone(); });
    jQuery('.fader-controls li:eq(' + this.current + ')', this.target).addClass('Selected');

    // Try to use the callback to notify people
    if (this.callback != null) this.callback(this.current);
};

faderController.prototype.selectPanel = function (panelIndex) {
    if (this.timer == null) {
        this.queuedIndex = panelIndex;
        return;
    }

    this.selectPanelInternal(panelIndex);
};

faderController.prototype.selectPanelInternal = function (panelIndex) {
    // Kill the existing timer to make sure it doesn't
    // continue on.
    clearTimeout(this.timer);
    this.timer = null;

    // Fade out the existing element
    jQuery('ul.fader > li:eq(' + this.current + ')', this.target).fadeOut(this.fadeTime);
    jQuery('.fader-controls li.Selected', this.target).removeClass('Selected');

    // Update the index!
    this.current = panelIndex;

    // Verify that we haven't gone out of bounds and reset if we have.
    var liCount = jQuery('ul.fader > li', this.target).size();
    if (this.current == liCount) this.current = 0;

    // Setup the fade and recreation of the timeout
    var scope = this;
    jQuery('ul.fader > li:eq(' + this.current + ')', this.target)
        .delay(this.fadeDelay)
        .fadeIn(this.fadeTime, function () { scope.updateDone(); });
    jQuery('.fader-controls li:eq(' + this.current + ')', this.target).addClass('Selected');
}

faderController.prototype.updateDone = function () {
    if (this.queuedIndex != null && this.queuedIndex != undefined) {
        this.selectPanelInternal(this.queuedIndex);
        this.queuedIndex = null;
        return;
    }

    var scope = this;

    // Recreate the timeout!
    this.timer = setTimeout(function () { scope.update(); }, this.timeout);
}

faderController.prototype.stop = function () {
    clearTimeout(this.timer);
    this.timer = null;
};

/*
 * ###########################################################################
 * Name: submitTestimonial
 * Description: Submits a testimonial for a site
 * ###########################################################################
 */
jQuery.fn.submitTestimonial = function (itemLink) {
    var data = {
        'firstName': jQuery('#FirstNameBox', jQuery(this)).val(),
        'lastName': jQuery('#LastNameBox', jQuery(this)).val(),
        'email': jQuery('#EmailBox', jQuery(this)).val(),
        'address': jQuery('#AddressBox', jQuery(this)).val(),
        'city': jQuery('#CityBox', jQuery(this)).val(),
        'state': jQuery('#StateBox', jQuery(this)).val(),
        'zip': jQuery('#ZipCodeBox', jQuery(this)).val(),
        'comments': jQuery('#CommentsBox', jQuery(this)).val(),
        'canContact': jQuery('#CanContact', jQuery(this)).isChecked().toString(),
        'actionMethod': 'widget'
    };

    jQuery.ajax({
        url: itemLink,
        data: data,
        dataType: 'json',
        complete: function (jqXHR, textStatus) {
            if (textStatus != 'success') {
                window.location = itemLink + '?m=e&code=0xF';
            }
        },
        success: function (data, textStatus, jqXHR) {
            if (data != undefined && data != null) {
                if (data.result == 'success') window.location = itemLink + "?m=s";
                else {
                    window.location = itemLink + '?m=e&code=' + data.code;
                }
            }
        }
    });
}

function getRequestVars() {
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for (var i = 0; i < hashes.length; i++) {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}
