//Gallerific
/*
 * jQuery Galleriffic plugin
 *
 * Copyright (c) 2008 Trent Foley (http://trentacular.com)
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Thanks to Taku Sano (Mikage Sawatari), whose history plugin I adapted to work with Galleriffic
 * Modified by Ghismo (ghismo.com) to disable the location rewrite 
 */
;(function($) {

    // Write noscript style
    document.write("<style type='text/css'>.noscript{display:none;}</style>");

    var ver = 'galleriffic-1.0';
    var galleryOffset = 0;
    var galleries = [];
    var allImages = [];
    var historyCurrentHash;
    var historyBackStack;
    var historyForwardStack;
    var isFirst = false;
    var dontCheck = false;
    var isInitialized = false;

    function getHashFromString(hash) {
        if (!hash) return -1;
        hash = hash.replace(/^.*#/, '');
        if (isNaN(hash)) return -1;
        return (+hash);
    }

    function getHash() {
        var hash = location.hash;
        return getHashFromString(hash);
    }

    function registerGallery(gallery) {
        galleries.push(gallery);

        // update the global offset value
        galleryOffset += gallery.data.length;
    }

    function getGallery(hash) {
        for (i = 0; i < galleries.length; i++) {
            var gallery = galleries[i];
            if (hash < (gallery.data.length + gallery.offset))
                return gallery;
        }
        return 0;
    }

    function getIndex(gallery, hash) {
        return hash - gallery.offset;
    }

    function clickHandler(e, gallery, link) {
        gallery.pause();

        if (!gallery.settings.enableHistory) {
            var hash = getHashFromString(link.href);
            if (hash >= 0) {
                var index = getIndex(gallery, hash);
                if (index >= 0)
                    gallery.goto(index);
            }
            e.preventDefault();
        }
    }

    function historyCallback() {
        // Using present location.hash always (seems to work, unlike the hash argument passed to this callback)
        var hash = getHash();
        if (hash < 0) return;

        var gallery = getGallery(hash);
        if (!gallery) return;

        var index = hash - gallery.offset;
        gallery.goto(index);
    }

    function historyInit() {
        if (isInitialized) return;
        isInitialized = true;

        var current_hash = location.hash; //(enableHistory) ? location.hash : currentIndexHash; // Ghismo

        historyCurrentHash = current_hash;
        if ($.browser.msie) {
            // To stop the callback firing twice during initilization if no hash present
            if (historyCurrentHash == '') {
                historyCurrentHash = '#';
            }
        } else if ($.browser.safari) {
            // etablish back/forward stacks
            historyBackStack = [];
            historyBackStack.length = history.length;
            historyForwardStack = [];
            isFirst = true;
        }

        setInterval(function() { historyCheck(); }, 100);
    }

    function historyAddHistory(hash) {
        // This makes the looping function do something
        historyBackStack.push(hash);
        historyForwardStack.length = 0; // clear forwardStack (true click occured)
        isFirst = true;
    }

    function historyCheck() {
        if ($.browser.safari) {
            if (!dontCheck) {
                var historyDelta = history.length - historyBackStack.length;

                if (historyDelta) { // back or forward button has been pushed
                    isFirst = false;
                    if (historyDelta < 0) { // back button has been pushed
                        // move items to forward stack
                        for (var i = 0; i < Math.abs(historyDelta); i++) historyForwardStack.unshift(historyBackStack.pop());
                    } else { // forward button has been pushed
                        // move items to back stack
                        for (var i = 0; i < historyDelta; i++) historyBackStack.push(historyForwardStack.shift());
                    }
                    var cachedHash = historyBackStack[historyBackStack.length - 1];
                    if (cachedHash != undefined) {
                        historyCurrentHash = location.hash; // (enableHistory) ? location.hash : currentIndexHash; // Ghismo
                        historyCallback();
                    }
                } else if (historyBackStack[historyBackStack.length - 1] == undefined && !isFirst) {
                    historyCallback();
                    isFirst = true;
                }
            }
        } else {
            // otherwise, check for location.hash
            var current_hash = location.hash; // (enableHistory) ? location.hash : currentIndexHash; // Ghismo
            if (current_hash != historyCurrentHash) {
                historyCurrentHash = current_hash;
                historyCallback();
            }
        }
    }

    var defaults = {
        delay: 3000,
        numThumbs: 20,
        preloadAhead: 40, // Set to -1 to preload all images
        enableTopPager: false,
        enableBottomPager: true,
        imageContainerSel: '',
        captionContainerSel: '',
        controlsContainerSel: '',
        loadingContainerSel: '',
        renderSSControls: true,
        renderNavControls: true,
        playLinkText: 'Play',
        pauseLinkText: 'Pause',
        prevLinkText: 'Previous',
        nextLinkText: 'Next',
        nextPageLinkText: 'Next &rsaquo;',
        prevPageLinkText: '&lsaquo; Prev',
        enableHistory: false,
        autoStart: false,
        onChange: undefined, // accepts a delegate like such: function(prevIndex, nextIndex) { ... }
        onTransitionOut: undefined, // accepts a delegate like such: function(callback) { ... }
        onTransitionIn: undefined, // accepts a delegate like such: function() { ... }
        onPageTransitionOut: undefined, // accepts a delegate like such: function(callback) { ... }
        onPageTransitionIn: undefined  // accepts a delegate like such: function() { ... }
    };

    $.fn.galleriffic = function(thumbsContainerSel, settings) {
        //  Extend Gallery Object
        $.extend(this, {
            ver: function() {
                return ver;
            },

            initializeThumbs: function() {
                this.data = [];
                var gallery = this;

                this.$thumbsContainer.find('ul.thumbs > li').each(function(i) {
                    var $li = $(this);
                    var $aThumb = $li.find('a.thumb');
                    var hash = gallery.offset + i;

                    gallery.data.push({
                        title: $aThumb.attr('title'),
                        slideUrl: $aThumb.attr('href'),
                        caption: $li.find('.caption').remove(),
                        hash: hash
                    });

                    // Setup history
                    $aThumb.attr('rel', 'history');
                    $aThumb.attr('href', '#' + hash);
                    $aThumb.click(function(e) {
                        clickHandler(e, gallery, this);
                    });
                });
                return this;
            },

            isPreloadComplete: false,

            preloadInit: function() {
                if (this.settings.preloadAhead == 0) return this;

                this.preloadStartIndex = this.currentIndex;
                var nextIndex = this.getNextIndex(this.preloadStartIndex);
                return this.preloadRecursive(this.preloadStartIndex, nextIndex);
            },

            preloadRelocate: function(index) {
                // By changing this startIndex, the current preload script will restart
                this.preloadStartIndex = index;
                return this;
            },

            preloadRecursive: function(startIndex, currentIndex) {
                // Check if startIndex has been relocated
                if (startIndex != this.preloadStartIndex) {
                    var nextIndex = this.getNextIndex(this.preloadStartIndex);
                    return this.preloadRecursive(this.preloadStartIndex, nextIndex);
                }

                var gallery = this;

                // Now check for preloadAhead count
                var preloadCount = currentIndex - startIndex;
                if (preloadCount < 0)
                    preloadCount = this.data.length - 1 - startIndex + currentIndex;
                if (this.settings.preloadAhead >= 0 && preloadCount > this.settings.preloadAhead) {
                    // Do this in order to keep checking for relocated start index
                    setTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);
                    return this;
                }

                var imageData = this.data[currentIndex];
                if (!imageData)
                    return this;

                // If already loaded, continue
                if (imageData.image)
                    return this.preloadNext(startIndex, currentIndex);

                // Preload the image
                var image = new Image();

                image.onload = function() {
                    imageData.image = this;
                    gallery.preloadNext(startIndex, currentIndex);
                };

                image.alt = imageData.title;
                image.src = imageData.slideUrl;

                return this;
            },

            preloadNext: function(startIndex, currentIndex) {
                var nextIndex = this.getNextIndex(currentIndex);
                if (nextIndex == startIndex) {
                    this.isPreloadComplete = true;
                } else {
                    // Use set timeout to free up thread
                    var gallery = this;
                    setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);
                }
                return this;
            },

            getNextIndex: function(index) {
                var nextIndex = index + 1;
                if (nextIndex >= this.data.length)
                    nextIndex = 0;
                return nextIndex;
            },

            getPrevIndex: function(index) {
                var prevIndex = index - 1;
                if (prevIndex < 0)
                    prevIndex = this.data.length - 1;
                return prevIndex;
            },

            pause: function() {
                if (this.interval)
                    this.toggleSlideshow();

                return this;
            },

            play: function() {
                if (!this.interval)
                    this.toggleSlideshow();

                return this;
            },

            toggleSlideshow: function() {
                if (this.interval) {
                    clearInterval(this.interval);
                    this.interval = 0;

                    if (this.$controlsContainer) {
                        this.$controlsContainer
							.find('div.ss-controls a').removeClass().addClass('play')
							.attr('title', this.settings.playLinkText)
							.attr('href', '#play')
							.html(this.settings.playLinkText);
                    }
                } else {
                    this.ssAdvance();

                    var gallery = this;
                    this.interval = setInterval(function() {
                        gallery.ssAdvance();
                    }, this.settings.delay);

                    if (this.$controlsContainer) {
                        this.$controlsContainer
							.find('div.ss-controls a').removeClass().addClass('pause')
							.attr('title', this.settings.pauseLinkText)
							.attr('href', '#pause')
							.html(this.settings.pauseLinkText);
                    }
                }

                return this;
            },

            ssAdvance: function() {
                var nextIndex = this.getNextIndex(this.currentIndex);
                var nextHash = this.data[nextIndex].hash;

                // Seems to be working on both FF and Safari
                if (this.settings.enableHistory)
                    location.href = '#' + nextHash;
                else
                    this.goto(nextIndex);

                // IE we need to explicity call goto
                //if ($.browser.msie) {
                //	this.goto(nextIndex);
                //}

                return this;
            },

            goto: function(index) {
                if (index < 0) index = 0;
                else if (index >= this.data.length) index = this.data.length - 1;

                if (this.settings.onChange)
                    this.settings.onChange(this.currentIndex, index);

                this.currentIndex = index;
                this.preloadRelocate(index);
                return this.refresh();
            },

            refresh: function() {
                var imageData = this.data[this.currentIndex];
                if (!imageData)
                    return this;

                // Flag we are transitioning
                var isTransitioning = true;

                var gallery = this;

                var transitionOutCallback = function() {
                    // Flag that the transition has completed
                    isTransitioning = false;

                    // Update Controls
                    if (gallery.$controlsContainer) {
                        gallery.$controlsContainer
							.find('div.nav-controls a.prev').attr('href', '#' + gallery.data[gallery.getPrevIndex(gallery.currentIndex)].hash).end()
							.find('div.nav-controls a.next').attr('href', '#' + gallery.data[gallery.getNextIndex(gallery.currentIndex)].hash);
                    }

                    var imageData = gallery.data[gallery.currentIndex];

                    // Replace Caption
                    if (gallery.$captionContainer) {
                        gallery.$captionContainer.empty().append(imageData.caption);
                    }

                    if (imageData.image) {
                        gallery.buildImage(imageData.image);
                    } else {
                        // Show loading container
                        if (gallery.$loadingContainer) {
                            gallery.$loadingContainer.show();
                        }
                    }
                }

                if (this.settings.onTransitionOut) {
                    this.settings.onTransitionOut(transitionOutCallback);
                } else {
                    this.$transitionContainers.hide();
                    transitionOutCallback();
                }

                if (!imageData.image) {
                    var image = new Image();

                    // Wire up mainImage onload event
                    image.onload = function() {
                        imageData.image = this;

                        if (!isTransitioning) {
                            gallery.buildImage(imageData.image);
                        }
                    };

                    // set alt and src
                    image.alt = imageData.title;
                    image.src = imageData.slideUrl;
                }

                // This causes the preloader (if still running) to relocate out from the currentIndex
                this.relocatePreload = true;

                return this.syncThumbs();
            },

            buildImage: function(image) {
                if (this.$imageContainer) {
                    this.$imageContainer.empty();

                    var gallery = this;
                    var nextIndex = this.getNextIndex(this.currentIndex);

                    // Hide the loading conatiner
                    if (this.$loadingContainer) {
                        this.$loadingContainer.hide();
                    }

                    // Setup image
                    this.$imageContainer
						.append('<span class="image-wrapper"><a class="advance-link" rel="history" href="#' + this.data[nextIndex].hash + '" title="' + image.alt + '"></a></span>')
						.find('a')
						.append(image)
						.click(function(e) {
						    clickHandler(e, gallery, this);
						});
                }

                if (this.settings.onTransitionIn)
                    this.settings.onTransitionIn();
                else
                    this.$transitionContainers.show();

                return this;
            },

            syncThumbs: function() {
                if (this.$thumbsContainer) {
                    var page = Math.floor(this.currentIndex / this.settings.numThumbs);
                    if (page != this.currentPage) {
                        this.currentPage = page;
                        this.updateThumbs();
                    }

                    // Remove existing selected class and add selected class to new thumb
                    var $thumbs = this.$thumbsContainer.find('ul.thumbs').children();
                    $thumbs.filter('.selected').removeClass('selected');
                    //alert("selected removed");
                    //$thumbs.eq(this.currentIndex).addClass('selected');
                }

                return this;
            },

            updateThumbs: function() {
                var gallery = this;
                var transitionOutCallback = function() {
                    gallery.rebuildThumbs();

                    // Transition In the thumbsContainer
                    if (gallery.settings.onPageTransitionIn)
                        gallery.settings.onPageTransitionIn();
                    else
                        gallery.$thumbsContainer.show();
                };

                // Transition Out the thumbsContainer
                if (this.settings.onPageTransitionOut) {
                    this.settings.onPageTransitionOut(transitionOutCallback);
                } else {
                    this.$thumbsContainer.hide();
                    transitionOutCallback();
                }

                return this;
            },

            rebuildThumbs: function() {
                // Initialize currentPage to first page
                if (this.currentPage < 0)
                    this.currentPage = 0;

                var needsPagination = this.data.length > this.settings.numThumbs;

                // Rebuild top pager
                var $topPager = this.$thumbsContainer.find('div.top');
                if ($topPager.length == 0)
                    $topPager = this.$thumbsContainer.prepend('<div class="top pagination"></div>').find('div.top');

                if (needsPagination && this.settings.enableTopPager) {
                    $topPager.empty();
                    this.buildPager($topPager);
                }

                // Rebuild bottom pager
                if (needsPagination && this.settings.enableBottomPager) {
                    var $bottomPager = this.$thumbsContainer.find('div.bottom');
                    if ($bottomPager.length == 0)
                        $bottomPager = this.$thumbsContainer.append('<div class="bottom pagination"></div>').find('div.bottom');
                    else
                        $bottomPager.empty();

                    this.buildPager($bottomPager);
                }

                var startIndex = this.currentPage * this.settings.numThumbs;
                var stopIndex = startIndex + this.settings.numThumbs - 1;
                if (stopIndex >= this.data.length)
                    stopIndex = this.data.length - 1;

                // Show/Hide thumbs
                var $thumbsUl = this.$thumbsContainer.find('ul.thumbs');
                $thumbsUl.find('li').each(function(i) {
                    var $li = $(this);
                    if (i >= startIndex && i <= stopIndex) {
                        $li.show();
                    } else {
                        $li.hide();
                    }
                });

                // Remove the noscript class from the thumbs container ul
                $thumbsUl.removeClass('noscript');

                return this;
            },

            buildPager: function(pager) {
                var gallery = this;
                var startIndex = this.currentPage * this.settings.numThumbs;

                // Prev Page Link
                if (this.currentPage > 0) {
                    var prevPage = startIndex - this.settings.numThumbs;
                    pager.append('<a rel="history" href="#' + this.data[prevPage].hash + '" title="' + this.settings.prevPageLinkText + '">' + this.settings.prevPageLinkText + '</a>');
                }

                // Page Index Links
                for (i = this.currentPage - 3; i <= this.currentPage + 3; i++) {
                    var pageNum = i + 1;

                    if (i == this.currentPage)
                        pager.append('<span class="current">' + pageNum + '</span>');
                    else if (i >= 0 && i < this.numPages) {
                        var imageIndex = i * this.settings.numThumbs;
                        pager.append('<a rel="history" href="#' + this.data[imageIndex].hash + '" title="' + pageNum + '">' + pageNum + '</a>');
                    }
                }

                // Next Page Link
                var nextPage = startIndex + this.settings.numThumbs;
                if (nextPage < this.data.length) {
                    pager.append('<a rel="history" href="#' + this.data[nextPage].hash + '" title="' + this.settings.nextPageLinkText + '">' + this.settings.nextPageLinkText + '</a>');
                }

                pager.find('a').click(function(e) {
                    clickHandler(e, gallery, this);
                });

                return this;
            }
        });

        // Now initialize the gallery
        this.settings = $.extend({}, defaults, settings);
        //enableHistory = this.settings.enableHistory; // Ghismo

        if (this.interval)
            clearInterval(this.interval);

        this.interval = 0;

        if (this.settings.imageContainerSel) this.$imageContainer = $(this.settings.imageContainerSel);
        if (this.settings.captionContainerSel) this.$captionContainer = $(this.settings.captionContainerSel);
        if (this.settings.loadingContainerSel) this.$loadingContainer = $(this.settings.loadingContainerSel);

        // Setup the jQuery object holding each container that will be transitioned
        this.$transitionContainers = $([]);
        if (this.$imageContainer)
            this.$transitionContainers = this.$transitionContainers.add(this.$imageContainer);
        if (this.$captionContainer)
            this.$transitionContainers = this.$transitionContainers.add(this.$captionContainer);

        // Set the hash index offset for this gallery
        this.offset = galleryOffset;

        this.$thumbsContainer = $(thumbsContainerSel);
        this.initializeThumbs();

        // Add this gallery to the global galleries array
        registerGallery(this);

        this.numPages = Math.ceil(this.data.length / this.settings.numThumbs);
        this.currentPage = -1;
        this.currentIndex = 0;
        var gallery = this;

        // Hide the loadingContainer
        if (this.$loadingContainer)
            this.$loadingContainer.hide();

        // Setup controls
        if (this.settings.controlsContainerSel) {
            this.$controlsContainer = $(this.settings.controlsContainerSel).empty();

            if (this.settings.renderSSControls) {
                if (this.settings.autoStart) {
                    this.$controlsContainer
						.append('<div class="ss-controls"><a href="#pause" class="pause" title="' + this.settings.pauseLinkText + '">' + this.settings.pauseLinkText + '</a></div>');
                } else {
                    this.$controlsContainer
						.append('<div class="ss-controls"><a href="#play" class="play" title="' + this.settings.playLinkText + '">' + this.settings.playLinkText + '</a></div>');
                }

                this.$controlsContainer.find('div.ss-controls a')
					.click(function(e) {
					    gallery.toggleSlideshow();
					    e.preventDefault();
					    return false;
					});
            }

            if (this.settings.renderNavControls) {
                var $navControls = this.$controlsContainer
					.append('<div class="nav-controls"><a class="prev" rel="history" title="' + this.settings.prevLinkText + '">' + this.settings.prevLinkText + '</a><a class="next" rel="history" title="' + this.settings.nextLinkText + '">' + this.settings.nextLinkText + '</a></div>')
					.find('div.nav-controls a')
					.click(function(e) {
					    clickHandler(e, gallery, this);
					});
            }
        }

        // Initialize history only once when the first gallery on the page is initialized
        historyInit();

        // Build image
        var hash = getHash();
        var hashGallery = (hash >= 0) ? getGallery(hash) : 0;
        var gotoIndex = (hashGallery && this == hashGallery) ? (hash - this.offset) : 0;
        this.goto(gotoIndex);

        if (this.settings.autoStart) {

            setTimeout(function() { gallery.play(); }, this.settings.delay);
        }

        // Kickoff Image Preloader after 1 second
        setTimeout(function() { gallery.preloadInit(); }, 1000);

        return this;
    };
})($telerik.$);

//Validator
/*
 * jQuery validation plug-in 1.5.5
 *
 * 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 6403 2009-06-17 14:27:16Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

(function($) {

$.extend($.fn, {
	// http://docs.jquery.com/Plugins/Validation/validate
	validate: function( options ) {
		//alert("validate");
		// 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;
			});
		
			// when a submitHandler is used, capture the submitting button
			if (validator.settings.submitHandler) {
				this.find("input, button").filter(":submit").click(function() {
					validator.submitButton = this;
				});
			}
		
			// 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 ) {
						if (validator.submitButton) {
							// insert a hidden input as a replacement for the missing submit button
							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
						}
						validator.settings.submitHandler.call( validator, validator.currentForm );
						if (validator.submitButton) {
							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
							hidden.remove();
						}
						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 = true;
            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;}
});

// constructor for validator
$.validator = function( options, form ) {
	this.settings = $.extend( {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

$.validator.format = function(source, params) {
	if ( arguments.length == 1 ) 
		return function() {
			var args = $.makeArray(arguments);
			args.unshift(source);
			return $.validator.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;
};

$.extend($.validator, {

	defaults: {
		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		validClass: "valid",
		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.settings.validClass );
				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, validClass ) {
			$(element).addClass(errorClass).removeClass(validClass);
		},
		unhighlight: function( element, errorClass, validClass ) {
			$(element).removeClass(errorClass).addClass(validClass);
		}
	},

	// 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: $.validator.format("Please enter no more than {0} characters."),
		minlength: $.validator.format("Please enter at least {0} characters."),
		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
		range: $.validator.format("Please enter a value between {0} and {1}."),
		max: $.validator.format("Please enter a value less than or equal to {0}."),
		min: $.validator.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() {
			//alert("In Valid dinges");
			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.replace(/\r/g, ""), 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.parent( 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.settings.validClass );
				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.settings.validClass );
				}
			}
			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 || $.validator.messages[name];
		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) {
						var valid = response === true;
						if ( valid ) {
							var submitted = validator.formSubmitted;
							validator.prepareElement(element);
							validator.formSubmitted = submitted;
							validator.successList.push(element);
							validator.showErrors();
						} else {
							var errors = {};
							errors[element.name] = previous.message = response || validator.defaultMessage( element, "remote" );
							validator.showErrors(errors);
						}
						previous.valid = valid;
						validator.stopRequest(element, valid);
					}
				}, 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.replace(/,/g, '|') : "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();
		}
		
	}
	
});

// deprecated, use $.validator.format instead
$.format = $.validator.format;
})($telerik.$);

// 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);
	};
})($telerik.$);

// 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 })]);
		}
	})
})($telerik.$);

//Scroll Pack
/*-----------------------
* jQuery Plugin: Scroll to Top
* by Craig Wilson, Ph.Creative (http://www.ph-creative.com)
* 
* Copyright (c) 2009 Ph.Creative Ltd.
* Description: Adds an unobtrusive "Scroll to Top" link to your page with smooth scrolling.
* For usage instructions and version updates to go http://blog.ph-creative.com/post/jquery-plugin-scroll-to-top-v2.aspx
* 
* Version: 2.0, 22/06/2009
-----------------------*/
$telerik.$(function() {
    $.fn.scrollToTop = function(options) {
		if ( !$.browser.msie || ($.browser.msie &&  !( $.browser.version.substring( 0, 1 ) == '5' || $.browser.version.substring( 0, 1 ) == '6' ) )){
        if (options) {
            var speed = options.speed;
            var ease = options.ease;
        } else {
            var speed = "slow";
            var ease = "jswing";
        }
        var scrollDiv = $(this);
        $(this).hide().removeAttr("href");
        if ($(window).scrollTop() != "0") {
            $(this).fadeIn("slow");
        }
        $(window).scroll(function() {
            if ($(window).scrollTop() == "0") {
                $(scrollDiv).fadeOut("slow");
            } else {
                $(scrollDiv).fadeIn("slow");
            }
        });
        $(this).click(function(event) {
            $("html, body").animate({
                scrollTop: "0px"
            },
            speed, ease);
        });
    }
	}
});

//Local Scroll
/**
 * jQuery.LocalScroll
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/11/2009
 *
 * @projectDescription Animated scrolling navigation, using anchors.
 * http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html
 * @author Ariel Flesler
 * @version 1.2.7
 *
 * @id jQuery.fn.localScroll
 * @param {Object} settings Hash of settings, it is passed in to jQuery.ScrollTo, none is required.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example $('ul.links').localScroll();
 *
 * @example $('ul.links').localScroll({ filter:'.animated', duration:400, axis:'x' });
 *
 * @example $.localScroll({ target:'#pane', axis:'xy', queue:true, event:'mouseover' });
 *
 * Notes:
 *	- The plugin requires jQuery.ScrollTo.
 *	- The hash of settings, is passed to jQuery.ScrollTo, so the settings are valid for that plugin as well.
 *	- jQuery.localScroll can be used if the desired links, are all over the document, it accepts the same settings.
 *  - If the setting 'lazy' is set to true, then the binding will still work for later added anchors.
  *	- If onBefore returns false, the event is ignored.
 **/
;(function( $ ){
	var URI = location.href.replace(/#.*/,''); // local url without hash

	var $localScroll = $.localScroll = function( settings ){
		$('body').localScroll( settings );
	};

	// Many of these defaults, belong to jQuery.ScrollTo, check it's demo for an example of each option.
	// @see http://flesler.demos.com/jquery/scrollTo/
	// The defaults are public and can be overriden.
	$localScroll.defaults = {
		duration:1000, // How long to animate.
		axis:'y', // Which of top and left should be modified.
		event:'click', // On which event to react.
		stop:true, // Avoid queuing animations 
		target: window, // What to scroll (selector or element). The whole window by default.
		reset: true // Used by $.localScroll.hash. If true, elements' scroll is resetted before actual scrolling
		/*
		lock:false, // ignore events if already animating
		lazy:false, // if true, links can be added later, and will still work.
		filter:null, // filter some anchors out of the matched elements.
		hash: false // if true, the hash of the selected link, will appear on the address bar.
		*/
	};

	// If the URL contains a hash, it will scroll to the pointed element
	$localScroll.hash = function( settings ){
		if( location.hash ){
			settings = $.extend( {}, $localScroll.defaults, settings );
			settings.hash = false; // can't be true
			
			if( settings.reset ){
				var d = settings.duration;
				delete settings.duration;
				$(settings.target).scrollTo( 0, settings );
				settings.duration = d;
			}
			scroll( 0, location, settings );
		}
	};

	$.fn.localScroll = function( settings ){
		settings = $.extend( {}, $localScroll.defaults, settings );

		return settings.lazy ?
			// use event delegation, more links can be added later.		
			this.bind( settings.event, function( e ){
				// Could use closest(), but that would leave out jQuery -1.3.x
				var a = $([e.target, e.target.parentNode]).filter(filter)[0];
				// if a valid link was clicked
				if( a )
					scroll( e, a, settings ); // do scroll.
			}) :
			// bind concretely, to each matching link
			this.find('a,area')
				.filter( filter ).bind( settings.event, function(e){
					scroll( e, this, settings );
				}).end()
			.end();

		function filter(){// is this a link that points to an anchor and passes a possible filter ? href is checked to avoid a bug in FF.
			return !!this.href && !!this.hash && this.href.replace(this.hash,'') == URI && (!settings.filter || $(this).is( settings.filter ));
		};
	};

	function scroll( e, link, settings ){
		var id = link.hash.slice(1),
			elem = document.getElementById(id) || document.getElementsByName(id)[0];

		if ( !elem )
			return;

		if( e )
			e.preventDefault();

		var $target = $( settings.target );

		if( settings.lock && $target.is(':animated') ||
			settings.onBefore && settings.onBefore.call(settings, e, elem, $target) === false ) 
			return;

		if( settings.stop )
			$target.stop(true); // remove all its animations

		if( settings.hash ){
			var attr = elem.id == id ? 'id' : 'name',
				$a = $('<a> </a>').attr(attr, id).css({
					position:'absolute',
					top: $(window).scrollTop(),
					left: $(window).scrollLeft()
				});

			elem[attr] = '';
			$('body').prepend($a);
			location = link.hash;
			$a.remove();
			elem[attr] = id;
		}
			
		$target
			.scrollTo( elem, settings ) // do scroll
			.trigger('notify.serialScroll',[elem]); // notify serialScroll about this change
	};

})($telerik.$);

//Scroll To
/**
 * jQuery.ScrollTo
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/9/2009
 *
 * @projectDescription Easy element scrolling using jQuery.
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 * Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7/8, Opera 9.5/6, Safari 3, Chrome 1 on WinXP.
 *
 * @author Ariel Flesler
 * @version 1.4.1
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 *		- The string 'max' for go-to-end. 
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object,Function} settings Optional set of settings or the onAfter callback.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @desc Scroll to a fixed position
 * @example $('div').scrollTo( 340 );
 *
 * @desc Scroll relatively to the actual position
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @dec Scroll using a selector (relative to the scrolled element)
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @ Scroll to a DOM element (same for jQuery object)
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @desc Scroll on both axes, to different values
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
 */
;(function( $ ){
	
	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$(window).scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'xy',
		duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1
	};

	// Returns the element that needs to be animated to scroll the window.
	// Kept for backwards compatibility (specially for localScroll & serialScroll)
	$scrollTo.window = function( scope ){
		return $(window).scrollable();
	};

	// Hack, hack, hack... stay away!
	// Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
	$.fn.scrollable = function(){
		return this.map(function(){
			var elem = this,
				isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;

				if( !isWin )
					return elem;

			var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
			
			return $.browser.safari || doc.compatMode == 'BackCompat' ?
				doc.body : 
				doc.documentElement;
		});
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		if( typeof settings == 'function' )
			settings = { onAfter:settings };
			
		if( target == 'max' )
			target = 9e9;
			
		settings = $.extend( {}, $scrollTo.defaults, settings );
		// Speed is still recognized for backwards compatibility
		duration = duration || settings.speed || settings.duration;
		// Make sure the settings are given right
		settings.queue = settings.queue && settings.axis.length > 1;
		
		if( settings.queue )
			// Let's keep the overall duration
			duration /= 2;
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this.scrollable().each(function(){
			var elem = this,
				$elem = $(elem),
				targ = target, toff, attr = {},
				win = $elem.is('html,body');

			switch( typeof targ ){
				// A number will pass the regex
				case 'number':
				case 'string':
					if( /^([+-]=)?\d+(\.\d+)?(px)?$/.test(targ) ){
						targ = both( targ );
						// We are done
						break;
					}
					// Relative selector, no break!
					targ = $(targ,this);
				case 'object':
					// DOMElement / jQuery
					if( targ.is || targ.style )
						// Get the real position of the target 
						toff = (targ = $(targ)).offset();
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					old = elem[key],
					Dim = axis == 'x' ? 'Width' : 'Height';

				if( toff ){// jQuery / DOMElement
					attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );

					// If it's a dom element, reduce the margin
					if( settings.margin ){
						attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
					}
					
					attr[key] += settings.offset[pos] || 0;
					
					if( settings.over[pos] )
						// Scroll to a fraction of its width/height
						attr[key] += targ[Dim.toLowerCase()]() * settings.over[pos];
				}else
					attr[key] = targ[pos];

				// Number or 'number'
				if( /^\d+$/.test(attr[key]) )
					// Check the limits
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );

				// Queueing axes
				if( !i && settings.queue ){
					// Don't waste time animating, if there's no need.
					if( old != attr[key] )
						// Intermediate animation
						animate( settings.onAfterFirst );
					// Don't animate this axis again in the next iteration.
					delete attr[key];
				}
			});

			animate( settings.onAfter );			

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target, settings);
				});
			};

			// Max scrolling position, works on quirks mode
			// It only fails (not too badly) on IE, quirks mode.
			function max( Dim ){
				var scroll = 'scroll'+Dim;
				
				if( !win )
					return elem[scroll];
				
				var size = 'client' + Dim,
					html = elem.ownerDocument.documentElement,
					body = elem.ownerDocument.body;

				return Math.max( html[scroll], body[scroll] ) 
					 - Math.min( html[size]  , body[size]   );
					
			};

		}).end();
	};

	function both( val ){
		return typeof val == 'object' ? val : { top:val, left:val };
	};

})($telerik.$);

//IE 6 Update
/**
 * IE6Update is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * IE6Update is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Activebar2; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * * * * * * * * * * * *
 * 
 * This is code is derived from Activebar2
 *
 * Activebar2 is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * Activebar2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Activebar2; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * You may contact the author by mail: jakob@php.net
 * 
 * Or write to:
 * Jakob Westhoff
 * Kleiner Floraweg 35
 * 44229 Dortmund
 * Germany
 *
 * The latest version of ActiveBar can be obtained from:
 * http://www.westhoffswelt.de/
 *
 * @package Core
 * @version $Revision$
 * @license http://www.gnu.org/licenses/gpl-3.0.txt GPL
 */
 
 
try {
  document.execCommand("BackgroundImageCache", true, true);
} catch(err) {}

if(window.__noconflict){ jQuery.noConflict();} 
(function($) {
    
    
    $.fn.activebar = function( options ) {
        // Merge the specified options with the default ones
        options = $.fn.extend( {}, $.fn.activebar.defaults, options );
        
        if ( $.fn.activebar.container === null ) {
            $.fn.activebar.container = initializeActivebar( options );
        }

        // Update the style values according to the provided options
        setOptionsOnContainer( $.fn.activebar.container, options );

        // If the activebar is currently visible hide it
        $.fn.activebar.hide();
        
        // Remove all elements from the activebar content, which might be there
        $( '.content', $.fn.activebar.container ).empty();

        // Use all provided elements as new content source
        $(this).each( function() {
            $( '.content', $.fn.activebar.container ).append( this );
        });

        // Remove any "gotoURL" function
        $.fn.activebar.container.unbind( 'click' );

        // Add a new "gotoURL" function if one has been supplied
        if( options.url !== null ) {
            $.fn.activebar.container.click( 
                function() {
                    window.location.href = options.url;
                }
            );
        }

        // Update the position based on the new content data height
        $.fn.activebar.container.css( 'top', '-' + $.fn.activebar.container.height() + 'px' );

        // Show the activebar
        if(options.preload){
          var load = {a:0, b:0, c:0, d:0}          
          
          function preloadInit(){
            if(load.a && load.b && load.c && load.d){
              $.fn.activebar.show();
            }
          }
          
          $('<img src="'+options.icons_path+'icon.png" class="normal">').load(function(){load.a=1; preloadInit()});
          $('<img src="'+options.icons_path+'icon-over.png" class="normal">').load(function(){load.b=1; preloadInit()});
          $('<img src="'+options.icons_path+'close.png" class="normal">').load(function(){load.c=1; preloadInit()});
          $('<img src="'+options.icons_path+'close-over.png" class="normal">').load(function(){load.d=1; preloadInit()});
          
        }else{
          $.fn.activebar.show();
        }
        
    };

    /**
     * Default options used if nothing more specific is provided.
     */
    $.fn.activebar.defaults = {
        'background': '#ffffe1',
        'border': '#666', 
        'highlight': '#3399ff',
        'font': 'Bitstream Vera Sans,verdana,sans-serif',
        'fontColor': 'InfoText',
        'fontSize': '11px',
        'icons_path' : '../images/',
        'url': 'http://www.microsoft.com/windows/internet-explorer/default.aspx',
        'preload': true
    };

    /**
     * Indicator in which state the activebar currently is
     * 0: Moved in (hidden)
     * 1: Moving in (hiding)
     * 2: Moving out (showing)
     * 3: Moved out (shown)
     */
    $.fn.activebar.state = 0;

    /**
     * Activebar container object which holds the shown content
     */
    $.fn.activebar.container = null;

    /**
     * Show the activebar by moving it in
     */
    $.fn.activebar.show = function() {
        if ( $.fn.activebar.state > 1 ) {
            // Already moving out or visible. Do Nothing.
            return;
        }
        
        $.fn.activebar.state = 2;
        $.fn.activebar.container.css( 'display', 'block' );
        
        var height = $.fn.activebar.container.height();
        $.fn.activebar.container.animate({
            'top': '+=' + height + 'px' 
        }, height * 20, 'linear', function() {
            $.fn.activebar.state = 3;
        });
    };

    /**
     * Hide the activebar by moving it out
     */
    $.fn.activebar.hide = function() {
        if ( $.fn.activebar.state < 2 ) {
            // Already moving in or hidden. Do nothing.
            return;
        }

        $.fn.activebar.state = 1;

        var height   = $.fn.activebar.container.height();
        $.fn.activebar.container.animate({
            'top': '-=' + height + 'px' 
        }, height * 20, 'linear', function() {
            $.fn.activebar.container.css( 'display', 'none' );
            $.fn.activebar.visible = false;
        });
    };

    /****************************************************************
     * Private function only accessible from within this plugin
     ****************************************************************/

     /**
      * Create the a basic activebar container object and return it
      */
     function initializeActivebar( options ) {
        // Create the container object
        var container = $( '<div></div>' ).attr( 'id', 'activebar-container' );
        
        // Set the needed css styles
        container.css({
          'display': 'none',
          'position': 'fixed',
          'zIndex': '9999',
          'top': '0px',
          'left': '0px',            
          'cursor': 'default',
          'padding': '4px',
          'font-size' : '9px',
          'background': options.background,
          'borderBottom': '1px solid ' + options.border,
          'color': options.fontColor
        });

        // Make sure the bar has always the correct width
        $(window).bind( 'resize', function() {
            container.width( $(this).width() );
        });

        // Set the initial bar width
        $(window).trigger( 'resize' );
        
        // The IE prior to version 7.0 does not support position fixed. However
        // the correct behaviour can be emulated using a hook to the scroll
        // event. This is a little choppy, but it works.
        if ( $.browser.msie && ( $.browser.version.substring( 0, 1 ) == '5' || $.browser.version.substring( 0, 1 ) == '6' ) ) {
            // Position needs to be changed to absolute, because IEs fallback
            // for fixed is static, which is quite useless here.
            container.css( 'position', 'absolute' );
            $( window ).scroll(
                function() {
                    container.stop( true, true );
                    if ( $.fn.activebar.state == 3 ) {
                      // Activebar is visible
                      container.css( 'top', $( window ).scrollTop() + 'px' );
                    }
                    else {
                      // Activebar is hidden
                      container.css( 'top', ( $( window ).scrollTop() - container.height() ) + 'px' );
                    }
                }
            ).resize(function(){$(window).scroll();}); 
        }

        // Add the icon container
        container.append( 
          $( '<div></div>' ).attr( 'class', 'icon' )
          .css({
            'float': 'left',
            'width': '16px',
            'height': '16px',
            'margin': '0 4px 0 0',
            'padding': '0'
          })
          .append('<img src="'+options.icons_path+'icon.png" class="normal">')
          .append('<img src="'+options.icons_path+'icon-over.png" class="hover">')
        );

        // Add the close button
        container.append( 
          $( '<div></div>' ).attr( 'class', 'close' )
          .css({
            'float': 'right',
            'margin': '0 5px 0 0 ',
            'width': '16px',
            'height': '16px'
          })
          .click(function(event) {
                $.fn.activebar.hide();
                event.stopPropagation();
          }) 
          .append('<img src="'+options.icons_path+'close.png" class="normal">')
          .append('<img src="'+options.icons_path+'close-over.png" class="hover">')
        );
       
        // Create the initial content container
        container.append( 
          $( '<div></div>' ).attr( 'class', 'content' )
          .css({
            'margin': '0px 8px',
            'paddingTop': '1px'
          })
        );
        $('.hover', container).hide();
        $('body').prepend( container );

        return container;
     };

     /**
      * Set the provided options on the given activebar container object
      */
     function setOptionsOnContainer( container, options ) {
        // Register functions to change between normal and highlight background
        // color on mouseover
        container.unbind( 'mouseenter mouseleave' );
        container.hover( 
            function() {
                $(this).css({backgroundColor: options.highlight, color: "#FFFFFF"}).addClass('hover');
                $('.hover', container).show();
                $('.normal', container).hide();
            },
            function() {
                $(this).css( {'backgroundColor': options.background, color: "#000000"} ).removeClass('hover');
                $('.hover', container).hide();
                $('.normal', container).show();
            }
        );

        // Set the content font styles
        $( '.content', container ).css({
            'fontFamily': options.font,
            'fontSize': options.fontSize
        });                                      
     }

})($telerik.$);

$telerik.$(document).ready(function($) {
	if ( $.browser.msie && ( $.browser.version.substring( 0, 1 ) == '5' || $.browser.version.substring( 0, 1 ) == '6' ) ) {
		var IE6UPDATE_OPTIONS = {
			icons_path: "../images/"
		}
		$('<div></div>').html(IE6UPDATE_OPTIONS.message || 'Your version of Internet Explorer is out of date please click here to update')
		  .activebar(window.IE6UPDATE_OPTIONS);
	}
});

/**drop shadow**/
(function($) {

    var dropShadowZindex = 1;  //z-index counter

    $.fn.dropShadow = function(options) {
        // Default options
        var opt = $.extend({
            left: 4,
            top: 4,
            blur: 2,
            opacity: .5,
            color: "black",
            swap: false
        }, options);
        var jShadows = $([]);  //empty jQuery collection

        // Loop through original elements
        this.not(".dropShadow").each(function() {
            var jthis = $(this);
            var shadows = [];
            var blur = (opt.blur <= 0) ? 0 : opt.blur;
            var opacity = (blur == 0) ? opt.opacity : opt.opacity / (blur * 8);
            var zOriginal = (opt.swap) ? dropShadowZindex : dropShadowZindex + 1;
            var zShadow = (opt.swap) ? dropShadowZindex + 1 : dropShadowZindex;

            // Create ID for shadow
            var shadowId;
            if (this.id) {
                shadowId = this.id + "_dropShadow";
            }
            else {
                shadowId = "ds" + (1 + Math.floor(9999 * Math.random()));
            }

            // Modify original element
            $.data(this, "shadowId", shadowId); //store id in expando
            $.data(this, "shadowOptions", options); //store options in expando
            jthis
				.attr("shadowId", shadowId)
				.css("zIndex", zOriginal);
            if (jthis.css("position") != "absolute") {
                jthis.css({
                    position: "relative",
                    zoom: 1 //for IE layout
                });
            }

            // Create first shadow layer
            bgColor = jthis.css("backgroundColor");
            if (bgColor == "rgba(0, 0, 0, 0)") bgColor = "transparent";  //Safari
            if (bgColor != "transparent" || jthis.css("backgroundImage") != "none"
					|| this.nodeName == "SELECT"
					|| this.nodeName == "INPUT"
					|| this.nodeName == "TEXTAREA") {
                shadows[0] = $("<div></div>")
					.css("background", opt.color);
            }
            else {
                shadows[0] = jthis
					.clone()
					.removeAttr("id")
					.removeAttr("name")
					.removeAttr("shadowId")
					.css("color", opt.color);
            }
            shadows[0]
				.addClass("dropShadow")
				.css({
				    height: jthis.outerHeight(),
				    left: blur,
				    opacity: opacity,
				    position: "absolute",
				    top: blur,
				    width: jthis.outerWidth(),
				    zIndex: zShadow
				});

            // Create other shadow layers
            var layers = (8 * blur) + 1;
            for (i = 1; i < layers; i++) {
                shadows[i] = shadows[0].clone();
            }

            // Position layers
            var i = 1;
            var j = blur;
            while (j > 0) {
                shadows[i].css({ left: j * 2, top: 0 });           //top
                shadows[i + 1].css({ left: j * 4, top: j * 2 });   //right
                shadows[i + 2].css({ left: j * 2, top: j * 4 });   //bottom
                shadows[i + 3].css({ left: 0, top: j * 2 });       //left
                shadows[i + 4].css({ left: j * 3, top: j });       //top-right
                shadows[i + 5].css({ left: j * 3, top: j * 3 });   //bottom-right
                shadows[i + 6].css({ left: j, top: j * 3 });       //bottom-left
                shadows[i + 7].css({ left: j, top: j });           //top-left
                i += 8;
                j--;
            }

            // Create container
            var divShadow = $("<div></div>")
				.attr("id", shadowId)
				.addClass("dropShadow")
				.css({
				    left: jthis.position().left + opt.left - blur,
				    marginTop: jthis.css("marginTop"),
				    marginRight: jthis.css("marginRight"),
				    marginBottom: jthis.css("marginBottom"),
				    marginLeft: jthis.css("marginLeft"),
				    position: "absolute",
				    top: jthis.position().top + opt.top - blur,
				    zIndex: zShadow
				});

            // Add layers to container	
            for (i = 0; i < layers; i++) {
                divShadow.append(shadows[i]);
            }

            // Add container to DOM
            jthis.after(divShadow);

            // Add shadow to return set
            jShadows = jShadows.add(divShadow);

            // Re-align shadow on window resize
            $(window).resize(function() {
                try {
                    divShadow.css({
                        left: jthis.position().left + opt.left - blur,
                        top: jthis.position().top + opt.top - blur
                    });
                }
                catch (e) { }
            });

            // Increment z-index counter
            dropShadowZindex += 2;

        });  //end each

        return this.pushStack(jShadows);
    };

    $.fn.redrawShadow = function() {
        // Remove existing shadows
        this.removeShadow();

        // Draw new shadows
        return this.each(function() {
            var shadowOptions = $.data(this, "shadowOptions");
            $(this).dropShadow(shadowOptions);
        });
    };

    $.fn.removeShadow = function() {
        return this.each(function() {
            var shadowId = $(this).shadowId();
            $("div#" + shadowId).remove();
        });
    };

    $.fn.shadowId = function() {
        return $.data(this[0], "shadowId");
    };

    $(function() {
        // Suppress printing of shadows
        var noPrint = "<style type='text/css' media='print'>";
        noPrint += ".dropShadow{visibility:hidden;}</style>";
        $("head").append(noPrint);
    });

})($telerik.$);