/*
 * jQuery Cycle Plugin for light-weight slideshows
 * Examples and documentation at: http://malsup.com/jquery/cycle/
 * Copyright (c) 2007-2008 M. Alsup
 * Version: 2.28 (06-OCT-2008)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Requires: jQuery v1.2.3 or later
 *
 * Based on the work of:
 *  1) Matt Oakes (http://portfolio.gizone.co.uk/applications/slideshow/)
 *  2) Torsten Baldes (http://medienfreunde.com/lab/innerfade/)
 *  3) Benjamin Sterling (http://www.benjaminsterling.com/experiments/jqShuffle/)
 */
;(function($) {

var ver = '2.28';
var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);

function log() {
    if (window.console && window.console.log)
        window.console.log('[cycle] ' + Array.prototype.join.call(arguments,''));
};

$.fn.cycle = function(options) {
	var opt2 = arguments[1];
    return this.each(function() {
        if (options === undefined || options === null)
            options = {};
        if (options.constructor == String) {
            switch(options) {
            case 'stop':
                if (this.cycleTimeout) clearTimeout(this.cycleTimeout);
                this.cycleTimeout = 0;
                $(this).data('cycle.opts', '');
                return;
            case 'pause':
                this.cyclePause = 1;
                return;
            case 'resume':
				this.cyclePause = 0;
				if (opt2 === true) { // resume now!
		            options = $(this).data('cycle.opts');
		            if (!options) {
		                log('options not found, can not resume');
		                return;
		            }
					if (this.cycleTimeout) {
						clearTimeout(this.cycleTimeout);
						this.cycleTimeout = 0;
					}            
					go(options.elements, options, 1, 1);
				}
                return;
            default:
                options = { fx: options };
            };
        }
        else if (options.constructor == Number) {
            // go to the requested slide
            var num = options;
            options = $(this).data('cycle.opts');
            if (!options) {
                log('options not found, can not advance slide');
                return;
            }
            if (num < 0 || num >= options.elements.length) {
                log('invalid slide index: ' + num);
                return;
            }
            options.nextSlide = num;
            if (this.cycleTimeout) {
                clearTimeout(this.cycleTimeout);
                this.cycleTimeout = 0;
            }            
            go(options.elements, options, 1, num >= options.currSlide);
            return;
        }

        // stop existing slideshow for this container (if there is one)
        if (this.cycleTimeout) clearTimeout(this.cycleTimeout);
        this.cycleTimeout = 0;
        this.cyclePause = 0;
        
        var $cont = $(this);
        var $slides = options.slideExpr ? $(options.slideExpr, this) : $cont.children();
        var els = $slides.get();
        if (els.length < 2) {
            log('terminating; too few slides: ' + els.length);
            return; // don't bother
        }

        // support metadata plugin (v1.0 and v2.0)
        var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
        if (opts.autostop) 
            opts.countdown = opts.autostopCount || els.length;

        $cont.data('cycle.opts', opts);
        opts.container = this;

        opts.elements = els;
        opts.before = opts.before ? [opts.before] : [];
        opts.after = opts.after ? [opts.after] : [];
        opts.after.unshift(function(){ opts.busy=0; });
        if (opts.continuous)
            opts.after.push(function() { go(els,opts,0,!opts.rev); });
            
        // clearType corrections
        if (ie6 && opts.cleartype && !opts.cleartypeNoBg)
            clearTypeFix($slides);

        // allow shorthand overrides of width, height and timeout
        var cls = this.className;
        opts.width = parseInt((cls.match(/w:(\d+)/)||[])[1]) || opts.width;
        opts.height = parseInt((cls.match(/h:(\d+)/)||[])[1]) || opts.height;
        opts.timeout = parseInt((cls.match(/t:(\d+)/)||[])[1]) || opts.timeout;

        if ($cont.css('position') == 'static') 
            $cont.css('position', 'relative');
        if (opts.width) 
            $cont.width(opts.width);
        if (opts.height && opts.height != 'auto') 
            $cont.height(opts.height);

		if (opts.startingSlide) opts.startingSlide = parseInt(opts.startingSlide);	
			
        if (opts.random) {
            opts.randomMap = [];
            for (var i = 0; i < els.length; i++) 
                opts.randomMap.push(i);
            opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
            opts.randomIndex = 0;
            opts.startingSlide = opts.randomMap[0];
        }
        else if (opts.startingSlide >= els.length)
            opts.startingSlide = 0; // catch bogus input
        var first = opts.startingSlide || 0;
        $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) { 
            var z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
            $(this).css('z-index', z) 
        });
        
        $(els[first]).css('opacity',1).show(); // opacity bit needed to handle reinit case
        if ($.browser.msie) els[first].style.removeAttribute('filter');

        if (opts.fit && opts.width) 
            $slides.width(opts.width);
        if (opts.fit && opts.height && opts.height != 'auto') 
            $slides.height(opts.height);
        if (opts.pause) 
            $cont.hover(function(){this.cyclePause=1;},function(){this.cyclePause=0;});

        // run transition init fn
        var init = $.fn.cycle.transitions[opts.fx];
        if ($.isFunction(init))
            init($cont, $slides, opts);
        else if (opts.fx != 'custom')
            log('unknown transition: ' + opts.fx);
        
        $slides.each(function() {
            var $el = $(this);
            this.cycleH = (opts.fit && opts.height) ? opts.height : $el.height();
            this.cycleW = (opts.fit && opts.width) ? opts.width : $el.width();
        });

        opts.cssBefore = opts.cssBefore || {};
        opts.animIn = opts.animIn || {};
        opts.animOut = opts.animOut || {};

        $slides.not(':eq('+first+')').css(opts.cssBefore);
        if (opts.cssFirst)
            $($slides[first]).css(opts.cssFirst);

        if (opts.timeout) {
			opts.timeout = parseInt(opts.timeout);
            // ensure that timeout and speed settings are sane
            if (opts.speed.constructor == String)
                opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed);
            if (!opts.sync)
                opts.speed = opts.speed / 2;
            while((opts.timeout - opts.speed) < 250)
                opts.timeout += opts.speed;
        }
        if (opts.easing) 
            opts.easeIn = opts.easeOut = opts.easing;
        if (!opts.speedIn) 
            opts.speedIn = opts.speed;
        if (!opts.speedOut) 
            opts.speedOut = opts.speed;

 		opts.slideCount = els.length;
        opts.currSlide = first;
        if (opts.random) {
            opts.nextSlide = opts.currSlide;
            if (++opts.randomIndex == els.length) 
                opts.randomIndex = 0;
            opts.nextSlide = opts.randomMap[opts.randomIndex];
        }
        else
            opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;

        // fire artificial events
        var e0 = $slides[first];
        if (opts.before.length)
            opts.before[0].apply(e0, [e0, e0, opts, true]);
        if (opts.after.length > 1)
            opts.after[1].apply(e0, [e0, e0, opts, true]);
        
        if (opts.click && !opts.next)
            opts.next = opts.click;
        if (opts.next)
            $(opts.next).bind('click', function(){return advance(els,opts,opts.rev?-1:1)});
        if (opts.prev)
            $(opts.prev).bind('click', function(){return advance(els,opts,opts.rev?1:-1)});
        if (opts.pager)
            buildPager(els,opts);

        // expose fn for adding slides after the show has started
        opts.addSlide = function(newSlide) {
            var $s = $(newSlide), s = $s[0];
            if (!opts.autostopCount)
                opts.countdown++;
            els.push(s);
            if (opts.els) 
                opts.els.push(s); // shuffle needs this
            opts.slideCount = els.length;
            
            $s.css('position','absolute').appendTo($cont);
            
            if (ie6 && opts.cleartype && !opts.cleartypeNoBg)
                clearTypeFix($s);

            if (opts.fit && opts.width) 
                $s.width(opts.width);
            if (opts.fit && opts.height && opts.height != 'auto') 
                $slides.height(opts.height);
            s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
            s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();

            $s.css(opts.cssBefore);

            if (opts.pager)
                $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
            
            if (typeof opts.onAddSlide == 'function')
                opts.onAddSlide($s);
        };

        if (opts.timeout || opts.continuous)
            this.cycleTimeout = setTimeout(
                function(){go(els,opts,0,!opts.rev)}, 
                opts.continuous ? 10 : opts.timeout + (opts.delay||0));
    });
};

function go(els, opts, manual, fwd) {
    if (opts.busy) return;
    var p = opts.container, curr = els[opts.currSlide], next = els[opts.nextSlide];
    if (p.cycleTimeout === 0 && !manual) 
        return;

    if (!manual && !p.cyclePause && 
        ((opts.autostop && (--opts.countdown <= 0)) ||
        (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
        if (opts.end)
            opts.end(opts);
        return;
    }

    if (manual || !p.cyclePause) {
        if (opts.before.length)
            $.each(opts.before, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
        var after = function() {
            if ($.browser.msie && opts.cleartype)
                this.style.removeAttribute('filter');
            $.each(opts.after, function(i,o) { o.apply(next, [curr, next, opts, fwd]); });
        };

        if (opts.nextSlide != opts.currSlide) {
            opts.busy = 1;
            if (opts.fxFn)
                opts.fxFn(curr, next, opts, after, fwd);
            else if ($.isFunction($.fn.cycle[opts.fx]))
                $.fn.cycle[opts.fx](curr, next, opts, after);
            else
                $.fn.cycle.custom(curr, next, opts, after, manual && opts.fastOnEvent);
        }
        if (opts.random) {
            opts.currSlide = opts.nextSlide;
            if (++opts.randomIndex == els.length) 
                opts.randomIndex = 0;
            opts.nextSlide = opts.randomMap[opts.randomIndex];
        }
        else { // sequence
            var roll = (opts.nextSlide + 1) == els.length;
            opts.nextSlide = roll ? 0 : opts.nextSlide+1;
            opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
        }
        if (opts.pager)
            $.fn.cycle.updateActivePagerLink(opts.pager, opts.currSlide);
    }
    if (opts.timeout && !opts.continuous)
        p.cycleTimeout = setTimeout(function() { go(els,opts,0,!opts.rev) }, opts.timeout);
    else if (opts.continuous && p.cyclePause) 
        p.cycleTimeout = setTimeout(function() { go(els,opts,0,!opts.rev) }, 10);
};

$.fn.cycle.updateActivePagerLink = function(pager, currSlide) {
    $(pager).find('a').removeClass('activeSlide').filter('a:eq('+currSlide+')').addClass('activeSlide');
};

// advance slide forward or back
function advance(els, opts, val) {
    var p = opts.container, timeout = p.cycleTimeout;
    if (timeout) {
        clearTimeout(timeout);
        p.cycleTimeout = 0;
    }
    if (opts.random && val < 0) {
        // move back to the previously display slide
        opts.randomIndex--;
        if (--opts.randomIndex == -2)
            opts.randomIndex = els.length-2;
        else if (opts.randomIndex == -1)
            opts.randomIndex = els.length-1;
        opts.nextSlide = opts.randomMap[opts.randomIndex];
    }
    else if (opts.random) {
        if (++opts.randomIndex == els.length) 
            opts.randomIndex = 0;
        opts.nextSlide = opts.randomMap[opts.randomIndex];
    }
    else {
        opts.nextSlide = opts.currSlide + val;
        if (opts.nextSlide < 0) {
            if (opts.nowrap) return false;
            opts.nextSlide = els.length - 1;
        }
        else if (opts.nextSlide >= els.length) {
            if (opts.nowrap) return false;
            opts.nextSlide = 0;
        }
    }
    
    if (opts.prevNextClick && typeof opts.prevNextClick == 'function')
        opts.prevNextClick(val > 0, opts.nextSlide, els[opts.nextSlide]);
    go(els, opts, 1, val>=0);
    return false;
};

function buildPager(els, opts) {
    var $p = $(opts.pager);
    $.each(els, function(i,o) {
        $.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
    });
   $.fn.cycle.updateActivePagerLink(opts.pager, opts.startingSlide);
};

$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
    var $a = (typeof opts.pagerAnchorBuilder == 'function')
        ? $(opts.pagerAnchorBuilder(i,el))
        : $('<a href="#">'+(i+1)+'</a>');
    
    // don't reparent if anchor is in the dom
    if ($a.parents('body').length == 0)
        $a.appendTo($p);
        
    $a.bind(opts.pagerEvent, function() {
        opts.nextSlide = i;
        var p = opts.container, timeout = p.cycleTimeout;
        if (timeout) {
            clearTimeout(timeout);
            p.cycleTimeout = 0;
        }            
        if (typeof opts.pagerClick == 'function')
            opts.pagerClick(opts.nextSlide, els[opts.nextSlide]);
        go(els,opts,1,opts.currSlide < i);
        return false;
    });
	if (opts.pauseOnPagerHover)
		$a.hover(function() { opts.container.cyclePause = 1; }, function() { opts.container.cyclePause = 0; } );
};


// this fixes clearType problems in ie6 by setting an explicit bg color
function clearTypeFix($slides) {
    function hex(s) {
        var s = parseInt(s).toString(16);
        return s.length < 2 ? '0'+s : s;
    };
    function getBg(e) {
        for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
            var v = $.css(e,'background-color');
            if (v.indexOf('rgb') >= 0 ) { 
                var rgb = v.match(/\d+/g); 
                return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
            }
            if (v && v != 'transparent')
                return v;
        }
        return '#ffffff';
    };
    $slides.each(function() { $(this).css('background-color', getBg(this)); });
};


$.fn.cycle.custom = function(curr, next, opts, cb, immediate) {
    var $l = $(curr), $n = $(next);
    $n.css(opts.cssBefore);
    var speedIn = immediate ? 1 : opts.speedIn;
    var speedOut = immediate ? 1 : opts.speedOut;
    var easeIn = immediate ? null : opts.easeIn;
    var easeOut = immediate ? null : opts.easeOut;
    var fn = function() {$n.animate(opts.animIn, speedIn, easeIn, cb)};
    $l.animate(opts.animOut, speedOut, easeOut, function() {
        if (opts.cssAfter) $l.css(opts.cssAfter);
        if (!opts.sync) fn();
    });
    if (opts.sync) fn();
};

$.fn.cycle.transitions = {
    fade: function($cont, $slides, opts) {
        $slides.not(':eq('+opts.startingSlide+')').css('opacity',0);
        opts.before.push(function() { $(this).show() });
        opts.animIn    = { opacity: 1 };
        opts.animOut   = { opacity: 0 };
        opts.cssBefore = { opacity: 0 };
        opts.cssAfter  = { display: 'none' };
    }
};

$.fn.cycle.ver = function() { return ver; };

// override these globally if you like (they are all optional)
$.fn.cycle.defaults = {
    fx:           'fade', // one of: fade, shuffle, zoom, scrollLeft, etc
    timeout:       4000,  // milliseconds between slide transitions (0 to disable auto advance)
    continuous:    0,     // true to start next transition immediately after current one completes
    speed:         1000,  // speed of the transition (any valid fx speed value)
    speedIn:       null,  // speed of the 'in' transition
    speedOut:      null,  // speed of the 'out' transition
    next:          null,  // id of element to use as click trigger for next slide
    prev:          null,  // id of element to use as click trigger for previous slide
    prevNextClick: null,  // callback fn for prev/next clicks:  function(isNext, zeroBasedSlideIndex, slideElement)
    pager:         null,  // id of element to use as pager container
    pagerClick:    null,  // callback fn for pager clicks:  function(zeroBasedSlideIndex, slideElement)
    pagerEvent:   'click', // event which drives the pager navigation
    pagerAnchorBuilder: null, // callback fn for building anchor links
    before:        null,  // transition callback (scope set to element to be shown)
    after:         null,  // transition callback (scope set to element that was shown)
    end:           null,  // callback invoked when the slideshow terminates (use with autostop or nowrap options)
    easing:        null,  // easing method for both in and out transitions
    easeIn:        null,  // easing for "in" transition
    easeOut:       null,  // easing for "out" transition
    shuffle:       null,  // coords for shuffle animation, ex: { top:15, left: 200 }
    animIn:        null,  // properties that define how the slide animates in
    animOut:       null,  // properties that define how the slide animates out
    cssBefore:     null,  // properties that define the initial state of the slide before transitioning in
    cssAfter:      null,  // properties that defined the state of the slide after transitioning out
    fxFn:          null,  // function used to control the transition
    height:       'auto', // container height
    startingSlide: 0,     // zero-based index of the first slide to be displayed
    sync:          1,     // true if in/out transitions should occur simultaneously
    random:        0,     // true for random, false for sequence (not applicable to shuffle fx)
    fit:           0,     // force slides to fit container
    pause:         0,     // true to enable "pause on hover"
	pauseOnPagerHover: 0, // true to pause when hovering over pager link
    autostop:      0,     // true to end slideshow after X transitions (where X == slide count)
    autostopCount: 0,     // number of transitions (optionally used with autostop to define X)
    delay:         0,     // additional delay (in ms) for first transition (hint: can be negative)
    slideExpr:     null,  // expression for selecting slides (if something other than all children is required)
    cleartype:     0,     // true if clearType corrections should be applied (for IE)
    nowrap:        0,     // true to prevent slideshow from wrapping
    fastOnEvent:   0      // force immediate transition when triggered manually (via pager or prev/next)
};

})(jQuery);


/*
 * jQuery Cycle Plugin Transition Definitions
 * This script is a plugin for the jQuery Cycle Plugin
 * Examples and documentation at: http://malsup.com/jquery/cycle/
 * Copyright (c) 2007-2008 M. Alsup
 * Version:  2.22
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
(function($) {

//
// These functions define one-time slide initialization for the named
// transitions. To save file size feel free to remove any of these that you 
// don't need.
//

// scrollUp/Down/Left/Right
$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.top = next.offsetHeight;
        opts.animOut.top = 0-curr.offsetHeight;
    });
    opts.cssFirst = { top: 0 };
    opts.animIn   = { top: 0 };
    opts.cssAfter = { display: 'none' };
};
$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.top = 0-next.offsetHeight;
        opts.animOut.top = curr.offsetHeight;
    });
    opts.cssFirst = { top: 0 };
    opts.animIn   = { top: 0 };
    opts.cssAfter = { display: 'none' };
};
$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.left = next.offsetWidth;
        opts.animOut.left = 0-curr.offsetWidth;
    });
    opts.cssFirst = { left: 0 };
    opts.animIn   = { left: 0 };
};
$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.left = 0-next.offsetWidth;
        opts.animOut.left = curr.offsetWidth;
    });
    opts.cssFirst = { left: 0 };
    opts.animIn   = { left: 0 };
};
$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
    $cont.css('overflow','hidden').width();
//    $slides.show();
    opts.before.push(function(curr, next, opts, fwd) {
        $(this).show();
        var currW = curr.offsetWidth, nextW = next.offsetWidth;
        opts.cssBefore = fwd ? { left: nextW } : { left: -nextW };
        opts.animIn.left = 0;
        opts.animOut.left = fwd ? -currW : currW;
        $slides.not(curr).css(opts.cssBefore);
    });
    opts.cssFirst = { left: 0 };
    opts.cssAfter = { display: 'none' }
};
$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
    $cont.css('overflow','hidden');
//    $slides.show();
    opts.before.push(function(curr, next, opts, fwd) {
        $(this).show();
        var currH = curr.offsetHeight, nextH = next.offsetHeight;
        opts.cssBefore = fwd ? { top: -nextH } : { top: nextH };
        opts.animIn.top = 0;
        opts.animOut.top = fwd ? currH : -currH;
        $slides.not(curr).css(opts.cssBefore);
    });
    opts.cssFirst = { top: 0 };
    opts.cssAfter = { display: 'none' }
};

// slideX/slideY
$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { zIndex: 2 };
    opts.animIn  = { width: 'show' };
    opts.animOut = { width: 'hide' };
};
$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { zIndex: 2 };
    opts.animIn  = { height: 'show' };
    opts.animOut = { height: 'hide' };
};

// shuffle
$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
    var w = $cont.css('overflow', 'visible').width();
    $slides.css({left: 0, top: 0});
    opts.before.push(function() { $(this).show() });
    opts.speed = opts.speed / 2; // shuffle has 2 transitions        
    opts.random = 0;
    opts.shuffle = opts.shuffle || {left:-w, top:15};
    opts.els = [];
    for (var i=0; i < $slides.length; i++)
        opts.els.push($slides[i]);

    for (var i=0; i < opts.startingSlide; i++)
        opts.els.push(opts.els.shift());

    // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
    opts.fxFn = function(curr, next, opts, cb, fwd) {
        var $el = fwd ? $(curr) : $(next);
        $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
            fwd ? opts.els.push(opts.els.shift()) : opts.els.unshift(opts.els.pop());
            if (fwd) 
                for (var i=0, len=opts.els.length; i < len; i++)
                    $(opts.els[i]).css('z-index', len-i);
            else {
                var z = $(curr).css('z-index');
                $el.css('z-index', parseInt(z)+1);
            }
            $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
                $(fwd ? this : curr).hide();
                if (cb) cb();
            });
        });
    };
    opts.onAddSlide = function($s) { $s.hide(); };
};

// turnUp/Down/Left/Right
$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.top = next.cycleH;
        opts.animIn.height = next.cycleH;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssFirst  = { top: 0 };
    opts.cssBefore = { height: 0 };
    opts.animIn    = { top: 0 };
    opts.animOut   = { height: 0 };
    opts.cssAfter  = { display: 'none' };
};
$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.animIn.height = next.cycleH;
        opts.animOut.top   = curr.cycleH;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssFirst  = { top: 0 };
    opts.cssBefore = { top: 0, height: 0 };
    opts.animOut   = { height: 0 };
    opts.cssAfter  = { display: 'none' };
};
$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore.left = next.cycleW;
        opts.animIn.width = next.cycleW;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { width: 0 };
    opts.animIn    = { left: 0 };
    opts.animOut   = { width: 0 };
    opts.cssAfter  = { display: 'none' };
};
$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.animIn.width = next.cycleW;
        opts.animOut.left = curr.cycleW;
    });
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { left: 0, width: 0 };
    opts.animIn    = { left: 0 };
    opts.animOut   = { width: 0 };
    opts.cssAfter  = { display: 'none' };
};

// zoom
$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
    opts.cssFirst = { top:0, left: 0 }; 
    opts.cssAfter = { display: 'none' };
    
    opts.before.push(function(curr, next, opts) {
        $(this).show();
        opts.cssBefore = { width: 0, height: 0, top: next.cycleH/2, left: next.cycleW/2 };
        opts.cssAfter  = { display: 'none' };
        opts.animIn    = { top: 0, left: 0, width: next.cycleW, height: next.cycleH };
        opts.animOut   = { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 };
        $(curr).css('zIndex',2);
        $(next).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
};

// fadeZoom
$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { width: 0, height: 0, opacity: 1, left: next.cycleW/2, top: next.cycleH/2, zIndex: 1 };
        opts.animIn    = { top: 0, left: 0, width: next.cycleW, height: next.cycleH };
    });    
    opts.animOut  = { opacity: 0 };
    opts.cssAfter = { zIndex: 0 };
};

// blindX
$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
    var w = $cont.css('overflow','hidden').width();
    $slides.show();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.cssBefore = { left: w, zIndex: 2 };
    opts.cssAfter = { zIndex: 1 };
    opts.animIn = { left: 0 };
    opts.animOut  = { left: w };
};
// blindY
$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
    var h = $cont.css('overflow','hidden').height();
    $slides.show();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.cssBefore = { top: h, zIndex: 2 };
    opts.cssAfter = { zIndex: 1 };
    opts.animIn = { top: 0 };
    opts.animOut  = { top: h };
};
// blindZ
$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
    var h = $cont.css('overflow','hidden').height();
    var w = $cont.width();
    $slides.show();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',1);
    });    
    opts.cssBefore = { top: h, left: w, zIndex: 2 };
    opts.cssAfter = { zIndex: 1 };
    opts.animIn = { top: 0, left: 0 };
    opts.animOut  = { top: h, left: w };
};

// growX - grow horizontally from centered 0 width
$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { left: this.cycleW/2, width: 0, zIndex: 2 };
        opts.animIn = { left: 0, width: this.cycleW };
        opts.animOut = { left: 0 };
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide().css('zIndex',1); };
};
// growY - grow vertically from centered 0 height
$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { top: this.cycleH/2, height: 0, zIndex: 2 };
        opts.animIn = { top: 0, height: this.cycleH };
        opts.animOut = { top: 0 };
        $(curr).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide().css('zIndex',1); };
};

// curtainX - squeeze in both edges horizontally
$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { left: next.cycleW/2, width: 0, zIndex: 1, display: 'block' };
        opts.animIn = { left: 0, width: this.cycleW };
        opts.animOut = { left: curr.cycleW/2, width: 0 };
        $(curr).css('zIndex',2);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssAfter = { zIndex: 1, display: 'none' };
};
// curtainY - squeeze in both edges vertically
$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = { top: next.cycleH/2, height: 0, zIndex: 1, display: 'block' };
        opts.animIn = { top: 0, height: this.cycleH };
        opts.animOut = { top: curr.cycleH/2, height: 0 };
        $(curr).css('zIndex',2);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssAfter = { zIndex: 1, display: 'none' };
};

// cover - curr slide covered by next slide
$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
    var d = opts.direction || 'left';
    var w = $cont.css('overflow','hidden').width();
    var h = $cont.height();
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore = opts.cssBefore || {};
        opts.cssBefore.zIndex = 2;
        opts.cssBefore.display = 'block';
        
        if (d == 'right') 
            opts.cssBefore.left = -w;
        else if (d == 'up')    
            opts.cssBefore.top = h;
        else if (d == 'down')  
            opts.cssBefore.top = -h;
        else
            opts.cssBefore.left = w;
        $(curr).css('zIndex',1);
    });    
    if (!opts.animIn)  opts.animIn = { left: 0, top: 0 };
    if (!opts.animOut) opts.animOut = { left: 0, top: 0 };
    opts.cssAfter = opts.cssAfter || {};
    opts.cssAfter.zIndex = 2;
    opts.cssAfter.display = 'none';
};

// uncover - curr slide moves off next slide
$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
    var d = opts.direction || 'left';
    var w = $cont.css('overflow','hidden').width();
    var h = $cont.height();
    opts.before.push(function(curr, next, opts) {
        opts.cssBefore.display = 'block';
        if (d == 'right') 
            opts.animOut.left = w;
        else if (d == 'up')    
            opts.animOut.top = -h;
        else if (d == 'down')  
            opts.animOut.top = h;
        else
            opts.animOut.left = -w;
        $(curr).css('zIndex',2);
        $(next).css('zIndex',1);
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    if (!opts.animIn)  opts.animIn = { left: 0, top: 0 };
    opts.cssBefore = opts.cssBefore || {};
    opts.cssBefore.top = 0;
    opts.cssBefore.left = 0;
    
    opts.cssAfter = opts.cssAfter || {};
    opts.cssAfter.zIndex = 1;
    opts.cssAfter.display = 'none';
};

// toss - move top slide and fade away
$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
    var w = $cont.css('overflow','visible').width();
    var h = $cont.height();
    opts.before.push(function(curr, next, opts) {
        $(curr).css('zIndex',2);
        opts.cssBefore.display = 'block'; 
        // provide default toss settings if animOut not provided
        if (!opts.animOut.left && !opts.animOut.top)
            opts.animOut = { left: w*2, top: -h/2, opacity: 0 };
        else
            opts.animOut.opacity = 0;
    });    
    opts.onAddSlide = function($s) { $s.hide(); };
    opts.cssBefore = { left: 0, top: 0, zIndex: 1, opacity: 1 };
    opts.animIn = { left: 0 };
    opts.cssAfter = { zIndex: 2, display: 'none' };
};

// wipe - clip animation
$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
    var w = $cont.css('overflow','hidden').width();
    var h = $cont.height();
    opts.cssBefore = opts.cssBefore || {};
    var clip;
    if (opts.clip) {
        if (/l2r/.test(opts.clip))
            clip = 'rect(0px 0px '+h+'px 0px)';
        else if (/r2l/.test(opts.clip))
            clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
        else if (/t2b/.test(opts.clip))
            clip = 'rect(0px '+w+'px 0px 0px)';
        else if (/b2t/.test(opts.clip))
            clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
        else if (/zoom/.test(opts.clip)) {
            var t = parseInt(h/2);
            var l = parseInt(w/2);
            clip = 'rect('+t+'px '+l+'px '+t+'px '+l+'px)';
        }
    }
    
    opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
    
    var d = opts.cssBefore.clip.match(/(\d+)/g);
    var t = parseInt(d[0]), r = parseInt(d[1]), b = parseInt(d[2]), l = parseInt(d[3]);
    
    opts.before.push(function(curr, next, opts) {
        if (curr == next) return;
        var $curr = $(curr).css('zIndex',2);
        var $next = $(next).css({
            zIndex:  3,
            display: 'block'
        });
        
        var step = 1, count = parseInt((opts.speedIn / 13)) - 1;
        function f() {
            var tt = t ? t - parseInt(step * (t/count)) : 0;
            var ll = l ? l - parseInt(step * (l/count)) : 0;
            var bb = b < h ? b + parseInt(step * ((h-b)/count || 1)) : h;
            var rr = r < w ? r + parseInt(step * ((w-r)/count || 1)) : w;
            $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
            (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
        }
        f();
    });    
    opts.cssAfter  = { };
    opts.animIn    = { left: 0 };
    opts.animOut   = { left: 0 };
};

})(jQuery);



/* 
JQuery Curvy Corners by Mike Jolley - 
http://blue-anvil.com
19th May 2008
v1.5 - B190508 
*/
(function($){$.fn.corner=function(a){var b={tl:{radius:8},tr:{radius:8},bl:{radius:8},br:{radius:8},antiAlias:true,autoPad:true,validTags:["div"]};if(a&&typeof(a)!='string')jQuery.extend(b,a);return this.each(function(){new curvyObject(b,this).applyCorners()})};function curvyObject(){this.box=arguments[1];this.masterCorners=new Array();this.settings=arguments[0];var F=$(this.box).css("height");var G=$(this.box).css("width");var H=$(this.box).css("borderTopWidth");var I=$(this.box).css("backgroundImage");var J=$(this.box).css("position");var K=$(this.box).css("paddingTop");var L=$(this.box).css("paddingBottom");var M=$(this.box).css("paddingLeft");var N=$(this.box).css("paddingRight");this.boxHeight=parseInt(((F!=""&&F!="auto"&&F.indexOf("%")==-1)?F.substring(0,F.indexOf("px")):this.box.scrollHeight));this.boxWidth=parseInt(((G!=""&&G!="auto"&&G.indexOf("%")==-1)?G.substring(0,G.indexOf("px")):this.box.scrollWidth));this.borderWidth=parseInt(((H!=""&&H.indexOf("px")!==-1)?H.slice(0,H.indexOf("px")):0));this.boxPaddingTop=strip_px(K);this.boxPaddingBottom=strip_px(L);this.boxPaddingLeft=strip_px(M);this.boxPaddingRight=strip_px(N);this.borderColour=format_colour($(this.box).css("borderTopColor"));this.boxColour=format_colour($(this.box).css("backgroundColor"));this.borderString=this.borderWidth+"px"+" solid "+this.borderColour;this.bgImage=(I!="none"&&I!="initial")?I:"";this.boxContent=$(this.box).html();$(this.box).css("padding","0px");if(J!="absolute")$(this.box).css("position","relative");if(($.browser.msie&&$.browser.version==6)&&G=="auto"&&F=="auto")$(this.box).css("width","100%");if(($.browser.msie)){$(this.box).css("zoom","1");$(this.box+" *").css("zoom","normal")}if(this.settings.autoPad==true)$(this.box).html("");this.applyCorners=function(){var a=Math.max(this.settings.tl?this.settings.tl.radius:0,this.settings.tr?this.settings.tr.radius:0);var b=Math.max(this.settings.bl?this.settings.bl.radius:0,this.settings.br?this.settings.br.radius:0);for(var t=0;t<2;t++){switch(t){case 0:if(this.settings.tl||this.settings.tr){var c=document.createElement("div");this.topContainer=this.box.appendChild(c);$(this.topContainer).css({width:"100%","font-size":"1px",overflow:"hidden",position:"absolute","padding-left":this.borderWidth,"padding-right":this.borderWidth,height:a+"px",top:0-a+"px",left:0-this.borderWidth+"px"})};break;case 1:if(this.settings.bl||this.settings.br){var c=document.createElement("DIV");var c=document.createElement("div");this.bottomContainer=this.box.appendChild(c);$(this.bottomContainer).css({width:"100%","font-size":"1px",overflow:"hidden",position:"absolute","padding-left":this.borderWidth,"padding-right":this.borderWidth,height:b,bottom:0-b+"px",left:0-this.borderWidth+"px"})};break}};if(this.settings.autoPad==true){var d=document.createElement("DIV");var e=document.createElement("DIV");$(d).css({position:"relative",float:"left","margin-top":"-"+a+"px","margin-bottom":"-"+b+"px","padding-bottom":this.boxPaddingBottom,"padding-top":this.boxPaddingTop,"padding-left":this.boxPaddingLeft,"padding-right":this.boxPaddingRight}).html(this.boxContent).addClass="autoPadDiv";$(e).css("clear","both");this.contentDIV=this.box.appendChild(d);this.contentDIV=this.box.appendChild(e)};if(this.topContainer)$(this.box).css("border-top",0);if(this.bottomContainer)$(this.box).css("border-bottom",0);var f=["tr","tl","br","bl"];for(var i in f){if(i>-1<4){var g=f[i];if(!this.settings[g]){if(((g=="tr"||g=="tl")&&this.topContainer!=null)||((g=="br"||g=="bl")&&this.bottomContainer!=null)){var h=document.createElement("DIV");$(h).css({position:"relative","font-size":"1px",overflow:"hidden"});if(this.bgImage=="")$(h).css("background-color",this.boxColour);else $(h).css("background-image",this.bgImage).css("background-color",this.boxColour);switch(g){case"tl":$(h).css({height:a-this.borderWidth,"margin-right":this.settings.tr.radius-(this.borderWidth*2),"border-left":this.borderString,"border-top":this.borderString,left:-this.borderWidth+"px","background-repeat":$(this.box).css("background-repeat"),"background-position":this.borderWidth+"px 0px"});break;case"tr":$(h).css({height:a-this.borderWidth,"margin-left":this.settings.tl.radius-(this.borderWidth*2),"border-right":this.borderString,"border-top":this.borderString,left:this.borderWidth+"px","background-repeat":$(this.box).css("background-repeat"),"background-position":"-"+(a+this.borderWidth)+"px 0px"});break;case"bl":if(a>0)$(h).css({height:b-this.borderWidth,"margin-right":this.settings.br.radius-(this.borderWidth*2),"border-left":this.borderString,"border-bottom":this.borderString,left:-this.borderWidth+"px","background-repeat":$(this.box).css("background-repeat"),"background-position":"0px -"+($(this.box).height()+a-this.borderWidth+1)+"px"});else $(h).css({height:b-this.borderWidth,"margin-right":this.settings.br.radius-(this.borderWidth*2),"border-left":this.borderString,"border-bottom":this.borderString,left:-this.borderWidth+"px","background-repeat":$(this.box).css("background-repeat"),"background-position":"0px -"+($(this.box).height())+"px"});break;case"br":if(a>0)$(h).css({height:b-this.borderWidth,"margin-left":this.settings.bl.radius-(this.borderWidth*2),"border-right":this.borderString,"border-bottom":this.borderString,left:this.borderWidth+"px","background-repeat":$(this.box).css("background-repeat"),"background-position":"-"+this.settings.bl.radius+this.borderWidth+"px -"+($(this.box).height()+a-this.borderWidth+1)+"px"});else $(h).css({height:b-this.borderWidth,"margin-left":this.settings.bl.radius-(this.borderWidth*2),"border-right":this.borderString,"border-bottom":this.borderString,left:this.borderWidth+"px","background-repeat":$(this.box).css("background-repeat"),"background-position":"-"+this.settings.bl.radius+this.borderWidth+"px -"+($(this.box).height())+"px"});break}}}else{if(this.masterCorners[this.settings[g].radius]){var h=this.masterCorners[this.settings[g].radius].cloneNode(true)}else{var h=document.createElement("DIV");$(h).css({height:this.settings[g].radius,width:this.settings[g].radius,position:"absolute","font-size":"1px",overflow:"hidden"});var l=parseInt(this.settings[g].radius-this.borderWidth);for(var m=0,j=this.settings[g].radius;m<j;m++){if((m+1)>=l)var n=-1;else var n=(Math.floor(Math.sqrt(Math.pow(l,2)-Math.pow((m+1),2)))-1);if(l!=j){if((m)>=l)var o=-1;else var o=Math.ceil(Math.sqrt(Math.pow(l,2)-Math.pow(m,2)));if((m+1)>=j)var p=-1;else var p=(Math.floor(Math.sqrt(Math.pow(j,2)-Math.pow((m+1),2)))-1)};if((m)>=j)var q=-1;else var q=Math.ceil(Math.sqrt(Math.pow(j,2)-Math.pow(m,2)));if(n>-1)this.drawPixel(m,0,this.boxColour,100,(n+1),h,-1,this.settings[g].radius);if(l!=j){for(var r=(n+1);r<o;r++){if(this.settings.antiAlias){if(this.bgImage!=""){var s=(pixelFraction(m,r,l)*100);if(s<30){this.drawPixel(m,r,this.borderColour,100,1,h,0,this.settings[g].radius)}else{this.drawPixel(m,r,this.borderColour,100,1,h,-1,this.settings[g].radius)}}else{var u=BlendColour(this.boxColour,this.borderColour,pixelFraction(m,r,l));this.drawPixel(m,r,u,100,1,h,0,this.settings[g].radius,g)}}};if(this.settings.antiAlias){if(p>=o){if(o==-1)o=0;this.drawPixel(m,o,this.borderColour,100,(p-o+1),h,0,0)}}else{if(p>=n){this.drawPixel(m,(n+1),this.borderColour,100,(p-n),h,0,0)}};var v=this.borderColour}else{var v=this.boxColour;var p=n};if(this.settings.antiAlias){for(var r=(p+1);r<q;r++){this.drawPixel(m,r,v,(pixelFraction(m,r,j)*100),1,h,((this.borderWidth>0)?0:-1),this.settings[g].radius)}}};this.masterCorners[this.settings[g].radius]=h.cloneNode(true)};if(g!="br"){for(var t=0,k=h.childNodes.length;t<k;t++){var w=h.childNodes[t];var x=strip_px($(w).css("top"));var y=strip_px($(w).css("left"));var A=strip_px($(w).css("height"));if(g=="tl"||g=="bl"){$(w).css("left",this.settings[g].radius-y-1+"px")};if(g=="tr"||g=="tl"){$(w).css("top",this.settings[g].radius-A-x+"px")};switch(g){case"tr":$(w).css("background-position","-"+Math.abs((this.boxWidth-this.settings[g].radius+this.borderWidth)+y)+"px -"+Math.abs(this.settings[g].radius-A-x-this.borderWidth)+"px");break;case"tl":$(w).css("background-position","-"+Math.abs((this.settings[g].radius-y-1)-this.borderWidth)+"px -"+Math.abs(this.settings[g].radius-A-x-this.borderWidth)+"px");break;case"bl":if(a>0)$(w).css("background-position","-"+Math.abs((this.settings[g].radius-y-1)-this.borderWidth)+"px -"+Math.abs(($(this.box).height()+a-this.borderWidth+1))+"px");else $(w).css("background-position","-"+Math.abs((this.settings[g].radius-y-1)-this.borderWidth)+"px -"+Math.abs(($(this.box).height()))+"px");break}}}};if(h){switch(g){case"tl":if($(h).css("position")=="absolute")$(h).css("top","0");if($(h).css("position")=="absolute")$(h).css("left","0");if(this.topContainer)this.topContainer.appendChild(h);break;case"tr":if($(h).css("position")=="absolute")$(h).css("top","0");if($(h).css("position")=="absolute")$(h).css("right","0");if(this.topContainer)this.topContainer.appendChild(h);break;case"bl":if($(h).css("position")=="absolute")$(h).css("bottom","0");if(h.style.position=="absolute")$(h).css("left","0");if(this.bottomContainer)this.bottomContainer.appendChild(h);break;case"br":if($(h).css("position")=="absolute")$(h).css("bottom","0");if($(h).css("position")=="absolute")$(h).css("right","0");if(this.bottomContainer)this.bottomContainer.appendChild(h);break}}}};var B=new Array();B["t"]=Math.abs(this.settings.tl.radius-this.settings.tr.radius);B["b"]=Math.abs(this.settings.bl.radius-this.settings.br.radius);for(z in B){if(z=="t"||z=="b"){if(B[z]){var C=((this.settings[z+"l"].radius<this.settings[z+"r"].radius)?z+"l":z+"r");var D=document.createElement("DIV");$(D).css({height:B[z],width:this.settings[C].radius+"px",position:"absolute","font-size":"1px",overflow:"hidden","background-color":this.boxColour});switch(C){case"tl":$(D).css({"bottom":"0","left":"0","border-left":this.borderString});this.topContainer.appendChild(D);break;case"tr":$(D).css({"bottom":"0","right":"0","border-right":this.borderString});this.topContainer.appendChild(D);break;case"bl":$(D).css({"top":"0","left":"0","border-left":this.borderString});this.bottomContainer.appendChild(D);break;case"br":$(D).css({"top":"0","right":"0","border-right":this.borderString});this.bottomContainer.appendChild(D);break}};var E=document.createElement("DIV");$(E).css({position:"relative","font-size":"1px",overflow:"hidden","background-color":this.boxColour,"background-image":this.bgImage,"background-repeat":$(this.box).css("background-repeat")});switch(z){case"t":if(this.topContainer){if(this.settings.tl.radius&&this.settings.tr.radius){$(E).css({height:a-this.borderWidth+"px","margin-left":this.settings.tl.radius-this.borderWidth+"px","margin-right":this.settings.tr.radius-this.borderWidth+"px","border-top":this.borderString});if(this.bgImage!="")$(E).css("background-position","-"+(a+this.borderWidth)+"px 0px");this.topContainer.appendChild(E)};$(this.box).css("background-position","0px -"+(a-this.borderWidth+1)+"px")};break;case"b":if(this.bottomContainer){if(this.settings.bl.radius&&this.settings.br.radius){$(E).css({height:b-this.borderWidth+"px","margin-left":this.settings.bl.radius-this.borderWidth+"px","margin-right":this.settings.br.radius-this.borderWidth+"px","border-bottom":this.borderString});if(this.bgImage!=""&&a>0)$(E).css("background-position","-"+(this.settings.bl.radius-this.borderWidth)+"px -"+($(this.box).height()+a-this.borderWidth+1)+"px");else $(E).css("background-position","-"+(this.settings.bl.radius-this.borderWidth)+"px -"+($(this.box).height())+"px");this.bottomContainer.appendChild(E)}};break}}}};this.drawPixel=function(a,b,c,d,e,f,g,h){var i=document.createElement("DIV");$(i).css({height:e,width:"1px",position:"absolute","font-size":"1px",overflow:"hidden"});var j=Math.max(this.settings["tr"].radius,this.settings["tl"].radius);if(g==-1&&this.bgImage!=""){if(j>0)$(i).css("background-position","-"+((this.boxWidth-h-this.borderWidth)+a)+"px -"+(($(this.box).height()+j-this.borderWidth)-b)+"px");else $(i).css("background-position","-"+((this.boxWidth-h-this.borderWidth)+a)+"px -"+(($(this.box).height())-b)+"px");$(i).css({"background-image":this.bgImage,"background-repeat":$(this.box).css("background-repeat"),"background-color":c})}else{$(i).css("background-color",c)};if(d!=100)setOpacity(i,d);$(i).css({top:b+"px",left:a+"px"});f.appendChild(i)}};function BlendColour(a,b,c){var d=parseInt(a.substr(1,2),16);var e=parseInt(a.substr(3,2),16);var f=parseInt(a.substr(5,2),16);var g=parseInt(b.substr(1,2),16);var h=parseInt(b.substr(3,2),16);var i=parseInt(b.substr(5,2),16);if(c>1||c<0)c=1;var j=Math.round((d*c)+(g*(1-c)));if(j>255)j=255;if(j<0)j=0;var k=Math.round((e*c)+(h*(1-c)));if(k>255)k=255;if(k<0)k=0;var l=Math.round((f*c)+(i*(1-c)));if(l>255)l=255;if(l<0)l=0;return"#"+IntToHex(j)+IntToHex(k)+IntToHex(l)};function IntToHex(a){base=a/16;rem=a%16;base=base-(rem/16);baseS=MakeHex(base);remS=MakeHex(rem);return baseS+''+remS};function MakeHex(x){if((x>=0)&&(x<=9)){return x}else{switch(x){case 10:return"A";case 11:return"B";case 12:return"C";case 13:return"D";case 14:return"E";case 15:return"F"}}};function pixelFraction(x,y,r){var a=0;var b=new Array(1);var c=new Array(1);var d=0;var e="";var f=Math.sqrt((Math.pow(r,2)-Math.pow(x,2)));if((f>=y)&&(f<(y+1))){e="Left";b[d]=0;c[d]=f-y;d=d+1};var f=Math.sqrt((Math.pow(r,2)-Math.pow(y+1,2)));if((f>=x)&&(f<(x+1))){e=e+"Top";b[d]=f-x;c[d]=1;d=d+1};var f=Math.sqrt((Math.pow(r,2)-Math.pow(x+1,2)));if((f>=y)&&(f<(y+1))){e=e+"Right";b[d]=1;c[d]=f-y;d=d+1};var f=Math.sqrt((Math.pow(r,2)-Math.pow(y,2)));if((f>=x)&&(f<(x+1))){e=e+"Bottom";b[d]=f-x;c[d]=0};switch(e){case"LeftRight":a=Math.min(c[0],c[1])+((Math.max(c[0],c[1])-Math.min(c[0],c[1]))/2);break;case"TopRight":a=1-(((1-b[0])*(1-c[1]))/2);break;case"TopBottom":a=Math.min(b[0],b[1])+((Math.max(b[0],b[1])-Math.min(b[0],b[1]))/2);break;case"LeftBottom":a=(c[0]*b[1])/2;break;default:a=1};return a};function rgb2Hex(a){try{var b=rgb2Array(a);var c=parseInt(b[0]);var d=parseInt(b[1]);var f=parseInt(b[2]);var g="#"+IntToHex(c)+IntToHex(d)+IntToHex(f)}catch(e){alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex")};return g};function rgb2Array(a){var b=a.substring(4,a.indexOf(")"));var c=b.split(", ");return c};function setOpacity(a,b){b=(b==100)?99.999:b;if($.browser.safari&&a.tagName!="IFRAME"){var c=rgb2Array(a.style.backgroundColor);var d=parseInt(c[0]);var e=parseInt(c[1]);var f=parseInt(c[2]);a.style.backgroundColor="rgba("+d+", "+e+", "+f+", "+b/100+")"}else if(typeof(a.style.opacity)!="undefined"){a.style.opacity=b/100}else if(typeof(a.style.MozOpacity)!="undefined"){a.style.MozOpacity=b/100}else if(typeof(a.style.filter)!="undefined"){a.style.filter="alpha(opacity:"+b+")"}else if(typeof(a.style.KHTMLOpacity)!="undefined"){a.style.KHTMLOpacity=b/100}};function format_colour(a){var b="transparent";if(a!=""&&a!="transparent"){if(a.substr(0,3)=="rgb"){b=rgb2Hex(a)}else if(a.length==4){b="#"+a.substring(1,2)+a.substring(1,2)+a.substring(2,3)+a.substring(2,3)+a.substring(3,4)+a.substring(3,4)}else{b=a}};return b};function strip_px(a){return parseInt(((a!=""&&a.indexOf("px")!==-1)?a.slice(0,a.indexOf("px")):0))}})(jQuery);

jQuery.autocomplete = function(input, options) {
	// Create a link to self
	var me = this;

	// Create jQuery object for input element
	var $input = $(input).attr("autocomplete", "off");

	// Apply inputClass if necessary
	if (options.inputClass) $input.addClass(options.inputClass);

	// Create results
	var results = document.createElement("div");
	// Create jQuery object for results
	var $results = $(results);
	$results.hide().addClass(options.resultsClass).css("position", "absolute");
	if( options.width > 0 ) $results.css("width", options.width);

	// Add to body element
	$("body").append(results);

	input.autocompleter = me;

	var timeout = null;
	var prev = "";
	var active = -1;
	var cache = {};
	var keyb = false;
	var hasFocus = false;
	var lastKeyPressCode = null;

	// flush cache
	function flushCache(){
		cache = {};
		cache.data = {};
		cache.length = 0;
	};

	// flush cache
	flushCache();

	// if there is a data array supplied
	if( options.data != null ){
		var sFirstChar = "", stMatchSets = {}, row = [];

		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
		if( typeof options.url != "string" ) options.cacheLength = 1;

		// loop through the array and create a lookup structure
		for( var i=0; i < options.data.length; i++ ){
			// if row is a string, make an array otherwise just reference the array
			row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]);

			// if the length is zero, don't add to list
			if( row[0].length > 0 ){
				// get the first character
				sFirstChar = row[0].substring(0, 1).toLowerCase();
				// if no lookup array for this character exists, look it up now
				if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = [];
				// if the match is a string
				stMatchSets[sFirstChar].push(row);
			}
		}

		// add the data items to the cache
		for( var k in stMatchSets ){
			// increase the cache size
			options.cacheLength++;
			// add to the cache
			addToCache(k, stMatchSets[k]);
		}
	}

	$input
	.keydown(function(e) {
		// track last key pressed
		lastKeyPressCode = e.keyCode;
		switch(e.keyCode) {
			case 38: // up
				e.preventDefault();
				moveSelect(-1);
				break;
			case 40: // down
				e.preventDefault();
				moveSelect(1);
				break;
			case 9:  // tab
			case 13: // return
				if( selectCurrent() ){
					// make sure to blur off the current field
					$input.get(0).blur();
					e.preventDefault();
				}
				break;
			default:
				active = -1;
				if (timeout) clearTimeout(timeout);
				timeout = setTimeout(function(){onChange();}, options.delay);
				break;
		}
	})
	.focus(function(){
		// track whether the field has focus, we shouldn't process any results if the field no longer has focus
		hasFocus = true;
	})
	.blur(function() {
		// track whether the field has focus
		hasFocus = false;
		hideResults();
	});

	hideResultsNow();

	function onChange() {
		// ignore if the following keys are pressed: [del] [shift] [capslock]
		if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide();
		var v = $input.val();
		if (v == prev) return;
		prev = v;
		if (v.length >= options.minChars) {
			$input.addClass(options.loadingClass);
			requestData(v);
		} else {
			$input.removeClass(options.loadingClass);
			$results.hide();
		}
	};

 	function moveSelect(step) {

		var lis = $("li", results);
		if (!lis) return;

		active += step;

		if (active < 0) {
			active = 0;
		} else if (active >= lis.size()) {
			active = lis.size() - 1;
		}

		lis.removeClass("ac_over");

		$(lis[active]).addClass("ac_over");

		// Weird behaviour in IE
		// if (lis[active] && lis[active].scrollIntoView) {
		// 	lis[active].scrollIntoView(false);
		// }

	};

	function selectCurrent() {
		var li = $("li.ac_over", results)[0];
		if (!li) {
			var $li = $("li", results);
			if (options.selectOnly) {
				if ($li.length == 1) li = $li[0];


			} else if (options.selectFirst) {
				li = $li[0];
			}
		}
		if (li) {
			selectItem(li);
			return true;
		} else {
			return false;
		}
	};

	function selectItem(li) {
		if (!li) {
			li = document.createElement("li");
			li.extra = [];
			li.selectValue = "";
		}
		var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
		input.lastSelected = v;
		prev = v;
		$results.html("");
		$input.val(v);
		hideResultsNow();
		if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);
	};

	// selects a portion of the input string
	function createSelection(start, end){
		// get a reference to the input element
		var field = $input.get(0);
		if( field.createTextRange ){
			var selRange = field.createTextRange();
			selRange.collapse(true);
			selRange.moveStart("character", start);
			selRange.moveEnd("character", end);
			selRange.select();
		} else if( field.setSelectionRange ){
			field.setSelectionRange(start, end);
		} else {
			if( field.selectionStart ){
				field.selectionStart = start;
				field.selectionEnd = end;
			}
		}
		field.focus();
	};

	// fills in the input box w/the first match (assumed to be the best match)
	function autoFill(sValue){
		// if the last user key pressed was backspace, don't autofill
		if( lastKeyPressCode != 8 ){
			// fill in the value (keep the case the user has typed)
			$input.val($input.val() + sValue.substring(prev.length));
			// select the portion of the value not typed by the user (so the next character will erase)
			createSelection(prev.length, sValue.length);
		}
	};

	function showResults() {
		// get the position of the input field right now (in case the DOM is shifted)
		var pos = findPos(input);
		// either use the specified width, or autocalculate based on form element
		var iWidth = (options.width > 0) ? options.width : $input.width();
		// reposition
		$results.css({
			width: parseInt(iWidth) + "px",
			top: (pos.y + input.offsetHeight) + "px",
			left: pos.x + "px"
		}).show();
	};

	function hideResults() {
		if (timeout) clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, 200);
	};

	function hideResultsNow() {
		if (timeout) clearTimeout(timeout);
		$input.removeClass(options.loadingClass);
		if ($results.is(":visible")) {
			$results.hide();
		}
		if (options.mustMatch) {
			var v = $input.val();
			if (v != input.lastSelected) {
				selectItem(null);
			}
		}
	};

	function receiveData(q, data) {
		if (data) {
			$input.removeClass(options.loadingClass);
			results.innerHTML = "";

			// if the field no longer has focus or if there are no matches, do not display the drop down
			if( !hasFocus || data.length == 0 ) return hideResultsNow();

			if ($.browser.msie) {
				// we put a styled iframe behind the calendar so HTML SELECT elements don't show through
				$results.append(document.createElement('iframe'));
			}
			results.appendChild(dataToDom(data));
			// autofill in the complete box w/the first match as long as the user hasn't entered in more data
			if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);
			showResults();
		} else {
			hideResultsNow();
		}
	};

	function parseData(data) {
		if (!data) return null;
		var parsed = [];
		var rows = data.split(options.lineSeparator);
		for (var i=0; i < rows.length; i++) {
			var row = $.trim(rows[i]);
			if (row) {
				parsed[parsed.length] = row.split(options.cellSeparator);
			}
		}
		return parsed;
	};

	function dataToDom(data) {
		var ul = document.createElement("ul");
		var num = data.length;

		// limited results to a max number
		if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;

		for (var i=0; i < num; i++) {
			var row = data[i];
			if (!row) continue;
			var li = document.createElement("li");
			if (options.formatItem) {
				li.innerHTML = options.formatItem(row, i, num);
				li.selectValue = row[0];
			} else {
				li.innerHTML = row[0];
				li.selectValue = row[0];
			}
			var extra = null;
			if (row.length > 1) {
				extra = [];
				for (var j=1; j < row.length; j++) {
					extra[extra.length] = row[j];
				}
			}
			li.extra = extra;
			ul.appendChild(li);
			$(li).hover(
				function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); },
				function() { $(this).removeClass("ac_over"); }
			).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });
		}
		return ul;
	};

	function requestData(q) {
		if (!options.matchCase) q = q.toLowerCase();
		var data = options.cacheLength ? loadFromCache(q) : null;
		// recieve the cached data
		if (data) {
			receiveData(q, data);
		// if an AJAX url has been supplied, try loading the data now
		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
			$.get(makeUrl(q), function(data) {
				data = parseData(data);
				addToCache(q, data);
				receiveData(q, data);
			});
		// if there's been no data found, remove the loading class
		} else {
			$input.removeClass(options.loadingClass);
		}
	};

	function makeUrl(q) {
		var url = options.url + "?q=" + encodeURI(q);
		for (var i in options.extraParams) {
			url += "&" + i + "=" + encodeURI(options.extraParams[i]);
		}
		return url;
	};

	function loadFromCache(q) {
		if (!q) return null;
		if (cache.data[q]) return cache.data[q];
		if (options.matchSubset) {
			for (var i = q.length - 1; i >= options.minChars; i--) {
				var qs = q.substr(0, i);
				var c = cache.data[qs];
				if (c) {
					var csub = [];
					for (var j = 0; j < c.length; j++) {
						var x = c[j];
						var x0 = x[0];
						if (matchSubset(x0, q)) {
							csub[csub.length] = x;
						}
					}
					return csub;
				}
			}
		}
		return null;
	};

	function matchSubset(s, sub) {
		if (!options.matchCase) s = s.toLowerCase();
		var i = s.indexOf(sub);
		if (i == -1) return false;
		return i == 0 || options.matchContains;
	};

	this.flushCache = function() {
		flushCache();
	};

	this.setExtraParams = function(p) {
		options.extraParams = p;
	};

	this.findValue = function(){
		var q = $input.val();

		if (!options.matchCase) q = q.toLowerCase();
		var data = options.cacheLength ? loadFromCache(q) : null;
		if (data) {
			findValueCallback(q, data);
		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
			$.get(makeUrl(q), function(data) {
				data = parseData(data)
				addToCache(q, data);
				findValueCallback(q, data);
			});
		} else {
			// no matches
			findValueCallback(q, null);
		}
	}

	function findValueCallback(q, data){
		if (data) $input.removeClass(options.loadingClass);

		var num = (data) ? data.length : 0;
		var li = null;

		for (var i=0; i < num; i++) {
			var row = data[i];

			if( row[0].toLowerCase() == q.toLowerCase() ){
				li = document.createElement("li");
				if (options.formatItem) {
					li.innerHTML = options.formatItem(row, i, num);
					li.selectValue = row[0];
				} else {
					li.innerHTML = row[0];
					li.selectValue = row[0];
				}
				var extra = null;
				if( row.length > 1 ){
					extra = [];
					for (var j=1; j < row.length; j++) {
						extra[extra.length] = row[j];
					}
				}
				li.extra = extra;
			}
		}

		if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1);
	}

	function addToCache(q, data) {
		if (!data || !q || !options.cacheLength) return;
		if (!cache.length || cache.length > options.cacheLength) {
			flushCache();
			cache.length++;
		} else if (!cache[q]) {
			cache.length++;
		}
		cache.data[q] = data;
	};

	function findPos(obj) {
		var curleft = obj.offsetLeft || 0;
		var curtop = obj.offsetTop || 0;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
		return {x:curleft,y:curtop};
	}
}

jQuery.fn.autocomplete = function(url, options, data) {
	// Make sure options exists
	options = options || {};
	// Set url as option
	options.url = url;
	// set some bulk local data
	options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;

	// Set default values for required options
	options.inputClass = options.inputClass || "ac_input";
	options.resultsClass = options.resultsClass || "ac_results";
	options.lineSeparator = options.lineSeparator || "\n";
	options.cellSeparator = options.cellSeparator || "|";
	options.minChars = options.minChars || 1;
	options.delay = options.delay || 400;
	options.matchCase = options.matchCase || 0;
	options.matchSubset = options.matchSubset || 1;
	options.matchContains = options.matchContains || 0;
	options.cacheLength = options.cacheLength || 1;
	options.mustMatch = options.mustMatch || 0;
	options.extraParams = options.extraParams || {};
	options.loadingClass = options.loadingClass || "ac_loading";
	options.selectFirst = options.selectFirst || false;
	options.selectOnly = options.selectOnly || false;
	options.maxItemsToShow = options.maxItemsToShow || -1;
	options.autoFill = options.autoFill || false;
	options.width = parseInt(options.width, 10) || 0;

	this.each(function() {
		var input = this;
		new jQuery.autocomplete(input, options);
	});

	// Don't break the chain
	return this;
}

jQuery.fn.autocompleteArray = function(data, options) {
	return this.autocomplete(null, options, data);
}

jQuery.fn.indexOf = function(e){
	for( var i=0; i<this.length; i++ ){
		if( this[i] == e ) return i;
	}
	return -1;
};


/*
 * jQuery validation plug-in 1.4
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.validate.js 5841 2008-08-27 20:46:54Z 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($) {

$.extend($.fn, {
	// http://docs.jquery.com/Plugins/Validation/validate
	validate: function( options ) {
		
		// if nothing is selected, return nothing; can't chain anyway
		if (!this.length) {
			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
			return;
		}
		
		// check if a validator for this form was already created
		var validator = $.data(this[0], 'validator');
		if ( validator ) {
			return validator;
		}
		
		validator = new $.validator( options, this[0] );
		$.data(this[0], 'validator', validator); 
		
		if ( validator.settings.onsubmit ) {
		
			// allow suppresing validation by adding a cancel class to the submit button
			this.find("input, button").filter(".cancel").click(function() {
				validator.cancelSubmit = true;
			});
		
			// validate the form on submit
			this.submit( function( event ) {
				if ( validator.settings.debug )
					// prevent form submit to be able to see console output
					event.preventDefault();
					
				function handle() {
					if ( validator.settings.submitHandler ) {
						validator.settings.submitHandler.call( validator, validator.currentForm );
						return false;
					}
					return true;
				}
					
				// prevent submit for invalid forms or custom submit handlers
				if ( validator.cancelSubmit ) {
					validator.cancelSubmit = false;
					return handle();
				}
				if ( validator.form() ) {
					if ( validator.pendingRequest ) {
						validator.formSubmitted = true;
						return false;
					}
					return handle();
				} else {
					validator.focusInvalid();
					return false;
				}
			});
		}
		
		return validator;
	},
	// http://docs.jquery.com/Plugins/Validation/valid
	valid: function() {
        if ( $(this[0]).is('form')) {
            return this.validate().form();
        } else {
            var valid = false;
            var validator = $(this[0].form).validate();
            this.each(function() {
				valid |= validator.element(this);
            });
            return valid;
        }
    },
	// attributes: space seperated list of attributes to retrieve and remove
	removeAttrs: function(attributes) {
		var result = {},
			$element = this;
		$.each(attributes.split(/\s/), function() {
			result[this] = $element.attr(this);
			$element.removeAttr(this);
		});
		return result;
	},
	// http://docs.jquery.com/Plugins/Validation/rules
	rules: function(command, argument) {
		var element = this[0];
		
		if (command) {
			var staticRules = $.data(element.form, 'validator').settings.rules;
			var existingRules = $.validator.staticRules(element);
			switch(command) {
			case "add":
				$.extend(existingRules, $.validator.normalizeRule(argument));
				staticRules[element.name] = existingRules;
				break;
			case "remove":
				if (!argument) {
					delete staticRules[element.name];
					return existingRules;
				}
				var filtered = {};
				$.each(argument.split(/\s/), function(index, method) {
					filtered[method] = existingRules[method];
					delete existingRules[method];
				});
				return filtered;
			}
		}
		
		var data = $.validator.normalizeRules(
		$.extend(
			{},
			$.validator.metadataRules(element),
			$.validator.classRules(element),
			$.validator.attributeRules(element),
			$.validator.staticRules(element)
		), element);
		
		// make sure required is at front
		if (data.required) {
			var param = data.required;
			delete data.required;
			data = $.extend({required: param}, data);
		}
		
		return data;
	},
	// destructive add
	push: function( t ) {
		return this.setArray( this.add(t).get() );
	}
});

// Custom selectors
$.extend($.expr[":"], {
	// http://docs.jquery.com/Plugins/Validation/blank
	blank: function(a) {return !$.trim(a.value);},
	// http://docs.jquery.com/Plugins/Validation/filled
	filled: function(a) {return !!$.trim(a.value);},
	// http://docs.jquery.com/Plugins/Validation/unchecked
	unchecked: function(a) {return !a.checked;}
});


$.format = function(source, params) {
	if ( arguments.length == 1 ) 
		return function() {
			var args = $.makeArray(arguments);
			args.unshift(source);
			return $.format.apply( this, args );
		};
	if ( arguments.length > 2 && params.constructor != Array  ) {
		params = $.makeArray(arguments).slice(1);
	}
	if ( params.constructor != Array ) {
		params = [ params ];
	}
	$.each(params, function(i, n) {
		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
	});
	return source;
};

// constructor for validator
$.validator = function( options, form ) {
	this.settings = $.extend( {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

$.extend($.validator, {

	defaults: {
		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		errorElement: "label",
		focusInvalid: true,
		errorContainer: $( [] ),
		errorLabelContainer: $( [] ),
		onsubmit: true,
		ignore: [],
		onfocusin: function(element) {
			this.lastActive = element;
				
			// hide error label and remove error class on focus if enabled
			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );
				this.errorsFor(element).hide();
			}
		},
		onfocusout: function(element) {
			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
				this.element(element);
			}
		},
		onkeyup: function(element) {
			if ( element.name in this.submitted || element == this.lastElement ) {
				this.element(element);
			}
		},
		onclick: function(element) {
			if ( element.name in this.submitted )
				this.element(element);
		},
		highlight: function( element, errorClass ) {
			$( element ).addClass( errorClass );
		},
		unhighlight: function( element, errorClass ) {
			$( element ).removeClass( errorClass );
		}
	},

	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
	setDefaults: function(settings) {
		$.extend( $.validator.defaults, settings );
	},

	messages: {
		required: "This field is required.",
		remote: "Please fix this field.",
		email: "Please enter a valid Email.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date.",
		dateDE: "Bitte geben Sie ein gültiges Datum ein.",
		number: "Please enter a valid number.",
		numberDE: "Bitte geben Sie eine Nummer ein.",
		digits: "Please enter digits only.",
		creditcard: "Please enter a valid credit card.",
		equalTo: "Password don't match.",
		accept: "Please enter a value with a valid extension.",
		maxlength: $.format("No more than {0} allowed."),
		minlength: $.format("At least {0} required."),
		rangelength: $.format("Please enter a value between {0} and {1} characters long."),
		range: $.format("Please enter a value between {0} and {1}."),
		max: $.format("Please enter a value less than or equal to {0}."),
		min: $.format("Please enter a value greater than or equal to {0}.")
	},
	
	autoCreateRanges: false,
	
	prototype: {
		
		init: function() {
			this.labelContainer = $(this.settings.errorLabelContainer);
			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
			this.submitted = {};
			this.valueCache = {};
			this.pendingRequest = 0;
			this.pending = {};
			this.invalid = {};
			this.reset();
			
			var groups = (this.groups = {});
			$.each(this.settings.groups, function(key, value) {
				$.each(value.split(/\s/), function(index, name) {
					groups[name] = key;
				});
			});
			var rules = this.settings.rules;
			$.each(rules, function(key, value) {
				rules[key] = $.validator.normalizeRule(value);
			});
			
			function delegate(event) {
				var validator = $.data(this[0].form, "validator");
				validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
			}
			$(this.currentForm)
				.delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
				.delegate("click", ":radio, :checkbox", delegate);
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/form
		form: function() {
			this.checkForm();
			$.extend(this.submitted, this.errorMap);
			this.invalid = $.extend({}, this.errorMap);
			if (!this.valid())
				$(this.currentForm).triggerHandler("invalid-form.validate", [this]);
			this.showErrors();
			return this.valid();
		},
		
		checkForm: function() {
			this.prepareForm();
			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
				this.check( elements[i] );
			}
			return this.valid(); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/element
		element: function( element ) {
			element = this.clean( element );
			this.lastElement = element;
			this.prepareElement( element );
			this.currentElements = $(element);
			var result = this.check( element );
			if ( result ) {
				delete this.invalid[element.name];
			} else {
				this.invalid[element.name] = true;
			}
			if ( !this.numberOfInvalids() ) {
				// Hide error containers on last error
				this.toHide.push( this.containers );
			}
			this.showErrors();
			return result;
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
		showErrors: function(errors) {
			if(errors) {
				// add items to error list and map
				$.extend( this.errorMap, errors );
				this.errorList = [];
				for ( var name in errors ) {
					this.errorList.push({
						message: errors[name],
						element: this.findByName(name)[0]
					});
				}
				// remove items from success list
				this.successList = $.grep( this.successList, function(element) {
					return !(element.name in errors);
				});
			}
			this.settings.showErrors
				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
				: this.defaultShowErrors();
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
		resetForm: function() {
			if ( $.fn.resetForm )
				$( this.currentForm ).resetForm();
			this.submitted = {};
			this.prepareForm();
			this.hideErrors();
			this.elements().removeClass( this.settings.errorClass );
		},
		
		numberOfInvalids: function() {
			return this.objectLength(this.invalid);
		},
		
		objectLength: function( obj ) {
			var count = 0;
			for ( var i in obj )
				count++;
			return count;
		},
		
		hideErrors: function() {
			this.addWrapper( this.toHide ).hide();
		},
		
		valid: function() {
			return this.size() == 0;
		},
		
		size: function() {
			return this.errorList.length;
		},
		
		focusInvalid: function() {
			if( this.settings.focusInvalid ) {
				try {
					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
				} catch(e) { /* ignore IE throwing errors when focusing hidden elements */ }
			}
		},
		
		findLastActive: function() {
			var lastActive = this.lastActive;
			return lastActive && $.grep(this.errorList, function(n) {
				return n.element.name == lastActive.name;
			}).length == 1 && lastActive;
		},
		
		elements: function() {
			var validator = this,
				rulesCache = {};
			
			// select all valid inputs inside the form (no submit or reset buttons)
			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
			return $([]).add(this.currentForm.elements)
			.filter(":input")
			.not(":submit, :reset, :image, [disabled]")
			.not( this.settings.ignore )
			.filter(function() {
				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
			
				// select only the first element for each name, and only those with rules specified
				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
					return false;
				
				rulesCache[this.name] = true;
				return true;
			});
		},
		
		clean: function( selector ) {
			return $( selector )[0];
		},
		
		errors: function() {
			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
		},
		
		reset: function() {
			this.successList = [];
			this.errorList = [];
			this.errorMap = {};
			this.toShow = $([]);
			this.toHide = $([]);
			this.formSubmitted = false;
			this.currentElements = $([]);
		},
		
		prepareForm: function() {
			this.reset();
			this.toHide = this.errors().push( this.containers );
		},
		
		prepareElement: function( element ) {
			this.reset();
			this.toHide = this.errorsFor(element);
		},
	
		check: function( element ) {
			element = this.clean( element );
			
			// if radio/checkbox, validate first element in group instead
			if (this.checkable(element)) {
				element = this.findByName( element.name )[0];
			}
			
			var rules = $(element).rules();
			var dependencyMismatch = false;
			for( method in rules ) {
				var rule = { method: method, parameters: rules[method] };
				try {
					var result = $.validator.methods[method].call( this, element.value, element, rule.parameters );
					
					// if a method indicates that the field is optional and therefore valid,
					// don't mark it as valid when there are no other rules
					if ( result == "dependency-mismatch" ) {
						dependencyMismatch = true;
						continue;
					}
					dependencyMismatch = false;
					
					if ( result == "pending" ) {
						this.toHide = this.toHide.not( this.errorsFor(element) );
						return;
					}
					
					if( !result ) {
						this.formatAndAdd( element, rule );
						return false;
					}
				} catch(e) {
					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
						 + ", check the '" + rule.method + "' method");
					throw e;
				}
			}
			if (dependencyMismatch)
				return;
			if ( this.objectLength(rules) )
				this.successList.push(element);
			return true;
		},
		
		// return the custom message for the given element and validation method
		// specified in the element's "messages" metadata
		customMetaMessage: function(element, method) {
			if (!$.metadata)
				return;
			
			var meta = this.settings.meta
				? $(element).metadata()[this.settings.meta]
				: $(element).metadata();
			
			return meta.messages && meta.messages[method];
		},
		
		// return the custom message for the given element name and validation method
		customMessage: function( name, method ) {
			var m = this.settings.messages[name];
			return m && (m.constructor == String
				? m
				: m[method]);
		},
		
		// return the first defined argument, allowing empty strings
		findDefined: function() {
			for(var i = 0; i < arguments.length; i++) {
				if (arguments[i] !== undefined)
					return arguments[i];
			}
			return undefined;
		},
		
		defaultMessage: function( element, method) {
			return this.findDefined(
				this.customMessage( element.name, method ),
				this.customMetaMessage( element, method ),
				// title is never undefined, so handle empty string as undefined
				element.title || undefined,
				$.validator.messages[method],
				"<strong>Warning: No message defined for " + element.name + "</strong>"
			);
		},
		
		formatAndAdd: function( element, rule ) {
			var message = this.defaultMessage( element, rule.method );
			if ( typeof message == "function" ) 
				message = message.call(this, rule.parameters, element);
			this.errorList.push({
				message: message,
				element: element
			});
			this.errorMap[element.name] = message;
			this.submitted[element.name] = message;
		},
		
		addWrapper: function(toToggle) {
			if ( this.settings.wrapper )
				toToggle.push( toToggle.parents( this.settings.wrapper ) );
			return toToggle;
		},
		
		defaultShowErrors: function() {
			for ( var i = 0; this.errorList[i]; i++ ) {
				var error = this.errorList[i];
				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass );
				this.showLabel( error.element, error.message );
			}
			if( this.errorList.length ) {
				this.toShow.push( this.containers );
			}
			if (this.settings.success) {
				for ( var i = 0; this.successList[i]; i++ ) {
					this.showLabel( this.successList[i] );
				}
			}
			if (this.settings.unhighlight) {
				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass );
				}
			}
			this.toHide = this.toHide.not( this.toShow );
			this.hideErrors();
			this.addWrapper( this.toShow ).show();
		},
		
		validElements: function() {
			return this.currentElements.not(this.invalidElements());
		},
		
		invalidElements: function() {
			return $(this.errorList).map(function() {
				return this.element;
			});
		},
		
		showLabel: function(element, message) {
			var label = this.errorsFor( element );
			if ( label.length ) {
				// refresh error/success class
				label.removeClass().addClass( this.settings.errorClass );
			
				// check if we have a generated label, replace the message then
				label.attr("generated") && label.html(message);
			} else {
				// create label
				label = $("<" + this.settings.errorElement + "/>")
					.attr({"for":  this.idOrName(element), generated: true})
					.addClass(this.settings.errorClass)
					.html(message || "");
				if ( this.settings.wrapper ) {
					// make sure the element is visible, even in IE
					// actually showing the wrapped element is handled elsewhere
					label = label.hide().show().wrap("<" + this.settings.wrapper + ">").parent();
				}
				if ( !this.labelContainer.append(label).length )
					this.settings.errorPlacement
						? this.settings.errorPlacement(label, $(element) )
						: label.insertAfter(element);
			}
			if ( !message && this.settings.success ) {
				label.text("");
				typeof this.settings.success == "string"
					? label.addClass( this.settings.success )
					: this.settings.success( label );
			}
			this.toShow.push(label);
		},
		
		errorsFor: function(element) {
			return this.errors().filter("[@for='" + this.idOrName(element) + "']");
		},
		
		idOrName: function(element) {
			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
		},

		checkable: function( element ) {
			return /radio|checkbox/i.test(element.type);
		},
		
		findByName: function( name ) {
			// select by name and filter by form for performance over form.find("[name=...]")
			var form = this.currentForm;
			return $(document.getElementsByName(name)).map(function(index, element) {
				return element.form == form && element.name == name && element  || null;
			});
		},
		
		getLength: function(value, element) {
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				return $("option:selected", element).length;
			case 'input':
				if( this.checkable( element) )
					return this.findByName(element.name).filter(':checked').length;
			}
			return value.length;
		},
	
		depend: function(param, element) {
			return this.dependTypes[typeof param]
				? this.dependTypes[typeof param](param, element)
				: true;
		},
	
		dependTypes: {
			"boolean": function(param, element) {
				return param;
			},
			"string": function(param, element) {
				return !!$(param, element.form).length;
			},
			"function": function(param, element) {
				return param(element);
			}
		},
		
		optional: function(element) {
			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
		},
		
		startRequest: function(element) {
			if (!this.pending[element.name]) {
				this.pendingRequest++;
				this.pending[element.name] = true;
			}
		},
		
		stopRequest: function(element, valid) {
			this.pendingRequest--;
			// sometimes synchronization fails, make pendingRequest is never < 0
			if (this.pendingRequest < 0)
				this.pendingRequest = 0;
			delete this.pending[element.name];
			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
				$(this.currentForm).submit();
			}
		},
		
		previousValue: function(element) {
			return $.data(element, "previousValue") || $.data(element, "previousValue", previous = {
				old: null,
				valid: true,
				message: this.defaultMessage( element, "remote" )
			});
		}
		
	},
	
	classRuleSettings: {
		required: {required: true},
		email: {email: true},
		url: {url: true},
		date: {date: true},
		dateISO: {dateISO: true},
		dateDE: {dateDE: true},
		number: {number: true},
		numberDE: {numberDE: true},
		digits: {digits: true},
		creditcard: {creditcard: true}
	},
	
	addClassRules: function(className, rules) {
		className.constructor == String ?
			this.classRuleSettings[className] = rules :
			$.extend(this.classRuleSettings, className);
	},
	
	classRules: function(element) {
		var rules = {};
		var classes = $(element).attr('class');
		classes && $.each(classes.split(' '), function() {
			if (this in $.validator.classRuleSettings) {
				$.extend(rules, $.validator.classRuleSettings[this]);
			}
		});
		return rules;
	},
	
	attributeRules: function(element) {
		var rules = {};
		var $element = $(element);
		
		for (method in $.validator.methods) {
			var value = $element.attr(method);
			if (value) {
				rules[method] = value;
			}
		}
		
		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
			delete rules.maxlength;
		}
		
		return rules;
	},
	
	metadataRules: function(element) {
		if (!$.metadata) return {};
		
		var meta = $.data(element.form, 'validator').settings.meta;
		return meta ?
			$(element).metadata()[meta] :
			$(element).metadata();
	},
	
	staticRules: function(element) {
		var rules = {};
		var validator = $.data(element.form, 'validator');
		if (validator.settings.rules) {
			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
		}
		return rules;
	},
	
	normalizeRules: function(rules, element) {
		// handle dependency check
		$.each(rules, function(prop, val) {
			// ignore rule when param is explicitly false, eg. required:false
			if (val === false) {
				delete rules[prop];
				return;
			}
			if (val.param || val.depends) {
				var keepRule = true;
				switch (typeof val.depends) {
					case "string":
						keepRule = !!$(val.depends, element.form).length;
						break;
					case "function":
						keepRule = val.depends.call(element, element);
						break;
				}
				if (keepRule) {
					rules[prop] = val.param !== undefined ? val.param : true;
				} else {
					delete rules[prop];
				}
			}
		});
		
		// evaluate parameters
		$.each(rules, function(rule, parameter) {
			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
		});
		
		// clean number parameters
		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
			if (rules[this]) {
				rules[this] = Number(rules[this]);
			}
		});
		$.each(['rangelength', 'range'], function() {
			if (rules[this]) {
				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			}
		});
		
		if ($.validator.autoCreateRanges) {
			// auto-create ranges
			if (rules.min && rules.max) {
				rules.range = [rules.min, rules.max];
				delete rules.min;
				delete rules.max;
			}
			if (rules.minlength && rules.maxlength) {
				rules.rangelength = [rules.minlength, rules.maxlength];
				delete rules.minlength;
				delete rules.maxlength;
			}
		}
		
		// To support custom messages in metadata ignore rule methods titled "messages"
		if (rules.messages) {
			delete rules.messages
		}
		
		return rules;
	},
	
	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
	normalizeRule: function(data) {
		if( typeof data == "string" ) {
			var transformed = {};
			$.each(data.split(/\s/), function() {
				transformed[this] = true;
			});
			data = transformed;
		}
		return data;
	},
	
	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
	addMethod: function(name, method, message) {
		$.validator.methods[name] = method;
		$.validator.messages[name] = message;
		if (method.length < 3) {
			$.validator.addClassRules(name, $.validator.normalizeRule(name));
		}
	},

	methods: {

		// http://docs.jquery.com/Plugins/Validation/Methods/required
		required: function(value, element, param) {
			// check if dependency is met
			if ( !this.depend(param, element) )
				return "dependency-mismatch";
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				var options = $("option:selected", element);
				return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
			case 'input':
				if ( this.checkable(element) )
					return this.getLength(value, element) > 0;
			default:
				return $.trim(value).length > 0;
			}
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/remote
		remote: function(value, element, param) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			
			var previous = this.previousValue(element);
			
			if (!this.settings.messages[element.name] )
				this.settings.messages[element.name] = {};
			this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;
			
			if ( previous.old !== value ) {
				previous.old = value;
				var validator = this;
				this.startRequest(element);
				var data = {};
				data[element.name] = value;
				$.ajax({
					url: param,
					mode: "abort",
					port: "validate" + element.name,
					dataType: "json",
					data: data,
					success: function(response) {
						if ( !response ) {
							var errors = {};
							errors[element.name] =  response || validator.defaultMessage( element, "remote" );
							validator.showErrors(errors);
						} else {
							var submitted = validator.formSubmitted;
							validator.prepareElement(element);
							validator.formSubmitted = submitted;
							validator.successList.push(element);
							validator.showErrors();
						}
						previous.valid = response;
						validator.stopRequest(element, response);
					}
				});
				return "pending";
			} else if( this.pending[element.name] ) {
				return "pending";
			}
			return previous.valid;
		},

		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
		minlength: function(value, element, param) {
			return this.optional(element) || this.getLength(value, element) >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
		maxlength: function(value, element, param) {
			return this.optional(element) || this.getLength(value, element) <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
		rangelength: function(value, element, param) {
			var length = this.getLength(value, element);
			return this.optional(element) || ( length >= param[0] && length <= param[1] );
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/min
		min: function( value, element, param ) {
			return this.optional(element) || value >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/max
		max: function( value, element, param ) {
			return this.optional(element) || value <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/range
		range: function( value, element, param ) {
			return this.optional(element) || ( value >= param[0] && value <= param[1] );
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/email
		email: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
			return this.optional(element) || /^((([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(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/url
		url: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([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])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
		},
        
		// http://docs.jquery.com/Plugins/Validation/Methods/date
		date: function(value, element) {
			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
		dateISO: function(value, element) {
			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateDE
		dateDE: function(value, element) {
			return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/number
		number: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/numberDE
		numberDE: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/digits
		digits: function(value, element) {
			return this.optional(element) || /^\d+$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
		// based on http://en.wikipedia.org/wiki/Luhn
		creditcard: function(value, element) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			// accept only digits and dashes
			if (/[^0-9-]+/.test(value))
				return false;
			var nCheck = 0,
				nDigit = 0,
				bEven = false;

			value = value.replace(/\D/g, "");

			for (n = value.length - 1; n >= 0; n--) {
				var cDigit = value.charAt(n);
				var nDigit = parseInt(cDigit, 10);
				if (bEven) {
					if ((nDigit *= 2) > 9)
						nDigit -= 9;
				}
				nCheck += nDigit;
				bEven = !bEven;
			}

			return (nCheck % 10) == 0;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/accept
		accept: function(value, element, param) {
			param = typeof param == "string" ? param : "png|jpe?g|gif";
			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
		equalTo: function(value, element, param) {
			return value == $(param).val();
		}
		
	}
	
});

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
;(function($) {
	var ajax = $.ajax;
	var pendingRequests = {};
	$.ajax = function(settings) {
		// create settings for compatibility with ajaxSetup
		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
		var port = settings.port;
		if (settings.mode == "abort") {
			if ( pendingRequests[port] ) {
				pendingRequests[port].abort();
			}
			return (pendingRequests[port] = ajax.apply(this, arguments));
		}
		return ajax.apply(this, arguments);
	};
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 

// provides triggerEvent(type: String, target: Element) to trigger delegated events
;(function($) {
	$.each({
		focus: 'focusin',
		blur: 'focusout'	
	}, function( original, fix ){
		$.event.special[fix] = {
			setup:function() {
				if ( $.browser.msie ) return false;
				this.addEventListener( original, $.event.special[fix].handler, true );
			},
			teardown:function() {
				if ( $.browser.msie ) return false;
				this.removeEventListener( original,
				$.event.special[fix].handler, true );
			},
			handler: function(e) {
				arguments[0] = $.event.fix(e);
				arguments[0].type = fix;
				return $.event.handle.apply(this, arguments);
			}
		};
	});
	$.extend($.fn, {
		delegate: function(type, delegate, handler) {
			return this.bind(type, function(event) {
				var target = $(event.target);
				if (target.is(delegate)) {
					return handler.apply(target, arguments);
				}
			});
		},
		triggerEvent: function(type, target) {
			return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);
		}
	})
})(jQuery);

