﻿/*
* Application specific JS
* 
* Requires JQuery.
* Additional Libraries below.  
*/

/*
* These scripts are called for every page.  They are mostly browser bug fixes, etc.
* Revised: 2008/11/23
*/

// to handel IE 6 background image flickering.  From: http://www.zachleat.com/web/2008/10/18/dear-ie6-please-cache-my-images/
if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) == 6)
{
    try
    {
        document.execCommand("BackgroundImageCache", false, true);
    } catch (err) { }
}


/*
* Sweet Library Functions
* Revised: 2008/11/23
*/

var SWEET = function()
{
    var _tmplCache = {}

    return {
        insertAltRowClasses: function(selector)
        {
            $(selector + "even").addClass("even");
            $(selector + "odd").addClass("odd");
        },

        setEventValidatorEnable: function(cntrlId, isEnabled)
        {
            ValidatorEnable($("#" + cntrlId)[0], isEnabled);
            $("#" + cntrlId).css("display", "none");
        },

        displayRequired: function()
        {
            $('.required').prepend('<span class="required">*</span>');
        },

        parseTemplate: function(str, data)
        {
            /// <summary>
            /// Client side template parser that uses &lt;#= #&gt; and &lt;# code #&gt; expressions.
            /// and # # code blocks for template expansion.
            /// NOTE: chokes on single quotes in the document in some situations
            ///       use &amp;rsquo; for literals in text and avoid any single quote
            ///       attribute delimiters.
            /// </summary>    
            /// <param name="str" type="string">The text of the template to expand</param>    
            /// <param name="data" type="var">
            /// Any data that is to be merged. Pass an object and
            /// that object's properties are visible as variables.
            /// </param>    
            /// <returns type="string" />  
            var err = "";
            try
            {
                var func = _tmplCache[str];
                if (!func)
                {
                    var strFunc =
                    "var p=[],print=function(){p.push.apply(p,arguments);};" +
                                "with(obj){p.push('" +
                    //                        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('');";

                    str.replace(/[\r\t\n]/g, " ")
                       .replace(/'(?=[^#]*#>)/g, "\t")
                       .split("'").join("\\'")
                       .split("\t").join("'")
                       .replace(/<#=(.+?)#>/g, "',$1,'")
                       .split("<#").join("');")
                       .split("#>").join("p.push('")
                       + "');}return p.join('');";

                    //alert(strFunc);
                    func = new Function("obj", strFunc);
                    _tmplCache[str] = func;
                }
                return func(data);
            } catch (e) { err = e.message; }
            return "< # ERROR: " + err + " # >";
        },

        limitChars: function(textid, limit, infodiv)
        {
            var text = $('#' + textid).val();
            var textlength = text.length;
            if (textlength > limit)
            {
                $('#' + infodiv).html('You cannot write more then ' + limit + ' characters!');
                $('#' + textid).val(text.substr(0, limit));
                return false;
            }
            else
            {
                $('#' + infodiv).html('You have ' + (limit - textlength) + ' characters left.');
                return true;
            }
        },

        stripHTML: function(oldString) 
        {
            return oldString.replace(/<&#91;^>&#93;*>/g, "");
        }
    }
} ();


/*
* Autotab - jQuery plugin 1.0
* http://dev.lousyllama.com/auto-tab
* 
* Copyright (c) 2008 Matthew Miller
* 
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
* 
* Revised: 2008/05/22 01:23:25
*/

(function($) {

    $.fn.autotab = function(options) {
        var defaults = {
            format: 'all', 		// text, numeric, alphanumeric, all
            maxlength: 2147483647, // Defaults to maxlength value
            uppercase: false, 	// Converts a string to UPPERCASE
            lowercase: false, 	// Converts a string to lowecase
            nospace: false, 	// Remove spaces in the user input
            target: null, 		// Where to auto tab to
            previous: null			// Backwards auto tab when all data is backspaced
        };

        $.extend(defaults, options);

        var check_element = function(name) {
            var val = null;
            var check_id = $('#' + name)[0];
            var check_name = $('input[name=' + name + ']')[0];

            if (check_id != undefined)
                val = $(check_id);
            else if (check_name != undefined)
                val = $(check_name);

            return val;
        };

        var key = function(e) {
            if (!e)
                e = window.event;

            return e.keyCode;
        };

        // Sets targets to element based on the name or ID passed
        if (typeof defaults.target == 'string')
            defaults.target = check_element(defaults.target);

        if (typeof defaults.previous == 'string')
            defaults.previous = check_element(defaults.previous);

        var maxlength = $(this).attr('maxlength');

        // Each text field has a maximum character limit of 2147483647

        // defaults.maxlength has not changed and maxlength was specified
        if (defaults.maxlength == 2147483647 && maxlength != 2147483647)
            defaults.maxlength = maxlength;
        // defaults.maxlength overrides maxlength
        else if (defaults.maxlength > 0)
            $(this).attr('maxlength', defaults.maxlength)
        // defaults.maxlength and maxlength have not been specified
        // A target cannot be used since there is no defined maxlength
        else
            defaults.target = null;

        // IE does not recognize the backspace key
        // with keypress in a blank input box
        if ($.browser.msie) {
            this.keydown(function(e) {
                if (key(e) == 8) {
                    var val = this.value;

                    if (val.length == 0 && defaults.previous)
                        defaults.previous.focus();
                }
            });
        }

        return this.keypress(function(e) {
            if (key(e) == 8) {
                var val = this.value;

                if (val.length == 0 && defaults.previous)
                    defaults.previous.focus();
            }
        }).keyup(function(e) {
            var val = this.value;

            switch (defaults.format) {
                case 'text':
                    var pattern = new RegExp('[0-9]+', 'g');
                    var val = val.replace(pattern, '');
                    break;

                case 'alpha':
                    var pattern = new RegExp('[^a-zA-Z]+', 'g');
                    var val = val.replace(pattern, '');
                    break;

                case 'number':
                case 'numeric':
                    var pattern = new RegExp('[^0-9]+', 'g');
                    var val = val.replace(pattern, '');
                    break;

                case 'alphanumeric':
                    var pattern = new RegExp('[^0-9a-zA-Z]+', 'g');
                    var val = val.replace(pattern, '');
                    break;

                case 'all':
                default:
                    break;
            }

            if (defaults.nospace) {
                pattern = new RegExp('[ ]+', 'g');
                val = val.replace(pattern, '');
            }

            if (defaults.uppercase)
                val = val.toUpperCase();

            if (defaults.lowercase)
                val = val.toLowerCase();

            this.value = val;

            /**
            * Do not auto tab when the following keys are pressed
            * 8:	Backspace
            * 9:	Tab
            * 16:	Shift
            * 17:	Ctrl
            * 18:	Alt
            * 19:	Pause Break
            * 20:	Caps Lock
            * 27:	Esc
            * 33:	Page Up
            * 34:	Page Down
            * 35:	End
            * 36:	Home
            * 37:	Left Arrow
            * 38:	Up Arrow
            * 39:	Right Arrow
            * 40:	Down Arroww
            * 45:	Insert
            * 46:	Delete
            * 144:	Num Lock
            * 145:	Scroll Lock
            */
            var keys = [8, 9, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 144, 145];
            var string = keys.toString();

            if (string.indexOf(key(e)) == -1 && val.length == defaults.maxlength && defaults.target)
                defaults.target.focus();
        });
    };

})(jQuery);

/*
* JavaScript Pretty Date
* Copyright (c) 2008 John Resig (jquery.com)
* Licensed under the MIT license.
*/

// Takes an ISO time and returns a string representing how
// long ago the date represents.
function prettyDate(time)
{
    var date = new Date((time || "").replace(/-/g, "/").replace(/[TZ]/g, " ")),
		diff = (((new Date()).getTime() - date.getTime()) / 1000),
		day_diff = Math.floor(diff / 86400);

    if (isNaN(day_diff) || day_diff < 0)
        return;
    if (day_diff >= 31)
    {
        var hours = date.getHours();
        var amPm = "AM";
        if (hours > 12)
        {
            hours -= 12;
            amPm = "PM";
        }
        return date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear() + ' ' + hours + ":" + date.getMinutes() + ' ' + amPm;
    }   
    return day_diff == 0 && (
			diff < 60 && "just now" ||
			diff < 120 && "1 minute ago" ||
			diff < 3600 && Math.floor(diff / 60) + " minutes ago" ||
			diff < 7200 && "1 hour ago" ||
			diff < 86400 && Math.floor(diff / 3600) + " hours ago") ||
		day_diff == 1 && "Yesterday" ||
		day_diff < 7 && day_diff + " days ago" ||
		day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago";
}

// If jQuery is included in the page, adds a jQuery plugin to handle it as well
if (typeof jQuery != "undefined")
jQuery.fn.prettyDate = function()
{
    return this.each(function()
    {
        var date = prettyDate(this.title);
        if (date)
            jQuery(this).text(date);
    });
};


/*
* jQuery Tooltip plugin 1.3
*
* http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
* http://docs.jquery.com/Plugins/Tooltip
*
* Copyright (c) 2006 - 2008 Jörn Zaefferer
*
* $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
* 
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*/

; (function($) {

    // the tooltip element
    var helper = {},
    // the current tooltipped element
		current,
    // the title of the current element, used for restoring
		title,
    // timeout id for delayed tooltips
		tID,
    // IE 5.5 or 6
		IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
    // flag for mouse tracking
		track = false;

    $.tooltip = {
        blocked: false,
        defaults: {
            delay: 200,
            fade: false,
            showURL: true,
            extraClass: "",
            top: 15,
            left: 15,
            id: "tooltip"
        },
        block: function() {
            $.tooltip.blocked = !$.tooltip.blocked;
        }
    };

    $.fn.extend({
        tooltip: function(settings) {
            settings = $.extend({}, $.tooltip.defaults, settings);
            createHelper(settings);
            return this.each(function() {
                $.data(this, "tooltip", settings);
                this.tOpacity = helper.parent.css("opacity");
                // copy tooltip into its own expando and remove the title
                this.tooltipText = this.title;
                $(this).removeAttr("title");
                // also remove alt attribute to prevent default tooltip in IE
                this.alt = "";
            })
				.mouseover(save)
				.mouseout(hide)
				.click(hide);
        },
        fixPNG: IE ? function() {
            return this.each(function() {
                var image = $(this).css('backgroundImage');
                if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
                    image = RegExp.$1;
                    $(this).css({
                        'backgroundImage': 'none',
                        'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
                    }).each(function() {
                        var position = $(this).css('position');
                        if (position != 'absolute' && position != 'relative')
                            $(this).css('position', 'relative');
                    });
                }
            });
        } : function() { return this; },
        unfixPNG: IE ? function() {
            return this.each(function() {
                $(this).css({ 'filter': '', backgroundImage: '' });
            });
        } : function() { return this; },
        hideWhenEmpty: function() {
            return this.each(function() {
                $(this)[$(this).html() ? "show" : "hide"]();
            });
        },
        url: function() {
            return this.attr('href') || this.attr('src');
        }
    });

    function createHelper(settings) {
        // there can be only one tooltip helper
        if (helper.parent)
            return;
        // create the helper, h3 for title, div for url
        helper.parent = $('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>')
        // add to document
			.appendTo(document.body)
        // hide it at first
			.hide();

        // apply bgiframe if available
        if ($.fn.bgiframe)
            helper.parent.bgiframe();

        // save references to title and url elements
        helper.title = $('h3', helper.parent);
        helper.body = $('div.body', helper.parent);
        helper.url = $('div.url', helper.parent);
    }

    function settings(element) {
        return $.data(element, "tooltip");
    }

    // main event handler to start showing tooltips
    function handle(event) {
        // show helper, either with timeout or on instant
        if (settings(this).delay)
            tID = setTimeout(show, settings(this).delay);
        else
            show();

        // if selected, update the helper position when the mouse moves
        track = !!settings(this).track;
        $(document.body).bind('mousemove', update);

        // update at least once
        update(event);
    }

    // save elements title before the tooltip is displayed
    function save() {
        // if this is the current source, or it has no title (occurs with click event), stop
        if ($.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler))
            return;

        // save current
        current = this;
        title = this.tooltipText;

        if (settings(this).bodyHandler) {
            helper.title.hide();
            var bodyContent = settings(this).bodyHandler.call(this);
            if (bodyContent.nodeType || bodyContent.jquery) {
                helper.body.empty().append(bodyContent)
            } else {
                helper.body.html(bodyContent);
            }
            helper.body.show();
        } else if (settings(this).showBody) {
            var parts = title.split(settings(this).showBody);
            helper.title.html(parts.shift()).show();
            helper.body.empty();
            for (var i = 0, part; (part = parts[i]); i++) {
                if (i > 0)
                    helper.body.append("<br/>");
                helper.body.append(part);
            }
            helper.body.hideWhenEmpty();
        } else {
            helper.title.html(title).show();
            helper.body.hide();
        }

        // if element has href or src, add and show it, otherwise hide it
        if (settings(this).showURL && $(this).url())
            helper.url.html($(this).url().replace('http://', '')).show();
        else
            helper.url.hide();

        // add an optional class for this tip
        helper.parent.addClass(settings(this).extraClass);

        // fix PNG background for IE
        if (settings(this).fixPNG)
            helper.parent.fixPNG();

        handle.apply(this, arguments);
    }

    // delete timeout and show helper
    function show() {
        tID = null;
        if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
            if (helper.parent.is(":animated"))
                helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
            else
                helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
        } else {
            helper.parent.show();
        }
        update();
    }

    /**
    * callback for mousemove
    * updates the helper position
    * removes itself when no current element
    */
    function update(event) {
        if ($.tooltip.blocked)
            return;

        if (event && event.target.tagName == "OPTION") {
            return;
        }

        // stop updating when tracking is disabled and the tooltip is visible
        if (!track && helper.parent.is(":visible")) {
            $(document.body).unbind('mousemove', update)
        }

        // if no current element is available, remove this listener
        if (current == null) {
            $(document.body).unbind('mousemove', update);
            return;
        }

        // remove position helper classes
        helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");

        var left = helper.parent[0].offsetLeft;
        var top = helper.parent[0].offsetTop;
        if (event) {
            // position the helper 15 pixel to bottom right, starting from mouse position
            left = event.pageX + settings(current).left;
            top = event.pageY + settings(current).top;
            var right = 'auto';
            if (settings(current).positionLeft) {
                right = $(window).width() - left;
                left = 'auto';
            }
            helper.parent.css({
                left: left,
                right: right,
                top: top
            });
        }

        var v = viewport(),
			h = helper.parent[0];
        // check horizontal position
        if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
            left -= h.offsetWidth + 20 + settings(current).left;
            helper.parent.css({ left: left + 'px' }).addClass("viewport-right");
        }
        // check vertical position
        if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
            top -= h.offsetHeight + 20 + settings(current).top;
            helper.parent.css({ top: top + 'px' }).addClass("viewport-bottom");
        }
    }

    function viewport() {
        return {
            x: $(window).scrollLeft(),
            y: $(window).scrollTop(),
            cx: $(window).width(),
            cy: $(window).height()
        };
    }

    // hide helper and restore added classes and the title
    function hide(event) {
        if ($.tooltip.blocked)
            return;
        // clear timeout if possible
        if (tID)
            clearTimeout(tID);
        // no more current element
        current = null;

        var tsettings = settings(this);
        function complete() {
            helper.parent.removeClass(tsettings.extraClass).hide().css("opacity", "");
        }
        if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
            if (helper.parent.is(':animated'))
                helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
            else
                helper.parent.stop().fadeOut(tsettings.fade, complete);
        } else
            complete();

        if (settings(this).fixPNG)
            helper.parent.unfixPNG();
    }

})(jQuery);


/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/

/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
*       used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
*                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
*                             If set to null or omitted, the cookie will be a session cookie and will not be retained
*                             when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
*                        require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/

/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
* @url: http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/
*/

jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};


/*
* jQuery corner plugin
*
* version 1.92 (12/18/2007)
*
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*/

/**
* The corner() method provides a simple way of styling DOM elements.  
*
* corner() takes a single string argument:  $().corner("effect corners width")
*
*   effect:  The name of the effect to apply, such as round or bevel. 
*            If you don't specify an effect, rounding is used.
*
*   corners: The corners can be one or more of top, bottom, tr, tl, br, or bl. 
*            By default, all four corners are adorned. 
*
*   width:   The width specifies the width of the effect; in the case of rounded corners this 
*            will be the radius of the width. 
*            Specify this value using the px suffix such as 10px, and yes it must be pixels.
*
* For more details see: http://methvin.com/jquery/jq-corner.html
* For a full demo see:  http://malsup.com/jquery/corner/
*
*
* @example $('.adorn').corner();
* @desc Create round, 10px corners 
*
* @example $('.adorn').corner("25px");
* @desc Create round, 25px corners 
*
* @example $('.adorn').corner("notch bottom");
* @desc Create notched, 10px corners on bottom only
*
* @example $('.adorn').corner("tr dog 25px");
* @desc Create dogeared, 25px corner on the top-right corner only
*
* @example $('.adorn').corner("round 8px").parent().css('padding', '4px').corner("round 10px");
* @desc Create a rounded border effect by styling both the element and its parent
* 
* @name corner
* @type jQuery
* @param String options Options which control the corner style
* @cat Plugins/Corner
* @return jQuery
* @author Dave Methvin (dave.methvin@gmail.com)
* @author Mike Alsup (malsup@gmail.com)
*/
(function($)
{

    $.fn.corner = function(o)
    {
        var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
        function sz(el, p) { return parseInt($.css(el, p)) || 0; };
        function hex2(s)
        {
            var s = parseInt(s).toString(16);
            return (s.length < 2) ? '0' + s : s;
        };
        function gpc(node)
        {
            for (; node && node.nodeName.toLowerCase() != 'html'; node = node.parentNode)
            {
                var v = $.css(node, 'backgroundColor');
                if (v.indexOf('rgb') >= 0)
                {
                    if ($.browser.safari && v == 'rgba(0, 0, 0, 0)')
                        continue;
                    var rgb = v.match(/\d+/g);
                    return '#' + hex2(rgb[0]) + hex2(rgb[1]) + hex2(rgb[2]);
                }
                if (v && v != 'transparent')
                    return v;
            }
            return '#ffffff';
        };
        function getW(i)
        {
            switch (fx)
            {
                case 'round': return Math.round(width * (1 - Math.cos(Math.asin(i / width))));
                case 'cool': return Math.round(width * (1 + Math.cos(Math.asin(i / width))));
                case 'sharp': return Math.round(width * (1 - Math.cos(Math.acos(i / width))));
                case 'bite': return Math.round(width * (Math.cos(Math.asin((width - i - 1) / width))));
                case 'slide': return Math.round(width * (Math.atan2(i, width / i)));
                case 'jut': return Math.round(width * (Math.atan2(width, (width - i - 1))));
                case 'curl': return Math.round(width * (Math.atan(i)));
                case 'tear': return Math.round(width * (Math.cos(i)));
                case 'wicked': return Math.round(width * (Math.tan(i)));
                case 'long': return Math.round(width * (Math.sqrt(i)));
                case 'sculpt': return Math.round(width * (Math.log((width - i - 1), width)));
                case 'dog': return (i & 1) ? (i + 1) : width;
                case 'dog2': return (i & 2) ? (i + 1) : width;
                case 'dog3': return (i & 3) ? (i + 1) : width;
                case 'fray': return (i % 2) * width;
                case 'notch': return width;
                case 'bevel': return i + 1;
            }
        };
        o = (o || "").toLowerCase();
        var keep = /keep/.test(o);                       // keep borders?
        var cc = ((o.match(/cc:(#[0-9a-f]+)/) || [])[1]);  // corner color
        var sc = ((o.match(/sc:(#[0-9a-f]+)/) || [])[1]);  // strip color
        var width = parseInt((o.match(/(\d+)px/) || [])[1]) || 10; // corner width
        var re = /round|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dog/;
        var fx = ((o.match(re) || ['round'])[0]);
        var edges = { T: 0, B: 1 };
        var opts = {
            TL: /top|tl/.test(o), TR: /top|tr/.test(o),
            BL: /bottom|bl/.test(o), BR: /bottom|br/.test(o)
        };
        if (!opts.TL && !opts.TR && !opts.BL && !opts.BR)
            opts = { TL: 1, TR: 1, BL: 1, BR: 1 };
        var strip = document.createElement('div');
        strip.style.overflow = 'hidden';
        strip.style.height = '1px';
        strip.style.backgroundColor = sc || 'transparent';
        strip.style.borderStyle = 'solid';
        return this.each(function(index)
        {
            var pad = {
                T: parseInt($.css(this, 'paddingTop')) || 0, R: parseInt($.css(this, 'paddingRight')) || 0,
                B: parseInt($.css(this, 'paddingBottom')) || 0, L: parseInt($.css(this, 'paddingLeft')) || 0
            };

            if ($.browser.msie) this.style.zoom = 1; // force 'hasLayout' in IE
            if (!keep) this.style.border = 'none';
            strip.style.borderColor = cc || gpc(this.parentNode);
            var cssHeight = $.curCSS(this, 'height');

            for (var j in edges)
            {
                var bot = edges[j];
                // only add stips if needed
                if ((bot && (opts.BL || opts.BR)) || (!bot && (opts.TL || opts.TR)))
                {
                    strip.style.borderStyle = 'none ' + (opts[j + 'R'] ? 'solid' : 'none') + ' none ' + (opts[j + 'L'] ? 'solid' : 'none');
                    var d = document.createElement('div');
                    $(d).addClass('jquery-corner');
                    var ds = d.style;

                    bot ? this.appendChild(d) : this.insertBefore(d, this.firstChild);

                    if (bot && cssHeight != 'auto')
                    {
                        if ($.css(this, 'position') == 'static')
                            this.style.position = 'relative';
                        ds.position = 'absolute';
                        ds.bottom = ds.left = ds.padding = ds.margin = '0';
                        if ($.browser.msie)
                            ds.setExpression('width', 'this.parentNode.offsetWidth');
                        else
                            ds.width = '100%';
                    }
                    else if (!bot && $.browser.msie)
                    {
                        if ($.css(this, 'position') == 'static')
                            this.style.position = 'relative';
                        ds.position = 'absolute';
                        ds.top = ds.left = ds.right = ds.padding = ds.margin = '0';

                        // fix ie6 problem when blocked element has a border width
                        var bw = 0;
                        if (ie6 || !$.boxModel)
                            bw = sz(this, 'borderLeftWidth') + sz(this, 'borderRightWidth');
                        ie6 ? ds.setExpression('width', 'this.parentNode.offsetWidth - ' + bw + '+ "px"') : ds.width = '100%';
                    }
                    else
                    {
                        ds.margin = !bot ? '-' + pad.T + 'px -' + pad.R + 'px ' + (pad.T - width) + 'px -' + pad.L + 'px' :
                                        (pad.B - width) + 'px -' + pad.R + 'px -' + pad.B + 'px -' + pad.L + 'px';
                    }

                    for (var i = 0; i < width; i++)
                    {
                        var w = Math.max(0, getW(i));
                        var e = strip.cloneNode(false);
                        e.style.borderWidth = '0 ' + (opts[j + 'R'] ? w : 0) + 'px 0 ' + (opts[j + 'L'] ? w : 0) + 'px';
                        bot ? d.appendChild(e) : d.insertBefore(e, d.firstChild);
                    }
                }
            }
        });
    };

    $.fn.uncorner = function(o) { return $('.jquery-corner', this).remove(); };

})(jQuery);

