﻿/*
* 2Toad jQuery Library
* Copyright (C)2009 2Toad, LLC.
* licensing@2toad.com
* 
* http://2toad.com/licensing
*/

/*-------------------------------------------------------
AJAX
-------------------------------------------------------*/

// JSONP Ajax call
// See toadAjax() method comments for general parameters
// Required Parameters: 
//      callback: the name of the jsonp callback method.
jQuery.jsonpAjax = function(p) {
    // Add parameters
    $.extend(p, {
        type: "GET",
        dataType: 'json'
    });

    // Format URL with JSONP Callback
    p.url = p.url + '?' + p.callback + '=?';

    // Ajax call
    return jQuery.toadAjax(p);
};

// Ajax call to .NET Page Method
// See toadAjax() method comments for general parameters
jQuery.pageAjax = function(p) {
    // Add parameters
    $.extend(p, {
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: 'json'
    });

    // Format data
    if (typeof p.data == 'undefined') {
        // Add data parameter with empty JSON object as value
        $.extend(p, { data: '{}' });
    } else if (typeof p.data == 'object') {
        // Convert JSON object into string
        p.data = JSON.stringify(p.data);
    }

    // Hook Success event
    if (typeof p.success == 'function') {
        var success = p.success;
        p.success = function(response) { success(response.d); };
    }

    // Ajax call
    return jQuery.toadAjax(p);
};

// Ajax call
// Required Parameters: 
//      type: the type of request to make.
//      dataType: the type of data that you're expecting back from the server. 
//      url: the url to request.
// Optional Parameters:
//      contentType: sets the content-type for sending data to the server.
//      data: the data to send to the server.
//      before(): called immediately, before anything else occurs.
//      loading(): called before the ajax call, after waiting the number of milliseconds specified in loadingDelay.
//      loadingDelay: the number of milliseconds to delay calling the loading() method (default: 500).
//      success(): a method to call when the ajax call is successful.
//      error(): a method to call when an ajax error occurs.
//      complete(): a method to call when the ajax call completes.
//      timeout: the number of milliseconds to wait for an ajax call to succeed before aborting and raising an error (default: 5000).
jQuery.toadAjax = function(p) {
    // Declare vars
    var delayTimer;

    // Call Before() function
    if (typeof p.before == 'function') { p.before(); }

    // Loading() function?
    if (typeof p.loading == 'function') {
        // Set delay
        delayTimer = setTimeout(
			p.loading,
			(typeof p.loadingDelay == 'number') ? p.loadingDelay : 500,
            'JavaScript'
		);
    }

    // Set timeout
    var timeout = setTimeout(
		function() {
		    // Abort XMLHttpRequest
		    if (xhr) { xhr.abort(); }

		    // Call functions
		    if (typeof p.error == 'function') { p.error(xhr, 'timeout'); }
		    if (typeof p.complete == 'function') { p.complete(xhr, 'timeout'); }
		},
		(typeof p.timeout == 'number') ? p.timeout : 5000,
        'JavaScript'
	);

    // Call Ajax
    var xhr = jQuery.ajax({
        type: p.type,
        contentType: p.contentType || undefined,
        dataType: p.dataType,
        url: p.url,
        data: p.data || undefined,
        success: function(response, status) {
            // Clear timers
            clearTimers();
            // Call function
            if (typeof p.success == 'function') { p.success(response, status); }
        },
        error: function(xhr, status, error) {
            // Clear timers
            clearTimers();
            // Call function
            if (typeof p.error == 'function') { p.error(xhr, status, error); }
        },
        complete: function(xhr, status) {
            // Clear timers
            clearTimers();
            // Call function
            if (typeof p.complete == 'function') { p.complete(xhr, status); }
        }
    });

    // Timer clearer
    function clearTimers() {
        if (delayTimer) { clearTimeout(delayTimer); }
        if (timeout) { clearTimeout(timeout); }
    }

    // Return XMLHttpRequest
    return xhr;
};

/*-------------------------------------------------------
.NET HELPERS
-------------------------------------------------------*/

// Finds elements by ID, even if they've been altered by ASP.NET ID mangling
jQuery.dotNetID = function(id) {
    return jQuery("[id$='" + id + "']");
};

/*-------------------------------------------------------
VALIDATION
-------------------------------------------------------*/

jQuery.validate = {
    min: function(element, minValue) {
        return element.value >= minValue;
    },
    max: function(element, maxValue) {
        return element.value <= maxValue;
    },
    range: function(element, minValue, maxValue) {
        return (this.min(element, minValue) && this.max(element, maxValue));
    },
    date: function(element) {
        return !(/Invalid|NaN/).test(new Date(element.value));
    },
    ssn: function(element) {
        return (/^([0-6]\d{2}|7[0-6]\d|77[0-2])([ \-]?)(\d{2})\2(\d{4})$/).test(element.value);
    },
    email: function(element) {
        return (/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i).test(element.value);
    },
    phoneNumber: function(element) {
        return ((/\d{10,}/i).test(element.value.replace(/[\s()+-]|x|ext\.?/gi, '')));
    },
    zipCode: function(element) {
        return (/(^\d{5}$)|(^\d{5}-\d{4}$)/).test(element.value);
    }
};

/*-------------------------------------------------------
CONVERTERS
-------------------------------------------------------*/

jQuery.yesNoToBool = function(value) {
    if (value.toLowerCase() == 'yes') { return 'True'; }
    if (value.toLowerCase() == 'no') { return 'False'; }
    return value;
};

jQuery.boolToYesNo = function(value) {
    if (value.toLowerCase() == 'true') { return 'Yes'; }
    if (value.toLowerCase() == 'false') { return 'No'; }
    return value;
};

jQuery.boolToBit = function(value) {
    if (value.toLowerCase() == 'true') { return '1'; }
    if (value.toLowerCase() == 'false') { return '0'; }
    return value;
};

jQuery.boolToBit = function(value) {
    if (value.toLowerCase() == 'true') { return '1'; }
    if (value.toLowerCase() == 'false') { return '0'; }
    return value;
};

jQuery.trinaryToYesNo = function(value) {
    if (value === -1) { return 'Yes'; }
    if (value === 0) { return 'No'; }
    return '';
};

/*-------------------------------------------------------
URL
-------------------------------------------------------*/

// Extracts the specified param from the current URL
jQuery.getUrlParam = function(param) {
    var regex = '[?&]' + param + '=([^&#]*)';
    var results = (new RegExp(regex)).exec(window.location.href);
    if (results) { return results[1]; }
    return '';
};

/*-------------------------------------------------------
FORMATTERS
-------------------------------------------------------*/

jQuery.format = {
    // Formats the specified value as U.S. Currency.
    currency: function(value) {
        value = value.toString().replace(/\$|\,/g, '');
        if (isNaN(value)) { value = '0'; }
        sign = (value == (value = Math.abs(value)));
        value = Math.floor(value * 100 + 0.50000000001);
        cents = value % 100;
        value = Math.floor(value / 100).toString();
        if (cents < 10) { cents = '0' + cents; }
        for (var i = 0; i < Math.floor((value.length - (1 + i)) / 3); i++) {
            value = value.substring(0, value.length - (4 * i + 3)) + ',' + value.substring(value.length - (4 * i + 3));
        }
        return ((sign ? '' : '-') + '$' + value + '.' + cents);
    }
};