



Event.observe( document, 'dom:loaded', function()
{
	var current_image = 0;
	var images		  = $$( '#banner img' );


	for( i = 0; i < images.length; ++i )
	{
		if( i == current_image ) continue;

		images[ i ].setStyle({ 'opacity': 0 });
	}

	new PeriodicalExecuter
	(
		function( pe )
		{
			var next_image  = current_image + 1;
			if( next_image >= images.length ) next_image = 0;

			Effect.Appear( images[ current_image ],	{ duration: 2.5, from: 1, to: 0 });
			Effect.Appear( images[ next_image ],	{ duration: 2.5, from: 0, to: 1 });

			current_image = next_image;
		},
		15
	);


/*
	var banner_images = new Array( images_base_dir + 'banner_1.png' );
	var current_image = 0;

	var url = images_base_dir + 'banner_2.png';

	new Ajax.Request
	(
		url,
		{
			method		: 'get',
			onComplete	: function( transport )
			{
				banner_images.push( url );
				// switch images in some kinda order to enable more than 2 images to be displayed
				$( 'banner_2' ).setStyle({ 'backgroundImage': 'url(' + banner_images[1] + ')' });
			}
		}
	);


	new PeriodicalExecuter
	(
		function( pe )
		{
			if( banner_images.length > 1 )
			{
				if( $( 'banner_1' ).getStyle( 'opacity' ) == 1 )
				{
					Effect.Appear( 'banner_1', { duration: 2.5, from: 1, to: 0 });
					Effect.Appear( 'banner_2', { duration: 2.5, from: 0, to: 1 });
				}
				else
				{
					Effect.Appear( 'banner_1', { duration: 2.5, from: 0, to: 1 });
					Effect.Appear( 'banner_2', { duration: 2.5, from: 1, to: 0 });
				}
			}
		},
		15
	);
/**/

	// animation for the header navigation
	$$( '#navigation li' ).each
	(
		function( el )
		{
			$( el ).observe( 'mouseover', function(){ this.addClassName( 'hover' ); });
			$( el ).observe( 'mouseout', function() { this.removeClassName( 'hover' ); });
		}
	);


	// animation for the categories menu
	$$( '#categories li' ).each
	(
		function( el )
		{
			$( el ).observe( 'mouseover', function()
			{
				if( !this.hasClassName( 'parent' ) )
				{
					this.addClassName( 'hover' );
				}
			});

			$( el ).observe( 'mouseout', function()
			{
				if( !this.hasClassName( 'parent' ) )
				{
					this.removeClassName( 'hover' );
				}
			});

			$( el ).observe( 'click', function( e )
			{
				e.stop();
				window.location = this.down( 0 ).readAttribute( 'href' );
			});
		}
	);


	// animation for the categories menu
	$$( '#account_navigation li' ).each
	(
		function( el )
		{
			$( el ).observe( 'mouseover', function()
			{
				this.addClassName( 'hover' );
			});

			$( el ).observe( 'mouseout', function()
			{
				this.removeClassName( 'hover' );
			});

			$( el ).observe( 'click', function( e )
			{
				e.stop();
				window.location = this.down( 0 ).readAttribute( 'href' );
			});
		}
	);

	// adding functionality to the 'show per site' menu
	$$( '.viewswitch .right p a' ).each
	(
		function( el )
		{
			$( el ).observe( 'click', function( e )
			{
				e.stop();
				this.up( 0 ).next( 0 ).toggleClassName( 'hide' );
			});
		}
	);

	$$( '.viewswitch li' ).each
	(
		function( el )
		{
			$( el ).observe( 'mouseover', function( e )
			{
				this.addClassName( 'hover' );
			});

			$( el ).observe( 'mouseout', function( e )
			{
				this.removeClassName( 'hover' );
			});

			$( el ).observe( 'click', function( e )
			{
				window.location = this.down( 0 ).readAttribute( 'href' );
				this.up( 0 ).toggleClassName( 'hide' );
			});
		}
	);

	// animate the main gallery of the page
	if( $( 'section_gallery' ) )
	{
		var lb = new Lightbox();

		var img_arr = new Array();

		$( 'section_gallery' ).childElements( 'a' ).each
		(
			function( el, index )
			{
				if( index < 3 ) return;

				img_arr.push( [el.readAttribute( 'href' ), el.readAttribute( 'title' )] );

				el.observe
				(
					'click', function( e )
					{
						e.stop();
						lb.startWithImageArray( img_arr, index - 3 );
					}
				);
			}
		);
	}

	if( $( 'thumbnails' ) )
	{
		var lb = new Lightbox();

		LightboxOptions.fileLoadingImage		= images_base_dir + 'lightbox/loading.gif';
		LightboxOptions.fileBottomNavCloseImage	= images_base_dir + 'lightbox/closelabel.gif';


		var thumb_list	= $( 'thumbnails' ).down( 0 );
		var thumbnails	= new Array();
		var index		= 0;

		// fetch the numerical value
		var list_width	= thumb_list.getStyle( 'width' );
		list_width		= Number( list_width.substr( 0, list_width.length - 2 ) );

		// grab all product images from the list and ..
		thumb_list.select( 'a' ).each
		(
			function( el, i )
			{
				// .. apply the animation and ..
				el.observe
				(
					'click',
					function( e )
					{
						e.stop();

						$( 'product_image' ).down( 0 ).writeAttribute( 'src', el.readAttribute( 'href' ) );

						// store the current index. that enables us to view the current image in $( 'product_image' ) on the first slimbox page
						index = i;
					}
				);

				// .. add them to the array
				thumbnails.push( [el.readAttribute( 'href' ), el.readAttribute( 'title' )] );
			}
		);


		// add the slimbox listener to the large image view
		$( 'product_image' ).observe
		(
			'click',
			function( e )
			{
				e.stop();
				lb.startWithImageArray( thumbnails, index );
			}
		);


		if( $( 'thumbnails' ).down( 0 ).childElements().length > 3 )
		{
			var scroller = new Scroller( $( 'gallery' ), $( 'thumbnails' ) );

			$( 'thumbnails' ).observe( 'mouseenter', function(){ scroller.start(); });
			$( 'thumbnails' ).observe( 'mouseleave', function(){ scroller.stop(); });
		}
	}

	$$( '.preview_link' ).each
	(
		function( el )
		{
			el.observe
			(
				'click', function( e )
				{
					e.stop();

					if( el.readAttribute( 'href' ) != '#' )
						lb.startWithImageArray( [[el.readAttribute( 'href' ), el.readAttribute( 'title' )]], 0 );
				}
			);
		}
	);




	new Select_Replacement(
	{
		'type'		: 'jsui_select_color',

		'onReplaced': function( el )
		{
			var item = el.down( '.selected' );

			if( item )
			{
				applyItemColor( item, item.innerHTML );
			}
		},

		'onSelected': function( el, val, caption )
		{
			applyItemColor( el, caption );
		}
	});

	new Select_Replacement(
	{
		'type': 'jsui_select'
	});

	new Radio_Replacement(
	{
		'type': 'jsui_radio',

		'onChecked': function( el, val, caption )
		{
			var preview_link = el.up( 2 ).next().down( 0 );

			preview_link.update( caption );

			preview_link.writeAttribute( 'href', images_base_dir + 'wood/' + caption + '.png' );
			preview_link.writeAttribute( 'title', caption );
		},

		'onMouseover': function( el, val, caption )
		{
			el.up( 2 ).next().down( 0 ).update( caption );
		},

		'onMouseout': function( el, val, caption )
		{
			var container	= el.up( 2 ).next().down( 0 );
			var checked		= el.up( 2 ).down( '.jsui_checked' );

			if( typeof checked != 'undefined' )
			{
				container.update( checked.up( 0 ).readAttribute( 'jsui_caption' ) );
			}
			else
			{
				container.update( 'Bitte w&auml;hlen' );
			}
		}
	});


	function applyItemColor( el, val )
	{
		var color = null;
		var image = val;

		switch( val )
		{
			case 'Schwarz':			color = '#000'; break;
			case 'Hellblau':		color = '#8CC3FF'; break;
			case 'Flieder':			color = '#D598FF'; break;
			case 'Rosa':			color = '#FFD0EF'; break;
			case 'Hellbraun':		color = '#E9C990'; break;
			case 'Rot':				color = '#F00'; break;
			case 'Gelb':			color = '#FF0'; break;
			case 'Orange':			color = '#F70'; break;
			case 'Violett': 		color = '#800080'; break;
		}

		if( val.substr( 0, 8 ) == 'Dunkelgr' )
		{
			color = '#090';
			image = 'Dunkelgruen';
		}

		if( val.substr( 0, 3 ) == 'Wei' )
		{
			color = '#FFF';
			image = 'Weiss';
		}

		el.up( 1 ).previous().setStyle({ 'backgroundColor': color });

		el.up( 1 ).next().down( 0 ).writeAttribute( 'href', images_base_dir + 'straps/' + image + '.jpg' );
		el.up( 1 ).next().down( 0 ).writeAttribute( 'title', val );
	}
});


		var Scroller = Class.create();
		Scroller.prototype =
		{
			initialize : function( container, wrapper )
			{
				this.container	= container;
				this.wrapper	= wrapper;
				this.direction	= 0;
				this.running	= false;
				this.mousex		= 0;
				this.mousey		= 0;
				this.position	= 0;
				this.element	= this.wrapper.down( 0 );
				this.speed		= 0.025;

				this.timeoutdelay = 40;

				Event.observe( this.wrapper, 'mousemove', this.mousemove.bindAsEventListener( this ) );

				this.originalLeft = parseFloat( this.element.getStyle( 'left' ) || '0' );
		   		this.originalTop  = parseFloat( this.element.getStyle( 'top' )  || '0' );
			},
			mousemove : function( e )
			{
				this.mousex = Event.pointerX( e );
				this.mousey = Event.pointerY( e );
			},
			start : function()
			{
				this.running = true;
				this.run();
			},
			stop : function()
			{
				this.running = false;
			},
			moveLeft : function()
			{
				this.direction = 1;
			},
			moveRight : function()
			{
				this.direction = -1;
			},
			run : function()
			{
				var p = this.mousex - Position.cumulativeOffset( this.wrapper )[0];
				var p1 = p / Element.getDimensions( this.wrapper ).width;

				var p = this.mousey - Position.cumulativeOffset( this.wrapper )[1];
				var p2 = p / ( Element.getDimensions( this.wrapper ).height + 20 );

				if( p2 > 1.4 && this.container.style.top === "0px" )
				{
	//				this.container.toggleCarousel();
					this.stop();
				}

				if( p1 > 0.8 && this.position <= 1 - this.speed && p2 >= 0 && p2 <= 1 )
				{
					this.position += this.speed;
				}
				else if ( p1 < 0.2 && this.position >= this.speed && p2 >= 0 && p2 <= 1 )
				{
					this.position -= this.speed;
				}
				else
				{
				}

				this.position = Math.round( this.position * 100 ) / 100;

				Element.setStyle
				(
					this.element,
					{
						left: Math.round( ( Element.getDimensions( this.element ).width - Element.getDimensions( this.wrapper ).width )  * -this.position + this.originalLeft ) + 'px'
					}
				);

				if( !this.running ) return;
				setTimeout( function(){ this.run() }.bind( this ) , this.timeoutdelay );
			}
		}


Validation.addAllThese([
    ['validate-select', 'Bitte treffen Sie eine Auswahl.', function(v) {
                return ((v != "none") && (v != null) && (v.length != 0));
            }],
    ['required-entry', 'Dies ist ein Pflichtfeld.', function(v) {
                return !Validation.get('IsEmpty').test(v);
            }],
    ['validate-number', 'Die Eingabe muss eine g&uuml;ltige Zahl sein.', function(v) {
                return Validation.get('IsEmpty').test(v) || (!isNaN(parseNumber(v)) && !/^\s+$/.test(parseNumber(v)));
            }],
    ['validate-digits', 'Die Eingabe darf nur aus Zahlen bestehen. Bitte verwenden Sie keine Leerzeichen oder andere Zeichen wie Punkte oder Kommas.', function(v) {
                return Validation.get('IsEmpty').test(v) ||  !/[^\d]/.test(v);
            }],
    ['validate-alpha', 'Die Eingabe darf nur aus Buchstaben (a-z or A-Z) bestehen.', function (v) {
                return Validation.get('IsEmpty').test(v) ||  /^[a-zA-Z]+$/.test(v)
            }],
    ['validate-code', 'Die Eingabe darf nur aus Buchstaben(a-z), Ziffern (0-9) und/oder einen Unterstrich (_) bestehen, das erste Zeichen sollte ein Buchstabe sein.', function (v) {
                return Validation.get('IsEmpty').test(v) ||  /^[a-z]+[a-z0-9_]+$/.test(v)
            }],
    ['validate-alphanum', 'Die Eingabe darf nur aus Buchstaben (a-z or A-Z) oder Ziffern (0-9) bestehen.', function(v) {
                return Validation.get('IsEmpty').test(v) ||  /^[a-zA-Z0-9]+$/.test(v) /*!/\W/.test(v)*/
            }],
    ['validate-street', 'Die Eingabe darf nur aus Buchstaben (a-z or A-Z), Ziffern (0-9) oder Leerzeichen und # bestehen.', function(v) {
                return Validation.get('IsEmpty').test(v) ||  /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(v)
            }],
    ['validate-phoneStrict', 'Bitte geben Sie eine g&uuml;ltige Telefonnummer ein. Beispiel: (123) 456-7890 or 123-456-7890.', function(v) {
                return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
            }],
    ['validate-phoneLax', 'Bitte geben Sie eine g&uuml;ltige Telefonnummer ein. Beispiel: (123) 456-7890 or 123-456-7890.', function(v) {
                return Validation.get('IsEmpty').test(v) || /^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(v);
            }],
    ['validate-fax', 'Bitte geben Sie eine g&uuml;ltige Faxnummer ein. Beispiel: (123) 456-7890 oder 123-456-7890.', function(v) {
                return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
            }],
    ['validate-date', 'Bitte geben Sie ein g&uul;ltiges Datum ein.', function(v) {
                var test = new Date(v);
                return Validation.get('IsEmpty').test(v) || !isNaN(test);
            }],
    ['validate-email', 'Bitte geben Sie eine g&uuml;ltige E-Mail Adresse ein. Beispiel: maxmustermann@domain.de', function (v) {
                //return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
                //return Validation.get('IsEmpty').test(v) || /^[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9][\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9\.]{1,30}[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9]@([a-z0-9_-]{1,30}\.){1,5}[a-z]{2,4}$/i.test(v)
                return Validation.get('IsEmpty').test(v) || /^[a-z0-9,!\#\$%&'\*\+/=\?\^_`\{\|}~-]+(\.[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})/i.test(v)
            }],
    ['validate-emailSender', 'Die Eingabe darf nur aus Buchstaben (a-z oder A-Z), Ziffern (0-9), Unterstrich "_" oder Leerzeichen bestehen.', function (v) {
                return Validation.get('IsEmpty').test(v) ||  /^[a-zA-Z0-9_\s]+$/.test(v)
                    }],
    ['validate-password', 'Die Eingabe muss aus mindestens 6 Zeichen bestehen. Vorangestellte Leerzeichen werden ignoriert.', function(v) {
                var pass=v.strip(); /*strip leading and trailing spaces*/
                return !(pass.length>0 && pass.length < 6);
            }],
    ['validate-admin-password', 'Die Eingabe muss aus mindestens 7 Zeichen bestehen. Ihr Passwort sollte sowohl Buchstaben als auch Zahlen enthalten.', function(v) {
                var pass=v.strip();
                if (0 == pass.length) {
                    return true;
                }
                if (!(/[a-z]/i.test(v)) || !(/[0-9]/.test(v))) {
                    return false;
                }
                return !(pass.length < 7);
            }],
    ['validate-cpassword', 'Die eingegebenen Passw&ouml;rter stimmen nicht &uuml;berein.', function(v) {
                if ($('password')) {
                    var pass = $('password');
                }
                else {
                    var pass = $$('.validate-password').length ? $$('.validate-password')[0] : $$('.validate-admin-password')[0];
                }
                var conf = $('confirmation') ? $('confirmation') : $$('.validate-cpassword')[0];
                return (pass.value == conf.value);
            }],
    ['validate-url', 'Bitte geben Sie eine g&uuml;ltige URL ein. Ein vorangestelltes http:// ist notwendig.', function (v) {
                return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)
            }],
    ['validate-clean-url', 'Bitte geben Sie eine g&uuml;ltige URL ein. Beispiel: http://www.example.com oder www.example.com', function (v) {
                return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v) || /^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v)
            }],
    ['validate-identifier', 'Bitte geben Sie einen g&uuml;ltigen Identifikator ein. Beispiel: muster-seite, muster-seite.html oder verzeichnis/muster-seite', function (v) {
                return Validation.get('IsEmpty').test(v) || /^[A-Z0-9][A-Z0-9_\/-]+(\.[A-Z0-9_-]+)*$/i.test(v)
            }],
    ['validate-xml-identifier', 'Bitte geben Sie einen g&uuml;ltigen XML-Identifikator ein. Beispiel: irgendwas_1, block5, id-4', function (v) {
                return Validation.get('IsEmpty').test(v) || /^[A-Z][A-Z0-9_\/-]*$/i.test(v)
            }],
    ['validate-ssn', 'Bitte geben Sie eine g&uuml;ltige Sozialversicherungsnummer ein. Beispiel: 123-45-6789.', function(v) {
            return Validation.get('IsEmpty').test(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v);
            }],
    ['validate-zip', 'Bitte geben Sie eine g&uuml;ltige Postleitzahl ein. Beispiel: 90602 oder 90602-1234.', function(v) {
            return Validation.get('IsEmpty').test(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v);
            }],
    ['validate-zip-international', 'Bitte geben Sie eine g&uuml;ltige Postleitzahl ein.', function(v) {
            //return Validation.get('IsEmpty').test(v) || /(^[A-z0-9]{2,10}([\s]{0,1}|[\-]{0,1})[A-z0-9]{2,10}$)/.test(v);
            return true;
            }],
    ['validate-date-au', 'Bitte verwenden Sie folgende Formatierung: tt/mm/jjjj. Beispiel 17/03/2009 f&uuml;r den 17. M&auml;rz, 2009.', function(v) {
                if(Validation.get('IsEmpty').test(v)) return true;
                var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
                if(!regex.test(v)) return false;
                var d = new Date(v.replace(regex, '$2/$1/$3'));
                return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) &&
                            (parseInt(RegExp.$1, 10) == d.getDate()) &&
                            (parseInt(RegExp.$3, 10) == d.getFullYear() );
            }],
    ['validate-currency-dollar', 'Bitte geben Sie einen g&uuml;ltigen $ Betrag ein. Beispiel: $100.00.', function(v) {
                // [$]1[##][,###]+[.##]
                // [$]1###+[.##]
                // [$]0.##
                // [$].##
                return Validation.get('IsEmpty').test(v) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
            }],
    ['validate-one-required', 'Bitte w&auml;hlen Sie eine der angezeigten Optionen.', function (v,elm) {
                var p = elm.parentNode;
                var options = p.getElementsByTagName('INPUT');
                return $A(options).any(function(elm) {
                    return $F(elm);
                });
            }],
    ['validate-one-required-by-name', 'Bitte w&auml;hlen Sie eine Option.', function (v,elm) {
                var inputs = $$('input[name="' + elm.name.replace(/([\\"])/g, '\\$1') + '"]');

                var error = 1;
                for(var i=0;i<inputs.length;i++) {
                    if((inputs[i].type == 'checkbox' || inputs[i].type == 'radio') && inputs[i].checked == true) {
                        error = 0;
                    }

                    if(Validation.isOnChange && (inputs[i].type == 'checkbox' || inputs[i].type == 'radio')) {
                        Validation.reset(inputs[i]);
                    }
                }

                if( error == 0 ) {
                    return true;
                } else {
                    return false;
                }
            }],
    ['validate-not-negative-number', 'Bitte geben Sie eine g&uuml;ltige, positive Zahl ein.', function(v) {
                v = parseNumber(v);
                return (!isNaN(v) && v>=0);
            }],
    ['validate-state', 'Bitte w&auml;hlen Sie ein g&uuml;ltiges Land/Provinz.', function(v) {
                return (v!=0 || v == '');
            }],

    ['validate-new-password', 'Die Eingabe muss aus mindestens 6 Zeichen bestehen. Leerzeichen am Anfang und am Ende werden ignoriert.', function(v) {
                if (!Validation.get('validate-password').test(v)) return false;
                if (Validation.get('IsEmpty').test(v) && v != '') return false;
                return true;
            }],
    ['validate-greater-than-zero', 'Die Eingabe muss gr&ouml;&szlig;er 0 sein.', function(v) {
                if(v.length)
                    return parseFloat(v) > 0;
                else
                    return true;
            }],
    ['validate-zero-or-greater', 'Die Eingabe darf nicht negativ sein.', function(v) {
                if(v.length)
                    return parseFloat(v) >= 0;
                else
                    return true;
            }],
    ['validate-cc-number', 'Bitte geben Sie eine g&uuml;ltige Kreditkartennummer ein.', function(v, elm) {
                // remove non-numerics
                var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_number')) + '_cc_type');
                if (ccTypeContainer && typeof Validation.creditCartTypes.get(ccTypeContainer.value) != 'undefined'
                        && Validation.creditCartTypes.get(ccTypeContainer.value)[2] == false) {
                    if (!Validation.get('IsEmpty').test(v) && Validation.get('validate-digits').test(v)) {
                        return true;
                    } else {
                        return false;
                    }
                }
                return validateCreditCard(v);
            }],
    ['validate-cc-type', 'Die eingegebene Kreditkartennummer passt nicht zum gew&auml;hlten Kartentyp.', function(v, elm) {
                // remove credit card number delimiters such as "-" and space
                elm.value = removeDelimiters(elm.value);
                v         = removeDelimiters(v);

                var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_number')) + '_cc_type');
                if (!ccTypeContainer) {
                    return true;
                }
                var ccType = ccTypeContainer.value;

                if (typeof Validation.creditCartTypes.get(ccType) == 'undefined') {
                    return false;
                }

                // Other card type or switch or solo card
                if (Validation.creditCartTypes.get(ccType)[0]==false) {
                    return true;
                }

                // Matched credit card type
                var ccMatchedType = '';

                Validation.creditCartTypes.each(function (pair) {
                    if (pair.value[0] && v.match(pair.value[0])) {
                        ccMatchedType = pair.key;
                        throw $break;
                    }
                });

                if(ccMatchedType != ccType) {
                    return false;
                }

                if (ccTypeContainer.hasClassName('validation-failed') && Validation.isOnChange) {
                    Validation.validate(ccTypeContainer);
                }

                return true;
            }],
     ['validate-cc-type-select', 'Der gew&auml;hlte Kreditkarten-Typ passt nicht zur eingegebenen Kreditkartennummer.', function(v, elm) {
                var ccNumberContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_type')) + '_cc_number');
                if (Validation.isOnChange && Validation.get('IsEmpty').test(ccNumberContainer.value)) {
                    return true;
                }
                if (Validation.get('validate-cc-type').test(ccNumberContainer.value, ccNumberContainer)) {
                    Validation.validate(ccNumberContainer);
                }
                return Validation.get('validate-cc-type').test(ccNumberContainer.value, ccNumberContainer);
            }],
     ['validate-cc-exp', 'Bitte geben Sie ein g&uuml;ltiges Ablaufdatum ein.', function(v, elm) {
                var ccExpMonth   = v;
                var ccExpYear    = $('ccsave_expiration_yr').value;
                var currentTime  = new Date();
                var currentMonth = currentTime.getMonth() + 1;
                var currentYear  = currentTime.getFullYear();
                if (ccExpMonth < currentMonth && ccExpYear == currentYear) {
                    return false;
                }
                return true;
            }],
     ['validate-cc-cvn', 'Bitte geben Sie eine g&uuml;ltige Kreditkarten-Kontrollnummer ein.', function(v, elm) {
                var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_cid')) + '_cc_type');
                if (!ccTypeContainer) {
                    return true;
                }
                var ccType = ccTypeContainer.value;

                if (typeof Validation.creditCartTypes.get(ccType) == 'undefined') {
                    return false;
                }

                var re = Validation.creditCartTypes.get(ccType)[1];

                if (v.match(re)) {
                    return true;
                }

                return false;
            }],
     ['validate-ajax', '', function(v, elm) { return true; }],
     ['validate-data', 'Die Eingabe darf nur aus Buchstaben(a-z oder A-Z), Ziffern (0-9) und/oder einen Unterstrich (_) bestehen, das erste Zeichen sollte ein Buchstabe sein.', function (v) {
                if(v != '' && v) {
                    return /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v);
                }
                return true;
            }],
     ['validate-css-length', 'Bitte geben Sie eine g&uuml;ltige CSS-L&auml;ngenangabe ein. Beispiel: 100px oder 77pt oder 20em oder .5ex oder 50%', function (v) {
                if (v != '' && v) {
                    return /^[0-9\.]+(px|pt|em|ex|%)?$/.test(v) && (!(/\..*\./.test(v))) && !(/\.$/.test(v));
                }
                return true;
            }],
     ['validate-length', 'Maximall&auml;nge erreicht.', function (v, elm) {
                var re = new RegExp(/^maximum-length-[0-9]+$/);
                var result = true;
                $w(elm.className).each(function(name, index) {
                        if (name.match(re) && result) {
                           var length = name.split('-')[2];
                           result = (v.length <= length);
                        }
                    });
                return result;
            }]
]);


// -----------------------------------------------------------------------------------
//
//	Lightbox v2.04
//	by Lokesh Dhakar - http://www.lokeshdhakar.com
//	Last Modification: 2/9/08
//
//	For more information, visit:
//	http://lokeshdhakar.com/projects/lightbox2/
//
//	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
//  	- Free for use in both personal and commercial projects
//		- Attribution requires leaving author name, author link, and the license info intact.
//
//  Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
//  		Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
//
// -----------------------------------------------------------------------------------
/*

    Table of Contents
    -----------------
    Configuration

    Lightbox Class Declaration
    - initialize()
    - updateImageList()
    - start()
    - changeImage()
    - resizeImageContainer()
    - showImage()
    - updateDetails()
    - updateNav()
    - enableKeyboardNav()
    - disableKeyboardNav()
    - keyboardAction()
    - preloadNeighborImages()
    - end()

    Function Calls
    - document.observe()

*/
// -----------------------------------------------------------------------------------

//
//  Configurationl
//
LightboxOptions = Object.extend
(
	{
	    fileLoadingImage:        'http://michelwald.de/dev/magento/skin/frontend/default/default/images/lightbox/loading.gif',
	    fileBottomNavCloseImage: 'http://michelwald.de/dev/magento/skin/frontend/default/default/images/lightbox/closelabel.png',

	    overlayOpacity: 0.8,   // controls transparency of shadow overlay

	    animate: true,         // toggles resizing animations
	    resizeSpeed: 7,        // controls the speed of the image resizing animations (1=slowest and 10=fastest)

	    borderSize: 10,         //if you adjust the padding in the CSS, you will need to update this variable

		// When grouping images this is used to write: Image # of #.
		// Change it for non-english localization
		labelImage: "Ansicht",
		labelOf: "von"
	},
	window.LightboxOptions || {}
);

// -----------------------------------------------------------------------------------

var Lightbox = Class.create();
Lightbox.prototype =
{
    imageArray: [],
    activeImage: undefined,

    // initialize()
    // Constructor runs on completion of the DOM loading. Calls updateImageList and then
    // the function inserts html at the bottom of the page which is used to display the shadow
    // overlay and the image container.
    //
    initialize: function() {

        this.updateImageList();

        this.keyboardAction = this.keyboardAction.bindAsEventListener(this);

        if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
        if (LightboxOptions.resizeSpeed < 1)  LightboxOptions.resizeSpeed = 1;

	    this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
	    this.overlayDuration = LightboxOptions.animate ? 0.2 : 0;  // shadow fade in/out duration

        // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
        // If animations are turned off, it will be hidden as to prevent a flicker of a
        // white 250 by 250 box.
        var size = (LightboxOptions.animate ? 250 : 1) + 'px';


        // Code inserts html at the bottom of the page that looks similar to this:
        //
        //  <div id="overlay"></div>
        //  <div id="lightbox">
        //      <div id="outerImageContainer">
        //          <div id="imageContainer">
        //              <img id="lightboxImage">
        //              <div style="" id="hoverNav">
        //                  <a href="#" id="prevLink"></a>
        //                  <a href="#" id="nextLink"></a>
        //              </div>
        //              <div id="loading">
        //                  <a href="#" id="loadingLink">
        //                      <img src="images/loading.gif">
        //                  </a>
        //              </div>
        //          </div>
        //      </div>
        //      <div id="imageDataContainer">
        //          <div id="imageData">
        //              <div id="imageDetails">
        //                  <span id="caption"></span>
        //                  <span id="numberDisplay"></span>
        //              </div>
        //              <div id="bottomNav">
        //                  <a href="#" id="bottomNavClose">
        //                      <img src="images/close.gif">
        //                  </a>
        //              </div>
        //          </div>
        //      </div>
        //  </div>


        var objBody = $$('body')[0];

		objBody.appendChild(Builder.node('div',{id:'overlay'}));

        objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
            Builder.node('div',{id:'outerImageContainer'},
                Builder.node('div',{id:'imageContainer'}, [
                    Builder.node('img',{id:'lightboxImage'}),
                    Builder.node('div',{id:'hoverNav'}, [
                        Builder.node('a',{id:'prevLink', href: '#' }),
                        Builder.node('a',{id:'nextLink', href: '#' })
                    ]),
                    Builder.node('div',{id:'loading'},
                        Builder.node('a',{id:'loadingLink', href: '#' },
                            Builder.node('img', {src: LightboxOptions.fileLoadingImage})
                        )
                    )
                ])
            ),
            Builder.node('div', {id:'imageDataContainer'},
                Builder.node('div',{id:'imageData'}, [
                    Builder.node('div',{id:'imageDetails'}, [
                        Builder.node('span',{id:'caption'}),
                        Builder.node('span',{id:'numberDisplay'})
                    ]),
                    Builder.node('div',{id:'bottomNav'},
                        Builder.node('a',{id:'bottomNavClose', href: '#' },
                            Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
                        )
                    )
                ])
            )
        ]));


		$('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
		$('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
		$('outerImageContainer').setStyle({ width: size, height: size });
		$('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
		$('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
		$('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
		$('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));

        var th = this;
        (function(){
            var ids =
                'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +
                'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';
            $w(ids).each(function(id){ th[id] = $(id); });
        }).defer();
    },

    //
    // updateImageList()
    // Loops through anchor tags looking for 'lightbox' references and applies onclick
    // events to appropriate links. You can rerun after dynamically adding images w/ajax.
    //
    updateImageList: function() {
/*
        this.updateImageList = Prototype.emptyFunction;

        document.observe('click', (function(event){
            var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
            if (target) {
                event.stop();
                this.start(target);
            }
        }).bind(this));
*/
    },

    //
    //  start()
    //  Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
    //
    start: function(imageLink) {

        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });

        // stretch overlay to fill page and fade in
        var arrayPageSize = this.getPageSize();
        $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });

        new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });

        this.imageArray = [];
        var imageNum = 0;

        if( ( imageLink.rel == 'lightbox' ) )
        {
            // if image is NOT part of a set, add single image to imageArray
            this.imageArray.push( [imageLink.href, imageLink.title] );
        }
        else
        {
            // if image is part of a set..
            this.imageArray = $$( imageLink.tagName + '[href][rel="' + imageLink.rel + '"]' )
				                .
				                collect( function( anchor ){ return [anchor.href, anchor.title]; } )
				                .
				                uniq();

            while( this.imageArray[imageNum][0] != imageLink.href )
            {
            	imageNum++;
            }
        }

        // calculate top and left offset for the lightbox
        var arrayPageScroll	= document.viewport.getScrollOffsets();
        var lightboxTop		= arrayPageScroll[1] + ( document.viewport.getHeight() / 10 );
        var lightboxLeft	= arrayPageScroll[0];

        this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();

        this.changeImage(imageNum);
    },


	//
	//  startWithImageArray()
	//  @param array	- the image array (each index has to contain [href, title]
	//	@param index	- the image of the array to display first
	//
	startWithImageArray: function( arr, index )
	{
		$$( 'select', 'object', 'embed' ).each( function( node ){ node.style.visibility = 'hidden' });

		// stretch overlay to fill page and fade in
		var arrayPageSize = this.getPageSize();
		$( 'overlay' ).setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });

		new Effect.Appear( this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });
		this.imageArray = arr;

		// calculate top and left offset for the lightbox
		var arrayPageScroll	= document.viewport.getScrollOffsets();
		var lightboxTop		= arrayPageScroll[1] + ( document.viewport.getHeight() / 10 );
		var lightboxLeft	= arrayPageScroll[0];

		this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();

		this.changeImage( index );
    },

    //
    //  changeImage()
    //  Hide most elements and preload image in preparation for resizing image container.
    //
    changeImage: function(imageNum) {

        this.activeImage = imageNum; // update global var

        // hide elements during transition
        if (LightboxOptions.animate) this.loading.show();
        this.lightboxImage.hide();
        this.hoverNav.hide();
        this.prevLink.hide();
        this.nextLink.hide();
		// HACK: Opera9 does not currently support scriptaculous opacity and appear fx
        this.imageDataContainer.setStyle({opacity: .0001});
        this.numberDisplay.hide();

        var imgPreloader = new Image();

        // once image is preloaded, resize image container


        imgPreloader.onload = (function(){
            this.lightboxImage.src = this.imageArray[this.activeImage][0];
            this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
        }).bind(this);
        imgPreloader.src = this.imageArray[this.activeImage][0];
    },

    //
    //  resizeImageContainer()
    //
    resizeImageContainer: function(imgWidth, imgHeight) {

        // get current width and height
        var widthCurrent  = this.outerImageContainer.getWidth();
        var heightCurrent = this.outerImageContainer.getHeight();

        // get new width and height
        var widthNew  = (imgWidth  + LightboxOptions.borderSize * 2);
        var heightNew = (imgHeight + LightboxOptions.borderSize * 2);

        // scalars based on change from old to new
        var xScale = (widthNew  / widthCurrent)  * 100;
        var yScale = (heightNew / heightCurrent) * 100;

        // calculate size difference between new and old image, and resize if necessary
        var wDiff = widthCurrent - widthNew;
        var hDiff = heightCurrent - heightNew;

        if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});
        if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});

        // if new and old image are same size and no scaling transition is necessary,
        // do a quick pause to prevent image flicker.
        var timeout = 0;
        if ((hDiff == 0) && (wDiff == 0)){
            timeout = 100;
            if (Prototype.Browser.IE) timeout = 250;
        }

        (function(){
            this.prevLink.setStyle({ height: imgHeight + 'px' });
            this.nextLink.setStyle({ height: imgHeight + 'px' });
            this.imageDataContainer.setStyle({ width: widthNew + 'px' });

            this.showImage();
        }).bind(this).delay(timeout / 1000);
    },

    //
    //  showImage()
    //  Display image and begin preloading neighbors.
    //
    showImage: function(){
        this.loading.hide();
        new Effect.Appear(this.lightboxImage, {
            duration: this.resizeDuration,
            queue: 'end',
            afterFinish: (function(){ this.updateDetails(); }).bind(this)
        });
        this.preloadNeighborImages();
    },

    //
    //  updateDetails()
    //  Display caption, image number, and bottom nav.
    //
    updateDetails: function() {

        // if caption is not null
        if (this.imageArray[this.activeImage][1] != ""){
            this.caption.update(this.imageArray[this.activeImage][1]).show();
        }

        // if image is part of set display 'Image x of x'
        if (this.imageArray.length > 1){
            this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + '  ' + this.imageArray.length).show();
        }

        new Effect.Parallel(
            [
                new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),
                new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })
            ],
            {
                duration: this.resizeDuration,
                afterFinish: (function() {
	                // update overlay size and update nav
	                var arrayPageSize = this.getPageSize();
	                this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
	                this.updateNav();
                }).bind(this)
            }
        );
    },

    //
    //  updateNav()
    //  Display appropriate previous and next hover navigation.
    //
    updateNav: function() {

        this.hoverNav.show();

        // if not first image in set, display prev image button
        if (this.activeImage > 0) this.prevLink.show();

        // if not last image in set, display next image button
        if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();

        this.enableKeyboardNav();
    },

    //
    //  enableKeyboardNav()
    //
    enableKeyboardNav: function() {
        document.observe('keydown', this.keyboardAction);
    },

    //
    //  disableKeyboardNav()
    //
    disableKeyboardNav: function() {
        document.stopObserving('keydown', this.keyboardAction);
    },

    //
    //  keyboardAction()
    //
    keyboardAction: function(event) {
        var keycode = event.keyCode;

        var escapeKey;
        if (event.DOM_VK_ESCAPE) {  // mozilla
            escapeKey = event.DOM_VK_ESCAPE;
        } else { // ie
            escapeKey = 27;
        }

        var key = String.fromCharCode(keycode).toLowerCase();

        if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
            this.end();
        } else if ((key == 'p') || (keycode == 37)){ // display previous image
            if (this.activeImage != 0){
                this.disableKeyboardNav();
                this.changeImage(this.activeImage - 1);
            }
        } else if ((key == 'n') || (keycode == 39)){ // display next image
            if (this.activeImage != (this.imageArray.length - 1)){
                this.disableKeyboardNav();
                this.changeImage(this.activeImage + 1);
            }
        }
    },

    //
    //  preloadNeighborImages()
    //  Preload previous and next images.
    //
    preloadNeighborImages: function(){
        var preloadNextImage, preloadPrevImage;
        if (this.imageArray.length > this.activeImage + 1){
            preloadNextImage = new Image();
            preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
        }
        if (this.activeImage > 0){
            preloadPrevImage = new Image();
            preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
        }

    },

    //
    //  end()
    //
    end: function() {
        this.disableKeyboardNav();
        this.lightbox.hide();
        new Effect.Fade(this.overlay, { duration: this.overlayDuration });
        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
    },

    //
    //  getPageSize()
    //
    getPageSize: function() {

	     var xScroll, yScroll;

		if (window.innerHeight && window.scrollMaxY) {
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}

		var windowWidth, windowHeight;

		if (self.innerHeight) {	// all except Explorer
			if(document.documentElement.clientWidth){
				windowWidth = document.documentElement.clientWidth;
			} else {
				windowWidth = self.innerWidth;
			}
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}

		// for small pages with total height less then height of the viewport
		if(yScroll < windowHeight){
			pageHeight = windowHeight;
		} else {
			pageHeight = yScroll;
		}

		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth){
			pageWidth = xScroll;
		} else {
			pageWidth = windowWidth;
		}

		return [pageWidth,pageHeight];
	}
}
