/**
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($) { $.fn.hoverIntent = function(f, g) { var cfg = { sensitivity: 7, interval: 100, timeout: 0 }; cfg = $.extend(cfg, g ? { over: f, out: g} : f); var cX, cY, pX, pY; var track = function(ev) { cX = ev.pageX; cY = ev.pageY; }; var compare = function(ev, ob) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); if ((Math.abs(pX - cX) + Math.abs(pY - cY)) < cfg.sensitivity) { $(ob).unbind("mousemove", track); ob.hoverIntent_s = 1; return cfg.over.apply(ob, [ev]); } else { pX = cX; pY = cY; ob.hoverIntent_t = setTimeout(function() { compare(ev, ob); }, cfg.interval); } }; var delay = function(ev, ob) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); ob.hoverIntent_s = 0; return cfg.out.apply(ob, [ev]); }; var handleHover = function(e) { var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget; while (p && p != this) { try { p = p.parentNode; } catch (e) { p = this; } } if (p == this) { return false; } var ev = jQuery.extend({}, e); var ob = this; if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); } if (e.type == "mouseover") { pX = ev.pageX; pY = ev.pageY; $(ob).bind("mousemove", track); if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout(function() { compare(ev, ob); }, cfg.interval); } } else { $(ob).unbind("mousemove", track); if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout(function() { delay(ev, ob); }, cfg.timeout); } } }; return this.mouseover(handleHover).mouseout(handleHover); }; })(jQuery);/*
* Superfish v1.4.8 - jQuery menu widget
* Copyright (c) 2008 Joel Birch
*
* Dual licensed under the MIT and GPL licenses:
* 	http://www.opensource.org/licenses/mit-license.php
* 	http://www.gnu.org/licenses/gpl.html
*
* CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
*/

; (function($) {
    $.fn.superfish = function(op) {

        var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="', c.arrowClass, '"> &#187;</span>'].join('')),
			over = function() {
			    var $$ = $(this), menu = getMenu($$);
			    clearTimeout(menu.sfTimer);
			    $$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function() {
			    var $$ = $(this), menu = getMenu($$), o = sf.op;
			    clearTimeout(menu.sfTimer);
			    menu.sfTimer = setTimeout(function() {
			        o.retainPath = ($.inArray($$[0], o.$path) > -1);
			        $$.hideSuperfishUl();
			        if (o.$path.length && $$.parents(['li.', o.hoverClass].join('')).length < 1) { over.call(o.$path); }
			    }, o.delay);
			},
			getMenu = function($menu) {
			    var menu = $menu.parents(['ul.', c.menuClass, ':first'].join(''))[0];
			    sf.op = sf.o[menu.serial];
			    return menu;
			},
			addArrow = function($a) { $a.addClass(c.anchorClass).append($arrow.clone()); };

        return this.each(function() {
            var s = this.serial = sf.o.length;
            var o = $.extend({}, sf.defaults, op);
            o.$path = $('li.' + o.pathClass, this).slice(0, o.pathLevels).each(function() {
                $(this).addClass([o.hoverClass, c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
            });
            sf.o[s] = sf.op = o;

            $('li:has(ul)', this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over, out).each(function() {
                if (o.autoArrows) addArrow($('>a:first-child', this));
            })
			.not('.' + c.bcClass)
				.hideSuperfishUl();

            var $a = $('a', this);
            $a.each(function(i) {
                var $li = $a.eq(i).parents('li');
                $a.eq(i).focus(function() { over.call($li); }).blur(function() { out.call($li); });
            });
            o.onInit.call(this);

        }).each(function() {
            var menuClasses = [c.menuClass];
            if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
            $(this).addClass(menuClasses.join(' '));
        });
    };

    var sf = $.fn.superfish;
    sf.o = [];
    sf.op = {};
    sf.IE7fix = function() {
        var o = sf.op;
        if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity != undefined)
            this.toggleClass(sf.c.shadowClass + '-off');
    };
    sf.c = {
        bcClass: 'sf-breadcrumb',
        menuClass: 'sf-js-enabled',
        anchorClass: 'sf-with-ul',
        arrowClass: 'sf-sub-indicator',
        shadowClass: 'sf-shadow'
    };
    sf.defaults = {
        hoverClass: 'sfHover',
        pathClass: 'overideThisToUse',
        pathLevels: 1,
        delay: 800,
        animation: { opacity: 'show' },
        speed: 'normal',
        autoArrows: true,
        dropShadows: true,
        disableHI: false, 	// true disables hoverIntent detection
        onInit: function() { }, // callback functions
        onBeforeShow: function() { },
        onShow: function() { },
        onHide: function() { }
    };
    $.fn.extend({
        hideSuperfishUl: function() {
            var o = sf.op,
				not = (o.retainPath === true) ? o.$path : '';
            o.retainPath = false;
            var $ul = $(['li.', o.hoverClass].join(''), this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility', 'hidden');
            o.onHide.call($ul);
            return this;
        },
        showSuperfishUl: function() {
            var o = sf.op,
				sh = sf.c.shadowClass + '-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility', 'visible');
            sf.IE7fix.call($ul);
            o.onBeforeShow.call($ul);
            $ul.animate(o.animation, o.speed, function() { sf.IE7fix.call($ul); o.onShow.call($ul); });
            return this;
        }
    });

})(jQuery);
;/*
* Supersubs v0.2b - jQuery plugin
* Copyright (c) 2008 Joel Birch
*
* Dual licensed under the MIT and GPL licenses:
* 	http://www.opensource.org/licenses/mit-license.php
* 	http://www.gnu.org/licenses/gpl.html
*
*
* This plugin automatically adjusts submenu widths of suckerfish-style menus to that of
* their longest list item children. If you use this, please expect bugs and report them
* to the jQuery Google Group with the word 'Superfish' in the subject line.
*
*/

; (function($) { // $ will refer to jQuery within this closure

    $.fn.supersubs = function(options) {
        var opts = $.extend({}, $.fn.supersubs.defaults, options);
        // return original object to support chaining
        return this.each(function() {
            // cache selections
            var $$ = $(this);
            // support metadata
            var o = $.meta ? $.extend({}, opts, $$.data()) : opts;
            // get the font size of menu.
            // .css('fontSize') returns various results cross-browser, so measure an em dash instead
            var fontsize = $('<li id="menu-fontsize">&#8212;</li>').css({
                'padding': 0,
                'position': 'absolute',
                'top': '-999em',
                'width': 'auto'
            }).appendTo($$).width(); //clientWidth is faster, but was incorrect here
            // remove em dash
            $('#menu-fontsize').remove();
            // cache all ul elements
            $ULs = $$.find('ul');
            // loop through each ul in menu
            $ULs.each(function(i) {
                // cache this ul
                var $ul = $ULs.eq(i);
                // get all (li) children of this ul
                var $LIs = $ul.children();
                // get all anchor grand-children
                var $As = $LIs.children('a');
                // force content to one line and save current float property
                var liFloat = $LIs.css('white-space', 'nowrap').css('float');
                // remove width restrictions and floats so elements remain vertically stacked
                var emWidth = $ul.add($LIs).add($As).css({
                    'float': 'none',
                    'width': 'auto'
                })
                // this ul will now be shrink-wrapped to longest li due to position:absolute
                // so save its width as ems. Clientwidth is 2 times faster than .width() - thanks Dan Switzer
				.end().end()[0].clientWidth / fontsize;
                // add more width to ensure lines don't turn over at certain sizes in various browsers
                emWidth += o.extraWidth;
                // restrict to at least minWidth and at most maxWidth
                if (emWidth > o.maxWidth) { emWidth = o.maxWidth; }
                else if (emWidth < o.minWidth) { emWidth = o.minWidth; }
                emWidth += 'em';
                // set ul to width in ems
                $ul.css('width', emWidth);
                // restore li floats to avoid IE bugs
                // set li width to full width of this ul
                // revert white-space to normal
                $LIs.css({
                    'float': liFloat,
                    'width': '100%',
                    'white-space': 'normal'
                })
                // update offset position of descendant ul to reflect new width of parent
				.each(function() {
				    var $childUl = $('>ul', this);
				    var offsetDirection = $childUl.css('left') !== undefined ? 'left' : 'right';
				    $childUl.css(offsetDirection, emWidth);
				});
            });

        });
    };
    // expose defaults
    $.fn.supersubs.defaults = {
        minWidth: 9, 	// requires em unit.
        maxWidth: 25, 	// requires em unit.
        extraWidth: 0			// extra width can ensure lines don't sometimes turn over due to slight browser differences in how they round-off values
    };

})(jQuery); // plugin code ends
;/*
* jQuery Media Plugin for converting elements into rich media content.
*
* Examples and documentation at: http://malsup.com/jquery/media/
* Copyright (c) 2007-2008 M. Alsup
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* @author: M. Alsup
* @version: 0.85 (07-FEB-2009)
* @requires jQuery v1.1.2 or later
* $Id: jquery.media.js 2460 2007-07-23 02:53:15Z malsup $
*
* Supported Media Players:
*    - Flash
*    - Quicktime
*    - Real Player
*    - Silverlight
*    - Windows Media Player
*    - iframe
*
* Supported Media Formats:
*   Any types supported by the above players, such as:
*     Video: asf, avi, flv, mov, mpg, mpeg, mp4, qt, smil, swf, wmv, 3g2, 3gp
*     Audio: aif, aac, au, gsm, mid, midi, mov, mp3, m4a, snd, rm, wav, wma
*     Other: bmp, html, pdf, psd, qif, qtif, qti, tif, tiff, xaml
*
* Thanks to Mark Hicken and Brent Pedersen for helping me debug this on the Mac!
* Thanks to Dan Rossi for numerous bug reports and code bits!
*/
; (function($) {

    /**
    * Chainable method for converting elements into rich media.
    *
    * @param options
    * @param callback fn invoked for each matched element before conversion
    * @param callback fn invoked for each matched element after conversion
    */
    $.fn.media = function(options, f1, f2) {
        return this.each(function() {
            if (typeof options == 'function') {
                f2 = f1;
                f1 = options;
                options = {};
            }
            var o = getSettings(this, options);
            // pre-conversion callback, passes original element and fully populated options
            if (typeof f1 == 'function') f1(this, o);

            var r = getTypesRegExp();
            var m = r.exec(o.src) || [''];
            o.type ? m[0] = o.type : m.shift();
            for (var i = 0; i < m.length; i++) {
                fn = m[i].toLowerCase();
                if (isDigit(fn[0])) fn = 'fn' + fn; // fns can't begin with numbers
                if (!$.fn.media[fn])
                    continue;  // unrecognized media type
                // normalize autoplay settings
                var player = $.fn.media[fn + '_player'];
                if (!o.params) o.params = {};
                if (player) {
                    var num = player.autoplayAttr == 'autostart';
                    o.params[player.autoplayAttr || 'autoplay'] = num ? (o.autoplay ? 1 : 0) : o.autoplay ? true : false;
                }
                var $div = $.fn.media[fn](this, o);

                $div.css('backgroundColor', o.bgColor).width(o.width);
                // post-conversion callback, passes original element, new div element and fully populated options
                if (typeof f2 == 'function') f2(this, $div[0], o, player.name);
                break;
            }
        });
    };

    /**
    * Non-chainable method for adding or changing file format / player mapping
    * @name mapFormat
    * @param String format File format extension (ie: mov, wav, mp3)
    * @param String player Player name to use for the format (one of: flash, quicktime, realplayer, winmedia, silverlight or iframe
    */
    $.fn.media.mapFormat = function(format, player) {
        if (!format || !player || !$.fn.media.defaults.players[player]) return; // invalid
        format = format.toLowerCase();
        if (isDigit(format[0])) format = 'fn' + format;
        $.fn.media[format] = $.fn.media[player];
        $.fn.media[format + '_player'] = $.fn.media.defaults.players[player];
    };

    // global defautls; override as needed
    $.fn.media.defaults = {
        width: 400,
        height: 400,
        autoplay: 0,         // normalized cross-player setting
        bgColor: '#ffffff', // background color
        params: { wmode: 'transparent' },  // added to object element as param elements; added to embed element as attrs
        attrs: {},        // added to object and embed elements as attrs
        flvKeyName: 'file',    // key used for object src param (thanks to Andrea Ercolino)
        flashvars: {},        // added to flash content as flashvars param/attr
        flashVersion: '7',       // required flash version
        expressInstaller: null,   // src for express installer

        // default flash video and mp3 player (@see: http://jeroenwijering.com/?item=Flash_Media_Player)
        flvPlayer: 'mediaplayer.swf',
        mp3Player: 'mediaplayer.swf',

        // @see http://msdn2.microsoft.com/en-us/library/bb412401.aspx
        silverlight: {
            inplaceInstallPrompt: 'true', // display in-place install prompt?
            isWindowless: 'true', // windowless mode (false for wrapping markup)
            framerate: '24',   // maximum framerate
            version: '0.9',  // Silverlight version
            onError: null,   // onError callback
            onLoad: null,   // onLoad callback
            initParams: null,   // object init params
            userContext: null    // callback arg passed to the load callback
        }
    };

    // Media Players; think twice before overriding
    $.fn.media.defaults.players = {
        flash: {
            name: 'flash',
            types: 'flv,mp3,swf',
            oAttrs: {
                classid: 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
                type: 'application/x-oleobject',
                codebase: 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + $.fn.media.defaults.flashVersion
            },
            eAttrs: {
                type: 'application/x-shockwave-flash',
                pluginspage: 'http://www.adobe.com/go/getflashplayer'
            }
        },
        quicktime: {
            name: 'quicktime',
            types: 'aif,aiff,aac,au,bmp,gsm,mov,mid,midi,mpg,mpeg,mp4,m4a,psd,qt,qtif,qif,qti,snd,tif,tiff,wav,3g2,3gp',
            oAttrs: {
                classid: 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
                codebase: 'http://www.apple.com/qtactivex/qtplugin.cab'
            },
            eAttrs: {
                pluginspage: 'http://www.apple.com/quicktime/download/'
            }
        },
        realplayer: {
            name: 'real',
            types: 'ra,ram,rm,rpm,rv,smi,smil',
            autoplayAttr: 'autostart',
            oAttrs: {
                classid: 'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA'
            },
            eAttrs: {
                type: 'audio/x-pn-realaudio-plugin',
                pluginspage: 'http://www.real.com/player/'
            }
        },
        winmedia: {
            name: 'winmedia',
            types: 'asx,asf,avi,wma,wmv',
            autoplayAttr: 'autostart',
            oUrl: 'url',
            oAttrs: {
                classid: 'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6',
                type: 'application/x-oleobject'
            },
            eAttrs: {
                type: $.browser.mozilla && isFirefoxWMPPluginInstalled() ? 'application/x-ms-wmp' : 'application/x-mplayer2',
                pluginspage: 'http://www.microsoft.com/Windows/MediaPlayer/'
            }
        },
        // special cases
        iframe: {
            name: 'iframe',
            types: 'html,pdf'
        },
        silverlight: {
            name: 'silverlight',
            types: 'xaml'
        }
    };

    //
    //  everything below here is private
    //


    // detection script for FF WMP plugin (http://www.therossman.org/experiments/wmp_play.html)
    // (hat tip to Mark Ross for this script)
    function isFirefoxWMPPluginInstalled() {
        var plugs = navigator.plugins;
        for (i = 0; i < plugs.length; i++) {
            var plugin = plugs[i];
            if (plugin['filename'] == 'np-mswmp.dll')
                return true;
        }
        return false;
    }

    var counter = 1;

    for (var player in $.fn.media.defaults.players) {
        var types = $.fn.media.defaults.players[player].types;
        $.each(types.split(','), function(i, o) {
            if (isDigit(o[0])) o = 'fn' + o;
            $.fn.media[o] = $.fn.media[player] = getGenerator(player);
            $.fn.media[o + '_player'] = $.fn.media.defaults.players[player];
        });
    };

    function getTypesRegExp() {
        var types = '';
        for (var player in $.fn.media.defaults.players) {
            if (types.length) types += ',';
            types += $.fn.media.defaults.players[player].types;
        };
        return new RegExp('\\.(' + types.replace(/,/g, '|') + ')$\\b');
    };

    function getGenerator(player) {
        return function(el, options) {
            return generate(el, options, player);
        };
    };

    function isDigit(c) {
        return '0123456789'.indexOf(c) > -1;
    };

    // flatten all possible options: global defaults, meta, option obj
    function getSettings(el, options) {
        options = options || {};
        var $el = $(el);
        var cls = el.className || '';
        // support metadata plugin (v1.0 and v2.0)
        var meta = $.metadata ? $el.metadata() : $.meta ? $el.data() : {};
        meta = meta || {};
        var w = meta.width || parseInt(((cls.match(/w:(\d+)/) || [])[1] || 0));
        var h = meta.height || parseInt(((cls.match(/h:(\d+)/) || [])[1] || 0));

        if (w) meta.width = w;
        if (h) meta.height = h;
        if (cls) meta.cls = cls;

        var a = $.fn.media.defaults;
        var b = options;
        var c = meta;

        var p = { params: { bgColor: options.bgColor || $.fn.media.defaults.bgColor} };
        var opts = $.extend({}, a, b, c);
        $.each(['attrs', 'params', 'flashvars', 'silverlight'], function(i, o) {
            opts[o] = $.extend({}, p[o] || {}, a[o] || {}, b[o] || {}, c[o] || {});
        });

        if (typeof opts.caption == 'undefined') opts.caption = $el.text();

        // make sure we have a source!
        opts.src = opts.src || $el.attr('href') || $el.attr('src') || 'unknown';
        return opts;
    };

    //
    //  Flash Player
    //

    // generate flash using SWFObject library if possible
    $.fn.media.swf = function(el, opts) {
        if (!window.SWFObject && !window.swfobject) {
            // roll our own
            if (opts.flashvars) {
                var a = [];
                for (var f in opts.flashvars)
                    a.push(f + '=' + opts.flashvars[f]);
                if (!opts.params) opts.params = {};
                opts.params.flashvars = a.join('&');
            }
            return generate(el, opts, 'flash');
        }

        var id = el.id ? (' id="' + el.id + '"') : '';
        var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
        var $div = $('<div' + id + cls + '>');

        // swfobject v2+
        if (window.swfobject) {
            $(el).after($div).appendTo($div);
            if (!el.id) el.id = 'movie_player_' + counter++;

            // replace el with swfobject content
            swfobject.embedSWF(opts.src, el.id, opts.width, opts.height, opts.flashVersion,
            opts.expressInstaller, opts.flashvars, opts.params, opts.attrs);
        }
        // swfobject < v2
        else {
            $(el).after($div).remove();
            var so = new SWFObject(opts.src, 'movie_player_' + counter++, opts.width, opts.height, opts.flashVersion, opts.bgColor);
            if (opts.expressInstaller) so.useExpressInstall(opts.expressInstaller);

            for (var p in opts.params)
                if (p != 'bgColor') so.addParam(p, opts.params[p]);
            for (var f in opts.flashvars)
                so.addVariable(f, opts.flashvars[f]);
            so.write($div[0]);
        }

        if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
        return $div;
    };

    // map flv and mp3 files to the swf player by default
    $.fn.media.flv = $.fn.media.mp3 = function(el, opts) {
        var src = opts.src;
        var player = /\.mp3\b/i.test(src) ? $.fn.media.defaults.mp3Player : $.fn.media.defaults.flvPlayer;
        var key = opts.flvKeyName;
        src = encodeURIComponent(src);
        opts.src = player;
        opts.src = opts.src + '?' + key + '=' + (src);
        var srcObj = {};
        srcObj[key] = src;
        opts.flashvars = $.extend({}, srcObj, opts.flashvars);
        return $.fn.media.swf(el, opts);
    };

    //
    //  Silverlight
    //
    $.fn.media.xaml = function(el, opts) {
        if (!window.Sys || !window.Sys.Silverlight) {
            if ($.fn.media.xaml.warning) return;
            $.fn.media.xaml.warning = 1;
            alert('You must include the Silverlight.js script.');
            return;
        }

        var props = {
            width: opts.width,
            height: opts.height,
            background: opts.bgColor,
            inplaceInstallPrompt: opts.silverlight.inplaceInstallPrompt,
            isWindowless: opts.silverlight.isWindowless,
            framerate: opts.silverlight.framerate,
            version: opts.silverlight.version
        };
        var events = {
            onError: opts.silverlight.onError,
            onLoad: opts.silverlight.onLoad
        };

        var id1 = el.id ? (' id="' + el.id + '"') : '';
        var id2 = opts.id || 'AG' + counter++;
        // convert element to div
        var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
        var $div = $('<div' + id1 + cls + '>');
        $(el).after($div).remove();

        Sys.Silverlight.createObjectEx({
            source: opts.src,
            initParams: opts.silverlight.initParams,
            userContext: opts.silverlight.userContext,
            id: id2,
            parentElement: $div[0],
            properties: props,
            events: events
        });

        if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
        return $div;
    };

    //
    // generate object/embed markup
    //
    function generate(el, opts, player) {
        var $el = $(el);
        var o = $.fn.media.defaults.players[player];

        if (player == 'iframe') {
            var o = $('<iframe' + ' width="' + opts.width + '" height="' + opts.height + '" >');
            o.attr('src', opts.src);
            o.css('backgroundColor', o.bgColor);
        }
        else if ($.browser.msie) {
            var a = ['<object width="' + opts.width + '" height="' + opts.height + '" '];
            for (var key in opts.attrs)
                a.push(key + '="' + opts.attrs[key] + '" ');
            for (var key in o.oAttrs || {}) {
                var v = o.oAttrs[key];
                if (key == 'codebase' && window.location.protocol == 'https')
                    v = v.replace('http', 'https');
                a.push(key + '="' + v + '" ');
            }
            a.push('></ob' + 'ject' + '>');
            var p = ['<param name="' + (o.oUrl || 'src') + '" value="' + opts.src + '">'];
            for (var key in opts.params)
                p.push('<param name="' + key + '" value="' + opts.params[key] + '">');
            var o = document.createElement(a.join(''));
            for (var i = 0; i < p.length; i++)
                o.appendChild(document.createElement(p[i]));
        }
        else {
            var a = ['<embed width="' + opts.width + '" height="' + opts.height + '" style="display:block"'];
            if (opts.src) a.push(' src="' + opts.src + '" ');
            for (var key in opts.attrs)
                a.push(key + '="' + opts.attrs[key] + '" ');
            for (var key in o.eAttrs || {})
                a.push(key + '="' + o.eAttrs[key] + '" ');
            for (var key in opts.params)
                if (key != 'wmode') // FF3/Quicktime borks on wmode
                a.push(key + '="' + opts.params[key] + '" ');
            a.push('></em' + 'bed' + '>');
        }
        // convert element to div
        var id = el.id ? (' id="' + el.id + '"') : '';
        var cls = opts.cls ? (' class="' + opts.cls + '"') : '';
        var $div = $('<div' + id + cls + '>');
        $el.after($div).remove();
        ($.browser.msie || player == 'iframe') ? $div.append(o) : $div.html(a.join(''));
        if (opts.caption) $('<div>').appendTo($div).html(opts.caption);
        return $div;
    };


})(jQuery);
;(function($) {
    $.fn.watermark = function(options) {
        var defaults = {
            color: '#999',
            psw: 'password'
        };
        var options = $.extend(defaults, options);
        return this.each(function() {
            var obj = $(this);
            var p = obj.parents('form');
            if (p.length != 0) p.bind('submit', function() {
                if (obj.val() == obj.attr('base')) obj.val('');
            });
            obj.attr('baseColor', obj.css('color'));
            if (obj.attr('type') == 'password') obj.val(options.psw);
            if (!obj.attr('base')) obj.attr('base', obj.val());
            obj.attr('isWatermark', 1);
            obj.css('color', options.color);
            obj.bind('focus', function() {
                var o = $(this);
                if (o.val() != o.attr('base') && o.val() != '') {
                    o.attr("isWatermark", 0);
                }
                if (o.attr('isWatermark') == 1) {
                    o.val('');
                    o.attr('isWatermark', 0);
                    o.css('color', o.attr('baseColor'));
                }
            }).bind('blur', function() {
                var o = $(this);
                if (o.val() != o.attr('base') && o.val() != '') {
                    o.attr('isWatermark', 1);
                }
                if (o.attr('isWatermark') == 0) {
                    o.css("color", options.color);
                    if (o.val() == '') {
                        o.attr('isWatermark', 1);
                        o.val(o.attr('base'));
                    }
                }
            });
        });
    };
})(jQuery);/*
===============================================================================
Chili is the jQuery code highlighter plugin
...............................................................................
LICENSE: http://www.opensource.org/licenses/mit-license.php
WEBSITE: http://noteslog.com/chili/

											   Copyright 2008 / Andrea Ercolino
===============================================================================
*/


(function($) {

    ChiliBook = { //implied global

        version: "2.2" // 2008-07-06

        // options --------------------------------------------------------------------

	, automatic: true
	, automaticSelector: "code"

	, lineNumbers: !true

	, codeLanguage: function(el) {
	    var recipeName = $(el).attr("class");
	    return recipeName ? recipeName : '';
	}

	, recipeLoading: true
	, recipeFolder: "" // used like: recipeFolder + recipeName + '.js'

        // IE and FF convert &#160; to "&nbsp;", Safari and Opera do not
	, replaceSpace: "&#160;"
	, replaceTab: "&#160;&#160;&#160;&#160;"
	, replaceNewLine: "&#160;<br/>"

	, selectionStyle: ["position:absolute; z-index:3000; overflow:scroll;"
						  , "width:16em;"
						  , "height:9em;"
						  , "border:1px solid gray;"
						  , "padding:15px;"
						  , "background-color:yellow;"
						  ].join(' ')

        // ------------------------------------------------------------- end of options

	, defaultReplacement: '<span class="$0">$$</span>' // TODO: make this an option again
	, recipes: {} //repository
	, queue: {} //registry

	, unique: function() {
	    return (new Date()).valueOf();
	}
    };



    $.fn.chili = function(options) {
        var book = $.extend({}, ChiliBook, options || {});

        function cook(ingredients, recipe, blockName) {

            function prepareBlock(recipe, blockName) {
                var steps = [];
                for (var stepName in recipe[blockName]) {
                    steps.push(prepareStep(recipe, blockName, stepName));
                }
                return steps;
            } // prepareBlock

            function prepareStep(recipe, blockName, stepName) {
                var step = recipe[blockName][stepName];
                var exp = (typeof step._match == "string") ? step._match : step._match.source;
                return {
                    recipe: recipe
				, blockName: blockName
				, stepName: stepName
				, exp: "(" + exp + ")"
				, length: 1                         // add 1 to account for the newly added parentheses
					+ (exp                          // count number of submatches in here
						.replace(/\\./g, "%")     // disable any escaped character
						.replace(/\[.*?\]/g, "%") // disable any character class
						.match(/\((?!\?)/g)       // match any open parenthesis, not followed by a ?
					|| []                           // make sure it is an empty array if there are no matches
					).length                        // get the number of matches
				, replacement: step._replace ? step._replace : book.defaultReplacement
                };
            } // prepareStep

            function knowHow(steps) {
                var prevLength = 1;
                var exps = [];
                for (var i = 0; i < steps.length; i++) {
                    var exp = steps[i].exp;
                    // adjust backreferences
                    exp = exp.replace(/\\\\|\\(\d+)/g, function(m, aNum) {
                        return !aNum ? m : "\\" + (prevLength + 1 + parseInt(aNum, 10));
                    });
                    exps.push(exp);
                    prevLength += steps[i].length;
                }
                var prolog = '((?:\\s|\\S)*?)';
                var epilog = '((?:\\s|\\S)+)';
                var source = '(?:' + exps.join("|") + ')';
                source = prolog + source + '|' + epilog;
                return new RegExp(source, recipe._case ? "g" : "gi");
            } // knowHow

            function escapeHTML(str) {
                return str.replace(/&/g, "&amp;").replace(/</g, "&lt;");
            } // escapeHTML

            function replaceSpaces(str) {
                return str.replace(/ +/g, function(spaces) {
                    return spaces.replace(/ /g, replaceSpace);
                });
            } // replaceSpaces

            function filter(str) {
                str = escapeHTML(str);
                if (replaceSpace) {
                    str = replaceSpaces(str);
                }
                return str;
            } // filter

            function applyRecipe(subject, recipe) {
                return cook(subject, recipe);
            } // applyRecipe

            function applyBlock(subject, recipe, blockName) {
                return cook(subject, recipe, blockName);
            } // applyBlock

            function applyStep(subject, recipe, blockName, stepName) {
                var replaceSpace = book.replaceSpace;

                var step = prepareStep(recipe, blockName, stepName);
                var steps = [step];

                var perfect = subject.replace(knowHow(steps), function() {
                    return chef.apply({ steps: steps }, arguments);
                });
                return perfect;
            } // applyStep

            function applyModule(subject, module, context) {
                if (!module) {
                    return filter(subject);
                }

                var sub = module.split('/');
                var recipeName = '';
                var blockName = '';
                var stepName = '';
                switch (sub.length) {
                    case 1:
                        recipeName = sub[0];
                        break;
                    case 2:
                        recipeName = sub[0]; blockName = sub[1];
                        break;
                    case 3:
                        recipeName = sub[0]; blockName = sub[1]; stepName = sub[2];
                        break;
                    default:
                        return filter(subject);
                }

                function getRecipe(recipeName) {
                    var path = getPath(recipeName);
                    var recipe = book.recipes[path];
                    if (!recipe) {
                        throw { msg: "recipe not available" };
                    }
                    return recipe;
                }

                try {
                    var recipe;
                    if ('' == stepName) {
                        if ('' == blockName) {
                            if ('' == recipeName) {
                                //nothing to do
                            }
                            else { // ( '' != recipeName )
                                recipe = getRecipe(recipeName);
                                return applyRecipe(subject, recipe);
                            }
                        }
                        else { // ( '' != blockName )
                            if ('' == recipeName) {
                                recipe = context.recipe;
                            }
                            else {
                                recipe = getRecipe(recipeName);
                            }
                            if (!(blockName in recipe)) {
                                return filter(subject);
                            }
                            return applyBlock(subject, recipe, blockName);
                        }
                    }
                    else { // ( '' != stepName )
                        if ('' == recipeName) {
                            recipe = context.recipe;
                        }
                        else {
                            recipe = getRecipe(recipeName);
                        }
                        if ('' == blockName) {
                            blockName = context.blockName;
                        }
                        if (!(blockName in recipe)) {
                            return filter(subject);
                        }
                        if (!(stepName in recipe[blockName])) {
                            return filter(subject);
                        }
                        return applyStep(subject, recipe, blockName, stepName);
                    }
                }
                catch (e) {
                    if (e.msg && e.msg == "recipe not available") {
                        var cue = 'chili_' + book.unique();
                        if (book.recipeLoading) {
                            var path = getPath(recipeName);
                            if (!book.queue[path]) {
                                /* this is a new recipe to download */
                                try {
                                    book.queue[path] = [{ cue: cue, subject: subject, module: module, context: context}];
                                    $.getJSON(path, function(recipeLoaded) {
                                        book.recipes[path] = recipeLoaded;
                                        var q = book.queue[path];
                                        for (var i = 0, iTop = q.length; i < iTop; i++) {
                                            var replacement = applyModule(q[i].subject, q[i].module, q[i].context);
                                            if (book.replaceTab) {
                                                replacement = replacement.replace(/\t/g, book.replaceTab);
                                            }
                                            if (book.replaceNewLine) {
                                                replacement = replacement.replace(/\n/g, book.replaceNewLine);
                                            }
                                            $('#' + q[i].cue).replaceWith(replacement);
                                        }
                                    });
                                }
                                catch (recipeNotAvailable) {
                                    alert("the recipe for '" + recipeName + "' was not found in '" + path + "'");
                                }
                            }
                            else {
                                /* not a new recipe, so just enqueue this element */
                                book.queue[path].push({ cue: cue, subject: subject, module: module, context: context });
                            }
                            return '<span id="' + cue + '">' + filter(subject) + '</span>';
                        }
                        return filter(subject);
                    }
                    else {
                        return filter(subject);
                    }
                }
            } // applyModule

            function addPrefix(prefix, replacement) {
                var aux = replacement.replace(/(<span\s+class\s*=\s*(["']))((?:(?!__)\w)+\2\s*>)/ig, "$1" + prefix + "__$3");
                return aux;
            } // addPrefix

            function chef() {
                if (!arguments[0]) {
                    return '';
                }
                var steps = this.steps;
                var i = 0;  // iterate steps
                var j = 2; // iterate chef's arguments
                var prolog = arguments[1];
                var epilog = arguments[arguments.length - 3];
                if (!epilog) {
                    var step;
                    while (step = steps[i++]) {
                        var aux = arguments; // this unmasks chef's arguments inside the next function
                        if (aux[j]) {
                            var replacement = '';
                            if ($.isFunction(step.replacement)) {
                                var matches = []; //Array.slice.call( aux, j, step.length );
                                for (var k = 0, kTop = step.length; k < kTop; k++) {
                                    matches.push(aux[j + k]);
                                }
                                matches.push(aux[aux.length - 2]);
                                matches.push(aux[aux.length - 1]);
                                replacement = step.replacement
								.apply({
								    x: function() {
								        var subject = arguments[0];
								        var module = arguments[1];
								        var context = {
								            recipe: step.recipe
											, blockName: step.blockName
								        };
								        return applyModule(subject, module, context);
								    }
								}, matches);
                            }
                            else { //we expect step.replacement to be a string
                                replacement = step.replacement
								.replace(/(\\\$)|(?:\$\$)|(?:\$(\d+))/g, function(m, escaped, K) {
								    if (escaped) {       /* \$ */
								        return "$";
								    }
								    else if (!K) {       /* $$ */
								        return filter(aux[j]);
								    }
								    else if (K == "0") { /* $0 */
								        return step.stepName;
								    }
								    else {                /* $K */
								        return filter(aux[j + parseInt(K, 10)]);
								    }
								});
                            }
                            replacement = addPrefix(step.recipe._name, replacement);
                            return filter(prolog) + replacement;
                        }
                        else {
                            j += step.length;
                        }
                    }
                }
                else {
                    return filter(epilog);
                }
            } // chef

            if (!blockName) {
                blockName = '_main';
                checkSpices(recipe);
            }
            if (!(blockName in recipe)) {
                return filter(ingredients);
            }
            var replaceSpace = book.replaceSpace;
            var steps = prepareBlock(recipe, blockName);
            var kh = knowHow(steps);
            var perfect = ingredients.replace(kh, function() {
                return chef.apply({ steps: steps }, arguments);
            });
            return perfect;

        } // cook

        function loadStylesheetInline(sourceCode) {
            if (document.createElement) {
                var e = document.createElement("style");
                e.type = "text/css";
                if (e.styleSheet) { // IE 
                    e.styleSheet.cssText = sourceCode;
                }
                else {
                    var t = document.createTextNode(sourceCode);
                    e.appendChild(t);
                }
                document.getElementsByTagName("head")[0].appendChild(e);
            }
        } // loadStylesheetInline

        function checkSpices(recipe) {
            var name = recipe._name;
            if (!book.queue[name]) {

                var content = ['/* Chili -- ' + name + ' */'];
                for (var blockName in recipe) {
                    if (blockName.search(/^_(?!main\b)/) < 0) {
                        for (var stepName in recipe[blockName]) {
                            var step = recipe[blockName][stepName];
                            if ('_style' in step) {
                                if (step['_style'].constructor == String) {
                                    content.push('.' + name + '__' + stepName + ' { ' + step['_style'] + ' }');
                                }
                                else {
                                    for (var className in step['_style']) {
                                        content.push('.' + name + '__' + className + ' { ' + step['_style'][className] + ' }');
                                    }
                                }
                            }
                        }
                    }
                }
                content = content.join('\n');

                loadStylesheetInline(content);

                book.queue[name] = true;
            }
        } // checkSpices

        function askDish(el) {
            var recipeName = book.codeLanguage(el);
            if ('' != recipeName) {
                var path = getPath(recipeName);
                if (book.recipeLoading) {
                    /* dynamic setups come here */
                    if (!book.queue[path]) {
                        /* this is a new recipe to download */
                        try {
                            book.queue[path] = [el];
                            $.getJSON(path, function(recipeLoaded) {
                                book.recipes[path] = recipeLoaded;
                                var q = book.queue[path];
                                for (var i = 0, iTop = q.length; i < iTop; i++) {
                                    makeDish(q[i], path);
                                }
                            });
                        }
                        catch (recipeNotAvailable) {
                            alert("the recipe for '" + recipeName + "' was not found in '" + path + "'");
                        }
                    }
                    else {
                        /* not a new recipe, so just enqueue this element */
                        book.queue[path].push(el);
                    }
                    /* a recipe could have been already downloaded */
                    makeDish(el, path);
                }
                else {
                    /* static setups come here */
                    makeDish(el, path);
                }
            }
        } // askDish

        function makeDish(el, recipePath) {
            var recipe = book.recipes[recipePath];
            if (!recipe) {
                return;
            }
            var $el = $(el);
            var ingredients = $el.text();
            if (!ingredients) {
                return;
            }

            //fix for msie: \r (13) is used instead of \n (10)
            //fix for opera: \r\n is used instead of \n
            ingredients = ingredients.replace(/\r\n?/g, "\n");

            //reverse fix for safari: msie, mozilla and opera render the initial \n
            if ($el.parent().is('pre')) {
                if (!$.browser.safari) {
                    ingredients = ingredients.replace(/^\n/g, "");
                }
            }

            var dish = cook(ingredients, recipe); // all happens here

            if (book.replaceTab) {
                dish = dish.replace(/\t/g, book.replaceTab);
            }
            if (book.replaceNewLine) {
                dish = dish.replace(/\n/g, book.replaceNewLine);
            }

            el.innerHTML = dish; //much faster than $el.html( dish );
            //tried also the function replaceHtml from http://blog.stevenlevithan.com/archives/faster-than-innerhtml
            //but it was not faster nor without sideffects (it was not possible to count spans into el)

            //opera and safari select PRE text correctly 
            if ($.browser.msie || $.browser.mozilla) {
                enableSelectionHelper(el);
            }

            var $that = $el.parent();
            var classes = $that.attr('class');
            var ln = /ln-(\d+)-([\w][\w\-]*)|ln-(\d+)|ln-/.exec(classes);
            if (ln) {
                addLineNumbers(el);
                var start = 0;
                if (ln[1]) {
                    start = parseInt(ln[1], 10);
                    var $pieces = $('.ln-' + ln[1] + '-' + ln[2]);
                    var pos = $pieces.index($that[0]);
                    $pieces.slice(0, pos).each(function() {
                        start += $(this).find('li').length;
                    });
                }
                else if (ln[3]) {
                    start = parseInt(ln[3], 10);
                }
                else {
                    start = 1;
                }
                $el.find('ol')[0].start = start;
                $('body').width($('body').width() - 1).width($('body').width() + 1);
            }
            else if (book.lineNumbers) {
                addLineNumbers(el);
            }

        } // makeDish

        function enableSelectionHelper(el) {
            return false; // Uncomment this line to re-enable the selection helper
             //var element = null;
            $(el)
		.parents()
		.filter("pre")
		.bind("mousedown", function() {
		    element = this;
		    if ($.browser.msie) {
		        document.selection.empty();
		    }
		    else {
		        window.getSelection().removeAllRanges();
		    }
		})
		.bind("mouseup", function(event) {
		    if (element && (element == this)) {
		        element = null;
		        var selected = '';
		        if ($.browser.msie) {
		            selected = document.selection.createRange().htmlText;
		            if ('' == selected) {
		                return;
		            }
		            selected = preserveNewLines(selected);
		            var container_tag = '<textarea style="STYLE">';
		        }
		        else {
		            selected = window.getSelection().toString(); //opera doesn't select new lines
		            if ('' == selected) {
		                return;
		            }
		            selected = selected
						.replace(/\r/g, '')
						.replace(/^# ?/g, '')
						.replace(/\n# ?/g, '\n')
					;
		            var container_tag = '<pre style="STYLE">';
		        }
		        var $container = $(container_tag.replace(/\bSTYLE\b/, ChiliBook.selectionStyle))
					.appendTo('body')
					.text(selected)
					.attr('id', 'chili_selection')
					.click(function() { $(this).remove(); })
				;
		        var top = event.pageY - Math.round($container.height() / 2) + "px";
		        var left = event.pageX - Math.round($container.width() / 2) + "px";
		        $container.css({ top: top, left: left });
		        if ($.browser.msie) {
		            //					window.clipboardData.setData( 'Text', selected ); //I couldn't find anything similar for Mozilla
		            $container[0].focus();
		            $container[0].select();
		        }
		        else {
		            var s = window.getSelection();
		            s.removeAllRanges();
		            var r = document.createRange();
		            r.selectNodeContents($container[0]);
		            s.addRange(r);
		        }
		    }
		})
		;
        } // enableSelectionHelper

        function getPath(recipeName) {
            return book.recipeFolder + recipeName + ".js";
        } // getPath

        function getSelectedText() {
            var text = '';
            if ($.browser.msie) {
                text = document.selection.createRange().htmlText;
            }
            else {
                text = window.getSelection().toString();
            }
            return text;
        } // getSelectedText

        function preserveNewLines(html) {
            do {
                var newline_flag = ChiliBook.unique();
            }
            while (html.indexOf(newline_flag) > -1);
            var text = '';
            if (/<br/i.test(html) || /<li/i.test(html)) {
                if (/<br/i.test(html)) {
                    html = html.replace(/\<br[^>]*?\>/ig, newline_flag);
                }
                else if (/<li/i.test(html)) {
                    html = html.replace(/<ol[^>]*?>|<\/ol>|<li[^>]*?>/ig, '').replace(/<\/li>/ig, newline_flag);
                }
                var el = $('<pre>').appendTo('body').hide()[0];
                el.innerHTML = html;
                text = $(el).text().replace(new RegExp(newline_flag, "g"), '\r\n');
                $(el).remove();
            }
            return text;
        } // preserveNewLines

        function addLineNumbers(el) {

            function makeListItem1(not_last_line, not_last, last, open) {
                var close = open ? '</span>' : '';
                var aux = '';
                if (not_last_line) {
                    aux = '<li>' + open + not_last + close + '</li>';
                }
                else if (last) {
                    aux = '<li>' + open + last + close + '</li>';
                }
                return aux;
            } // makeListItem1

            function makeListItem2(not_last_line, not_last, last, prev_li) {
                var aux = '';
                if (prev_li) {
                    aux = prev_li;
                }
                else {
                    aux = makeListItem1(not_last_line, not_last, last, '')
                }
                return aux;
            } // makeListItem2

            var html = $(el).html();
            var br = /<br>/.test(html) ? '<br>' : '<BR>';
            var empty_line = '<li>' + book.replaceSpace + '</li>';
            var list_items = html
            //extract newlines at the beginning of a span
			.replace(/(<span [^>]+>)((?:(?:&nbsp;|\xA0)<br>)+)(.*?)(<\/span>)/ig, '$2$1$3$4') // I don't know why <span .*?> does not work here
            //transform newlines inside of a span
			.replace(/(.*?)(<span .*?>)(.*?)(?:<\/span>(?:&nbsp;|\xA0)<br>|<\/span>)/ig,       // but here it does
				function(all, before, open, content) {
				    if (/<br>/i.test(content)) {
				        var pieces = before.split(br);
				        var lastPiece = pieces.pop();
				        before = pieces.join(br);
				        var aux = (before ? before + br : '') //+ replace1( lastPiece + content, open );
							+ (lastPiece + content).replace(/((.*?)(?:&nbsp;|\xA0)<br>)|(.*)/ig,
							function(tmp, not_last_line, not_last, last) {
							    var aux2 = makeListItem1(not_last_line, not_last, last, open);
							    return aux2;
							}
						);
				        return aux;
				    }
				    else {
				        return all;
				    }
				}
			)
            //transform newlines outside of a span
			.replace(/(<li>.*?<\/li>)|((.*?)(?:&nbsp;|\xA0)<br>)|(.+)/ig,
				function(tmp, prev_li, not_last_line, not_last, last) {
				    var aux2 = makeListItem2(not_last_line, not_last, last, prev_li);
				    return aux2;
				}
			)
            //fix empty lines for Opera
			.replace(/<li><\/li>/ig, empty_line)
		;

            el.innerHTML = '<ol>' + list_items + '</ol>';
        } // addLineNumbers

        function revealChars(tmp) {
            return $
			.map(tmp.split(''),
				function(n, i) {
				    return ' ' + n + ' ' + n.charCodeAt(0) + ' ';
				})
			.join(' ');
        } // revealChars

        //-----------------------------------------------------------------------------
        // the coloring starts here
        this
	.each(function() {
	    var $this = $(this);
	    $this.trigger('chili.before_coloring');
	    askDish(this);
	    $this.trigger('chili.after_coloring');
	});

        return this;
        //-----------------------------------------------------------------------------
    };



    //main
    $(function() {

        if (ChiliBook.automatic) {
            $(ChiliBook.automaticSelector).chili();
        }

    });

})(jQuery);
;/*
 * jQuery validation plug-in 1.5.1
 *
 * 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 6096 2009-01-12 14:12:04Z 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(index, value) {
			result[value] = $element.attr(value);
			$element.removeAttr(value);
		});
		return result;
	},
	// http://docs.jquery.com/Plugins/Validation/rules
	rules: function(command, argument) {
		var element = this[0];
		
		if (command) {
			var settings = $.data(element.form, 'validator').settings;
			var staticRules = settings.rules;
			var existingRules = $.validator.staticRules(element);
			switch(command) {
			case "add":
				$.extend(existingRules, $.validator.normalizeRule(argument));
				staticRules[element.name] = existingRules;
				if (argument.messages)
					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
				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;
	}
});

// 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: [],
		ignoreTitle: false,
		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 address.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date (ISO).",
		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 only digits",
		creditcard: "Please enter a valid credit card number.",
		equalTo: "Please enter the same value again.",
		accept: "Please enter a value with a valid extension.",
		maxlength: $.format("Please enter no more than {0} characters."),
		minlength: $.format("Please enter at least {0} characters."),
		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);

			if (this.settings.invalidHandler)
				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
		},

		// 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", [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 = this.toHide.add( 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().add( 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 && 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
				!this.settings.ignoreTitle && 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 = toToggle.add( 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 = this.toShow.add( 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 = this.toShow.add(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 sure 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();
			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
				$(this.currentForm).triggerHandler("invalid-form", [this]);
			}
		},
		
		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;
			
			param = typeof param == "string" && {url:param} || param; 
			
			if ( previous.old !== value ) {
				previous.old = value;
				var validator = this;
				this.startRequest(element);
				var data = {};
				data[element.name] = value;
				$.ajax($.extend(true, {
					url: param,
					mode: "abort",
					port: "validate" + element.name,
					dataType: "json",
					data: data,
					success: function(response) {
						if ( response ) {
							var submitted = validator.formSubmitted;
							validator.prepareElement(element);
							validator.formSubmitted = submitted;
							validator.successList.push(element);
							validator.showErrors();
						} else {
							var errors = {};
							errors[element.name] =  response || validator.defaultMessage( element, "remote" );
							validator.showErrors(errors);
						}
						previous.valid = response;
						validator.stopRequest(element, response);
					}
				}, param));
				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($.trim(value), element) >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
		maxlength: function(value, element, param) {
			return this.optional(element) || this.getLength($.trim(value), element) <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
		rangelength: function(value, element, param) {
			var length = this.getLength($.trim(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);
;/*
* Translated default messages for the jQuery validation plugin.
* Language: FR
*/
jQuery.extend(jQuery.validator.messages, {
    required: "Ce champ est requis.",
    remote: "Veuillez remplir ce champ pour continuer.",
    email: "Veuillez entrer une adresse email valide.",
    url: "Veuillez entrer une URL valide.",
    date: "Veuillez entrer une date valide.",
    dateISO: "Veuillez entrer une date valide (ISO).",
    number: "Veuillez entrer un nombre valide.",
    digits: "Veuillez entrer (seulement) une valeur numérique.",
    creditcard: "Veuillez entrer un numéro de carte de crédit valide.",
    equalTo: "Veuillez entrer une nouvelle fois la même valeur.",
    accept: "Veuillez entrer une valeur avec une extension valide.",
    maxlength: jQuery.format("Veuillez ne pas entrer plus de {0} caractères."),
    minlength: jQuery.format("Veuillez entrer au moins {0} caractères."),
    rangelength: jQuery.format("Veuillez entrer entre {0} et {1} caractères."),
    range: jQuery.format("Veuillez entrer une valeur entre {0} et {1}."),
    max: jQuery.format("Veuillez entrer une valeur inférieure ou égale à {0}."),
    min: jQuery.format("Veuillez entrer une valeur supérieure ou égale à {0}.")
});$(function() {
    $("ul.sf-menu").supersubs({
        minWidth: 12,   // minimum width of sub-menus in em units 
        maxWidth: 27,   // maximum width of sub-menus in em units 
        extraWidth: 1     // extra width can ensure lines don't sometimes turn over 
        // due to slight rounding differences and font-family
    }).superfish({
        delay: 300,
        speed: "fast"
    });

    var watermark = $(".watermark");
    if (watermark.length) {
        watermark.watermark();
    }

    ChiliBook.recipeFolder = "/Scripts/";
});