/**
 * @fileOverview This file holds the newest parts of the Slotmachine
 *					  and other stuff that is needed on the flyerpilot page.
 */

/* >> GenericConfigurator Version: rel-1-1-0 requires:
	jQuery 1.4+,
	AjaxUrlManager rel-1-0-1,
	Utilities rel-1-6-0 */

	/* >> Generic configurator */
		GenericConfigurator = $.extend(
			$.clone(LLObject),
			{
				create: function(){
					var o = LLObject.create.call(this);
					o.toJsonAttrs = ['data'];
					o.data = null;
					o.url = null;
					o.currentConfiguratorIndex = 0;
					o.onAfterSlotCatch = null;
					o.onDataRequest = null;
					o.onDataRequestSuccess = null;
					o.slots = [];
					o.urlParams = null;
					o.defaults = {
						dataType: 'GenericConfiguratorData',
						slotType: 'GenericConfiguratorSlot',
						slotItemType: 'GenericConfiguratorSlotItem',
						target: null,
						ajaxHandler: null,
						onBeforeInit: null,
						onInitDataReceive: null,
						onAfterInit: null,
						onAfterSlotCatch: null,
						onAfterSlotsUpdate: null,
						onSlotAction: null,
						onDataReceive: null,
						onDataRequest: null,
						onDataRequestSuccess: null,
						ignoreLockedSlots: false
					};
					return o;
				},
				init: function(opts){
					window.slotMachinePresent = 1;
					window.genericConfiguratorPresent = 1;
					if (typeof window.currentConfiguratorIndex == 'undefined'){
						window.currentConfiguratorIndex = 0;
					}else{
						window.currentConfiguratorIndex++;
					}
					this.currentConfiguratorIndex = window.currentConfiguratorIndex;
					if (opts){
						var defaults = this.defaults = $.extend(this.defaults, opts);
						var prefix = String.fromCharCode(this.currentConfiguratorIndex + 97);
						this.url = this.prepareUrl();
						this.makeShell(defaults.target);
						// call init callback if exists
						var cbbi = defaults.onBeforeInit;
						if (cbbi && typeof cbbi == 'function'){
							cbbi.call(this);
						}
						if (this.url){
							var self = this;
							$.getJSON(this.url, function(data, textStatus){
								var d = self.data = data;
								var cbidr = defaults.onInitDataReceive;
								if (cbidr && typeof cbidr == 'function'){
									cbidr.call(self, d);
								}
								if (d.type == self.defaults.dataType){
									var slotType = self.defaults.slotType;
									var slotItemType = self.defaults.slotItemType;
									$(d.slots).each(function(i){
										if (this.type == slotType){
											var slot = window[slotType].create(this.title, this.currentItem);
											slot.configurator = self;
											slot.id = prefix + '_slot_' + i;
											slot.itemId = i;
											slot.data = this;
											slot.width = this.width;
											$(this.items).each(function(i){
												if (this.type == slotItemType){
													var slotItem = window[slotItemType].create(this.title, this.value);
													slotItem.configurator = self;
													slotItem.id = slot.id + '_slotItem_' + i;
													slotItem.itemCnt = i;
													slotItem.data = this;
													slotItem.slot = slot;
													slotItem.width = slot.width;
													slot.appendItem(slotItem);
												}
											});
											self.appendSlot(slot);
											self.calculateSlotWidth(slot);
										}
									});
								}
								// call init callback if exists
								var initCb = defaults.onAfterInit;
								if (initCb && typeof initCb == 'function'){
									initCb.call(self, self.data);
								}
								var cbdrs = self.defaults.onDataRequestSuccess;
								if (cbdrs && typeof cbdrs == 'function'){
									cbdrs.call(self, null, d);
								}
							});
						}
					}
				},
				calculateSlotWidth: function(slot){},
				getURLParams: function(specParams){
					var url = window.location.href;
					var params =  Utils.getUrlParamsAsJson(url);
					params = $.extend(params, specParams);
					return params;
				},
				prepareUrl: function(){
					var urlParams = this.urlParams = this.getURLParams();
					var url = AjaxURLManager.getUrlWithKey(this.defaults.ajaxHandler, urlParams);
					return url;
				},
				makeShell: function(target){
					var shell = $(
						'<div id="genericConfiguratorOuter">' +
							'<div id="genericConfiguratorMainBg">' +
								'<table cellpadding="0" cellspacing="0" border="0" class="genericConfiguratorShell">' +
								'</table>' +
							'</div>' +
						'</div>'
					);
					target.append(shell);
				},
				appendSlot: function(slot){
					var d = this.data, showSlot = true, ignoreLockedSlots = this.defaults.ignoreLockedSlots;
					if (Utils.isArray(d.locked)){
						if ($.inArray(slot.itemId, d.locked) > -1 && ignoreLockedSlots){
							showSlot = false;
						}
					}
					if (slot.instanceOf(GenericConfiguratorSlot)){
						this.slots.push(slot);
						if(showSlot){
							slot.make(this.defaults.target);
						}
					}
				},
				slotUpdateCheck: function(){
					var data = this.data;
					var self = this;
					$(data.slots).each(function(i){
						var realSlot = self.slots[i];
						var slotData = this;
						if (slotData.update){
							realSlot.update(slotData);
						}
						self.data.slots[i].update = false;
					});
					var cb = this.defaults.onAfterSlotsUpdate;
					if (cb && typeof cb == 'function'){
						cb.call(this);
					}
				},
				verifyData: function(slot){
					slot = slot || null;
					var self = this;
					var oldData = this.data;
					if (slot){
						this.data.changedSlot = slot.itemId;
					}
					var cbdr = this.defaults.onDataRequest;
					if (cbdr && cbdr){
						cbdr.call(this, slot, this.data);
					}
					var url = AjaxURLManager.getUrlWithKey(this.defaults.ajaxHandler);
					//alter data and send it to cherrypy
					for (var i in this.data.slots){
						this.data.slots[i].currentItem = this.slots[i].currentItem;
					}
					$.ajax({
						type: 'post',
						url: url,
						data: {'content': encodeURIComponent($.toJson(self))},
						success: function(data, msg){self.verifyDataRequestSuccess(data, msg, slot);},
						error: function(req, status, error){self.verifyDataRequestError(req, status, error, slot);}
					});
				},
				verifyDataRequestSuccess: function(data, msg, slot){
					this.data = data;
					var cbdrs = this.defaults.onDataRequestSuccess;
					if (cbdrs && typeof cbdrs == 'function'){
						cbdrs.call(this, slot, data);
					}
					this.slotUpdateCheck();
				},
				verifyDataRequestError: function(req, status, error, slot){
					/* todo: .... */
				}
			}
		);
	/* << */

	/* >> Generic configurator slot */
		GenericConfiguratorSlot = $.extend(
			$.clone(LLObject),
			{
				create: function(title, currentItem){
					var o = LLObject.create.call(this);
					o.configurator = null;
					o.id = null;
					o.itemId = null;
					o.title = title;
					o.width = null;
					o.items = [];
					o.currentItem = currentItem;
					o.data = null;
					o.mouseDownInterval = null;
					o.initMode = true;
					o.clickTimeout = null;
					return o;
				},
				makeSlotLayout: function(){
					var slot = $(
						'<tr>' +
							'<td class="' + this.id + '_titleColumn titleColumn"><div class="slotTitle"><span>' + this.title + '</span></div></td>' +
							'<td class="' + this.id + '_column selectColumn">' +
								'<div class="slotSelect">' +
									'<select name="' + this.id + '_select" id="' + this.id + '_select"></select>' +
								'</div>' +
							'</td>' +
						'</tr>'
					);
					var self = this;
					slot.find('select').bind('change', function(e){
						var cb = self.configurator.defaults.onSlotAction;
						if (cb && typeof cb == 'function'){
							cb.call(self, this);
						}
						var select = $(this);
						var value = select.val();
						self.data.currentItem = self.currentItem = 0;
						select.find('option').each(function(i){
							if ($(this).attr('value') == value){
								self.data.currentItem = self.currentItem = i;
							}
						});

						self.configurator.data.art_id = null;
						self.configurator.data[self.configurator.data.pk] = null;
						self.configurator.verifyData(self);
					});
					return slot;
				},
				appendItem: function(item){
					if (item && item.instanceOf(GenericConfiguratorSlotItem)){
						this.items.push(item);
					}
				},
				appendItemsToSlot: function(){
					var target = $('#' + this.id + '_select');
					var self = this;
					$(this.items).each(function(i){
						this.make(target);
					});
				},
				make: function(target){
					if (target){
						var slotLay = this.makeSlotLayout();
						target = target.find('table.genericConfiguratorShell');
						target.append(slotLay);
						this.appendItemsToSlot();
						this.selectCurrentItem();
						var self = this;
					}
				},
				selectCurrentItem: function(){
					var self = this;
					$(this.items).each(function(i){
						if (self.currentItem == i){
							$('#' + self.id + '_slotItem_' + i).attr('selected', true);
						}else{
							$('#' + self.id + '_slotItem_' + i).attr('selected', false);
						}
					});
				},
				update: function(slotData){
					this.items = [];
					this.initMode = true;
					this.data = slotData;
					this.currentItem = slotData.currentItem;
					$('#' + this.id + '_select').empty();
					$('#' + this.id + '_titleColumn').find('.slotTitle').text(slotData.title);
					var self = this;
					var slotItemType = this.configurator.defaults.slotItemType;
					$(slotData.items).each(function(i){
						if (this.type == slotItemType){
							var slotItem = window[slotItemType].create(this.title, this.value);
							slotItem.id = self.id + '_slotItem_' + i;
							slotItem.itemCnt = i;
							slotItem.data = this;
							slotItem.slot = self;
							slotItem.width = self.width;
							self.appendItem(slotItem);
						}
					});
					this.appendItemsToSlot();
					this.selectCurrentItem();
				}
			}
		);
	/* << */

	/* >> Generic configurator slot item */
		GenericConfiguratorSlotItem = $.extend(
			$.clone(LLObject),
			{
				create: function(title, value){
					var o = LLObject.create.call(this);
					o.configurator = null;
					o.id = null;
					o.itemCnt = null;
					o.title = title;
					o.value = value;
					o.data = null;
					o.slot = null;
					o.width = null;
					return o;
				},
				makeItemLayout: function(){
					var item = $(
						'<option id="' + this.id + '" class="slotMachineItem" value="' + this.title + '">' + this.title + '</option>'
					);
					return item;
				},
				make: function(target){
					if (target){
						target.append(this.makeItemLayout());
					}
				}
			}
		);
	/* << */


	/* >> Generic configurator horizontal (inherit GenericConfigurator) */
		GenericConfiguratorHorizontal = $.extend(
			$.clone(GenericConfigurator),
			{
				create: function(){
					var o = GenericConfigurator.create.call(this);
					return o;
				},
				makeShell: function(target){
					var shell = $(
						'<div id="genericConfiguratorOuter">' +
							'<div id="genericConfiguratorMainBg">' +
								'<table cellpadding="0" cellspacing="0" border="0" class="genericConfiguratorShell">' +
									'<tr></tr>' +
								'</table>' +
							'</div>' +
						'</div>'
					);
					target.append(shell);
				}
			}
		);
	/* << */

	/* >> Generic configurator horizontal slot (inherit GenericConfiguratorSlot)*/
		GenericConfiguratorHorizontalSlot = $.extend(
			$.clone(GenericConfiguratorSlot),
			{
				create: function(title, currentItem){
					var o = GenericConfiguratorSlot.create.call(this);
					o.configurator = null;
					o.id = null;
					o.itemId = null;
					o.title = title;
					o.width = null;
					o.items = [];
					o.currentItem = currentItem;
					o.data = null;
					o.mouseDownInterval = null;
					o.initMode = true;
					o.clickTimeout = null;
					return o;
				},
				makeSlotLayout: function(){
					var slot = $(
						'<td class="' + this.id + '_titleColumn titleColumn"><div class="slotTitle"><span>' + this.title + '</span></div></td>' +
						'<td class="' + this.id + '_column selectColumn">' +
							'<div class="slotSelect">' +
								'<select name="' + this.id + '_select" id="' + this.id + '_select"></select>' +
							'</div>' +
						'</td>'
					);
					var self = this;
					slot.find('select').bind('change', function(e){
						var select = $(this);
						var value = select.val();
						self.data.currentItem = self.currentItem = 0;
						select.find('option').each(function(i){
							if ($(this).attr('value') == value){
								self.data.currentItem = self.currentItem = i;
							}
						});

						self.configurator.data.art_id = null;
						self.configurator.data[self.configurator.data.pk] = null;
						self.configurator.verifyData(self);
					});
					return slot;
				},
				make: function(target){
					if (target){
						var slotLay = this.makeSlotLayout();
						target = target.find('table.genericConfiguratorShell tr');
						target.append(slotLay);
						this.appendItemsToSlot();
						this.selectCurrentItem();
						var self = this;
					}
				}
			}
		);
	/* << */


	/* >> Slot Machine generic configurator (inherit GenericConfigurator)*/
		SlotMachineGenericConfigurator = $.extend(
			$.clone(GenericConfigurator),
			{
				create: function(){
					var o = GenericConfigurator.create.call(this);
					o.defaults = {
						dataType: 'SlotMachineData',
						slotType: 'SlotMachineSlot',
						slotItemType: 'SlotMachineSlotItem',
						target: null,
						ajaxHandler: null,
						onBeforeInit: null,
						onAfterInit: null,
						onAfterSlotCatch: null,
						onDataRequest: null,
						onDataRequestSuccess: null
					};
					return o;
				},
				getURLParams: function(specParams){
					var url = window.location.href;
					var params =  Utils.getUrlParamsAsJson(url);

					if (params && params.id){
						delete params.id;
					}
					var reg = /_dId_/;
					var id = null;
					if (reg.test(url)){
						id = url.substring(url.search(reg) + 5, url.search(/_\.htm/));
					}
					if (params && params.auf_id !== null){
						id = params.auf_id;
					}
					if (params && params.pos_id !== null && !params.auf_id){
						id = params.pos_id;
					}
					if (id){
						if (params.pos_id){
							params = $.extend(params, {'pos_id': id});
						}else{
							params = $.extend(params, {'auf_id': id});
						}
					}else{
						var cfd = window.CONFIGURATOR_FALLBACK_DATA, toMergeParams;
						if (cfd && cfd.auf_id){
							toMergeParams = {
								auf_id: null,
								freeConfig: 'true'
							};
							$.extend(toMergeParams, cfd);
							params = $.extend(params, toMergeParams);
						}
					}
					params = $.extend(params, specParams);
					if (params && !params.ovn){
						params.ovn = 'false';
					}
					return params;
				},
				prepareUrl: function(){
					var urlParams = this.urlParams = this.getURLParams();
					var url = AjaxURLManager.getUrlWithKey(this.defaults.ajaxHandler, urlParams);
					if (this.urlParams.loadPos){
						this.urlParams.loadPos = null;
					}
					return url;
				},
				makeShell: function(target){
					var shell = $(
						'<div id="slotMachineOuter">' +
							'<div id="slotMachineMainBg">' +
								'<table cellpaddig="0" cellspacing="0" border="0">' +
									'<tr class="titles">' +
									'</tr>' +
									'<tr class="slots">' +
									'</tr>' +
								'</table>' +
							'</div>' +
						'</div>'
					);
					target.append(shell);
				},
				calculateSlotWidth: function(slot){
					var realWidth = slot.width;
					var itemsHasImage = false;
					$(slot.items).each(function(i){
						if (this.data.img){
							itemsHasImage = true;
						}
						var item = $('#' + this.id);
						var scrollWidth = item.get(0).scrollWidth;
						if (scrollWidth > slot.width && scrollWidth > realWidth){
							realWidth = scrollWidth;
						}
						item.css({'width': 'auto'});
					});
					var addSpace = itemsHasImage ? 53 : 10;
					if (realWidth > slot.width){
						slot.setWidth(realWidth + addSpace);
					}
				}
			}
		);
	/* << */

	/* >> Slot machine slot (inherit GenericConfiguratorSlot)*/
		SlotMachineSlot = $.extend(
			$.clone(GenericConfiguratorSlot),
			{
				create: function(title, currentItem){
					var o = GenericConfiguratorSlot.create.call(this);
					o.configurator = null;
					o.id = null;
					o.itemId = null;
					o.title = title;
					o.width = null;
					o.items = [];
					o.currentItem = currentItem;
					o.data = null;
					o.mouseDownInterval = null;
					o.initMode = true;
					o.clickTimeout = null;
					return o;
				},
				makeSlotTitle: function(){
					var title = $(
						'<td class="' + this.id + '_titleColumn"><div class="slotTitle">' + this.title + '</div></td>'
					);
					return title;
				},
				makeSlotLayout: function(){
					var slot = $(
						'<td class="' + this.id + '_column">' +
							'<div id="' + this.id + '_outer" class="slotMachineSlotOuter viewport">' +
								'<div id="' + this.id + '_slotButtonTop" class="slotButton slotButtonTop">' +
									'<div class="top"></div>' +
								'</div>' +
								'<div id="' + this.id + '_slotScrollPane" class="slotScrollPane">' +
									'<div id="' + this.id + '_slotItems" class="slotItems">' +
									'</div>' +
								'</div>' +
								'<div class="slotLens slotLensLeft">' +
									'<div class="slotLens slotLensRight">' +
										'<div class="slotLens slotLensCenter">' +
										'</div>' +
									'</div>' +
								'</div>' +
								'<div class="slotGlass slotGlassLeft">' +
									'<div class="slotGlass slotGlassRight">' +
										'<div class="slotGlass slotGlassCenter">' +
										'</div>' +
									'</div>' +
								'</div>' +
								'<div id="' + this.id + '_slotButtonBottom" class="slotButton slotButtonBottom">' +
									'<div class="bottom"></div>' +
								'</div>' +
							'</div>' +
						'</td>'
					);
					return slot;
				},
				adaptSlotDimensions: function(){
					var outer = $('#' + this.id + '_outer');
					if (this.width){
						outer.width(this.width);
					}
					var slotGlass = outer.find('.slotGlassLeft');
					var slotLens = outer.find('.slotLensLeft');
					var slotScrollPane = outer.find('.slotScrollPane');
					// slot outer dimensions
					var ohDim = {'w': outer.width(), 'h': outer.height()};
					// adjust slot outer inner slot glass to the target center.
					slotGlass.css({'width': ohDim.w})
						.find('.slotGlassCenter')
						.css({'width': ohDim.w - 8, 'margin-left': 4});
					// slot glass dimenesions
					var glassDim = {'w': slotGlass.width(), 'h': slotGlass.height()};
					// slot glass offset.
					slotGlass.css({'top': (ohDim.h - glassDim.h) / 2, 'left': (ohDim.w - glassDim.w) / 2});
					// adjust slot lens.
					slotLens.css({'width': ohDim.w + 6, 'left': 0})
						.find('.slotLensCenter')
						.css({'width': ohDim.w + 6 - 16, 'margin-left': 8});
					// slot lens dimensions
					var lensDim = {'w': slotLens.width(), 'h': slotLens.height()};
					// adjust lens offset.
					slotLens.css({'top': (ohDim.h - lensDim.h) / 2 + 5, 'left': (ohDim.w - lensDim.w) / 2});
					// adjust slot outer inner slot scroll pane to the target center.
					slotScrollPane.css({'width': ohDim.w})
						.css({'width': glassDim.w, 'height': glassDim.h - 5});
					// slot scroll pane offset.
					slotScrollPane.css({'top': ((ohDim.h - glassDim.h) / 2) + 2, 'left': (ohDim.w - glassDim.w) / 2});

				},
				appendItemsToSlot: function(){
					var outer = $('#' + this.id + '_outer');
					var slotGlass = outer.find('.slotGlassLeft');
					var target = $('#' + this.id + '_slotItems');
					var spacerItem = $('<div class="slotItemsSpacerItem"></div>');
					spacerItem.height(slotGlass.height() / 2);
					var bottomSpacerItem = spacerItem.clone();
					var self = this;
					$(this.items).each(function(i){
						var first = i === 0 ? true : false;
						if (i === 0){
							target.append(spacerItem);
						}
						this.make(target, first);
						if (i + 1 == self.items.length){
							target.append(bottomSpacerItem);
						}
					});
				},
				adaptAndDisplayButtons: function(){
					var outer = $('#' + this.id + '_outer');
					var slotGlass = outer.find('.slotGlassLeft');
					var button = outer.find('.slotButton');
					var buttonTop = outer.find('.slotButtonTop');
					var buttonBottom = outer.find('.slotButtonBottom');
					button.css({'width': slotGlass.width()});
					buttonTop.css({'top': slotGlass.position().top - button.height()});
					buttonBottom.css({'top': slotGlass.position().top + slotGlass.height()});
				},
				setWidth: function(width){
					if (width && typeof width == 'number'){
						this.width = width;
						this.adaptSlotDimensions();
						this.adaptAndDisplayButtons();
					}
				},
				scrollToItem: function(currentItem, button, duration){
					var curr = null, up, down;
					if (button){
						if (button == 'up' || button == 'down'){
							up = button == 'up' ? true : false;
							down = button == 'down' ? true : false;
						}else{
							button = $(button);
							up = button.hasClass('top');
							down = button.hasClass('bottom');
						}
						if (down){
							if (currentItem < this.items.length - 1){
								$('#' + this.id + '_slotItem_' + currentItem).removeClass('slotMachineItemHere');
								curr = ++this.currentItem;
							}
						}
						if (up){
							if (currentItem > 0){
								$('#' + this.id + '_slotItem_' + currentItem).removeClass('slotMachineItemHere');
								curr = --this.currentItem;
							}else{
								curr = -1;
							}
						}
					}else{
						curr = this.currentItem = currentItem;
					}
					var self = this;
					var items = $('div[id^=' + this.id + '_slotItem_]');
					this.slotDataValidCheck(curr);
					if (curr !== null && curr > -1){
						var dur = 300;
						if (duration || duration === 0){
							dur = duration;
						}
						$('#' + this.id + '_slotScrollPane').scrollTo(
							'#' + this.id + '_slotItem_' + curr,
							{
								'offset': -60,
								'duration': dur,
								'easing': 'elasout',
								'onAfter': function(){
									// after the slot catch trigger a callback
									var cb = self.configurator.defaults.onAfterSlotCatch;
									if (cb && typeof cb == 'function'){
										cb.call(self.configurator, self);
									}
									$('#' + self.id + '_slotItem_' + curr).addClass('slotMachineItemHere');
									items.each(function(i){
										if (curr != i){
											$(this).removeClass('slotMachineItemHere');
										}
									});

									if (!self.initMode){
										if (self.clickTimeout){
											clearTimeout(self.clickTimeout);
										}
										self.clickTimeout = setTimeout(function(){
											self.clickTimeout = null;
											self.configurator.data.art_id = null;
											self.configurator.data[self.configurator.data.pk] = null;
											self.configurator.verifyData(self);
										}, 500);
									}
									self.initMode = false;
								}
							}
						);
					}
				},
				make: function(target){
					if (target){
						var slotLay = this.makeSlotLayout();
						var slotTitle = this.makeSlotTitle();
						var titleTarget = target.find('#slotMachineMainBg tr.titles');
						target = target.find('#slotMachineMainBg tr.slots');
						titleTarget.append(slotTitle);
						target.append(slotLay);
						this.adaptSlotDimensions();
						this.appendItemsToSlot();
						this.adaptAndDisplayButtons();
						var self = this;

						$('#' + this.id +'_slotButtonTop div, #' + this.id +'_slotButtonBottom div')
							.bind('click', function(e){
								var cb = self.configurator.defaults.onSlotAction;
								if (cb && typeof cb == 'function'){
									cb.call(self, this);
								}
								self.scrollToItem(self.currentItem, this);
							})
							.bind('mousedown', function(e){
								if (! self.mouseDownInterval){
									var button = this;
									self.mouseDownInterval = setInterval(function(){
										self.scrollToItem(self.currentItem, button, 200);
									}, 300);
								}
							})
							.bind('mouseup', function(e){
								if (self.mouseDownInterval){
									clearInterval(self.mouseDownInterval);
									self.mouseDownInterval = null;
								}
							})
							.hover(
								function(){$(this).addClass('active');},
								function(){$(this).removeClass('active');}
							);
						// initial scroll to the pre configured item.
						this.scrollToItem(this.currentItem);
					}
				},
				selectCurrentItem: function(){},
				update: function(slotData){
					this.items = [];
					this.initMode = true;
					$('#' + this.id + '_outer').find('.slotItems').empty();
					$('#' + this.id + '_titleColumn').find('.slotTitle').text(slotData.title);
					var self = this;
					var slotItemType = this.configurator.defaults.slotItemType;
					$(slotData.items).each(function(i){
						if (this.type == slotItemType){
							var slotItem = window[slotItemType].create(this.title, this.value);
							slotItem.configurator = self.configurator;
							slotItem.id = self.id + '_slotItem_' + i;
							slotItem.itemCnt = i;
							slotItem.data = this;
							slotItem.slot = self;
							slotItem.width = self.width;
							self.appendItem(slotItem);
						}
					});
					this.appendItemsToSlot();
					var realWidth = this.width;
					var itemsHasImage = false;
					$(this.items).each(function(i){
						if (this.data.img){
							itemsHasImage = true;
						}
						var item = $('#' + this.id);
						var scrollWidth = item.get(0).scrollWidth;
						if (scrollWidth > self.width && scrollWidth > realWidth){
							realWidth = scrollWidth;
						}
						item.css({'width': 'auto'});
					});
					if (this.items.length > 0){
						var addSpace = itemsHasImage ? 53 : 10;
						if (realWidth > this.width){
							this.setWidth(realWidth + addSpace);
						}
						this.scrollToItem(slotData.currentItem, null, 0);
					}
				},
				slotDataValidCheck: function(currentItem){
					var outer = $('#' + this.id + '_outer');
					if (currentItem === 0 || currentItem == -1){
						outer.addClass('slotMachineSlotOuter_pass');
						outer.find('.slotLensLeft').addClass('slotLensLeft_pass');
						outer.find('.slotLensRight').addClass('slotLensRight_pass');
						outer.find('.slotLensCenter').addClass('slotLensCenter_pass');
					}else{
						outer.removeClass('slotMachineSlotOuter_pass');
						outer.find('.slotLensLeft').removeClass('slotLensLeft_pass');
						outer.find('.slotLensRight').removeClass('slotLensRight_pass');
						outer.find('.slotLensCenter').removeClass('slotLensCenter_pass');
					}
				}
			}
		);
	/* << */

	/* >> Slot Machine item (inherit GenericConfiguratorSlotItem)*/
		SlotMachineSlotItem = $.extend(
			$.clone(GenericConfiguratorSlotItem),
			{
				create: function(title, value){
					var o = GenericConfiguratorSlotItem.create.call(this);
					o.configurator = null;
					o.id = null;
					o.itemCnt = null;
					o.title = title;
					o.value = value;
					o.data = null;
					o.slot = null;
					o.width = null;
					return o;
				},
				makeItemLayout: function(first){
					var item = $(
						'<div id="' + this.id + '" class="slotMachineItem"><div class="inner">' + this.title + '</div></div>'
					);
					item.css({'width': this.width, 'overflow': 'hidden'});
					if (first){
						item.addClass('slotMachineFirstItem');
					}
					if (this.data.img){
						var img = this.data.img;
						item.addClass('slotMachineItemWithImage').find('.inner').css({'background-image': 'url(' + img.src + ')'});
					}
					var self = this;
					item.bind('click', function(e){
						var cb = self.configurator.defaults.onSlotAction;
						if (cb && typeof cb == 'function'){
							cb.call(self, this);
						}
						var currItem = $('#' + self.slot.items[self.slot.currentItem].id);
						currItem.removeClass('slotMachineItemHere');
						self.slot.scrollToItem(self.itemCnt);
					});
					return item;
				},
				make: function(target, first){
					if (target){
						target.append(this.makeItemLayout(first));
					}
				}
			}
		);
	/* << */
/* << */


/* >> Slot Machine generic configurator locked mode (inherit SlotMachineGenericConfigurator)*/
	SlotMachineGenericConfiguratorWithLockedFeature = $.extend(
		$.clone(SlotMachineGenericConfigurator),
		{
			create: function(){
				var o = SlotMachineGenericConfigurator.create.call(this);
				o.defaults = {
					dataType: 'SlotMachineData',
					slotType: 'SlotMachineLockedModeSlot',
					slotItemType: 'SlotMachineSlotLockedModeItem',
					target: null,
					ajaxHandler: null,
					onBeforeInit: null,
					onAfterInit: null,
					onAfterSlotCatch: null,
					onDataRequest: null,
					onDataRequestSuccess: null
				};
				return o;
			}
		}
	);
/* << */


/* >> Slot machine slot locked mode (inherit SlotMachineSlot)*/
	SlotMachineLockedModeSlot = $.extend(
		$.clone(SlotMachineSlot),
		{
			create: function(title, currentItem){
				var o = SlotMachineSlot.create.call(this, title, currentItem);
				return o;
			},
			makeSlotLayout: function(){
				var locked = this.configurator.data.locked;
				var buttons = [];
				if (locked){
					if ($.inArray(this.itemId, locked) > -1){
						buttons[0] = '<div id="' + this.id + '_slotBulletLocked" class="slotButton slotButtonTop slotLocked"><div class="top"></div></div>';
						buttons[1] = '';
					}else{
						buttons[0] = '<div id="' + this.id + '_slotButtonTop" class="slotButton slotButtonTop"><div class="top"></div></div>';
						buttons[1] = '<div id="' + this.id + '_slotButtonBottom" class="slotButton slotButtonBottom"><div class="bottom"></div></div>';
					}
				}else{
					buttons[0] = '<div id="' + this.id + '_slotButtonTop" class="slotButton slotButtonTop"><div class="top"></div></div>';
					buttons[1] = '<div id="' + this.id + '_slotButtonBottom" class="slotButton slotButtonBottom"><div class="bottom"></div></div>';
				}

				var slot = $(
					'<td class="' + this.id + '_column">' +
						'<div id="' + this.id + '_outer" class="slotMachineSlotOuter viewport">' +
							buttons[0] +
							'<div id="' + this.id + '_slotScrollPane" class="slotScrollPane">' +
								'<div id="' + this.id + '_slotItems" class="slotItems">' +
								'</div>' +
							'</div>' +
							'<div class="slotLens slotLensLeft">' +
								'<div class="slotLens slotLensRight">' +
									'<div class="slotLens slotLensCenter">' +
									'</div>' +
								'</div>' +
							'</div>' +
							'<div class="slotGlass slotGlassLeft">' +
								'<div class="slotGlass slotGlassRight">' +
									'<div class="slotGlass slotGlassCenter">' +
									'</div>' +
								'</div>' +
							'</div>' +
							buttons[1] +
						'</div>' +
					'</td>'
				);
				return slot;
			},
			appendItemsToSlot: function(slotData){
				var outer = $('#' + this.id + '_outer');
				var slotGlass = outer.find('.slotGlassLeft');
				var target = $('#' + this.id + '_slotItems');
				var spacerItem = $('<div class="slotItemsSpacerItem"></div>');
				spacerItem.height(slotGlass.height() / 2);
				var bottomSpacerItem = spacerItem.clone();
				var self = this;
				$(this.items).each(function(i){
					var first = i === 0 ? true : false;
					if (i === 0){
						target.append(spacerItem);
					}
					var here = false;
					if (slotData){
						if (slotData.currentItem == this.itemCnt){
							here = true;
						}
					}else{
						if (self.currentItem == this.itemCnt){
							here = true;
						}
					}
					this.make(target, first, here);
					if (i + 1 == self.items.length){
						target.append(bottomSpacerItem);
					}
				});
			},
			make: function(target){
				if (target){
					var slotLay = this.makeSlotLayout();
					var slotTitle = this.makeSlotTitle();
					var titleTarget = target.find('#slotMachineMainBg tr.titles');
					target = target.find('#slotMachineMainBg tr.slots');
					titleTarget.append(slotTitle);
					target.append(slotLay);
					this.adaptSlotDimensions();
					this.appendItemsToSlot();
					this.adaptAndDisplayButtons();
					var self = this;

					$('#' + this.id +'_slotButtonTop div, #' + this.id +'_slotButtonBottom div')
						.bind('click', function(e){
							var cb = self.configurator.defaults.onSlotAction;
							if (cb && typeof cb == 'function'){
								cb.call(self, this);
							}
							self.scrollToItem(self.currentItem, this);
						})
						.bind('mousedown', function(e){
							if (! self.mouseDownInterval){
								var button = this;
								self.mouseDownInterval = setInterval(function(){
									self.scrollToItem(self.currentItem, button, 200);
								}, 300);
							}
						})
						.bind('mouseup', function(e){
							if (self.mouseDownInterval){
								clearInterval(self.mouseDownInterval);
								self.mouseDownInterval = null;
							}
						})
						.hover(
							function(){$(this).addClass('active');},
							function(){$(this).removeClass('active');}
						);
					// initial scroll to the pre configured item.
					this.scrollToItem(this.currentItem);
				}
			},
			update: function(slotData){
				this.items = [];
				this.initMode = true;
				$('#' + this.id + '_outer').find('.slotItems').empty();
				$('#' + this.id + '_titleColumn').find('.slotTitle').text(slotData.title);
				var self = this;
				var slotItemType = this.configurator.defaults.slotItemType;
				$(slotData.items).each(function(i){
					if (this.type == slotItemType){
						var slotItem = window[slotItemType].create(this.title, this.value);
						slotItem.configurator = self.configurator;
						slotItem.id = self.id + '_slotItem_' + i;
						slotItem.itemCnt = i;
						slotItem.data = this;
						slotItem.slot = self;
						slotItem.width = self.width;
						self.appendItem(slotItem);
					}
				});
				this.appendItemsToSlot(slotData);
				var realWidth = this.width;
				var itemsHasImage = false;
				$(this.items).each(function(i){
					if (this.data.img){
						itemsHasImage = true;
					}
					var item = $('#' + this.id);
					var scrollWidth = item.get(0).scrollWidth;
					if (scrollWidth > self.width && scrollWidth > realWidth){
						realWidth = scrollWidth;
					}
					item.css({'width': 'auto'});
				});
				if (this.items.length > 0){
					var addSpace = itemsHasImage ? 53 : 10;
					if (realWidth > this.width){
						this.setWidth(realWidth + addSpace);
					}
					this.scrollToItem(slotData.currentItem, null, 0);
				}
			}
		}
	);
/* << */


/* >> Slot Machine item locked mode (inherit SlotMachineSlotItem)*/
	SlotMachineSlotLockedModeItem = $.extend(
		$.clone(SlotMachineSlotItem),
		{
			create: function(title, value){
				var o = SlotMachineSlotItem.create.call(this, title, value);
				return o;
			},
			makeItemLayout: function(first, here){
				var locked = this.slot.configurator.data.locked || [], title;
				if ($.inArray(this.slot.itemId, locked) > -1){
					locked = true;
					title = here ? this.title : '&nbsp;';
				}else{
					locked = false;
					title = this.title;
				}
				var item = $(
					'<div id="' + this.id + '" class="slotMachineItem"><div class="inner">' + title + '</div></div>'
				);
				item.css({'width': this.width, 'overflow': 'hidden'});
				if (first){
					item.addClass('slotMachineFirstItem');
				}
				if (this.data.img){
					var img = this.data.img;
					item.addClass('slotMachineItemWithImage').find('.inner').css({'background-image': 'url(' + img.src + ')'});
				}
				var self = this;
				if (locked){
					item.addClass('slotMachineItemLocked');
				}else{
					item.bind('click', function(e){
						var cb = self.configurator.defaults.onSlotAction;
						if (cb && typeof cb == 'function'){
							cb.call(self, this);
						}
						var currItem = $('#' + self.slot.items[self.slot.currentItem].id);
						currItem.removeClass('slotMachineItemHere');
						self.slot.scrollToItem(self.itemCnt);
					});
				}
				return item;
			},
			make: function(target, first, here){
				if (target){
					target.append(this.makeItemLayout(first, here));
				}
			}
		}
	);
/* << */


/* >> Slot machine tabbed image mode (inherit GenericConfigurator)*/
	SlotMachineTabbedImageMode = $.extend(
		$.clone(GenericConfigurator),
		{
			create: function(){
				var o = GenericConfigurator.create.call(this);
				o.defaults = {
					dataType: 'SlotMachineData',
					slotType: 'SlotMachineTabbedImageModeSlot',
					slotItemType: 'SlotMachineTabbedImageModeSlotItem',
					target: null,
					ajaxHandler: null,
					onBeforeInit: null,
					onAfterInit: null,
					onAfterSlotCatch: null,
					onDataRequest: null,
					onDataRequestSuccess: null
				};
				return o;
			},
			getURLParams: function(specParams){
				var url = window.location.href;
				var params =  Utils.getUrlParamsAsJson(url);

				if (params && params.id){
					delete patam.id;
				}
				var reg = /_dId_/;
				var id = null;
				if (reg.test(url)){
					id = url.substring(url.search(reg) + 5, url.search(/_\.htm/));
				}
				if (params && params.auf_id !== null){
					id = params.auf_id;
				}
				if (params && params.pos_id !== null && !params.auf_id){
					id = params.pos_id;
				}
				if (id){
					if (params.pos_id){
						params = $.extend(params, {'pos_id': id});
					}else{
						params = $.extend(params, {'auf_id': id});
					}
				}else{
					var cfd = window.CONFIGURATOR_FALLBACK_DATA, toMergeParams;
					if (cfd && cfd.auf_id){
						toMergeParams = {
							auf_id: null,
							freeConfig: 'true'
						};
						$.extend(toMergeParams, cfd);
						params = $.extend(params, toMergeParams);
					}
				}
				params = $.extend(params, specParams);
				if (params && !params.ovn){
					params.ovn = 'false';
				}
				return params;
			},
			makeShell: function(target){
				var shell = $(
					'<div id="slotMachineOuter">' +
						'<div id="slotMachineTabs">' +
							'<ul></ul>' +
						'</div>' +
					'</div>'
				);
				target.append(shell);
			},
			handleHovertextContainer: function(data){
				var target = $('#itemHoverInfoContainer'), lay = $('<div class="hovertextContainer"><div class="inner"></div></div>'),
				baseHovertext = this.data.hovertext;
				if (target.length){
					if (data && data.item.hovertext){
						lay.find('.inner').html(data.item.hovertext);
						target.empty().append(lay);
					}else if (baseHovertext){
						lay.find('.inner').html(baseHovertext);
						target.empty().append(lay);
					}else{
						target.empty();
					}
				}
			}
		}
	);
/* << */

/* >> Slot machine tabbed image mode slot (inherit GenericConfiguratorSlot)*/
	SlotMachineTabbedImageModeSlot = $.extend(
		$.clone(GenericConfiguratorSlot),
		{
			create: function(title, currentItem){
				var o = GenericConfiguratorSlot.create.call(this);
				o.configurator = null;
				o.id = null;
				o.itemId = null;
				o.title = title;
				o.width = null;
				o.items = [];
				o.currentItem = currentItem;
				o.data = null;
				o.mouseDownInterval = null;
				o.initMode = true;
				o.clickTimeout = null;
				return o;
			},
			makeSlotTitle: function(){
				var title = $(
					'<li class="' + this.id + '_titleColumn">' +
						'<div class="slotTitle viewport">' +
							'<div class="slotArrow"></div>' +
							'<a href="#' + this.id + '_outer"><span>' + this.title + '</span></a>' +
						'</div>' +
					'</li>'
				);
				if (this.isLocked()){
					title.find('a').addClass('slotLocked');
				}
				return title;
			},
			isLocked: function(){
				var locked = this.configurator.data.locked || [];
				if ($.inArray(this.itemId, locked) > -1){
					return true;
				}
				return false;
			},
			makeSlotLayout: function(){
				var slot = $(
					'<div id="' + this.id + '_outer" class="slotMachineTabbedImageModeSlotOuter viewport">' +
						'<div id="' + this.id + '_slotScrollPane" class="slotTabbedImageModeScrollPane">' +
							'<div id="' + this.id + '_slotItems" class="slotTabbedImageModeItems">' +
							'</div>' +
						'</div>' +
					'</div>'
				);
				return slot;
			},
			appendItemsToSlot: function(){
				var target = $('#' + this.id + '_slotItems').empty();
				var self = this;
				$(this.items).each(function(i){
					this.make(target);
				});
			},
			toogleSlotTitleArrow: function(here, hasSelection){
				var col = $('#slotMachineImageMode li.' + this.id + '_titleColumn'), className;
				col.find('div.slotArrow').toggleClass('slotArrowActive', here);
				hasSelection = hasSelection ? true : false;
				col.find('a').toggleClass('slotArrow_hasSelection', hasSelection);
			},
			make: function(target){
				if (target){
					var slotLay = this.makeSlotLayout();
					var slotTitle = this.makeSlotTitle();
					var titleTarget = $('#slotMachineTabs ul');
					titleTarget.append(slotTitle);
					$('#slotMachineTabs').append(slotLay);
					this.appendItemsToSlot();
				}
			},
			selectCurrentItem: function(){},
			isValid: function(){
				if (this.currentItem > 0){
					return true;
				}
				return false;
			},
			selectNextInvalidTab: function(){
				var currentId = this.itemId;
				var ovSlots = this.configurator.slots.length;
				for (var i = currentId; i < currentId + ovSlots; ++i){
					var slot = this.configurator.slots[i % ovSlots];
					if(! slot.isValid()){
						$('#slotMachineTabs').tabs('select' , slot.itemId);
						break;
					}
				}
			},
			update: function(slotData){
				this.data = slotData;
				this.currentItem = slotData.currentItem;
				var here = this.currentItem !== 0 ? true : false;
				this.toogleSlotTitleArrow(here, this.currentItem);
				this.items = [];
				this.initMode = true;
				$('#' + this.id + '_outer').find('.slotItems').empty();
				$('#' + this.id + '_titleColumn').find('.slotTitle').text(slotData.title);
				var self = this;
				var slotItemType = this.configurator.defaults.slotItemType;
				$(slotData.items).each(function(i){
					if (this.type == slotItemType){
						var slotItem = window[slotItemType].create(this.title, this.value);
						slotItem.configurator = self.configurator;
						slotItem.id = self.id + '_slotItem_' + i;
						slotItem.itemCnt = i;
						slotItem.data = this;
						slotItem.slot = self;
						slotItem.width = self.width;
						self.appendItem(slotItem);
					}
				});
				this.appendItemsToSlot();
			}
		}
	);
/* << */

/* >> Slot machine tabbed image mode slot item (inherit GenericConfiguratorSlotItem) */
	SlotMachineTabbedImageModeSlotItem = $.extend(
		$.clone(GenericConfiguratorSlotItem),
		{
			create: function(title, value){
				var o = GenericConfiguratorSlotItem.create.call(this);
				o.configurator = null;
				o.id = null;
				o.itemCnt = null;
				o.title = title;
				o.value = value;
				o.data = null;
				o.slot = null;
				o.width = null;
				return o;
			},
			makeItemLayout: function(){
				var locked = this.slot.isLocked();
				if (this.itemCnt === 0){
					return $('<div></div>').hide();
				}else{
					var item = $(
						'<div id="' + this.id + '" class="slotMachineTabbedImageItem">' +
							'<div class="viewport">' +
								'<div class="hereSymbol"></div>' +
							'</div>' +
						'</div>'
					);
					if (locked){
						item.css({'cursor': 'default'});
						if (this.slot.currentItem != this.itemCnt){
							item.addClass('slotMachineTabbedImageItemLocked');
						}
					}
					item.data('itemData', {'value': this.value, 'slot': this.slot, 'configurator': this.configurator, 'item': this.data});
					if (this.data.img2){
						var img = this.data.img2;
						if (img){
							item.css({'background-image': 'url(' + img.src + ')'});
						}
					}else{
						item.css({'border': '1px solid #fff'}).append(this.data.title);
						item.width(93);
						item.height(93);
					}
					if (this.itemCnt == this.slot.currentItem){
						item.addClass('slotMachineTabbedImageItemHere');
						this.slot.toogleSlotTitleArrow(true, true);
					}
					var self = this;
					var items = $('div[id^=' + this.slot.id + '_slotItem_]');
					if (!locked){
						item.bind('click', function(e){
							if (self.slot.currentItem == self.itemCnt){
								self.slot.currentItem = 0;
								self.slot.toogleSlotTitleArrow(false, false);
							}else{
								self.slot.currentItem = self.itemCnt;
								self.slot.toogleSlotTitleArrow(true, true);
							}
							var cb = self.configurator.defaults.onSlotAction;
							if (cb && typeof cb == 'function'){
								cb.call(self, this);
							}
							self.configurator.data.art_id = null;
							self.configurator.data[self.configurator.data.pk] = null;
							self.configurator.verifyData(self.slot);
						});
					}
					item.bind('mouseover', function(e){
						var data = $(this).data('itemData');
						self.configurator.handleHovertextContainer(data);
					});
					item.bind('mouseout', function(e){
						self.configurator.handleHovertextContainer(null);
					});
					return item;
				}
			}
		}
	);
/* << */



/* >> Slot machine select mode (inherit GenericConfigurator)*/
	SlotMachineSelectMode = $.extend(
		$.clone(GenericConfigurator),
		{
			create: function(){
				var o = GenericConfigurator.create.call(this);
				o.defaults.ignoreLockedSlots = true;
				return o;
			},
			getURLParams: function(specParams){
				var url = window.location.href;
				var params =  Utils.getUrlParamsAsJson(url);

				if (params && params.id){
					delete params.id;
				}
				var reg = /_dId_/;
				var id = null;
				if (reg.test(url)){
					id = url.substring(url.search(reg) + 5, url.search(/_\.htm/));
				}
				if (params && params.auf_id !== null){
					id = params.auf_id;
					params = $.extend(params, {'auf_id': id});
				}
				if (params && params.pos_id !== null && !params.auf_id){
					id = params.pos_id;
					params = $.extend(params, {'pos_id': id});
				}
				var cfd = window.CONFIGURATOR_FALLBACK_DATA, toMergeParams;
				if (!id){
					if (cfd && cfd.auf_id){
						toMergeParams = {
							auf_id: null,
							freeConfig: true
						};
						$.extend(toMergeParams, cfd);
						params = $.extend(params, toMergeParams);
					}
				}
				if (cfd && cfd.cp){
					params = $.extend(params, {'cp': true});
				}
				params = $.extend(params, specParams);
				if (params && !params.ovn){
					params.ovn = 'false';
				}
				return params;
			}
		}
	);
/* << */

/* >> Slot machine select mode slot (inherit GenericConfiguratorSlot) */
	SlotMachineSelectModeSlot = $.extend(
		$.clone(GenericConfiguratorSlot),
		{
			create: function(title, currentItem){
				var o = GenericConfiguratorSlot.create.call(this);
				o.configurator = null;
				o.id = null;
				o.itemId = null;
				o.title = title;
				o.width = null;
				o.items = [];
				o.currentItem = currentItem;
				o.data = null;
				o.mouseDownInterval = null;
				o.initMode = true;
				o.clickTimeout = null;
				o.domel = null;
				return o;
			},
			makeSlotLayout: function(){
				var locked = this.isLocked();
				var slot = $(
					'<tr>' +
						'<td></td>' +
						'<td id="' + this.id + '_titleColumn" class="titleColumn">' +
							'<div class="slotTitle">' +
								'<span class="title">' + this.title + '</span>' +
								'<span class="arrow">' + Utils.pixelAsString() + '</span>' +
							'</div>' +
						'</td>' +
					'</tr>' +
					'<tr>' +
						'<td class="bullet"><div class="slotBullet"></div></td>' +
						'<td class="' + this.id + '_column selectColumn">' +
							'<div class="slotSelect">' +
								'<select name="' + this.id + '_select" id="' + this.id + '_select"></select>' +
							'</div>' +
						'</td>' +
					'</tr>'
				);
				if (locked){
					slot.find('.slotBullet').addClass('slotLocked').end().find('select').attr({'disabled': 'disabled'});
				}
				if (this.currentItem > 0){
					slot.find('.arrow').addClass('arrowActive');
				}
				var self = this;
				slot.find('select').bind('change', function(e){
					var cb = self.configurator.defaults.onSlotAction;
					if (cb && typeof cb == 'function'){
						cb.call(this);
					}
					var select = $(this);
					var value = select.val();
					self.data.currentItem = self.currentItem = 0;
					select.find('option').each(function(i){
						if ($(this).attr('value') == value){
							self.data.currentItem = self.currentItem = i;
						}
					});

					self.configurator.data.art_id = null;
					self.configurator.data[self.configurator.data.pk] = null;
					self.configurator.verifyData(self);
				});
				this.domel = slot;
				return slot;
			},
			isLocked: function(){
				var locked = this.configurator.data.locked || [];
				if ($.inArray(this.itemId, locked) > -1){
					return true;
				}
				return false;
			},
			update: function(slotData){
				this.items = [];
				this.initMode = true;
				this.data = slotData;
				this.currentItem = slotData.currentItem;
				$('#' + this.id + '_select').empty();
				$('#' + this.id + '_titleColumn .slotTitle .title').text(slotData.title);
				var ready = false;
				if (this.currentItem > 0){
					ready = true;
				}
				$('#' + this.id + '_titleColumn .slotTitle').find('.arrow').toggleClass('arrowActive', ready)
					.end().parents('tr').next().find('.slotBullet').toggleClass('slotBulletActive_hasSelection', ready);
				var self = this;
				var slotItemType = this.configurator.defaults.slotItemType;
				$(slotData.items).each(function(i){
					if (this.type == slotItemType){
						var slotItem = window[slotItemType].create(this.title, this.value);
						slotItem.id = self.id + '_slotItem_' + i;
						slotItem.itemCnt = i;
						slotItem.data = this;
						slotItem.slot = self;
						slotItem.width = self.width;
						self.appendItem(slotItem);
					}
				});
				this.appendItemsToSlot();
				this.selectCurrentItem();
				$('#' + this.id + '_select').hide().show();
			}
		}
	);
/* << */

/* >> Slot machine select mode slot item (inherit GenericConfiguratorSlotItem) */
	SlotMachineSelectModeSlotItem = $.extend(
		$.clone(GenericConfiguratorSlotItem),
		{
			create: function(title, value){
				var o = GenericConfiguratorSlotItem.create.call(this);
				o.configurator = null;
				o.id = null;
				o.itemCnt = null;
				o.title = title;
				o.value = value;
				o.data = null;
				o.slot = null;
				o.width = null;
				return o;
			},
			makeItemLayout: function(){
				var item = $(
					'<option id="' + this.id + '" class="slotMachineItem" value="' + this.title + '">' + this.title + '</option>'
				);
				return item;
			},
			make: function(target){
				if (target){
					target.append(this.makeItemLayout());
				}
			}
		}
	);
/* << */


/* >> Slot machine select mode with hide locked slot (inherit SlotMachineSelectMode) */
	SlotMachineSelectModeWithHideLockedSlots = $.extend(
		$.clone(GenericConfigurator),
		{
			create: function(){
				var o = SlotMachineSelectMode.create.call(this);
				o.defaults.ignoreLockedSlots = true;
				return o;
			},
			getURLParams: function(specParams){
				var url = window.location.href, cfd,
				params =  Utils.getUrlParamsAsJson(url);
				params = $.extend(params, specParams);
				cfd = window.CONFIGURATOR_FALLBACK_DATA;
				if (Utils.isObject(cfd) && typeof params.auf_id === 'undefined'){
					params = $.extend(params, cfd);
				}
				return params;
			}
		}
	);

/* << */

/* >>  Slot machine select mode with info layout slot (inherit SlotMachineSelectModeSlot) */
	SlotMachineSelectModeWithInfoSlot = $.extend(
		$.clone(SlotMachineSelectModeSlot),
		{
			create: function(title, currentItem){
				return SlotMachineSelectModeSlot.create.call(this, title, currentItem);
			},
			makeSlotLayout: function(){
				var locked = this.isLocked();
				var slot = $(
					'<tr>' +
						'<td></td>' +
						'<td id="' + this.id + '_titleColumn" class="titleColumn">' +
							'<div class="slotTitle">' +
								'<span class="title">' + this.title + '</span>' +
								'<span class="arrow">' + Utils.pixelAsString() + '</span>' +
							'</div>' +
						'</td>' +
						'<td></td>' +
					'</tr>' +
					'<tr>' +
						'<td class="bullet"><div class="slotBullet"></div></td>' +
						'<td class="' + this.id + '_column selectColumn">' +
							'<div class="slotSelect">' +
								'<select name="' + this.id + '_select" id="' + this.id + '_select"></select>' +
							'</div>' +
						'</td>' +
						'<td class="info"><a href="#" class="slotInfo" target="_blank"></a></td>' +
					'</tr>'
				);
				if (locked){
					slot.find('.slotBullet').addClass('slotLocked').end().find('select').attr({'disabled': 'disabled'});
				}
				if (this.currentItem > 0){
					slot.find('.arrow').addClass('arrowActive');
				}
				var self = this;
				slot.find('select').bind('change', function(e){
					var cb = self.configurator.defaults.onSlotAction;
					if (cb && typeof cb == 'function'){
						cb.call(this);
					}
					var select = $(this);
					var value = select.val();
					self.data.currentItem = self.currentItem = 0;
					select.find('option').each(function(i){
						if ($(this).attr('value') == value){
							self.data.currentItem = self.currentItem = i;
						}
					});

					self.configurator.data.art_id = null;
					self.configurator.data[self.configurator.data.pk] = null;
					self.configurator.verifyData(self);
				});
				this.domel = slot;
				return slot;
			}
		}
	);
/* << */


/* >> data type updater */
	updateDataTypes = function(data, mode){
		if (mode == 'select'){
			data.type = 'GenericConfiguratorData';
			$(data.slots).each(function(i){
				this.type = 'SlotMachineSelectModeSlot';
				$(this.items).each(function(j){
					this.type = 'SlotMachineSelectModeSlotItem';
				});
			});
		}else if (mode == 'image'){
			$(data.slots).each(function(i){
				this.type = 'SlotMachineTabbedImageModeSlot';
				$(this.items).each(function(j){
					this.type = 'SlotMachineTabbedImageModeSlotItem';
				});
			});
		}else if (mode == 'slotmachine'){
			data.type = 'GenericConfiguratorData';
			$(data.slots).each(function(i){
				this.type = 'SlotMachineSelectModeWithInfoSlot';
				$(this.items).each(function(j){
					this.type = 'SlotMachineSelectModeSlotItem';
				});
			});
		}else if (mode == 'sharedSelect'){
			data.type = 'SharedSlotMachineSelectMode';
			$(data.slots).each(function(i){
				this.type = 'SharedSlotMachineSelectModeSlot';
				$(this.items).each(function(j){
					this.type = 'SlotMachineSelectModeSlotItem';
				});
			});
		}else if (mode == 'displayPilotSelect'){
			data.type = 'SlotMachineSelectModeWithHideLockedSlots';
			$(data.slots).each(function(i){
				this.type = 'SlotMachineSelectModeSlot';
				$(this.items).each(function(j){
					this.type = 'SlotMachineSelectModeSlotItem';
				});
			});
		}
	};
/* << */


/* >> Locked slots register */
	registerLockedSlots = function(urlParams, data){
		var lockedSlotNames, locked;
		if (typeof urlParams.locked !== 'undefined'){
			lockedSlotNames = urlParams.locked;
			if (!Utils.isArray(urlParams.locked)){
				lockedSlotNames = [lockedSlotNames];
			}
			locked = [];
			$(data.slots).each(function(i){
				if ($.inArray(this.pk, lockedSlotNames) > -1){
					locked.push(i);
				}
			});
			if (locked.length > 0){
				data.locked = locked;
			}
		}
	};
/* << */

/* >> disabled template tab handling */
	handleTemplateTab = function(enable){
		var tab = $('.cni_vorlagen');
		if (enable){
			tab.removeClass('cni_disabled_vorlagen').unbind('click');
		}else{
			tab.addClass('cni_disabled_vorlagen').bind('click', function(e){
				e.preventDefault();
				e.stopPropagation();
			});
		}
	};
/* << */


/* >> Slot machine initialization */
	// starts the slot machine
	StartSlotmachine = function(){
		// makes slot machine titles
		prepareSlotmachineLayout = function(){
			var target = $('#genericConfiguratorMainBg'),
			titlePrd = $('<div class="colTitle colTitlePrd">' + $.lang('titlePrd') + '</div>'),
			titleOpts = $('<div class="colTitle colTitleOpts">' + $.lang('titleOpts') + '</div>'),
			titleConf = $('<div class="colTitle colTitleConf">' + $.lang('titleConf') + '</div>');
			addOpts = $('<div id="slotmachineAddOptsContainer" class="slotmachineAddOptsCont"></div>');
			target.prepend(titlePrd, titleOpts, titleConf, addOpts);
		};
		slotMachineActionKeeper = function(){
			if ($('#slotMachineActionKeeper').size() === 0){
				var opts = {'opacity': 1, 'background': 'transparent'};
				var akShell = $('<div id="slotMachineActionKeeper"></div>');
				var target = $('div.contColDes5');
				target.addClass('viewport').css({'overflow': 'hidden'});
				var w = target.width();
				var h = target.height();
				akShell.width(w).height(h);
				akShell.css(opts);
				target.append(akShell);
				var bgAnimation = BgAnimate.createAnimation('slotMachineBusyRotor', akShell);
				bgAnimation.start();
			}
		};
		initiateInfos = function(Machine, type){
			var attr, i, slot, url, options = $('#slotmachineAddOptsContainer .optionOuter'),
			bindXPopup = function(url, target, domTarget, display){
				var d = 'block';
				if (display){
					d = display;
				}
				if (url){
					LL_XPopup.registerPopup(
						domTarget,
						'click',
						'AJAX',
						'p_c',
						'c',
						0,
						0,
						{
							height: 500,
							width: 600,
							url: {
								data: {
									text: 'Wird geladen...'
								},
								useProperty: 'text',
								type: 'xpopupJsonContainer'
							},
							background: {
								r: 0,
								g: 0,
								b: 0,
								opacity: 0.3
							}
						},
						function(action){
							if (action === 'load'){
								$.getJSON(url, function(data, textStatus){
									$('#xpopupContent').find('>div').html(data.text);
								});
							}
						}
					);
					target.css({
						display: d
					});
				}
			};
			if (type == 'slots'){
				var x = function(url, slotInfo){
					bindXPopup(url, slotInfo, slotInfo.get(0));
				};
				for (i = 0; i < Machine.data.slots.length; i+=1){
					slot = Machine.data.slots[i];
					attr = slot.pk;
					url = AjaxURLManager.getUrlWithKey('infotext', {
						wg_id_super: Machine.data.wg_id_super,
						attr: attr
					});
					var slotInfo = Machine.slots[i].domel.find('.slotInfo');
					if (slot.infotextAvailable){
						x(url, slotInfo);
					}
				}
			}else if (type == 'options'){
				options.each(function(i){
					var zup_id, opt;
					if (Machine.data.options.length && Machine.data.options[i]){
						opt = Machine.data.options[i];
						if (opt.infotextAvailable){
							if ($(this).hasClass('optionOuterSelect')){
								zup_id = opt.items[1].value;
							}else if ($(this).hasClass('optionOuterText')){
								zup_id = opt.name;
							}else{
								zup_id = opt.value;
							}
							url = AjaxURLManager.getUrlWithKey('infotext', {
								zup_id: zup_id
							});
							(function(url, slotInfo){
								bindXPopup(url, slotInfo, slotInfo.get(0));
							}(url, $(this).find('.slotInfo')));
						}
					}
				});
			}else if (type === 'dataCheck'){
				url = null;
				if ($('#slotmachineAddOptsContainer .optionOuterStaticText').length){
					if (Machine && Machine.data){
						url = AjaxURLManager.getUrlWithKey('infotext', {
							wg_id_super: Machine.data.wg_id_super,
							attr: 'dc_id'
						});
					}
					if (url && Machine.data.meta && Machine.data.meta.datacheckInfotextAvailable){
						(function(url, domel){
							bindXPopup(url, domel, domel.get(0));
						}(url, $('#slotmachineAddOptsContainer .optionOuterStaticText').find('.slotInfo')));
					}
				}
			}else if (type === 'shippingMethod'){
				url = null;
				if ($('.shippingMethod_column').length){
					if (Machine && Machine.data){
						url = AjaxURLManager.getUrlWithKey('infotext', {
							wg_id_super: Machine.data.wg_id_super,
							attr: 'va_id'
						});
					}
					if (url && Machine.data.meta.shippingTypeInfotextAvailable){
						(function(url, domel){
							bindXPopup(url, domel, domel.get(0));
						}(url, $('.shippingMethod_column').next().find('.slotInfo')));
					}
				}
			}else if (type === 'shippingTime'){
				url = null;
				if (Machine && Machine.data){
					url = AjaxURLManager.getUrlWithKey('infotext', {
						wg_id_super: Machine.data.wg_id_super,
						attr: 'lz_id'
					});
				}
				if (url && Machine.data.meta && Machine.data.meta.deliveryTimeInfotextAvailable){
					(function(url, domel){
						bindXPopup(url, domel, domel.get(0), 'inline-block');
					}(url, $('.shippingTime .info')));
				}
			}
		};
		handleShippingTime = function(Machine, data, init){
			var target = $('#genericConfiguratorMainBg'), st;
			if (init){
				st = $(
					'<div class="shippingTime viewport">' +
						'<div class="timeOuter">' +
							'<span class="time"></span><a href="#" class="info"></a>' +
						'</div>' +
					'</div>'
				);
				target.prepend(st);
			}
			if (data && data.meta && data.meta.deliveryTime && data.auf_id){
				$('.shippingTime').find('.time').text(data.meta.deliveryTime);
			}else{
				$('.shippingTime').find('.time').text('---');
			}
			initiateInfos(Machine, 'shippingTime');
		};
		createStaticProductSelect = function(){
			var data = PRODUCT_CATEGORY_CONFIG,
			SelBox = SlotmachineSelectBox.create({
				target: $('.genericConfiguratorShell'),
				data: data,
				className: 'slotmachineProductSelect',
				onChangeCallback: function(value){
					if (Utils.getXist4cSessionId({'returnOnlyUrlSession': true})){
						value = value + Utils.getXist4cSessionId({
							returnWithPrefix: true
						});
					}
					window.location = value;
				},
				onAfterFinishCallback: function(){
					var Box = this, domel = $('#' + Box.defaults.data.name + '_select');
					domel.children('option').each(function(i){
						if (typeof Box.defaults.data.items[i].current !== 'undefined' && Box.defaults.data.items[i].current){
							$(this).attr('selected', 'selected');
						}else{
							$(this).attr('selected', null);
						}
					});
				}
			});
			SelBox.make('prepend');
		};
		handleShippingMethodSelect = function(Machine, data){
			var stdIdx, i, ShippingBox, opts, tableProp = 'costs', selected = false, item, text;
			if ($('.slotmachineShippingSelectBox').length){
				$('.slotmachineShippingSelectBox').next().remove();
				$('.slotmachineShippingSelectBox').remove();
			}
			if (data.auf_id){
				for (i = 0; i < data.costs.rows.length; i+=1){
					if (data.express){
						tableProp = 'exCosts';
					}else if (data.overnight){
						tableProp = 'ovCosts';
					}
					if (data[tableProp].rows[i].here){
						stdIdx = i;
						break;
					}
				}
				opts = {
						target: $('.genericConfiguratorShell'),
						data: {
							prompt: $.lang('shipping'),
							name: 'shippingMethod',
							items: [
								{
									title: $.lang('standard'),
									value: ''
								}
							]
						},
						className: 'slotmachineShippingSelectBox',
						onChangeCallback: function(value){
							Machine.data.express = false;
							Machine.data.overnight = false;
							if (value){
								Machine.data[value] = true;
							}
							Machine.verifyData();
						}
				};
				if (data.exCosts.rows[stdIdx].auf_id){
					opts.data.items.push({
						title: $.lang('express') + ' ' + data.costs.rows[stdIdx].additionalcostExpress,
						value: 'express'
					});
					if (data.express){
						selected = true;
						opts.data.items[opts.data.items.length - 1].here = true;
					}
				}
				if (data.ovCosts.rows[stdIdx].auf_id){
					opts.data.items.push({
						title: $.lang('overnight') + ' ' + data.costs.rows[stdIdx].additionalcostOvernight,
						value: 'overnight'
					});
					if (data.overnight){
						selected = true;
						opts.data.items[opts.data.items.length - 1].here = true;
					}
				}
				if (opts.data.items.length > 1){
					item = opts.data.items[0];
					for (i = 0; i < opts.data.items.length; i+=1){
						if (opts.data.items[i].here){
							item = opts.data.items[i];
							break;
						}
					}
					if (item.value !== ''){
						text = item.title;
						text = text.substring(text.indexOf('(') + 1, text.indexOf(')'));
						$('.shippingTime .timeOuter').prepend('<span class="time">' + text + '</span>');
						$('.shippingTime .timeOuter .time').eq(1).hide();
					}else{
						$('.shippingTime .timeOuter').find(':nth-child(1)').show().end().find(':nth-child(0)').remove();
					}
					ShippingBox = SlotmachineShippingOptionsSelectBoxExtension.create(opts);
					ShippingBox.make('append');
					ShippingBox.domel.find('.slotBullet').addClass(' slotBulletActive_hasSelection');
				}
			}
		};
		appendStaticDataCheckOption = function(){
			var data = {
				type: 'text',
				prompt: $.lang('dataCheck'),
				price: '+0,00 &euro;<span style="padding-left: 2px; color: rgb(51, 51, 51);">*</span>'
			},
			lay = SlotmachineAddOptions_GC.makeOptionLayout.call(this, data),
			field = $('<input type="text name="static" disabled="disabled" value="' + $.lang('dataCheckFieldValue') + '"/>'),
			starHint = $('<div class="starOptionHint"><span class="star">*</span>Nettopreis</div>');
			if (lay){
				lay.addClass('optionOuterStaticText');
				lay.find('.field').append(field);
				lay.find('.slotBullet').addClass(' slotBulletActive_hasSelection');
			}
			$('#slotmachineAddOptsContainer').find('.optionOuterNoItems').remove();
			$('#slotmachineAddOptsContainer').append(lay, starHint);
		};
		handleFreeFormatErrors = function(machine){
			var ffData;
			if (machine.data && machine.data.freeFormatData){
				ffData = machine.data.freeFormatData;
				if (ffData.errorMessage){
					alert(ffData.errorMessage.title + '\n' + ffData.errorMessage.text);
				}
			}
		};
		sendEcondaInfoIdAufId = function(data){
			var price = null;
			if (data.auf_id && typeof(window.emospro) !== 'undefined'){
				if (data.meta){
					price = data.meta.priceNum || null;
				}
				if (price){
					price = Math.round(price * 100) / 100;
				}
				window.emospro.ec_Event = [[
					'view',
					data.auf_id || 'NULL',
					data.productTitle || 'NULL',
					price || 'NULL',
					data.meta.econda.econdaCategory || 'NULL',
					'1',
					data.meta.econda.ev1 || 'NULL',
					data.meta.econda.ev2 || 'NULL',
					data.meta.econda.ev3 || 'NULL',
					data.meta.econda.ev4 || 'NULL',
					data.meta.econda.ev5 || 'NULL',
					data.meta.econda.ev6 || 'NULL',
					data.meta.econda.ev7 || 'NULL',
					data.meta.econda.ev8 || 'NULL',
					data.meta.econda.ev9 || 'NULL',
					data.meta.econda.ev10 || 'NULL'
				]];
				econdaRequestEvent();
			}
		};
		prepareServiceIcons = function(data){
			var LLSD = LL_ServiceDownloads.create({
				target: $('.prdConfTopShellSm')
			}, data);
			LLSD.make();
		};
		SlotMachine = SlotMachineSelectMode.create();
		LinkPreparer = PageLinkPreparer.create();
		ResetPreparer = ResetButtonPreparer.create();
		TopImagePrep = TopImagePreparer.create();
		ScartPreparer = SlotmachineShoppingcartPreparer.create();
		QuickChoice = SlotmachineRightQuickChoiceWithFreeFormat_GC.create(SlotMachine);
		CustFormats = CustomFormats_GC.create(SlotMachine);
		CostTables = CostsTableHandler_GC.create(SlotMachine);
		ErrorMsgHandler = ErrorMessagesHandler_GC.create(SlotMachine);
		handleTemplateTab(false);
		SlotMachine.init(
			{
				'target': $('#slotMachine'),
				'ajaxHandler': 'configarticle',
				'slotType': 'SlotMachineSelectModeWithInfoSlot',
				'slotItemType': 'SlotMachineSelectModeSlotItem',
				'onBeforeInit': function(){
					handleShippingTime(this, null, true);
					BgAnimate.registerAnimation('slotMachineBusyRotor', null, {'bgPosition': '675px 190px', 'prefix': 'rotorMedAni_', 'duration': 130});
				},
				'onInitDataReceive': function(data){
					prepareSlotmachineLayout();
					if (!CONFIGURATOR_FALLBACK_DATA.cp){
						AddOptions = SlotmachineAddOptions_GC.create(SlotMachine);
					}else{
						$('#slotmachineAddOptsContainer').html(
							'<div style="font-size: 14px; color: #999; padding: 0 0 0 28px;">' +
								'Für einen Online-Gestalten Artikel stehen keine Zusatzoptionen zur Verfügung!' +
							'</div>'
						);
					}
					updateDataTypes(data, 'slotmachine');
					if (data.overnight){
						this.urlParams.ovn = true;
					}
					registerLockedSlots(this.urlParams, data);
				},
				'onAfterInit': function(data){
					var opts = {
						'title': data.productTitle,
						'data': data,
						'target': $('#prdConfTopConfig'),
						'slot': this
					};
					createStaticProductSelect();
					QuickChoice.init(opts);
					ScartPreparer.update(data);
					if (!CONFIGURATOR_FALLBACK_DATA.cp){
						AddOptions.update(data);
					}
					CustFormats.update(data);
					CostTables.init(data, $('#prdConfCostsOuterTable'));
					LinkPreparer.update(data, this.urlParams);
					ResetPreparer.make();
					TopImagePrep.update(data);
					ErrorMsgHandler.handleError(data);
					initiateInfos(this, 'slots');
					window.SELECT_MODE_SLOTMACHINE = true;
				},
				'onAfterSlotCatch': function(slot){
				},
				'onAfterSlotsUpdate': function(){
					//clear action keeper
					$('#slotMachineActionKeeper').remove();
					$('div.contColDes5').css({
						overflow: 'auto',
						zIndex: 10000
					});
				},
				'onSlotAction': function(eventElement){
					// set action keeper
					slotMachineActionKeeper();
				},
				'onDataRequest': function(slot, oldData){
					// set action keeper
					slotMachineActionKeeper();
				},
				'onDataRequestSuccess': function(slot, data){
					var i, isSet, enable = true;
					updateDataTypes(data, 'slotmachine');
					// update auf_id.
					if (this.urlParams && this.urlParams.auf_id){
						this.urlParams.auf_id = data.auf_id;
					}
					ScartPreparer.update(data);
					if (!CONFIGURATOR_FALLBACK_DATA.cp){
						AddOptions.update(data);
					}
					CustFormats.update(data);
					CostTables.update(data);
					LinkPreparer.update(data, this.urlParams);
					ErrorMsgHandler.handleError(data);
					// update slot bullets
					for (i = 0; i < this.slots.length; i+=1){
						isSet = data.slots[i].currentItem > 0 ? true : false;
						if (!isSet){
							enable = false;
						}
						if (this.slots[i].domel){
							this.slots[i].domel.find('.slotBullet').toggleClass('slotBulletActive_hasSelection', isSet);
						}
					}
					QuickChoice.update(slot, data);
					initiateInfos(this, 'options');
					handleTemplateTab(enable);
					handleShippingTime(this, data, false);
					if (!CONFIGURATOR_FALLBACK_DATA.cp){
						appendStaticDataCheckOption();
						handleShippingMethodSelect(this, data);
						initiateInfos(this, 'shippingMethod');
					}
					initiateInfos(this, 'dataCheck');
					handleFreeFormatErrors(this);
					// econda stuff
					sendEcondaInfoIdAufId(data);
					prepareServiceIcons(data);
				}
			}
		);
	};
/* << */


/* >> Slot machine dual mode initialization */
	// starts the slot machines
	StartSlotmachineDualMode = function(){
		slotMachineActionKeeper = function(){
			if ($('#slotMachineActionKeeper').size() === 0){
				var opts = {'opacity': 1, 'background': 'transparent'};
				var akShell = $('<div id="slotMachineActionKeeper"></div>');
				var target = $('div.contColDes5');
				target.addClass('viewport').css({'overflow': 'hidden'});
				var w = target.width();
				var h = target.height();
				akShell.width(w).height(h);
				akShell.css(opts);
				target.append(akShell);
				var bgAnimation = BgAnimate.createAnimation('slotMachineBusyRotor', akShell);
				bgAnimation.start();
			}
		};
		Sm_SelectMode = SlotMachineSelectMode.create();
		Sm_TabbedImageMode = SlotMachineTabbedImageMode.create();
		QuickChoice = TopProductQuickChoice_GC.create(Sm_SelectMode);
		ScartPreparer = ShoppingcartPreparer.create();
		AddOptions = AdditionalOptions_GC.create(Sm_SelectMode);
		CustFormats = CustomFormats_GC.create(Sm_SelectMode);
		CostTables = CostsTableHandler_GC.create(Sm_SelectMode);
		LinkPreparer = PageLinkPreparer.create();
		ResetPreparer = ResetButtonPreparer.create();
		TopImagePrep = TopImagePreparer.create();
		ErrorMsgHandler = ErrorMessagesHandler_GC.create(Sm_SelectMode);

		Sm_SelectMode.init(
			{
				'target': $('#slotMachineSelectMode'),
				'ajaxHandler': 'configarticle',
				'slotType': 'SlotMachineSelectModeSlot',
				'slotItemType': 'SlotMachineSelectModeSlotItem',
				'onBeforeInit': function(){
					BgAnimate.registerAnimation('slotMachineBusyRotor', null, {'bgPosition': '912px 190px', 'prefix': 'rotorMedAni_', 'duration': 130});
				},
				'onInitDataReceive': function(data){
					updateDataTypes(data, 'select');
					if (data.overnight){
						this.urlParams.ovn = true;
					}
					registerLockedSlots(this.urlParams, data);
				},
				'onAfterInit': function(data){
					// Init some handlers
					var opts = {
						'title': data.productTitle,
						'data': data,
						'target': $('#prdConfTopConfig'),
						'slot': this
					};
					QuickChoice.init(opts);
					ScartPreparer.update(data);
					AddOptions.update(data);
					CustFormats.update(data);
					CostTables.init(data, $('#prdConfCostsOuterTable'));
					LinkPreparer.update(data, this.urlParams);
					ResetPreparer.make();
					TopImagePrep.update(data);
					ErrorMsgHandler.handleError(data);
					window.SELECT_MODE_SLOTMACHINE = true;
				},
				'onAfterSlotCatch': function(slot){
				},
				'onAfterSlotsUpdate': function(){
					//clear action keeper
					$('#slotMachineActionKeeper').remove();
					$('div.contColDes5').css({'overflow': 'auto'});
				},
				'onSlotAction': function(){
					// set action keeper
					slotMachineActionKeeper();
				},
				'onDataRequest': function(slot, oldData){
					// set action keeper
					slotMachineActionKeeper();
				},
				'onDataRequestSuccess': function(slot, data){
					var timData = $.extend(true, {}, data);
					updateDataTypes(data, 'select');
					updateDataTypes(timData, 'image');
					// update auf_id.
					if (this.urlParams && this.urlParams.auf_id){
						this.urlParams.auf_id = data.auf_id;
					}
					ScartPreparer.update(data);
					AddOptions.update(data);
					CustFormats.update(data);
					CostTables.update(data);
					LinkPreparer.update(data, this.urlParams);
					QuickChoice.update(slot, data);
					ErrorMsgHandler.handleError(data);
					// synchronize tabbed image mode slotmachine
					if (window.TABBED_IMAGE_MODE_SLOTMACHINE){
						Sm_TabbedImageMode.data = timData;
						if (Sm_TabbedImageMode.urlParams && Sm_TabbedImageMode.urlParams.auf_id){
							Sm_TabbedImageMode.urlParams.auf_id = timData.auf_id;
						}
						Sm_TabbedImageMode.slotUpdateCheck();
						if (slot){
							$('#slotMachineTabs').tabs('select' , slot.itemId);
						}
					}
				}
			}
		);

		Sm_TabbedImageMode.init(
			{
				'target': $('#slotMachineImageMode'),
				'ajaxHandler': 'configarticle',
				'onBeforeInit': function(){},
				'onInitDataReceive': function(data){
					if (data.overnight){
						this.urlParams.ovn = true;
					}
					updateDataTypes(data, 'image');
					registerLockedSlots(this.urlParams, data);
					$('table.prdConfTopTable .image').prepend('<div class="viewport" id="itemHoverInfoContainer"></div>');
					this.handleHovertextContainer(null);
				},
				'onAfterInit': function(data){
					// create tabs
					$(function(){
						$('#slotMachineTabs').tabs({
							select: function(event, ui){
								var slots = Sm_SelectMode.slots;
								$(slots).each(function(i){
									var here = i == ui.index ? true : false;
									this.domel.find('.slotBullet').toggleClass('slotBulletActive', here);
								});
							}
						});
						// initial bullet activation on the first slot.
						Sm_SelectMode.slots[0].domel.find('.slotBullet').toggleClass('slotBulletActive', true);
					});
					// Init some handlers
					var opts = {
						'title': data.productTitle,
						'data': data,
						'target': $('#prdConfTopConfig'),
						'slot': this
					};
					QuickChoice.init(opts);
					ScartPreparer.update(data);
					AddOptions.update(data);
					CustFormats.update(data);
					CostTables.init(data, $('#prdConfCostsOuterTable'));
					LinkPreparer.update(data, this.urlParams);
					//ResetPreparer.make();
					TopImagePrep.update(data);
					ErrorMsgHandler.handleError(data);
					window.TABBED_IMAGE_MODE_SLOTMACHINE = true;
				},
				'onAfterSlotCatch': function(slot){
				},
				'onAfterSlotsUpdate': function(){
					//clear action keeper
					$('#slotMachineActionKeeper').remove();
					$('div.contColDes5').css({'overflow': 'auto'});
				},
				'onSlotAction': function(){
					// set action keeper
					slotMachineActionKeeper();
				},
				'onDataRequest': function(slot, oldData){
					// set action keeper
					slotMachineActionKeeper();
				},
				'onDataRequestSuccess': function(slot, data){
					var smData = $.extend(true, {}, data);
					updateDataTypes(data, 'image');
					updateDataTypes(smData, 'select');
					// update auf_id.
					if (this.urlParams && this.urlParams.auf_id){
						this.urlParams.auf_id = data.auf_id;
					}
					ScartPreparer.update(data);
					AddOptions.update(data);
					CustFormats.update(data);
					CostTables.update(data);
					LinkPreparer.update(data, this.urlParams);
					QuickChoice.update(slot, data);
					ErrorMsgHandler.handleError(data);
					// synchronize select mode slotmachine
					if (window.SELECT_MODE_SLOTMACHINE){
						Sm_SelectMode.data = smData;
						if (Sm_SelectMode.urlParams && Sm_SelectMode.urlParams.auf_id){
							Sm_SelectMode.urlParams.auf_id = smData.auf_id;
						}
						Sm_SelectMode.slotUpdateCheck();
					}
					if (slot){
						slot.selectNextInvalidTab();
					}
				}
			}
		);
	};
/* << */


/* >> Slot Machine add ons there are triggered on slot machine events */
	/* >> top product quick choice generic configurator compatible*/
		TopProductQuickChoice_GC = $.extend(
			$.clone(TopProductQuickChoice),
			{
				create: function(configurator){
					var o = TopProductQuickChoice.create.call(this);
					o.configurator = configurator;
					return o;
				},
				makeRowsWithBindings: function(){
					var slots = this.configurator.slots;
					var infoText = this.configurator.data.infoText;
					var r = $(
						'<tr>' +
							'<td class="title"></td>' +
							'<td class="value"></td>' +
						'</tr>'
					);
					var table = this.target.find('table');
					var self = this;
					$(slots).each(function(i){
						var slot = this;
						var row = r.clone();
						row.find('.title').html(slot.title);
						var value = row.find('.value');
						var info = slot.items[slot.currentItem].title;
						var addInfoText = slot.items[slot.currentItem].data.addInfoText;
						if (addInfoText){
							info += ' (' + addInfoText + ')';
						}
						value.html(info);
						table.append(row);
					});
					var infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				},
				makeRowsForInfo: function(){
					var slots = this.configurator.data.slots;
					var infoText = this.configurator.data.infoText;
					var r = $(
						'<tr>' +
							'<td class="title"></td>' +
							'<td class="value"></td>' +
						'</tr>'
					);
					var table = this.target.find('table');
					var self = this;
					if (slots){
						$(slots).each(function(i){
							var slot = this;
							var row = r.clone();
							row.find('.title').html(slot.title);
							var value = row.find('.value');
							for (var j in slot.items){
								if (j == slot.currentItem){
									var info = slot.items[j].title;
									var addInfoText = slot.items[j].addInfoText;
									if (addInfoText){
										info += ' (' + addInfoText + ')';
									}
									value.html(info);
								}
							}
							table.append(row);
						});
					}
					var infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				}
			}
		);

		SlotmachineRightQuickChoice_GC = $.extend(
			$.clone(TopProductQuickChoice_GC),
			{
				create: function(configurator){
					return TopProductQuickChoice_GC.create.call(this, configurator);
				},
				makeRowLayout: function(){
					var lay = $(
						'<div class="rowOuter">' +
							'<div class="title"></div>' +
							'<div class="value"></div>' +
						'</div>'
					);
					return lay;
				},
				makeTableWithTitle: function(){
					var t = this.target;
					var title = this.opts.title || null;
					var subtitle = this.opts.data.subTitle || null;
					this.subtitle = subtitle;
					var table = $(
						'<div class="sharedConfProductInfo">' +
						'</div>'
					);
					if (title){
						var titleElm = $(
							'<div class="topTitle">' + title + '</div>'
						);
						if (subtitle){
							titleElm.addClass('withSub');
						}
						table.append(titleElm);
					}
					if (subtitle){
						table.append(
							'<div class="subtitle">' + subtitle + '</div>'
						);
					}

					t.empty().append(table);
				},
				makeRowsWithBindings: function(){
					var data = this.configurator.data, slots = this.configurator.slots,
					infoText = data.infoText,
					table = this.target.find('.sharedConfProductInfo'),
					self = this, infoRow;
					$(slots).each(function(i){
						var slot = this, value, addInfoText, row, freeFormat,
						info = slot.items[slot.currentItem].title;
						row = self.makeRowLayout();
						row.find('.title').html(slot.title);
						value = row.find('.value');
						addInfoText = slot.items[slot.currentItem].data.addInfoText;
						if (addInfoText){
							info += ' (' + addInfoText + ')';
						}
						value.html(info);
						table.append(row);
					});
					infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				},
				getFinalInfoRow: function(infoText){
					if (infoText){
						var row = this.makeRowLayout();
						row.find('.title').addClass('infoTextTitle').html($.lang('infoTextPmt'));
						row.find('.value').addClass('valueWrapped').append('<div class="infoText">' + infoText + '</div>');
						return row;
					}
					return null;
				},
				update: function(slot, data){
					var subtitle = this.subtitle, elm, index, valCol, info, addInfoText, infoText, infoRow;
					if (slot){
						elm = this.target;
						if (elm.size() > 0){
							index = 2;
							if (subtitle){
								index += 1;
							}
							info = slot.items[slot.currentItem].title;
							valCol = elm.find('div.rowOuter:nth-child(' + (slot.itemId + index) + ')').find('.value');
							addInfoText = slot.items[slot.currentItem].data.addInfoText;
							if (addInfoText){
								info += ' (' + addInfoText + ')';
							}
							valCol.html(info);
						}
					}
					infoText = data.infoText;
					if (infoText){
						if (this.target.find('.value .infoText').size() > 0){
							this.target.find('.value .infoText').addClass('valueWrapped').html(infoText);
						}else{
							infoRow = this.getFinalInfoRow(infoText);
							if (infoRow){
								$('.sharedConfProductInfo').append(infoRow);
							}
						}
					}else{
						this.target.find('.value .infoText').parents('.rowOuter').remove();
					}
				}
			}
		);

		SlotmachineRightQuickChoiceWithFreeFormat_GC = $.extend(
			$.clone(SlotmachineRightQuickChoice_GC),
			{
				create: function(configurator){
					var o = TopProductQuickChoice.create.call(this);
					o.configurator = configurator;
					return o;
				},
				makeTableWithTitle: function(){
					var t = this.target;
					var title = this.opts.title || null;
					var subtitle = this.opts.data.subTitle || null;
					this.subtitle = subtitle;
					var table = $(
						'<div class="sharedConfProductInfo">' +
						'</div>'
					);
					if (title){
						var titleElm = $(
							'<div class="topTitle">' + title + '</div>'
						);
						if (subtitle){
							titleElm.addClass('withSub');
						}
						table.append(titleElm);
					}
					if (subtitle){
						table.append(
							'<div class="subtitle">' + subtitle + '</div>'
						);
					}

					t.empty().append(table);
				},
				makeFreeFormatLayout: function(){
					var lay = $(
						'<div class="viewport quickInfoFreeFormat">' +
							'<div class="pane">' +
								'<div class="viewport">' +
									'<div class="field field-width">' +
										'<input type="text" name="width" value=""/>' +
									'</div>' +
									'<div class="field field-height">' +
										'<input type="text" name="width" value=""/>' +
									'</div>' +
									'<div class="button"></div>' +
									'<div class="fieldInfo fieldInfo-width"></div>' +
									'<div class="fieldInfo fieldInfo-height"></div>' +
								'</div>' +
							'</div>' +
						'</div>'
					);
					return lay;
				},
				makeFreeFormatInfoPaneLayout: function(){
					var lay = $(
						'<div class="viewport freeFormatInfoPaneAnchor">' +
							'<div class="pane"></div>' +
						'</div>'
					);
					return lay;
				},
				makeRowsWithBindings: function(){
					var data = this.configurator.data, slots = this.configurator.slots,
					infoText = data.infoText, minMaxWidthInfo = 'min.%s/max.%s', minMaxHeightInfo = minMaxWidthInfo,
					table = this.target.find('.sharedConfProductInfo'), minDims, maxDims,
					self = this, infoRow;
					$(slots).each(function(i){
						var slot = this, value, addInfoText, row, freeFormat,
						info = slot.items[slot.currentItem].title;
						row = self.makeRowLayout();
						row.find('.title').html(slot.title);
						if (info.toLowerCase() == 'freies format'){
							freeFormat = self.makeFreeFormatLayout();
							row.find('.value').append(freeFormat);
							if (data.freeFormatData){
								if (data.freeFormatData.width){
									freeFormat.find('.field-width input').val(data.freeFormatData.width);
									$('#prdConfTopWk_customerWidth').val(data.freeFormatData.width);
								}else if (!data.customFormat){
									$('#prdConfTopWk_customerWidth').val('');
								}
								if (data.freeFormatData.height){
									freeFormat.find('.field-height input').val(data.freeFormatData.height);
									$('#prdConfTopWk_customerHeight').val(data.freeFormatData.height);
								}else if (!data.customFormat){
									$('#prdConfTopWk_customerHeight').val('');
								}
							}
							minDims = data.freeformatmindims;
							maxDims = data.freeformatmaxdims;
							minMaxWidthInfo = minMaxWidthInfo.replace('%s', minDims.width || '--');
							minMaxWidthInfo = minMaxWidthInfo.replace('%s', maxDims.width || '--');
							minMaxHeightInfo = minMaxHeightInfo.replace('%s', minDims.height || '--');
							minMaxHeightInfo = minMaxHeightInfo.replace('%s', maxDims.height || '--');
							freeFormat.find('.fieldInfo-width').text(minMaxWidthInfo);
							freeFormat.find('.fieldInfo-height').text(minMaxHeightInfo);
						}else{
							value = row.find('.value');
							addInfoText = slot.items[slot.currentItem].data.addInfoText;
							if (addInfoText){
								info += ' (' + addInfoText + ')';
							}
							value.html(info);
						}
						table.append(row);
					});
					infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				},
				handleFreeFormatInfoPane: function(target){
					var pane = this.makeFreeFormatInfoPaneLayout(),
					targetLeftPos = target.position().left;
					target.append(pane);
					pane.css({
						zIndex: 10000
					}).find('.pane').css({
						left: targetLeftPos - 342
					}).fadeIn(2000, function(){
						var pane = $(this);
						window.setTimeout(function(){
							pane.fadeOut('slow', function(){
								$(this).parent().remove();
							});
						}, 10000);
					});
				},
				update: function(slot, data){
					var subtitle = this.subtitle, elm, index, valCol, info, addInfoText, infoText, infoRow,
					freeFormat, self = this;
					elm = this.target;
					if (data.freeFormatData.width){
						$('#prdConfTopWk_customerWidth').val(data.freeFormatData.width);
					}else if (!data.customFormat){
						$('#prdConfTopWk_customerWidth').val('');
					}
					if (data.freeFormatData.height){
						$('#prdConfTopWk_customerHeight').val(data.freeFormatData.height);
					}else if (!data.customFormat){
						$('#prdConfTopWk_customerHeight').val('');
					}
					if (slot){
						if (elm.size() > 0){
							index = 2;
							if (subtitle){
								index += 1;
							}
							info = slot.items[slot.currentItem].title;
							valCol = elm.find('div.rowOuter:nth-child(' + (slot.itemId + index) + ')').find('.value');
							addInfoText = slot.items[slot.currentItem].data.addInfoText;
							if (addInfoText){
								info += ' (' + addInfoText + ')';
							}
							valCol.html(info);
							if (data.freeformatmaxdims.width && data.freeformatmaxdims.height){
								elm.find('.rowOuter .value').each(function(i){
									var minMaxWidthInfo = 'min.%s/max.%s', minMaxHeightInfo = minMaxWidthInfo,
									minDims, maxDims;
									if ($(this).text().toLowerCase() == 'freies format'){
										freeFormat = self.makeFreeFormatLayout();
										$(this).html(freeFormat);
										self.handleFreeFormatInfoPane($(this));
										$(this).find('.field-width input').val(data.freeFormatData.width || '');
										$(this).find('.field-height input').val(data.freeFormatData.height || '');
										minDims = data.freeformatmindims;
										maxDims = data.freeformatmaxdims;
										minMaxWidthInfo = minMaxWidthInfo.replace('%s', minDims.width || '--');
										minMaxWidthInfo = minMaxWidthInfo.replace('%s', maxDims.width || '--');
										minMaxHeightInfo = minMaxHeightInfo.replace('%s', minDims.height || '--');
										minMaxHeightInfo = minMaxHeightInfo.replace('%s', maxDims.height || '--');
										$(this).find('.fieldInfo-width').text(minMaxWidthInfo);
										$(this).find('.fieldInfo-height').text(minMaxHeightInfo);
										$(this).find('.button').unbind().bind('click', function(e){
											self.handlePrepareDataModelAndVerify();
										});
									}
								});
							}
						}
					}
					infoText = data.infoText;
					if (infoText){
						if (this.target.find('.value .infoText').size() > 0){
							this.target.find('.value .infoText').addClass('valueWrapped').html(infoText);
						}else{
							infoRow = this.getFinalInfoRow(infoText);
							if (infoRow){
								$('.sharedConfProductInfo').append(infoRow);
							}
						}
					}else{
						this.target.find('.value .infoText').parents('.rowOuter').remove();
					}
				},
				handlePrepareDataModelAndVerify: function(){
					var formData = $('.quickInfoFreeFormat').find(':input').serializeArray(), Machine = this.configurator,
					freeFormatData = Machine.data.freeFormatData;
					freeFormatData.width = formData[0].value;
					freeFormatData.height = formData[1].value;
					freeFormatData.errorMessage = null;
					Machine.verifyData(null);
				}
			}
		);

		SlotmachineRightQuickChoice_XXL_GC = $.extend(
			$.clone(SlotmachineRightQuickChoice_GC),
			{
				create: function(configurator){
					return SlotmachineRightQuickChoice_GC.create.call(this, configurator);
				},
				makeRowsWithBindings: function(){
					var data = this.configurator.data, slots = this.configurator.slots,
					infoText = data.infoText, cnt = 0,
					table = this.target.find('.sharedConfProductInfo'),
					self = this, infoRow;
					$(slots).each(function(i){
						var slot = this, title, value, addInfoText, row, freeFormat,
						info = slot.items[slot.currentItem].title;
						row = self.makeRowLayout();
						title = row.find('.title');
						title.html(slot.title);
						value = row.find('.value');
						addInfoText = slot.items[slot.currentItem].data.addInfoText;
						if (addInfoText){
							info += ' (' + addInfoText + ')';
						}
						if ($.inArray(cnt, data.locked) == -1 && slot.items[slot.currentItem].value > -1){
							title.show();
							value.html(info);
						}
						table.append(row);
						cnt++;
					});
					infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				},
				update: function(slot, data){
					var subtitle = this.subtitle, elm, index, title, valCol, info, addInfoText, infoText, infoRow;
					if (slot){
						elm = this.target;
						if (elm.size() > 0){
							index = 2;
							if (subtitle){
								index += 1;
							}
							info = slot.items[slot.currentItem].title;
							title = elm.find('div.rowOuter:nth-child(' + (slot.itemId + index) + ')').find('.title');
							valCol = elm.find('div.rowOuter:nth-child(' + (slot.itemId + index) + ')').find('.value');
							addInfoText = slot.items[slot.currentItem].data.addInfoText;
							if (addInfoText){
								info += ' (' + addInfoText + ')';
							}
							if (slot.items[slot.currentItem].value > -1){
								title.show();
								valCol.html(info);
							}else{
								title.hide();
								valCol.empty();
							}
						}
					}
					infoText = data.infoText;
					if (infoText){
						if (this.target.find('.value .infoText').size() > 0){
							this.target.find('.value .infoText').addClass('valueWrapped').html(infoText);
						}else{
							infoRow = this.getFinalInfoRow(infoText);
							if (infoRow){
								$('.sharedConfProductInfo').append(infoRow);
							}
						}
					}else{
						this.target.find('.value .infoText').parents('.rowOuter').remove();
					}
				}
			}
		);
	/* << */

	/* >> additional options generic configurator compatible*/
		AdditionalOptions_GC = $.extend(
			$.clone(AdditionalOptions),
			{
				options: null,
				create: function(configurator){
					var o = AdditionalOptions.create.call(this);
					o.configurator = configurator;
					return o;
				},
				select: function(data){
					var f = $('<select></select>').attr({'name': data.name});
					$(data.items).each(function(i){
						var o = $('<option></option>').val(this.value).text(this.content);
						if (this.here){
							o.attr('selected', 'selected');
						}
						f.append(o);
					});
					var self = this;
					f.bind('change', function(e){
						var items = self.configurator.data.options[self.getOptId(this.id)].items;
						var elm = this;
						$(items).each(function(i){
							if (this.value == $(elm).val()){
								this.here = true;
							}else{
								this.here = false;
							}
						});
						self.configurator.data.options[self.getOptId(this.id)].items = items;
						self.verifyData();
					});
					return f;
				},
				checkbox: function(data){
					var f = $('<input/>').attr({'type': data.type, 'name': data.name, 'value': data.value});
					var self = this;
					f.bind('click', function(e){
						var here = $(this).attr('checked');
						self.configurator.data.options[self.getOptId(this.id)].here = here;
						self.verifyData();
					});
					return f;
				},
				radio: function(data){
					var f = $('<input/>').attr({'type': 'radio', 'name': data.name, 'value': data.value});
					var self = this;
					f.bind('click', function(e){
						var items = self.configurator.data.options[self.getOptId(this.id)].items;
						var elm = this;
						$(items).each(function(i){
							if (this.value == $(elm).val()){
								this.here = true;
							}else{
								this.here = false;
							}
						});
						self.configurator.data.options[self.getOptId(this.id)].items = items;
						self.verifyData();
					});
					return f;
				},
				text: function(data){
					var f =  $(
						'<div class="textFieldAndButtonOuter">' +
							'<div class="fieldOuter"><input type="text" name="' + data.name + '" value="' + data.value + '"/></div>' +
							'<div class="textFieldSaveButton"></div>' +
						'</div>'
					);
					// This is a static text field char limitation and should be solved
					// at the WAF administration.
					f.find(':input').attr({'maxlength': 5});
					var self = this;
					f.find('.textFieldSaveButton').bind('click', function(e){
						var field = $(this).prev('.fieldOuter').find(':input');
						var id = field.attr('id');
						self.configurator.data.options[self.getOptId(id)].value = field.val();
						self.verifyData();
					});
					return f;
				},
				verifyData: function(){
					this.configurator.verifyData();
				}
			}
		);
	/* << */

	SlotmachineAddOptions_GC = $.extend(
		$.clone(AdditionalOptions),
		{
			create: function(configurator){
				var o = AdditionalOptions.create.call(this, configurator);
				o.optsContainer = $('#slotmachineAddOptsContainer');
				return o;
			},
			makeOptionLayout: function(data){
				var o;
				if (data.type === 'select'){
					return $(
						'<div class="optionOuter optionOuterSelect">' +
							'<table cellpadding="0" cellspacing="0" border="0">' +
								'<tr>' +
									'<td></td>' +
									'<td>' +
										'<div class="pmt">' + data.prompt + '<span class="price"></span></div>' +
									'</td>' +
									'<td></td>' +
								'</tr>' +
								'<tr>' +
									'<td class="bullet"><div class="slotBullet"></div></td>' +
									'<td>' +
										'<div class="field"></div>' +
									'</td>' +
									'<td class="info"><a href="#" class="slotInfo" target="_blank"></a></td>' +
								'</tr>' +
							'</table>' +
						'</div>'
					);
				}else if(data.type === 'text'){
					return $(
						'<div class="optionOuter optionOuterText">' +
							'<table cellpadding="0" cellspacing="0" border="0">' +
								'<tr>' +
									'<td></td>' +
									'<td>' +
										'<div class="pmt">' + data.prompt + '<span class="price">' + data.price + '</span></div>' +
									'</td>' +
									'<td></td>' +
								'</tr>' +
								'<tr>' +
									'<td class="bullet"><div class="slotBullet"></div></td>' +
									'<td>' +
										'<div class="field"></div>' +
									'</td>' +
									'<td class="info"><a href="#" class="slotInfo" target="_blank"></a></td>' +
								'</tr>' +
							'</table>' +
						'</div>'
					);
				}else{
					return $(
						'<div class="optionOuter optionOuterOthers">' +
							'<table cellpadding="0" cellspacing="0" border="0">' +
								'<tr>' +
									'<td class="bullet"><div class="slotBullet"></div></td>' +
									'<td>' +
										'<div class="pmt">' + data.prompt + '<span class="price">' + data.price + '</span></div>' +
									'</td>' +
									'<td>' +
										'<div class="field"></div>' +
									'</td>' +
									'<td class="info"><a href="#" class="slotInfo" target="_blank"></a></td>' +
								'</tr>' +
							'</table>' +
						'</div>'
					);
				}
				return null;
			},
			update: function(data){
				var optsContainer = this.optsContainer;
				optsContainer.empty();
				var self = this;
				if (data.options && data.options.length > 0){
					$(data.options).each(function(i){
						if (this.type == 'radio'){
							var type = this.type,
							transSelectBox = {
								grpTitle: this.grpTitle,
								prompt: this.grpTitle,
								name: this.items[0].name,
								items: [],
								mandatory: true
							};
							$(this.items).each(function(j){
									var transItem = {
										value: this.value,
										content: this.prompt,
										price: this.price,
										img: this.img
									};
									transSelectBox.items.push(transItem);
							});
							optsContainer.append(self.makeOption($.extend(transSelectBox, {'type': 'select'}), i));
						}else{
							optsContainer.append(self.makeOption(this, i));
						}
					});
					self.makeShoppingCartOpts(data);
				}else{
					optsContainer.append(
						'<div class="optionOuter optionOuterNoItems">' +
							'<div class="pmt">Keine verfügbar.</div>' +
						'</div>'
					);
				}
				$(data.options).each(function(i){
					var id;
					if (this.type == 'radio' || this.type == 'select'){
						var type = this.type;
						$(this.items).each(function(j){
							var contextItem = this;
							if (this.here){
								id = 'opt_' + i;
								$('#' + id).find('option').eq(j).attr({
									selected: 'selected'
								}).end().parents('tr').prev().find('.price').html(this.price);
							}else{
								id = 'opt_' + i;
								$('#' + id).find('option').eq(j).attr({
									selected: null
								});
							}
						});
					}else{
						if (this.here){
							id = 'opt_' + i;
							$('#' + id).attr('checked', 'checked');
						}
					}
				});
			},
			makeOption: function(data, idx){
				var o = this.makeOptionLayout(data);
				o.find('.field').append(this.getField(data, idx));
				if (o.hasClass('optionOuterSelect')){
					if(o.find('select').val()){
						o.find('.slotBullet').addClass('slotBulletActive_hasSelection');
					}
				}else if (o.hasClass('optionOuterText')){
					if(o.find('input').val()){
						o.find('.slotBullet').addClass('slotBulletActive_hasSelection');
					}
				}else{
					if(o.find('input').attr('checked')){
						o.find('.slotBullet').addClass('slotBulletActive_hasSelection');
					}
				}
				return o;
			},
			select: function(data){
				var f = $('<select></select>').attr({'name': data.name});
				$(data.items).each(function(i){
					var o = $('<option></option>').val(this.value).text(this.content);
					if (this.here){
						o.attr('selected', 'selected');
					}
					f.append(o);
				});
				var self = this;
				f.bind('change', function(e){
					var items = SlotMachine.data.options[self.getOptId(this.id)].items;
					var elm = this;
					$(items).each(function(i){
						if (this.value == $(elm).val()){
							this.here = true;
						}else{
							this.here = false;
						}
					});
					SlotMachine.data.options[self.getOptId(this.id)].items = items;
					self.verifyData();
					if ($(this).val()){
						$(this).parent().parent().prev().find('.slotBullet').addClass('slotBulletActive_hasSelection');
					}else{
						$(this).parent().parent().prev().find('.slotBullet').removeClass('slotBulletActive_hasSelection');
					}
				});
				return f;
			},
			checkbox: function(data){
				var f = $('<input/>').attr({'type': data.type, 'name': data.name, 'value': data.value}),
				self = this;
				if (data.here){
					f.attr('checked', 'checked');
				}
				f.bind('click', function(e){
					var here = $(this).attr('checked');
					SlotMachine.data.options[self.getOptId(this.id)].here = here;
					self.verifyData();
					if ($(this).attr('checked')){
						$(this).parent().parent().prev().prev().find('.slotBullet').addClass('slotBulletActive_hasSelection');
					}else{
						$(this).parent().parent().prev().prev().find('.slotBullet').removeClass('slotBulletActive_hasSelection');
					}
				});
				return f;
			},
			text: function(data){
				var f =  $(
					'<div class="textFieldAndButtonOuter">' +
						'<div class="fieldOuter"><input type="text" name="' + data.name + '" value="' + data.value + '"/></div>' +
						'<div class="textFieldSaveButton"></div>' +
					'</div>'
				);
				// This is a static text field char limitation and should be solved
				// at the WAF administration.
				f.find(':input').attr({'maxlength': 5});
				var self = this;
				f.find('.textFieldSaveButton').bind('click', function(e){
					var field = $(this).prev('.fieldOuter').find(':input');
					var id = field.attr('id');
					SlotMachine.data.options[self.getOptId(id)].value = field.val();
					self.verifyData();
				});
				return f;
			}
		}
	);

	/* >> custom formats generic configurator compatible */
		CustomFormats_GC = $.extend(
			$.clone(CustomFormats),
			{
				create: function(configurator){
					var o = CustomFormats.create.call(this);
					o.format = $('#prdCustFormat');
					o.formatWidth = $('#prdCustFormatWidth');
					o.formatHeight = $('#prdCustFormatHeight');
					o.custWidth = $('#prdCustFormatWidthInput');
					o.custHeight = $('#prdCustFormatHeightInput');
					o.configurator = configurator;
					var saveFormatContentButton = $('#prdConfCustHeadFormatSaveButton');
					if (saveFormatContentButton.size() > 0){
						var self = o;
						saveFormatContentButton.unbind();
						saveFormatContentButton.bind('click', function(e){
							e.preventDefault();
							e.stopPropagation();
							self.configurator.data.meta.formatDims.custHeight = self.custHeight.val();
							self.configurator.data.meta.formatDims.custWidth = self.custWidth.val();
							self.configurator.verifyData();
						});
					}
					return o;
				}
			}
		);
	/* << */

	/* >> costs table handler */
		CostsTableHandler_GC = $.extend(
			$.clone(CostsTableHandler),
			{
				create: function(configurator){
					var o = CostsTableHandler.create.call(this);
					o.configurator = configurator;
					return o;
				},
				update: function(data){
					var tar = this.target;
					var lcol = tar.find('.left');
					var ccol = tar.find('.center');
					var rcol = tar.find('.right');
					var renderer;
					if (tar){
						if (data.costs){
							renderer = JSONRenderer.create(data.costs, lcol);
							renderer.renderCostsExtendedTable('costs', this.configurator);
						}else{
							lcol.empty();
							ccol.empty();
							rcol.empty();
						}
						if (data.exCosts){
							renderer = JSONRenderer.create(data.exCosts, ccol);
							renderer.renderCostsExtendedTable('exCosts', this.configurator);
						}
						if (data.ovCosts){
							renderer = JSONRenderer.create(data.ovCosts, rcol);
							renderer.renderCostsExtendedTable('ovCosts', this.configurator);
						}
					}
				}
			}
		);
	/* << */

	/* >> handle error messages */
		ErrorMessagesHandler_GC = $.extend(
			$.clone(ErrorMessagesHandler),
			{
				create: function(configurator){
					var o = ErrorMessagesHandler.create.call(this);
					o.configurator = configurator;
					return o;
				},
				handleError: function(data){
					if (data.errorMessage){
						alert(data.errorMessage.title + ':\n' + data.errorMessage.text);
						this.configurator.data.errorMessage = null;
					}
				}
			}
		);
	/* << */

	/* >> shopping cart preparer (inherit from ShoppingcartPreparer)*/
		SlotmachineShoppingcartPreparer = $.extend(
			$.clone(ShoppingcartPreparer),
			{
				create: function(){
					var o = ShoppingcartPreparer.create.call(this);
					o.prepareShoppingcartLayout();
					return o;
				},
				prepareShoppingcartLayout: function(){
					var cart = $('.prdConfTopWkShell').hide(), priceInfos = cart.find('.priceInfos'), sum = cart.find('.sum'),
					shippingCostsElm = $('<div class="viewport"><div class="shippingCostsFree"></div></div>'),
					bestPrice = $('<div class="viewport"><div class="bestPrice"></div></div>'), form,
					url = AjaxURLManager.getUrlWithKey('bestprice');
					if ($('.configProduct').length){
						$('.configProduct').append(shippingCostsElm, bestPrice);
					}
					if (!cart.hasClass('layout2PrdConfTopWkShell')){
						form = cart.find('form');
						form.prepend(priceInfos).end().addClass('layout2PrdConfTopWkShell');
						if (typeof CONFIGURATOR_FALLBACK_DATA !== 'undefined'){
							if (CONFIGURATOR_FALLBACK_DATA.auf_id){
								url = url + Utils.getUrlParamsFromJson({
									auf_id: CONFIGURATOR_FALLBACK_DATA.auf_id
								});
								$.getJSON(url, function(data, textStatus){
									if (data){
										$('.bestPrice').show().bind('click', function(e){
											var u = window.location.href;
											if (u.search(/\?/) > -1){
												u = u.substring(0, u.search(/\?/));
											}
											u = u + Utils.getUrlParamsFromJson({
												auf_id: data.auf_id,
												freeConfig: false
											});
											window.location = u;
										});
									}
								});
							}
							if (CONFIGURATOR_FALLBACK_DATA.cp){
								$(
									'#prdConfTopWk_pos_id,' +
									'#prdConfTopWk_overnight,' +
									'#prdConfTopWk_express,' +
									'#prdConfTopWk_sharedId,' +
									'#prdConfTopWk_handleArticle'
								).remove();
								form.append('<input type="hidden" name="id" value="9430" />');
								form.attr({
									action: '/Produkt_gestalten.htm',
									method: 'GET',
									target: null
								});
							}
						}
					}
				},
				triggerShoppingcartWithAvatar: function(){
					$('.prdConfTopWkShell').find('form').submit();
				},
				update: function(data){
					var url, ajaxCount = 0;
					if (data.auf_id && !data.freeConfig){
						$('.prdConfTopWkShell, #prdConfCustHeadWkButton').fadeIn('fast');
					}else{
						$('.prdConfTopWkShell, #prdConfCustHeadWkButton').fadeOut('fast');
					}
					if (data && data.auf_id && !data.freeConfig){
						if (data.meta){
							var m = data.meta;
							this.price.html(this.euroTpl.clone()).prepend(m.price);
							this.priceInfoWoTax.html(this.euroTpl.clone()).prepend(m.priceWoTax);
							this.priceTax.html(this.euroTpl.clone()).prepend(m.priceTax);
						}
						//var data = SlotMachine.data;
						$('#prdConfTopWk_express').val(data.express);
						$('#prdConfTopWk_overnight').val(data.overnight);
						$('#prdConfTopWk_auf_id').val(data.auf_id);
						if (data.pos_id){
							$('#prdConfTopWk_pos_id').val(data.pos_id);
						}else{
							$('#prdConfTopWk_pos_id').val('');
						}
						$('#prdConfTopWk_customerHeight').val(data.customerHeight);
						$('#prdConfTopWk_customerWidth').val(data.customerWidth);
						if (CONFIGURATOR_FALLBACK_DATA.cp){
							$('.shoppingcartButton')
							.addClass('shoppingcartButtonCreativePilot')
							.bind('click.scCreativePilot', function(e){
								e.preventDefault();
								e.stopPropagation();
							});
							url = AjaxURLManager.getUrlWithKey('creativepilotgetparams', {'auf_id': data.auf_id});
							ajaxCount++;
							$.getJSON(url, function(artData, textStatus){
								var grpId, prdGrp = artData.prdgrp, url;
								if (artData.format){
									grpId = artData.format.normal || '';
								}
								url = [
									'/cgi-bin/r31msvc_fremdsystem_aufruf.pl?',
									'var_hauptpfad=../creativpilot/r31/vc_media/&var_fa1_select=var_fa1_select||1|&',
									'var_aufruf_art=7&var_vs20=27&var_rueckgabe_encoding=utf8&var_vs58=',grpId,'&',
									'var_vs57=',prdGrp
								];
								ajaxCount--;
								$('.shoppingcartButton')
								.find('input')
								.unbind('click.scCreativePilot')
								.bind('click.scCreativePilot', function(e){
									e.preventDefault();
									e.stopPropagation();
									if (ajaxCount <= 0){
										(function(button){
											$.ajax({
												type: 'get',
												url: url.join(''),
												dataType: 'xml',
												success: function(prdData, msg){
													var pattern = $(prdData).children().children(':first-child'),
													id = pattern.find('vorlage_id').text(), form = button.parents('form');
													form.append(
														'<input type="hidden" name="patId" value="' + id + '"/>'
													);
													form.unbind().submit();
												},
												error: function(req, status, error){}
											});
										}($(this)));
									}
								});
							});
						}else{
							$('.shoppingcartButton input').bind('click.econda', function(e){
								var auf_id, name, price, cat, amount;
								e.preventDefault();
								e.stopPropagation();
								if (data.auf_id && typeof(window.emospro) !== 'undefined'){
									auf_id = data.auf_id;
									name = data.productTitle;
									price = data.meta.priceNum || null;
									if (price){
										price = Math.round(price * 100) / 100;
									}
									cat = data.meta.econda.econdaCategory;
									window.emospro.ec_Event = [[
										'c_add',
										auf_id || 'NULL',
										name || 'NULL',
										price || 'NULL',
										cat || 'NULL',
										'1',
										data.meta.econda.ev1 || 'NULL',
										data.meta.econda.ev2 || 'NULL',
										data.meta.econda.ev3 || 'NULL',
										data.meta.econda.ev4 || 'NULL',
										data.meta.econda.ev5 || 'NULL',
										data.meta.econda.ev6 || 'NULL',
										data.meta.econda.ev7 || 'NULL',
										data.meta.econda.ev8 || 'NULL',
										data.meta.econda.ev9 || 'NULL',
										data.meta.econda.ev10 || 'NULL'
									]];
									econdaRequestEvent();
								}
								$(this).parents('form').submit();
							});
						}
					}
				}
			}
		);
	/* << */
/* << */


/* >> json renderer require jQuery 1.2.6 Version: rel-1-0-0 */
	JSONRenderer = $.extend(
		$.clone(LLObject),
		{
			data: null,
			target: null,
			create: function(data, target){
				var o = LLObject.create.call(this);
				o.data = data || null;
				o.target = target || null;
				return o;
			},
			render: function(data, target){
				this.data = data;
				this.target = target;
				switch (data.type){
					case 'extendedTable':
						this.renderCostsExtendedTable(data);
						break;
					case 'formularRadioTable':
						this.renderFormularRadioTable(data);
						break;
				}
			},
			renderCostsExtendedTable: function(type, parent){
				var t = $('<table cellpadding="0" cellspacing="0" border="0"></table>');
				var data = this.data;
				if (data.stylename){
					t.attr({'class': data.stylename});
				}
				var tar = this.target;
				tar.empty();
				var self = this;
				if (data.allowSearch){
					this._makeMenuBarAndContentShell();
					this._renderSearchFieldBar('searchWknIsinName');
				}
				if (data.columnOrder){
					var r = $('<tr></tr>');
					$(data.columnOrder).each(function(i){
						var c = $('<th class="thead thead' + i + '">' + this.header + '</th>');
						if (! isNaN(parseInt(data.columnOrder[i].order, 10))){
							var key = data.columnOrder[i].key;
							var order = data.columnOrder[i].order;
							if (order !== null){
								c.addClass('receiveClick');
							}
							if (order == 1){
								c.addClass('sortedUp');
							}
							if (order == 2){
								c.addClass('sortedDown');
							}
							c.bind('click', function(e){
								(function(ord, parent, d){
									ord = (ord + 1) % 3;
									if (d.handler){
										var phrase = null;
										if (parent.searchPhrase){
											phrase = parent.searchPhrase;
										}
										var url = AjaxURLManager.getUrlWithKey(d.handler, {'phrase': phrase, 'field': key, 'order': ord});
										$.getJSON(url, function(data, textStatus){
											JSONPanelContentRenderer.render(data, parent);
										});
									}
								})(order, self.parent, data);
							});
						}
						r.append(c);
					});
					t.append(r);
				}
				var rows = data.rows;
				if (data.pager){
					rows = this._getPagerPreparedList(rows, data.pager);
				}
				$(rows).each(function(i){
					r = $('<tr></tr>');
					if (i % 2 !== 0){
						r.addClass('odd');
					}
					if (this.special){
						r.addClass('special');
					}
					if (this.here){
						r.addClass('here');
					}
					var rowData = this;
					if (data.columnOrder){
						$(data.columnOrder).each(function(j){
							var k = this.key;
							var c = $('<td class="col col_' + j + ' col_' + j + '_' + i + '"></td>');
							var row = rows[i];
							var cell = rows[i][k]; // data.rows[i][k];
							if (j === 0 && row.bestprice){
								c.addClass('bestprice');
							}
							// binding row for mouseevent click
							if (row[data.pk]){
								self._handleRowClick(c, row, type, parent, data);
								c.css({'cursor': 'pointer'});
							}
							// binding row for hover effects
							r.hover(
								function(){
									$(this).children('td').addClass('mouseOver');
								},
								function(){
									$(this).children('td').removeClass('mouseOver');
								}
							);
							var title;
							if (cell.title.__datetime__){
								title = $('<span>' + $.formatDate(cell.title.value, $.lang()).middle  + '&nbsp;' + $.formatTime(cell.title.value).time + '</span>');
							}else{
								if (parseInt(cell.mode, 10) > 0 || parseInt(cell.mode, 10) < 0 || parseInt(cell.mode, 10) === 0){
									title = $('<div><span>' + cell.title + '</span></div>');
									var sty = 'vNoChanges';
									if (parseInt(cell.mode, 10) > 0){
										sty = 'vPlus';
									}
									if (parseInt(cell.mode, 10 ) < 0){
										sty = 'vMinus';
									}
									title.addClass(sty);
								}else{
									title = $('<span>' + cell.title + '</span>');
								}
							}
							c.append(title);
							if (cell.href){
								title.wrap('<a href="' + cell.href + '" target="' + cell.target + '"></a>');
							}
							// add shoppingcart symbol to last column of the selected row
							if (j === 0){
								if (cell.meta){
									if (cell.meta.img){
										var iData = cell.meta.img;
										var img = $('<img width="' + iData.width + '" height="' + iData.height + '" src="' + iData.src + '"/>');
										var imgOuter = $('<div class="viewport"><div class="facetIcon"></div></div>');
										imgOuter.css({'text-align': 'left'});
										imgOuter.find('.facetIcon').append(img);
										c.prepend(imgOuter);
									}
								}
							}else if (j == data.columnOrder.length - 1 && rowData.here){
								if (c.text().charCodeAt(0) != 160){
									var scartSym = $('<div class="viewport"><div class="smallScartSym"></div></div>');
									self._handleRowShoppingcartClick(scartSym.find('.smallScartSym'), row, type, parent, data);
									c.prepend(scartSym);
								}
							}
							r.append(c);
						});
					}else{
						var cnt = 0;
						var x = function(row){
							c.bind('click', function(e){
								var m = MenuConfig[data.contextType](self.parent, row, e);
								m.init();
								m.show(e);
							});
						};
						for( var k in this){
							var c = $('<td class="col col_' + cnt + ' col_' + cnt + '_' + i + '"></td>');
							var row = rows[i];
							var cell = rows[i][k]; // data.rows[i][k];
							var title;
							// binding context menu
							if (data.contextType && this.contextActive){
								x(row);
								c.addClass('receiveClick');
							}
							if (cell.title.__datetime__){
								title = $('<span>' + $.formatDate(cell.title.value, $.lang()).middle  + '&nbsp;' + $.formatTime(cell.title.value).time + '</span>');
							}else{
								if (parseInt(cell.mode, 10) > 0 || parseInt(cell.mode, 10 ) < 0 || parseInt(cell.mode, 10 ) === 0){
									title = $('<div><span>' + cell.title + '<span></div>');
									var sty = 'vNoChanges';
									if (parseInt(cell.mode, 10) > 0){
										sty = 'vPlus';
									}
									if (parseInt(cell.mode, 10) < 0){
										sty = 'vMinus';
									}
									title.addClass(sty);
								}else{
									title = $('<span>' + cell.title + '</span>');
								}
							}
							c.append(title);
							if (cell.href){
								title.wrap('<a href="' + cell.href + '" target="' + cell.target + '"></a>');
							}
							r.append(c);
							cnt++;
						}
					}
					t.append(r);
				});
				if (data.allowSearch){
					tar.find('div[id$=_content]').append(t);
				}else{
					tar.append(t);
				}
			},
			renderFormularRadioTable: function(tableIdx, parent, id, item){
				var t = $('<table cellpadding="0" cellspacing="0" border="0"></table>');
				var data = this.data;
				if (data.stylename){
					t.attr({'class': data.stylename});
				}
				var tar = this.target;
				tar.empty();
				var self = this;
				if (data.allowSearch){
					this._makeMenuBarAndContentShell();
					this._renderSearchFieldBar('searchWknIsinName');
				}
				if (data.columnOrder){
					var r = $('<tr></tr>');
					$(data.columnOrder).each(function(i){
						var c = $('<th class="thead thead' + i + '">' + this.header + '</th>');
						if (! isNaN(parseInt(data.columnOrder[i].order, 10))){
							var key = data.columnOrder[i].key;
							var order = data.columnOrder[i].order;
							if (order !== null){
								c.addClass('receiveClick');
							}
							if (order == 1){
								c.addClass('sortedUp');
							}
							if (order == 2){
								c.addClass('sortedDown');
							}
							c.bind('click', function(e){
								(function(ord, parent, d){
									ord = (ord + 1) % 3;
									if (d.handler){
										var phrase = null;
										if (parent.searchPhrase){
											phrase = parent.searchPhrase;
										}
										var url = AjaxURLManager.getUrlWithKey(d.handler, {'phrase': phrase, 'field': key, 'order': ord});
										$.getJSON(url, function(data, textStatus){
											JSONPanelContentRenderer.render(data, parent);
										});
									}
								})(order, self.parent, data);
							});
						}
						r.append(c);
					});
					t.append(r);
				}
				var rows = data.rows;
				if (data.pager){
					rows = this._getPagerPreparedList(rows, data.pager);
				}
				$(rows).each(function(i){
					r = $('<tr></tr>');
					if (i % 2 !== 0){
						r.addClass('odd');
					}
					if (this.special){
						r.addClass('special');
					}
					var checked = false;
					if (this.here){
						r.addClass('here');
						checked = true;
					}
					if (data.columnOrder){
						$(data.columnOrder).each(function(j){
							var k = this.key;
							var c = $('<td class="col col_' + j + ' col_' + j + '_' + i + '"></td>');
							var row = rows[i];
							var cell = rows[i][k]; // data.rows[i][k];
							var title;
							// binding row for mouseevent click
							if (row[data.pk]){
								(function(row, parent, d, item, tableIdx, rowIdx){
									c.bind('click', function(e){
										item.handlePrepareDataModelAndVerify(tableIdx, rowIdx);
									});
								})(row, parent, data, item, tableIdx, i);
								c.css({'cursor': 'pointer'});
								if (j == data.columnOrder.length - 1){
									c.addClass('priceColumn');
								}
							}
							if (cell.title.__datetime__){
								title = $('<span>' + $.formatDate(cell.title.value, $.lang()).middle  + '&nbsp;' + $.formatTime(cell.title.value).time + '</span>');
							}else{
								var t = cell.title;
								if (parseInt(cell.mode, 10) > 0 || parseInt(cell.mode, 10) < 0 || parseInt(cell.mode, 10) === 0){
									title = $('<div><span>' + t + '</span></div>');
									var sty = 'vNoChanges';
									if (parseInt(cell.mode, 10) > 0){
										sty = 'vPlus';
									}
									if (parseInt(cell.mode, 10) < 0){
										sty = 'vMinus';
									}
									title.addClass(sty);
								}else{
									title = $('<span>' + t + '</span>');
								}
								if (k == 'option'){
									t = $('<input type="radio" name="' + id + '" value="' + row[data.pk] + '" />');
									t.attr({'checked': checked});
									if (title.find('span').size() > 0){
										title.find('span').append(t);
									}else{
										title.append(t);
									}
								}
							}
							c.append(title);
							if (cell.href){
								title.wrap('<a href="' + cell.href + '" target="' + cell.target + '"></a>');
							}
							r.append(c);
						});
					}else{
						var cnt = 0;
						var x = function(row){
							c.bind('click', function(e){
								var m = MenuConfig[data.contextType](self.parent, row, e);
								m.init();
								m.show(e);
							});
						};
						for(var k in this){
							var c = $('<td class="col col_' + cnt + ' col_' + cnt + '_' + i + '"></td>');
							var row = rows[i];
							var cell = rows[i][k]; // data.rows[i][k];
							var title;
							// binding context menu
							if (data.contextType && this.contextActive){
								x(row);
								c.addClass('receiveClick');
							}
							if (cell.title.__datetime__){
								title = $('<span>' + $.formatDate(cell.title.value, $.lang()).middle  + '&nbsp;' + $.formatTime(cell.title.value).time + '</span>');
							}else{
								if (parseInt(cell.mode, 10) > 0 || parseInt(cell.mode, 10) < 0 || parseInt(cell.mode, 10) === 0){
									title = $('<div><span>' + cell.title + '<span></div>');
									var sty = 'vNoChanges';
									if (parseInt(cell.mode, 10) > 0){
										sty = 'vPlus';
									}
									if (parseInt(cell.mode, 10) < 0){
										sty = 'vMinus';
									}
									title.addClass(sty);
								}else{
									title = $('<span>' + cell.title + '</span>');
								}
							}
							c.append(title);
							if (cell.href){
								title.wrap('<a href="' + cell.href + '" target="' + cell.target + '"></a>');
							}
							r.append(c);
							cnt++;
						}
					}
					t.append(r);
				});
				if (data.allowSearch){
					tar.find('div[id$=_content]').append(t);
				}else{
					tar.append(t);
				}
			},
			_handleRowClick: function(column, row, type, parent, d){
				column.bind('click', function(e){
					e.preventDefault();
					e.stopPropagation();
					var data = parent.data;
					parent.urlParams.ex = 'false';
					parent.urlParams.ovn = 'false';
					data.express = false;
					data.overnight = false;
					if (type == 'ovCosts'){
						data.overnight = true;
						data.express = false;
						parent.urlParams.ovn = 'true';
						parent.urlParams.ex = 'false';
					}else if (type == 'exCosts'){
						data.overnight = false;
						parent.urlParams.ovn = 'false';
						data.express = true;
						parent.urlParams.ex = 'true';
					}
					data[d.pk] = row[d.pk];
					parent.data = data;
					parent.verifyData();
				});
			},
			_handleRowShoppingcartClick: function(scart, row, type, parent, d){
				scart.bind('click', function(e){
					e.preventDefault();
					e.stopPropagation();
					var data = parent.data, Machine;
					parent.urlParams.ex = 'false';
					parent.urlParams.ovn = 'false';
					data.express = false;
					data.overnight = false;
					if (type == 'ovCosts'){
						data.overnight = true;
						data.express = false;
						parent.urlParams.ovn = 'true';
						parent.urlParams.ex = 'false';
					}else if (type == 'exCosts'){
						data.overnight = false;
						parent.urlParams.ovn = 'false';
						data.express = true;
						parent.urlParams.ex = 'true';
					}
					data[d.pk] = row[d.pk];
					parent.data = data;
					if (typeof parent.verifyDataAndAddToShoppingcart == 'undefined'){
						if (typeof Sm_TabbedImageMode !== 'undefined'){
							Machine = Sm_TabbedImageMode;
						}else{
							Machine = SlotMachine;
						}
						parent = $.extend(parent, {
							verifyDataAndAddToShoppingcart: function(){
								var slot = slot || null;
								var self = this;
								var oldData = Machine.data;
								if (slot){
									Machine.data.changedSlot = slot.itemId;
								}
								var cbdr = Machine.onDataRequest;
								if (cbdr){
									cbdr.call(Machine, self, Machine.data);
								}
								var url = AjaxURLManager.getUrlWithKey('configarticle');
								//alter data and send it to cherrypy
								for (var i in this.data.slots){
									this.data.slots[i].currentItem = this.slots[i].currentItem;
								}
								$.ajax({
									type: 'post',
									url: url,
									data: {'content': encodeURIComponent($.toJson(Machine))},
									success: function(data, msg){self.verifyDataAndAddToShoppingcartRequestSuccess(data, msg, slot);},
									error: function(req, status, error){self.verifyDataRequestError(req, status, error, slot);}
								});
							},
							verifyDataAndAddToShoppingcartRequestSuccess: function(data, msg, slot){
								//eval('var data = ' + data);
								this.data = data;
								if (this.urlParams && this.urlParams.auf_id){
									this.urlParams.auf_id = data.auf_id;
								}
								if (this.onDataRequestSuccess){
									this.onDataRequestSuccess.call(this, slot, data);
								}
								this.slotUpdateCheck();
								$('div.prdConfTopWkShell').find('form').submit();
							}
						});
						parent.verifyDataAndAddToShoppingcart();
					}
				});
			}
		}
	);
/* << */


/* >> Slot machine tapped pages shopping cart info */
	//show the quick config and shopping cart info on tabbed config pages.
	ShowShoppingCartInfo = $.extend(
		$.clone(LLObject),
		{
			create: function(){
				var o = LLObject.create.call(this);
				return o;
			},
			update: function(data, quickInfo, scart, configurator){
				var qi, opts, machine = configurator || null;
				if ($('#slotMachine').length){
					qi = SharedTopProductQuickChoice_GC.create(machine);
				}else{
					qi = TopProductQuickChoice.create();
				}
				opts = {
					'title': data.productTitle,
					'data': data,
					'target': quickInfo,
					'slot': null,
					'onlyInfo': true
				};
				qi.init(opts);
			}
		}
	);
/* << */


/* >> Tapped pages handling */
	handlePageTabs = function(){
		var configType = window.FLYPI_CONFIGURATION_TYPE || null, configurator,
		urlParams, url, quickInfo, scart;
		if (configType == 'sm'){
			configurator = $('#slotMachine');
			if (!configurator.length){
				urlParams = Utils.getUrlParamsAsJson(window.location.href);
				if (!urlParams){
					urlParams = {
						auf_id: null,
						freeConfig: true
					};
					$.extend(urlParams, window.CONFIGURATOR_FALLBACK_DATA);
				}else if (!urlParams.auf_id){
					urlParams.freeConfig = true;
					$.extend(urlParams, window.CONFIGURATOR_FALLBACK_DATA);
				}
				url = AjaxURLManager.getUrlWithKey('configarticle', urlParams);
				quickInfo = $('#prdConfTopConfig');
				scart = $('div.prdConfTopWkShell');
				if (quickInfo.length && scart.length){
					$.getJSON(url, function(data, textStatus){
						var enable = false;
						if (typeof urlParams.freeConfig === 'undefined' || urlParams.freeConfig !== true){
							ScartPrep = ShoppingcartPreparer.create();
							ScartPrep.update(data);
							SLOTMACHINE_DATA_ON_TABBED_PAGES = data;
							if (data.auf_id){
								enable = true;
							}
							handleTemplateTab(enable);
							//ScartInfo = ShowShoppingCartInfo.create();
							//ScartInfo.update(data, quickInfo, scart, SlotMachine);
						}
						if (typeof CustFormats === 'undefined'){
							CustFormats = CustomFormats_GC.create(null);
						}
						CustFormats.update(data);
						LinkPreparer = PageLinkPreparer.create();
						LinkPreparer.update(data);
						AddOption = AdditionalOptions_GC.create(null);
						AddOption.makeShoppingCartOpts(data);
						TopImagePrep = TopImagePreparer.create();
						TopImagePrep.update(data);
					});
				}
			}
		}else if(configType == 'xxl' && $('.contentNavigationShell').length){
			configurator = $('#rowFilteredXxlConfigurator');
			if (!configurator.length){
				urlParams = Utils.getUrlParamsAsJson(window.location.href);
				url = AjaxURLManager.getUrlWithKey('xxlproduct', urlParams);
				quickInfo = $('#prdConfTopConfigXxl');
				scart = $('div.prdConfTopWkShell');
				if (quickInfo.size() > 0 && scart.size() > 0){
					$.getJSON(url, function(data, textStatus){
						SLOTMACHINE_DATA_ON_TABBED_PAGES = data;
						LinkPreparerXxl = PageLinkPreparerXxl.create();
						LinkPreparerXxl.update(data);
						ScartInfo = ShowShoppingCartInfo.create();
						ScartInfo.update(data, quickInfo, scart);
						ScartPrep = ShoppingcartPreparer.create();
						ScartPrep.update(data);
						TopImagePrep = TopImagePreparer.create();
						TopImagePrep.update(data);
						AddOptsXxl = AdditionalOptionsXxl.create();
						AddOptsXxl.update(data);
						/* todo: add handlers for tabbed pages */
					});
				}
			}
		}
	};
/* << */


/* >> Shared configurator select mode */
	/* > simple select box with prompt */
		SimpleSelectBoxWithPrompt = $.extend(
			$.clone(SimpleSelectBox),
			{
				create: function(opts){
					var o = SimpleSelectBox.create.call(this, opts);
					return o;
				},
				makeSelectLayout: function(){
					var name = this.defaults.data.name, pmt = this.defaults.data.prompt,
					cn = this.defaults.className, cb = this.defaults.onChangeCallback, self = this,
					lay = $(
						'<div class="' + cn + '">' +
							'<div class="productSelectPrompt">' + pmt + '</div>' +
							'<div class="productSelect">' +
								'<select name="' + name + '" id="' + name + '_select"></select>' +
							'</div>' +
						'</div>'
					);
					if (cb && typeof cb === 'function'){
						lay.find('select').bind('change', function(e){
							cb.call(self, $(this).val());
						});
					}
					return lay;
				}
			}
		);
	/* < */


	/* > slotmachine static select */
		SlotmachineSelectBox = $.extend(
			$.clone(SimpleSelectBoxWithPrompt),
			{
				create: function(opts){
					return SimpleSelectBoxWithPrompt.create.call(this, opts);
				},
				makeSelectLayout: function(){
					var name = this.defaults.data.name, pmt = this.defaults.data.prompt,
					cn = this.defaults.className, cb = this.defaults.onChangeCallback, self = this,
					lay = $(
							'<tr>' +
								'<td></td>' +
								'<td class="titleColumn">' +
									'<div class="slotTitle">' +
										'<span class="title">Produkt</span>' +
										'<span class="arrow">' +
											'<img width="1" height="1" border="0" alt="" src="/xist4c/px/spc.gif" />' +
										'</span>' +
									'</div>' +
								'</td>' +
								'<td></td>' +
							'</tr>' +
							'<tr>' +
							'<td class="bullet">' +
								'<div class="slotBullet slotBulletActive_hasSelection"></div>' +
							'</td>' +
							'<td class="' + name+ '_column selectColumn">' +
								'<div class="slotSelect">' +
									'<select name="' + name + '" id="' + name + '_select"></select>' +
								'</div>' +
							'</td>' +
							'<td class="info"></td>' +
						'</tr>'
					);
					if (cb && typeof cb === 'function'){
						lay.find('select').bind('change', function(e){
							cb.call(self, $(this).val());
						});
					}
					return lay;
				}
			}
		);
	/* < */


	/* > product select box */
		ProductSelectBox = $.extend(
			$.clone(SimpleSelectBoxWithPrompt),
			{
				create: function(opts){
					var o = SimpleSelectBoxWithPrompt.create.call(this, opts);
					return o;
				},
				makeSelectLayout: function(){
					var name = this.defaults.data.name, pmt = this.defaults.data.prompt,
					cn = this.defaults.className, cb = this.defaults.onChangeCallback, self = this, params,
					lay = $(
						'<div class="' + cn + '">' +
							'<table cellpadding="0" cellspacing="0" border="0" class="slotOuterTable">' +
								'<tr>' +
									'<td class="bullet">' +
										Utils.pixelAsString() +
									'</td>' +
									'<td class="control">' +
										'<div class="productSelectPrompt">' + pmt + '</div>' +
										'<div class="productSelect">' +
											'<select name="' + name + '" id="' + name + '_select"></select>' +
										'</div>' +
									'</td>' +
								'</tr>' +
							'</table>' +
						'</div>'
					);
					params = Utils.getUrlParamsAsJson();
					if (params && typeof params.activeBulletColor !== 'undefined'){
						lay.find('img').css({'background-color': '#' + params.activeBulletColor});
					}
					if (cb && typeof cb === 'function'){
						lay.find('select').bind('change', function(e){
							cb.call(self, $(this).val());
						});
					}
					return lay;
				},
				addOptions: function(tar, opts){
					var opt, decHint = this.makeOptionLayout('-1', $.lang('pleaseChoose')),
					self = this, params = Utils.getUrlParamsAsJson();
					tar.empty();
					tar.append(decHint);
					$(opts).each(function(i){
						opt = self.makeOptionLayout(this.value, this.title).clone();
						if (params && params.auf_id && params.auf_id.toString() === this.value.toString()){
							opt.attr({'selected': 'selected'});
						}
						tar.append(opt);
					});
				},
				make: function(mode){
					var data = this.defaults.data, target = this.defaults.target, lay, opts,
							cb = this.defaults.onAfterFinishCallback;
					if (data){
						opts = data.items;
						lay = this.makeSelectLayout();
						this.addOptions(lay.find('select'), opts);
						if (target){
							if (mode === 'append'){
								target.append(lay);
							}else{
								target.empty().append(lay);
							}
							this.domel = lay;
						}
						if (cb && typeof cb === 'function'){
							cb.call(this);
						}
					}
				}
			}
		);
	/* < */

	/* > shipping options select box */
		ShippingOptionsSelectBox = $.extend(
			$.clone(ProductSelectBox),
			{
				create: function(opts){
					var o = ProductSelectBox.create.call(this, opts);
					return o;
				},
				addOptions: function(tar, opts){
					var opt, self = this, params = Utils.getUrlParamsAsJson();
					tar.empty();
					$(opts).each(function(i){
						opt = self.makeOptionLayout(this.value, this.title).clone();
						if (this.here){
							delete this.here;
							opt.attr({'selected': true});
						}
						tar.append(opt);
					});
				}
			}
		);
	/* < */

	/* > slotmachine shipping options select box */
		SlotmachineShippingOptionsSelectBox = $.extend(
			$.clone(ShippingOptionsSelectBox),
			{
				create: function(opts){
					var o = ShippingOptionsSelectBox.create.call(this, opts);
					return o;
				},
				makeSelectLayout: function(){
					var name = this.defaults.data.name, pmt = this.defaults.data.prompt,
					cn = this.defaults.className, cb = this.defaults.onChangeCallback, self = this,
					lay = $(
						'<div class="optionOuter optionOuterSelect">' +
							'<table cellpadding="0" cellspacing="0" border="0">' +
								'<tr class="' + cn + '">' +
									'<td></td>' +
									'<td id="' + name + '_titleColumn" class="titleColumn">' +
										'<div class="slotTitle">' +
										'<span class="pmt" style="font-weight: bold;">' + pmt + '<span class="price"></span></span>' +
											'<span class="arrow">' + Utils.pixelAsString() + '</span>' +
										'</div>' +
									'</td>' +
									'<td></td>' +
								'</tr>' +
								'<tr>' +
									'<td class="bullet"><div class="slotBullet"></div></td>' +
									'<td class="' + name+ '_column selectColumn">' +
										'<div class="slotSelect field">' +
											'<select name="' + name + '" id="' + name + '_select"></select>' +
										'</div>' +
									'</td>' +
									'<td class="info"><a href="#" class="slotInfo" target="_blank"></a></td>' +
								'</tr>' +
							'</table>' +
						'</div>'
					);
					if (cb && typeof cb === 'function'){
						lay.find('select').bind('change', function(e){
							cb.call(self, $(this).val());
						});
					}
					return lay;
				}
			}
		);
	/* < */

	/* > slotmachine shipping options select box extension */
		SlotmachineShippingOptionsSelectBoxExtension = $.extend(
			$.clone(SlotmachineShippingOptionsSelectBox),
			{
				create: function(opts){
					var o = SlotmachineShippingOptionsSelectBox.create.call(this, opts);
					return o;
				},
				makeSelectLayout: function(){
					var name = this.defaults.data.name, pmt = this.defaults.data.prompt,
					cn = this.defaults.className, cb = this.defaults.onChangeCallback, self = this,
					lay = $(
						'<tr class="' + cn + '">' +
							'<td></td>' +
							'<td id="' + name + '_titleColumn" class="titleColumn">' +
								'<div class="slotTitle">' +
									'<span class="pmt" style="font-weight: bold;">' + pmt + '<span class="price"></span></span>' +
									'<span class="arrow">' + Utils.pixelAsString() + '</span>' +
								'</div>' +
							'</td>' +
							'<td></td>' +
						'</tr>' +
						'<tr>' +
							'<td class="bullet"><div class="slotBullet"></div></td>' +
							'<td class="' + name+ '_column selectColumn">' +
								'<div class="slotSelect field">' +
									'<select name="' + name + '" id="' + name + '_select"></select>' +
								'</div>' +
							'</td>' +
							'<td class="info"><a href="#" class="slotInfo" target="_blank"></a></td>' +
						'</tr>'
					);
					if (cb && typeof cb === 'function'){
						lay.find('select').bind('change', function(e){
							cb.call(self, $(this).val());
						});
					}
					return lay;
				}
			}
		);
	/* < */

	/* >> Shared Slot machine select mode (inherit SlotMachineSelectMode)*/
		SharedSlotMachineSelectMode = $.extend(
			$.clone(SlotMachineSelectMode),
			{
				makeShell: function(target){
					var shell = $(
						'<div id="genericConfiguratorOuter">' +
							'<div id="genericConfiguratorMainBg">' +
								'<div class="genericConfiguratorShell">' +
								'</div>' +
							'</div>' +
						'</div>'
					);
					target.append(shell);
				}
			}
		);
	/* << */

	/* >> Slot machine select for sharing (inherit SlotMachineSelectModeSlot) */
		SharedSlotMachineSelectModeSlot = $.extend(
			$.clone(SlotMachineSelectModeSlot),
			{
				create: function(title, currentItem){
					return SlotMachineSelectModeSlot.create.call(this, title, currentItem);
				},
				makeSlotLayout: function(){
					var locked = this.isLocked();
					var slot = $(
						'<div id="' + this.id + '_slotFloatOuter" class="slotFloatOuter">' +
							'<table cellpadding="0" cellspacing="0" border="0" class="slotOuterTable">' +
								'<tr>' +
									'<td class="bullet">' +
										Utils.pixelAsString() +
									'</td>' +
									'<td class="control">' +
										'<div id="' + this.id + '_titleOuter" class="titleOuter">' +
											'<div class="slotTitle">' +
												'<span class="title">' + this.title + '</span>' +
											'</div>' +
										'</div>' +
										'<div class="' + this.id + '_selectOuter selectOuter">' +
											'<div class="slotSelect">' +
												'<select name="' + this.id + '_select" id="' + this.id + '_select"></select>' +
											'</div>' +
										'</div>' +
									'</td>' +
								'</tr>' +
							'</table>' +
						'</div>'
					);
					if (locked){
						slot.find('.slotBullet').addClass('slotLocked').end().find('select').attr({'disabled': 'disabled'});
					}
					var bulletCol = slot.find('.bullet');
					var params = Utils.getUrlParamsAsJson();
					if (params && typeof params.passiveBulletColor !== 'undefined'){
						bulletCol.find('img').css({'background-color': '#' + params.passiveBulletColor});
					}
					if (this.currentItem > 0){
						bulletCol.addClass('bulletActive');
						if (params && typeof params.activeBulletColor !== 'undefined'){
							bulletCol.find('img').css({'background-color': '#' + params.activeBulletColor});
						}
					}
					var self = this;
					slot.find('select').bind('change', function(e){
						var cb = self.configurator.defaults.onSlotAction;
						if (cb && typeof cb == 'function'){
							cb.call(this);
						}
						var select = $(this);
						var value = select.val();
						self.data.currentItem = self.currentItem = 0;
						select.find('option').each(function(i){
							if ($(this).attr('value') == value){
								self.data.currentItem = self.currentItem = i;
							}
						});

						self.configurator.data.art_id = null;
						self.configurator.data[self.configurator.data.pk] = null;
						self.configurator.verifyData(self);
					});
					this.domel = slot;
					return slot;
				},
				make: function(target){
					if (target){
						var slotLay = this.makeSlotLayout();
						target = target.find('div.genericConfiguratorShell');
						target.append(slotLay);
						this.appendItemsToSlot();
						this.selectCurrentItem();
						var self = this;
					}
				},
				update: function(slotData){
					this.items = [];
					this.initMode = true;
					this.data = slotData;
					this.currentItem = slotData.currentItem;
					$('#' + this.id + '_select').empty();
					$('#' + this.id + '_titleOuter .slotTitle .title').text(slotData.title);
					var ready = false;
					var params = Utils.getUrlParamsAsJson();
					var bulletCol = $('#' + this.id + '_slotFloatOuter').find('.bullet');
					if (params && typeof params.passiveBulletColor !== 'undefined'){
						bulletCol.find('img').css({'background-color': '#' + params.passiveBulletColor});
					}
					if (this.currentItem > 0){
						ready = true;
						if (params && typeof params.activeBulletColor !== 'undefined'){
							bulletCol.find('img').css({'background-color': '#' + params.activeBulletColor});
						}
					}else{
						ready = false;
						bulletCol.find('img').css({'background-color': null});
					}
					bulletCol.toggleClass('bulletActive', ready);
					var self = this;
					var slotItemType = this.configurator.defaults.slotItemType;
					$(slotData.items).each(function(i){
						if (this.type == slotItemType){
							var slotItem = window[slotItemType].create(this.title, this.value);
							slotItem.id = self.id + '_slotItem_' + i;
							slotItem.itemCnt = i;
							slotItem.data = this;
							slotItem.slot = self;
							slotItem.width = self.width;
							self.appendItem(slotItem);
						}
					});
					this.appendItemsToSlot();
					this.selectCurrentItem();
				}
			}
		);
	/* << */

	/* >> Shared additional options generic configurator compatible*/
		SharedAdditionalOptions_GC = $.extend(
			$.clone(AdditionalOptions_GC),
			{
				options: null,
				create: function(configurator){
					var o = AdditionalOptions_GC.create.call(this, configurator);
					o.optsContainer = $('#addOptions');
					return o;
				},
				update: function(data){
					var optsContainer = this.optsContainer;
					optsContainer.empty();
					var self = this;
					if (data.options.length > 0){
						$(data.options).each(function(i){
							if (this.type == 'radio' || this.type == 'select'){
								var type = this.type, option = this;
								$(this.items).each(function(j){
										if (type == 'select'){
											this.prompt = this.content;
										}
										optsContainer.append(self.makeOption($.extend(this, {'type': type}), j + '_' + i));
								});
							}else{
								optsContainer.append(self.makeOption(this, i));
							}
						});
						self.makeShoppingCartOpts(data);
					}else{
						optsContainer.append(
							'<div class="optionOuter">' +
								'<div class="pmt">Keine verfügbar.</div>' +
							'</div>'
						);
					}
					$(data.options).each(function(i){
							if (this.type == 'radio' || this.type == 'select'){
								var type = this.type;
								$(this.items).each(function(j){
									if (this.here){
										var id = 'opt_' + j + '_' + i;
										$('#' + id).attr('checked', 'checked');
									}
								});
							}else{
								if (this.here){
									var id = 'opt_' + i;
									$('#' + id).attr('checked', 'checked');
								}
							}
					});
				},
				makeShoppingCartOpts: function(data){
					var container = this.scOptsContainer;
					container.empty();
					$(data.options).each(function(i){
						if (this.type == 'text'){
							if (this.value !== ''){
								container.append('<input type="hidden" name="' + this.name + '" value="' + this.value + '"/>');
							}
						}else if(this.type == 'checkbox'){
							if (this.here){
								container.append('<input type="hidden" name="' + this.name + '" value="opt_' + this.value + '"/>');
							}
						}else if(this.type == 'radio' || this.type == 'select'){
							$(this.items).each(function(j){
								if (this.here){
									container.append('<input type="hidden" name="' + this.name + '" value="opt_' + this.value + '"/>');
								}
							});
						}
					});
				},
				makeOption: function(data, idx){
					var o;
					if (data.type === 'text'){
						o = $(
							'<div class="optionOuter">' +
								'<table cellpadding="0" cellspacing="0" border="0">' +
									'<tr>' +
										'<td colspan="2">' +
											'<div class="pmt">' + data.prompt + '</div>' +
											'<div class="field"></div>' +
										'</td>' +
									'</tr>' +
								'</table>' +
							'</div>'
						);
					}else{
						o = $(
							'<div class="optionOuter">' +
								'<table cellpadding="0" cellspacing="0" border="0">' +
									'<tr>' +
										'<td>' +
											'<div class="field"></div>' +
										'</td>' +
										'<td>' +
											'<div class="pmt">' + data.prompt + '</div>' +
										'</td>' +
									'</tr>' +
								'</table>' +
							'</div>'
						);
					}
					o.find('.field').append(this.getField(data, idx));
					return o;
				},
				getField: function(data, idx){
					var optIdPfx = 'opt_', f;
					switch (data.type){
						case 'select':
							// use radios instead select
							f = this.radio(data);
							f.attr('id', optIdPfx + idx);
							return f;
						case 'checkbox':
							f = this.checkbox(data);
							f.attr('id', optIdPfx + idx);
							return f;
						case 'radio':
							f = this.radio(data);
							f.attr('id', optIdPfx + idx);
							return f;
						case 'text':
							f = this.text(data);
							f.find(':input').attr('id', optIdPfx + idx);
							return f;
					}
					return false;
				},
				select: function(data){
					var f = $('<select></select>').attr({'name': data.name});
					$(data.items).each(function(i){
						var o = $('<option></option>').val(this.value).text(this.content);
						if (this.here){
							o.attr('selected', 'selected');
						}
						f.append(o);
					});
					var self = this;
					f.bind('change', function(e){
						var items = GenericConfiguratorSelect.data.options[self.getOptId(this.id)].items;
						var elm = this;
						$(items).each(function(i){
							if (this.value == $(elm).val()){
								this.here = true;
							}else{
								this.here = false;
							}
						});
						GenericConfiguratorSelect.data.options[self.getOptId(this.id)].items = items;
						self.verifyData();
					});
					return f;
				},
				checkbox: function(data){
					var f = $('<input/>').attr({'type': data.type, 'name': data.name, 'value': data.value});
					var self = this;
					f.bind('click', function(e){
						var here = $(this).attr('checked');
						GenericConfiguratorSelect.data.options[self.getOptId(this.id)].here = here;
						self.verifyData();
					});
					return f;
				},
				radio: function(data){
					var f = $('<input/>').attr({'type': 'radio', 'name': data.name, 'value': data.value});
					var self = this;
					f.bind('click', function(e){
						var items = GenericConfiguratorSelect.data.options[self.getOptId(this.id)].items;
						var elm = this;
						$(items).each(function(i){
							if (this.value == $(elm).val()){
								this.here = true;
							}else{
								this.here = false;
							}
						});
						GenericConfiguratorSelect.data.options[self.getOptId(this.id)].items = items;
						self.verifyData();
					});
					return f;
				},
				text: function(data){
					var f =  $(
						'<div class="textFieldAndButtonOuter">' +
							'<div class="fieldOuter"><input type="text" name="' + data.name + '" value="' + data.value + '"/></div>' +
							'<div class="textFieldSaveButton"></div>' +
						'</div>'
					);
					// This is a static text field char limitation and should be solved
					// at the WAF administration.
					f.find(':input').attr({'maxlength': 5});
					var self = this;
					f.find('.textFieldSaveButton').bind('click', function(e){
						var field = $(this).prev('.fieldOuter').find(':input');
						var id = field.attr('id');
						GenericConfiguratorSelect.data.options[self.getOptId(id)].value = field.val();
						self.verifyData();
					});
					return f;
				},
				verifyData: function(){
					GenericConfiguratorSelect.verifyData();
				}
			}
		);
	/* << */

	/* >> special isolated jsPager item */
	 SpecialJsPagerItem = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {
						target: null,
						itemId: 0,
						content: null
					};
					if (opts && typeof opts === 'object'){
						o.defaults = $.extend(o.defaults, opts);
					}
					return o;
				},
				makeItemLayout: function(){
					var lay, id;
					id = 'jsPager1' + this.defaults.itemId;
					lay = $(
						'<div class="jsPagerItem jsPagerItemSharedConfigurator" id="' + id + '">' +
							'<div class="jsPagerContent"></div>' +
						'</div>'
					);
				},
				make: function(){
					var lay = this.makeItemLayout(), def = this.defaults;
					lay.find('.jsPagerContent').append(def.content);
					if (def.target){
						def.target.append(lay);
					}
				}
			}
		);
	/* << */

	/* >> Shaerd configurator top product quick choice generic configurator compatible*/
		SharedTopProductQuickChoice_GC = $.extend(
			$.clone(TopProductQuickChoice_GC),
			{
				create: function(configurator){
					var o = TopProductQuickChoice.create.call(this);
					o.configurator = configurator;
					return o;
				},
				makeTableWithTitle: function(){
					var t = this.target;
					var title = this.opts.title || null;
					var subtitle = this.opts.data.subTitle || null;
					this.subtitle = subtitle;
					var table = $(
						'<div class="sharedConfProductInfo">' +
						'</div>'
					);
					if (title){
						var titleElm = $(
							'<div class="topTitle">' + title + '</div>'
						);
						if (subtitle){
							titleElm.addClass('withSub');
						}
						table.append(titleElm);
					}
					if (subtitle){
						table.append(
							'<div class="subtitle">' + subtitle + '</div>'
						);
					}

					t.empty().append(table);
				},
				makeRowLayout: function(){
					var lay = $(
						'<div class="rowOuter">' +
							'<div class="title"></div>' +
							'<div class="value"></div>' +
						'</div>'
					);
					return lay;
				},
				makeRowsWithBindings: function(){
					var slots = this.configurator.slots;
					var infoText = this.configurator.data.infoText;
					var table = this.target.find('.sharedConfProductInfo');
					var self = this;
					$(slots).each(function(i){
						var slot = this;
						var row = self.makeRowLayout();
						row.find('.title').html(slot.title);
						var value = row.find('.value');
						var info = slot.items[slot.currentItem].title;
						var addInfoText = slot.items[slot.currentItem].data.addInfoText;
						if (addInfoText){
							info += ' (' + addInfoText + ')';
						}
						value.html(info);
						table.append(row);
					});
					var infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				},
				makeRowsForInfo: function(){
					var slots = this.configurator.data.slots;
					var infoText = this.configurator.data.infoText;
					var table = this.target.find('.sharedConfProductInfo');
					var self = this;
					if (slots){
						$(slots).each(function(i){
							var slot = this;
							var row = self.makeRowLayout();
							row.find('.title').html(slot.title);
							var value = row.find('.value');
							for (var j in slot.items){
								if (j == slot.currentItem){
									var info = slot.items[j].title;
									var addInfoText = slot.items[j].addInfoText;
									if (addInfoText){
										info += ' (' + addInfoText + ')';
									}
									value.html(info);
								}
							}
							table.append(row);
						});
					}
					var infoRow = this.getFinalInfoRow(infoText);
					if (infoRow){
						table.append(infoRow);
					}
				},
				getRowClone: function(){
					var r = $(
						'<div class="rowOuter">' +
							'<div class="title"></div>' +
							'<div class="value"></div>' +
						'</div>'
					);
					return r.clone();
				},
				getFinalInfoRow: function(infoText){
					if (infoText){
						var row = this.getRowClone();
						row.find('.title').addClass('infoTextTitle').html($.lang('infoTextPmt'));
						row.find('.value').addClass('valueWrapped').append('<div class="infoText">' + infoText + '</div>');
						return row;
					}
					return null;
				},
				update: function(slot, data){
					var subtitle = this.subtitle;
					if (slot){
						var elm = $('#prdConfTopConfig');
						if (elm.size() > 0){
							var index = 2;
							if (subtitle){
								index += 1;
							}
							var valCol = elm.find('div.rowOuter:nth-child(' + (slot.itemId + index) + ')').find('.value');
							var info = slot.items[slot.currentItem].title;
							var addInfoText = slot.items[slot.currentItem].data.addInfoText;
							if (addInfoText){
								info += ' (' + addInfoText + ')';
							}
							valCol.html(info);
						}
					}
					var infoText = data.infoText;
					if (infoText){
						if (this.target.find('.value .infoText').size() > 0){
							this.target.find('.value .infoText').addClass('valueWrapped').html(infoText);
						}else{
							var infoRow = this.getFinalInfoRow(infoText);
							if (infoRow){
								$('.sharedConfProductInfo').append(infoRow);
							}
						}
					}else{
						this.target.find('.value .infoText').parents('.rowOuter').remove();
					}
				}
			}
		);
	/* << */
/* << */


/* >> Shared configurator select mode initialization */
	// starts the slot machine for shared implementation
	GenericConfiguratorForSharing = function(){
		var params = Utils.getUrlParamsAsJson(), sharedId = null, url, scSymbolColor;
		scSymbolColor = params.shoppingcartSymbolColor;
		if (scSymbolColor){
			$('#shoppingcartOuter .sum input').css({'background-color': '#' + scSymbolColor});
		}
		sharedId = params.sharedId;
		if (sharedId){
			url = AjaxURLManager.getUrlWithKey('sharedproductselect', {
				'sharedId': sharedId,
				'lang': $.lang()
			});
			$.getJSON(url, function(data, textStatus){
				$('#prdConfTopWk_sharedId').val(sharedId);
				$('.prdConfTopWkShell').hide();
				ProductBox = ProductSelectBox.create({
					target: $('#productSelect'),
					className: 'productSelectBox',
					data: data,
					onChangeCallback: function(value){
						var params = Utils.getUrlParamsAsJson() || {},
						loc = window.location.href, rex = /\?/;
						if (rex.test(loc)){
							loc = loc.substring(0, loc.search(rex));
						}
						params.auf_id = value;
						if (value === '-1'){
							delete params.auf_id;
						}
						window.location.href = loc + Utils.getUrlParamsFromJson(params);
					},
					onAfterFinishCallback: function(){
						GenericConfiguratorSelect = SharedSlotMachineSelectMode.create();
						QuickChoice = SharedTopProductQuickChoice_GC.create(GenericConfiguratorSelect);
						ScartPreparer = ShoppingcartPreparer.create();
						AddOptions = SharedAdditionalOptions_GC.create(GenericConfiguratorSelect);
						GenericConfiguratorSelect.init(
							{
								'target': $('#genericConfiguratorSelect'),
								'dataType': 'SharedSlotMachineSelectMode',
								'slotType': 'SharedSlotMachineSelectModeSlot',
								'slotItemType': 'SlotMachineSelectModeSlotItem',
								'ajaxHandler': 'configarticle',
								'onBeforeInit': function(){},
								'onInitDataReceive': function(data){
									updateDataTypes(data, 'sharedSelect');
									if (data.overnight){
										this.urlParams.ovn = true;
									}
								},
								'onAfterInit': function(data){
									var opts = {
										'title': data.productTitle,
										'data': data,
										'target': $('#prdConfTopConfig'),
										'slot': this
									};
									QuickChoice.init(opts);
									ScartPreparer.update(data);
									AddOptions.update(data);
									$('.prdConfTopWkShell form').attr({'action': '/Warenkorb.htm'});
								},
								'onAfterSlotCatch': function(slot){},
								'onAfterSlotsUpdate': function(){},
								'onSlotAction': function(eventElement){},
								'onDataRequest': function(slot, oldData){},
								'onDataRequestSuccess': function(slot, data){
									var machine = this;
									updateDataTypes(data, 'sharedSelect');
									// update auf_id.
									if (this.urlParams && this.urlParams.auf_id){
										this.urlParams.auf_id = data.auf_id;
									}
									ScartPreparer.update(data);
									AddOptions.update(data);
									QuickChoice.update(slot, data);
									if (data.auf_id){
										var url = AjaxURLManager.getUrlWithKey('get_shipping_options', {'auf_id': data.auf_id});
										$.getJSON(url, function(data, textStatus){
											SOSelectBox = ShippingOptionsSelectBox.create({
												target: $('#shippingOptionsSelect'),
												className: 'productSelectBox',
												data: data,
												onChangeCallback: function(value){
													var self = this;
													machine.data.express = false;
													machine.data.overnight = false;
													if (value !== 'standard'){
														machine.data[value] = true;
													}
													machine.verifyData();
												},
												onAfterFinishCallback: function(){
													$(this.defaults.data.items).each(function(i){
														if (typeof machine.data[this.value] !== 'undefined' && machine.data[this.value]){
															this.here = true;
														}
													});
													this.addOptions(this.defaults.target.find('select'), this.defaults.data.items);
												}
											});
											SOSelectBox.make();
										});
									}else{
										$('#shippingOptionsSelect').empty();
									}
								}
							}
						);
						$('#resetButton').bind('click', function(e){
							window.location.reload();
						});
					}
				});
				ProductBox.make();
			});
		}
	};
/* << */


// >> Display pilot configurator
	// > Media gallery
		DisplayPilotMediaGallery = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {
						target: null,
						data: null,
						ajaxHandler: 'mediagallery',
						detailViewAreaProps: {
							left: 1,
							top: 1,
							width: 433,
							height: 433
						},
						itemContainerProps: {
							left: 10,
							top: 445,
							width: 411,
							height: 62,
							zIndex: 10000,
							overflow: 'hidden',
							whiteSpace: 'nowrap',
							background: '#e4e3e2'
						},
						enableZoom: true,
						zoomFactor: 3
					};
					o.items = [];
					if(Utils.isObject(opts)){
						$.extend(o.defaults, opts);
					}
					return o;
				},
				makeDetailViewLayout: function(){
					var lay = $(
						'<div id ="display_pilot_media_gallery_detail_view" class="display_pilot_media_gallery_detail_view"></div>'
					);
					lay.css(this.defaults.detailViewAreaProps);
					return lay;
				},
				makeItemsContainerLayout: function(){
					var lay = $(
						'<div class="display_pilot_media_gallery_items_container"></div>'
					);
					lay.css(this.defaults.itemContainerProps);
					return lay;
				},
				activateFirstItem: function(){
					if (this.items.length){
						this.items[0].activate();
					}
				},
				each: function(callback){
					var k, ret;
					for (k in this.items){
						ret = callback.call(this.items[k], k);
						if (typeof(ret) !== 'undefined'){
							return ret;
						}
					}
					return null;
				},
				make: function(){
					var target = this.defaults.target, dv = this.makeDetailViewLayout(), cfd = window.CONFIGURATOR_FALLBACK_DATA,
					params = Utils.getUrlParamsAsJson(), url, self = this;
					ic = this.makeItemsContainerLayout();
					if (target && target.length){
						target.append(dv, ic);
					}

					if ((!params || !params.auf_id) && cfd.auf_id){
						params = {};
						params.auf_id = cfd.auf_id;
					}
					if (params && params.auf_id){
						url = AjaxURLManager.getUrlWithKey('mediagallery', {
							auf_id: params.auf_id
						});
						$.getJSON(url, function(data, textStatus){
							var i, item, MediaItem, Scroller;
							if (data.type && data.type === 'DisplayPilotMediaGallery'){
								for (i = 0; i < data.items.length; i+=1){
									item = data.items[i];
									if (item.type === 'imageItem'){
										MediaItem = DisplayPilotMediaGalleryItem.create({
											target: $('.display_pilot_media_gallery_items_container'),
											targetLarge: $('.display_pilot_media_gallery_detail_view'),
											parent: self,
											data: item
										});
									}else{
										MediaItem = DisplayPilotMediaGalleryVideoItem.create({
											target: $('.display_pilot_media_gallery_items_container'),
											targetLarge: $('.display_pilot_media_gallery_detail_view'),
											parent: self,
											data: item
										});
									}
									MediaItem.make();
									self.items.push(MediaItem);
								}
								self.activateFirstItem();
							}
							Scroller = ScrollBar.create({
								target: $('.display_pilot_media_gallery_items_container'),
								orientation: 'x',
								scrollerHeight: 10,
								scrollerWidth: 10,
								arrowHeight: 10,
								arrowWidth: 20,
								arrowMoveIn: 4,
								sliderCapsPadding: 4,
								stepSize: 38,
								ignoreTargetPosition: false
							});
						});
					}
				}
			}
		);

		DisplayPilotMediaGalleryItem = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {
						target: null,
						targetLarge: null,
						parent: null,
						data: null
					};
					o.domel = null;
					o.here = null;
					if(Utils.isObject(opts)){
						$.extend(o.defaults, opts);
					}
					return o;
				},
				makeItemLayout: function(){
					var self = this, lay = $(
						'<div class="galleryItem galleryItemImage"></div>'
					);
					lay.bind('click', function(e){
						e.preventDefault();
						e.stopPropagation();
						self.handleItemClick(e);
					});
					return lay;
				},
				activate: function(){
					var targetLarge = this.defaults.targetLarge, data = this.defaults.data, parentOpts = this.defaults.parent.defaults,
					magnifier, zoomArea;
					this.domel.addClass('galleryItemHere');
					if (targetLarge.length && data.large){
						targetLarge.css({
							backgroundImage: 'url(' + data.large.src + ')'
						});
					}
					this.here = true;
					if (parentOpts.enableZoom && data.zoom){
						magnifier = $('<div class="display_pilot_media_gallery_magnifier"></div>');
						zoomArea = $(
							'<div class="display_pilot_media_gallery_zoom">' +
								'<img src="' + data.zoom.src + '" width="' + data.zoom.width + '" height="' + data.zoom.height + '"/>' +
							'</div>'
						);
						targetLarge.empty().append(magnifier);
						targetLarge.append(zoomArea);
						zoomArea.css({
							width: parentOpts.detailViewAreaProps.width,
							height: parentOpts.detailViewAreaProps.height
						}).scrollLeft(0).scrollTop(0);
						magnifier.css({
							width: parentOpts.detailViewAreaProps.width / parentOpts.zoomFactor,
							height: parentOpts.detailViewAreaProps.height / parentOpts.zoomFactor
						});
						this.handleMagnifier(magnifier, zoomArea, targetLarge);
					}else{
						targetLarge.empty();
					}
				},
				handleMagnifier: function(magnifier, zoomArea, containment){
					var parentOpts = this.defaults.parent.defaults;
					containment.bind('mouseenter', function(e){
						magnifier.show();
						zoomArea.show();
					}).bind('mouseleave', function(e){
						magnifier.hide();
						zoomArea.hide();
					}).bind('mousemove', function(e){
						var x = e.pageX - $(this).offset().left,
						y = e.pageY - $(this).offset().top,
						magnifierCenterX = magnifier.width() / 2,
						magnifierCenterY = magnifier.height() / 2,
						left, top, magPos;
						if(x - magnifierCenterX >= 0 && x + magnifierCenterX <= $(this).width()){
							left = x - magnifierCenterX;
						}else if(x - magnifierCenterX < 0){
							left = 0;
						}else if(x + magnifierCenterX > $(this).width()){
							left = $(this).width() - magnifierCenterX * 2;
						}
						if(y - magnifierCenterY >= 0 && y + magnifierCenterY <= $(this).height()){
							top = y - magnifierCenterY;
						}else if(y - magnifierCenterY < 0){
							top = 0;
						}else if(y + magnifierCenterY > $(this).height()){
							top = $(this).height() - magnifierCenterY * 2;
						}
						if (left >= 0 && top >= 0){
							magnifier.css({
								left: left,
								top: top,
								cursor: 'crosshair'
							});
							zoomArea.scrollLeft(left * parentOpts.zoomFactor).scrollTop(top * parentOpts.zoomFactor);
						}
					});
				},
				deactivate: function(){
					this.domel.removeClass('galleryItemHere');
					this.here = false;
				},
				handleItemClick: function(e){
					var items = this.defaults.parent.items, i, item, currItem;
					if (items.length){
						for (i = 0; i < items.length; i+=1){
							item = items[i];
							if (item === this){
								currItem = item;
							}else{
								item.deactivate();
							}
						}
						currItem.activate();
					}
				},
				make: function(){
					var target = this.defaults.target, item, data = this.defaults.data;
					if (target.length){
						item = this.makeItemLayout();
						item.css({
							backgroundImage: 'url(' + data.thumbnail.src + ')'
						});
						target.append(item);
						this.domel = item;
					}
				}
			}
		);

		DisplayPilotMediaGalleryVideoItem = $.extend(
			$.clone(DisplayPilotMediaGalleryItem),
			{
				create: function(opts){
					var o = DisplayPilotMediaGalleryItem.create.call(this, opts);
					return o;
				},
				makeItemLayout: function(){
					var self = this, lay = $(
						'<div class="galleryItem galleryItemVideo"></div>'
					);
					lay.bind('click', function(e){
						e.preventDefault();
						e.stopPropagation();
						self.handleItemClick(e);
					});
					return lay;
				},
				activate: function(){
					var targetLarge = this.defaults.targetLarge, data = this.defaults.data,
					flashvars, params, attributes;
					this.domel.addClass('galleryItemHere');
					if (targetLarge.length && data.large){
						flashvars = {
							file: data.large.src,
							autostart: 'true'
						};
						params = {
							allowfullscreen: 'true',
							allowscriptaccess: 'always'
						};
						attributes = {
						};
						targetLarge.css({
							backgroundImage: 'none'
						});
						targetLarge.empty().append('<div id="display_pilot_video"></div>');
						swfobject.embedSWF(
							'/xist4c/web/mediaplayer/player-licensed.swf',
							'display_pilot_video',
							433,
							433,
							'9.0.0',
							null,
							flashvars,
							params,
							attributes
						);
					}
					this.here = true;
				},
				deactivate: function(){
					var targetLarge = this.defaults.targetLarge;
					this.domel.removeClass('galleryItemHere');
					this.here = false;
					if (targetLarge.length){
						targetLarge.empty();
					}
				}
			}
		);
	// <

	// > Customer format handler to use with generic configurator
		CustomerFormatHandler = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {
						target: null,
						machine: null
					};
					if (Utils.isObject(opts)){
						$.extend(o.defaults, opts);
					}
					return o;
				},
				makeVariantLayout: function(pmt){
					var name = 'variant';
					var select = $('<select name="' + name + '" id="customerSizeVariant"/>');
					var wl = $(
						'<table cellpadding="0" cellspacing="0" border="0" class="customerVariant">' +
							'<tr>' +
								'<td class="pmt">' +
									pmt + ':' +
								'</td>' +
								'<td class="field">' +
								'</td>' +
							'</tr>' +
						'</table>'
					);
					var self = this;
					select.bind('change', function(e){
						var data = StepFilteredConfigurator.data;
						var stepId = self.parent.itemId;
						var opts = self.data.options.items;
						var elm = this;
						$(opts).each(function(i){
							var value = this.value;
							if (value == $(elm).val()){
								data.steps[stepId].items[1].options.items[i].here = true;
							}else{
								data.steps[stepId].items[1].options.items[i].here = false;
							}
						});
						StepFilteredConfigurator.data = data;
						self.handlePrepareDataModelAndVerify();
					});
					wl.find('.field').append(select);
					return wl;
				},
				makeOptionLayout: function(opt){
					var o = $(
						'<option value="' + opt.value + '">' + opt.title + '</option>'
					);
					return o;
				},
				makeButtonLayout: function(){
					var b = $(
						'<input type="image" src="/xist4c/px/spc.gif" class="button formatSaveButton" id="formatSaveButton" />'
					);
					return b;
				},
				makeSizeLayout: function(pmt, hint, mode){
					var name = 'customerWidth';
					if (mode == 'height'){
						name = 'customerHeight';
					}
					var input = $('<input type="text" name="' + name + '" value="" id="' + name + '"/>');
					var self = this;
					if (hint){
						hint = '(max. ' + hint + ' mm)';
					}else{
						hint = '';
					}
					var sl = $(
						'<table cellpadding="0" cellspacing="0" border="0" class="customerSize">' +
							'<tr>' +
								'<td class="pmt">' +
									pmt + ':' +
								'</td>' +
								'<td class="field">' +
									'<div class="hint">' + hint + '</div>' +
								'</td>' +
							'</tr>' +
						'</table>'
					);
					sl.find('.field').prepend(input);
					return sl;
				},
				makeContentLayout: function(){
					var self = this, data = this.defaults.machine.data, cont, maxWidth = null, maxHeight = null;
					if (Utils.isObject(data.freeformatmaxdims)){
						if (data.freeformatmaxdims.width){
							maxWidth = data.freeformatmaxdims.width;
						}
						if (data.freeformatmaxdims.height){
							maxHeight = data.freeformatmaxdims.height;
						}
					}
					cont = $(
						'<div class="customFormatChecker">' +
							'<div class="freeFormatChecker">' +
								'<input type="checkbox" name="freeFormatChecker" value="ja"/>&nbsp;' +
								$.lang('freeFormatCheckerPrompt') +
							'</div>' +
							'<div class="customFormatPanel">' +
								'<div class="title">' +
									$.lang('setCustomFormat') +
								'</div>' +
								'<div class="content">' +
									'<form method="post" action="#">' +
										'<table cellpadding="0" cellspacing="0" border="0" class="customerFormat">' +
											'<tr>' +
												'<td class="variant cfCol0_0">' +
												'</td>' +
												'<td colspan="2" class="cfCol0_1">' +
												'</td>' +
												'<td class="cfCol0_3">' +
												'</td>' +
											'</tr>' +
											'<tr>' +
												'<td class="cfCol1_0">' +
												'</td>' +
												'<td class="cfCol1_1">' +
												'</td>' +
												'<td class="cfCol1_2">' +
												'</td>' +
												'<td class="price cfCol1_3">' +
												'</td>' +
											'</tr>' +
											'<tr>' +
												'<td class="cfCol2_0">' +
												'</td>' +
												'<td class="cfCol2_1">' +
												'</td>' +
												'<td class="cfCol2_2">' +
												'</td>' +
												'<td class="cfCol2_3">' +
												'</td>' +
											'</tr>' +
										'</table>' +
									'</form>' +
								'</div>' +
							'</div>' +
						'</div>'
					);
					cont.find('.cfCol1_1').append(this.makeSizeLayout($.lang('width'), maxWidth, 'width'));
					cont.find('.cfCol1_2').append(this.makeSizeLayout($.lang('heigth'), maxHeight, 'height'));
					cont.find('.cfCol2_2').append(this.makeButtonLayout());
					cont.bind('submit', function(e){
						e.preventDefault();
						e.stopPropagation();
						self.handlePrepareDataModelAndVerify();
					});
					return cont;
				},
				handlePrepareDataModelAndVerify: function(){
					var formData = $('table.customerSize').find(':input').serializeArray(), Machine = this.defaults.machine,
					freeFormatData = Machine.data.freeFormatData;
					freeFormatData.width = formData[0].value;
					freeFormatData.height = formData[1].value;
					freeFormatData.errorMessage = null;
					Machine.verifyData(null);
				},
				make: function(){
					var panel = this.makeContentLayout(), target = this.defaults.target, self = this,
					Machine = this.defaults.machine, k;
					panel.find('.customFormatPanel').css({
						opacity: 0.5
					}).find(':input').attr({
						disabled: true
					}).end().end().find('.freeFormatChecker :input').click(function(e){
						var machine = self.defaults.machine, slot_0 = machine.slots[0], k;
						if ($(this).attr('checked')){
							for (k in slot_0.items){
								if (slot_0.items[k].title == 'freies Format'){
									slot_0.currentItem = parseInt(k, 10);
									break;
								}
							}
						}else{
							slot_0.currentItem = 0;
						}
						machine.verifyData(slot_0);
					});
					for (k in Machine.data.slots[0].items){
						if (Machine.data.slots[0].items[k].title == 'freies Format'){
							target.append(panel);
							break;
						}
					}
				},
				update: function(target){
					var self = this, Machine = this.defaults.machine, freeFormatData = Machine.data.freeFormatData,
					hasFreeFormat = false, k;
					target = this.defaults.target;
					if (Utils.isObject(freeFormatData.errorMessage)){
						alert(freeFormatData.errorMessage.title + ':\n' + freeFormatData.errorMessage.text);
					}
					if (Machine.data && Machine.data.freeformat){
						target.find('.customFormatPanel').css({
							opacity: 1
						}).find(':input').attr({
							disabled: false
						});
						$('#customerWidth').val(Machine.data.customerWidth);
						$('#customerHeight').val(Machine.data.customerHeight);
						$('.freeFormatChecker :input').attr({
							checked: true
						});
					}else{
						target.find('.customFormatPanel').css({
							opacity: 0.5
						}).find(':input').attr({
							disabled: true
						});
						$('.freeFormatChecker :input').attr({
							checked: false
						});
					}
				}
			}
		);
	// <

	// > Downloads
		DisplayPilotDownloads = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {
						target: null,
						targetInfoData: null,
						targetTemplate: null,
						ajaxHandlerInfoData: 'datasheet',
						ajaxHandlerTemplate: 'formattemplate4article',
						machine: null
					};
					if(Utils.isObject(opts)){
						$.extend(o.defaults, opts);
					}
					return o;
				},
				makeHeadlineLayout: function(){
					var lay = $(
						'<div class="headline">' + $.lang('displayPilotDownloadHeader') + '</div>'
					);
					return lay;
				},
				makeDownloadTemplate: function(){
					var lay = $(
						'<div class="downloadTemplate viewport">' +
							'<div class="icon"><img src=""/></div>' +
							'<a href="#" class="reference" target="_blank"></a>' +
							'<div class="size"></div>' +
						'</div>'
					);
					return lay;
				},
				update: function(){
					var target = this.defaults.target, self = this,
					targetInfoData = this.defaults.targetInfoData,
					targetTemplate = this.defaults.targetTemplate,
					ajaxHandlerInfoData = this.defaults.ajaxHandlerInfoData,
					ajaxHandlerTemplate = this.defaults.ajaxHandlerTemplate,
					Machine = this.defaults.machine, url, auf_id;
					targetInfoData.empty();
					targetTemplate.empty();
					if (ajaxHandlerInfoData){
						url = AjaxURLManager.getUrlWithKey(ajaxHandlerInfoData, {
							auf_id: Machine.data.auf_id || Machine.data.baseArticle
						});
						$.getJSON(url, function(data, textStatus){
							if (data){
								var downloads = $('#display_pilot_product_downloads'), headline = $('.headline', downloads),
								tpl = self.makeDownloadTemplate(),
								src = data.src,
								type = src.substring(src.lastIndexOf('.') + 1, src.length),
								label = data.label ? data.label : $.lang('displayPilotDownloadDatasheet') + '&nbsp;' + Machine.data.productTitle;
								size = data.size;
								size = size > 1048576 ? parseInt((size / 1048576) * 100, 10) / 100 + '&nbsp;MB' : parseInt((size / 1024) * 100, 10) / 100 + '&nbsp;KB';
								if (!headline.length){
									downloads.prepend(self.makeHeadlineLayout());
								}
								tpl.addClass('downloadTemplate_datasheet');
								tpl.find('.icon img').attr({
									src: '/xist4c/images/icons/upload/' + type + '.gif'
								});
								tpl.find('.reference')
									.html(label)
									.attr({
										href: src
									});
								tpl.find('.size').html(size);
								targetInfoData.append(tpl);
							}
						});
					}
					if (ajaxHandlerTemplate){
						url = AjaxURLManager.getUrlWithKey(ajaxHandlerTemplate, {
							auf_id: Machine.data.auf_id
						});
						$.ajax({
							type: 'get',
							url: url,
							dataType: 'text/plain',
							success: function(data, msg){
								if (data){
									var downloads = $('#display_pilot_product_downloads'), headline = $('.headline', downloads),
									type = data.substring(data.lastIndexOf('.') + 1, data.length),
									tpl = self.makeDownloadTemplate();
									if (!headline.length){
										downloads.prepend(self.makeHeadlineLayout());
									}
									tpl.addClass('downloadTemplate_template');
									tpl.find('.icon img').attr({
										src: '/xist4c/images/icons/upload/' + type + '.gif'
									});
									tpl.find('.reference').text($.lang('displayPilotDownloadTemplate')).attr({
										href: data
									});
									targetTemplate.append(tpl);
								}
							},
							error: function(req, status, error){}
						});
					}
				}
			}
		);
	// <

	// > Customer download advise
		CustomerDownloadAdviseController = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {};
					if(Utils.isObject(opts)){
						$.extend(o.defaults, opts);
					}
					return o;
				},
				makeTabLayout: function(){
					var lay = $(
						'<div class="viewport rowConfigurator-viewport">' +
							'<div class="customerDownloadAdvise-tab"></div>' +
						'</div>'
					);
					return lay;
				},
				makeAdviseLayout: function(){
					var lay = $(
						'<div class="customerDownloadAdvise-advise"></div>'
					);
					return lay;
				},
				make: function(data){
					var target = $('.display_pilot_product_config_cutter'), tab, advise;
					if (!$('.customerDownloadAdvise-tab').length){
						tab = this.makeTabLayout().hide();
						advise = this.makeAdviseLayout().hide();
						tab.append(advise);
						target.prepend(tab);
					}
					Utils.busyWait(
						function(intervalObj){
							if ($('#display_pilot_product_info_data').find('a').length){
								return true;
							}
							return false;
						},
						200,
						500,
						function(intervalObj){
							target.find('.customerDownloadAdvise-tab').unbind().bind('click', function(e){
								$('.customerDownloadAdvise-advise').fadeIn('fast');
								setTimeout(function(){
									$('.customerDownloadAdvise-advise').fadeOut('fast');
								}, 6000);
							});
							target.find('.customerDownloadAdvise-tab').parent().show();
						}
					);
				}
			}
		);
	//<

	// > Initialize configurator
		startDisplayPilotConfigurator = function(){
			CustomerAdviseController = CustomerDownloadAdviseController.create();
			DisplayPilotMachine = SlotMachineSelectModeWithHideLockedSlots.create();
			var params = Utils.getUrlParamsAsJson(),
			DpDownloads = DisplayPilotDownloads.create({
				target: $('#display_pilot_product_downloads'),
				targetInfoData: $('#display_pilot_product_info_data'),
				targetTemplate: $('#display_pilot_product_template')
			}),
			CustFormat = CustomerFormatHandler.create({
				target: $('#display_pilot_product_free_format')
			}),
			AddOptions = AdditionalOptions.create(),
			QuickChoiceXxl = SlotmachineRightQuickChoice_XXL_GC.create(DisplayPilotMachine),
			HandleOptions = DisplayPilotHandleAddOptions.create(),
			ShoppingcartPrep = ShoppingcartPreparerXxl.create(),
			prepareResetButton = function(data){
				var button = $('#display_pilot_all_products'), baseId = data.baseArticle,
				locked,
				params = {
					auf_id: baseId,
					freeConfig: true,
					reset: true
				},
				url = window.location.href;
				if (data.locked && data.slots[data.locked] && data.slots[data.locked].pk){
					params.locked = data.slots[data.locked].pk;
				}
				if (url.search(/\?/) > -1){
					url = url.substring(0, url.search(/\?/));
				}
				url = url + Utils.getUrlParamsFromJson(params);
				button.bind('click', function(e){
					window.location = url;
				});
			},
			prepareStarHint = function(){
				var starHint = $('<div class="starOptionHint"><span class="star">*</span>Nettopreis</div>');
				$('.display_pilot_all_products_outer').append(starHint);
			},
			sendEcondaInfoIdAufId = function(data){
				var price = data.meta.priceNum || null;
				if (price){
					price = Math.round(price * 100) / 100;
				}
				if (data.auf_id && typeof(window.emospro) !== 'undefined'){
					window.emospro.ec_Event = [[
						'view',
						data.auf_id || 'NULL',
						data.productTitle || 'NULL',
						price || 'NULL',
						data.meta.econda.econdaCategory || 'NULL',
						'1',
						data.meta.econda.ev1 || data.auf_auflage || 'NULL',
						data.meta.econda.ev2 || 'NULL',
						data.meta.econda.ev3 || 'NULL',
						data.meta.econda.ev4 || 'NULL',
						data.meta.econda.ev5 || 'NULL',
						data.meta.econda.ev6 || 'NULL',
						data.meta.econda.ev7 || 'NULL',
						data.meta.econda.ev8 || 'NULL',
						data.meta.econda.ev9 || 'NULL',
						data.meta.econda.ev10 || 'NULL'
					]];
					econdaRequestEvent();
				}
			},
			handleShippingTime = function(Machine, data, init){
				var target = $('.display_pilot_product_info_outer'), st;
				if (init){
					st = $(
						'<div class="shippingTime viewport">' +
							'<div class="timeOuter">' +
								'<span class="time"></span><a href="#" class="info"></a>' +
							'</div>' +
						'</div>'
					);
					target.prepend(st);
				}
				if (data && data.meta && data.meta.deliveryTime && data.auf_id){
					$('.shippingTime').find('.time').text(data.meta.deliveryTime);
				}else{
					$('.shippingTime').find('.time').text('---');
				}
				//initiateInfos(Machine, 'shippingTime');
			},
			handleShippingMethodSelect = function(Machine, data){
				var stdIdx, i, ShippingBox, opts, tableProp = 'costs', selected = false, item, text;
				$('#slotmachineAddOptsContainer').empty();
				if (data.auf_id){
					for (i = 0; i < data.costs.rows.length; i+=1){
						if (data.express){
							tableProp = 'exCosts';
						}else if (data.overnight){
							tableProp = 'ovCosts';
						}
						if (data[tableProp].rows[i].here){
							stdIdx = i;
							break;
						}
					}
					opts = {
							target: $('#slotmachineAddOptsContainer'),
							data: {
								prompt: $.lang('shipping'),
								name: 'shippingMethod',
								items: [
									{
										title: $.lang('standard'),
										value: ''
									}
								]
							},
							className: 'slotmachineShippingSelectBox',
							onChangeCallback: function(value){
								Machine.data.express = false;
								Machine.data.overnight = false;
								if (value){
									Machine.data[value] = true;
								}
								Machine.verifyData();
							}
					};
					if (data.exCosts.rows[stdIdx].auf_id){
						opts.data.items.push({
							title: $.lang('express') + ' ' + data.costs.rows[stdIdx].additionalcostExpress,
							value: 'express'
						});
						if (data.express){
							selected = true;
							opts.data.items[opts.data.items.length - 1].here = true;
						}
					}
					if (data.ovCosts.rows[stdIdx].auf_id){
						opts.data.items.push({
							title: $.lang('overnight') + ' ' + data.costs.rows[stdIdx].additionalcostOvernight,
							value: 'overnight'
						});
						if (data.overnight){
							selected = true;
							opts.data.items[opts.data.items.length - 1].here = true;
						}
					}
					if (opts.data.items.length > 1){
						item = opts.data.items[0];
						for (i = 0; i < opts.data.items.length; i+=1){
							if (opts.data.items[i].here){
								item = opts.data.items[i];
								break;
							}
						}
						if (item.value !== ''){
							text = item.title;
							text = text.substring(text.indexOf('(') + 1, text.indexOf(')'));
							$('.shippingTime .timeOuter').prepend('<span class="time">' + text + '</span>');
							$('.shippingTime .timeOuter .time').eq(1).hide();
						}else{
							$('.shippingTime .timeOuter').find(':nth-child(1)').show().end().find(':nth-child(0)').remove();
						}
						ShippingBox = SlotmachineShippingOptionsSelectBox.create(opts);
						ShippingBox.make('append');
						ShippingBox.domel.find('.slotBullet').addClass(' slotBulletActive_hasSelection');
					}
				}
			},
			MediaGallery = DisplayPilotMediaGallery.create({
				target: $('#display_pilot_media_gallery')
			});
			MediaGallery.make();
			DisplayPilotMachine.init({
				target: $('#display_pilot_product_configurator'),
				dataType: 'SlotMachineSelectModeWithHideLockedSlots',
				slotType: 'SlotMachineSelectModeSlot',
				slotItemType: 'SlotMachineSelectModeSlotItem',
				ajaxHandler: 'configarticle',
				onBeforeInit: function(){
					handleShippingTime(this, null, true);
					prepareStarHint();
				},
				onInitDataReceive: function(data){
					updateDataTypes(data, 'displayPilotSelect');
					registerLockedSlots(this.urlParams, data);
					prepareResetButton(data);
					HandleOptions.defaults.data = data;
					HandleOptions.defaults.configurator = this;
					HandleOptions.make();
					AddOptions.makeShoppingCartOpts(data);
					DpDownloads.defaults.machine = DisplayPilotMachine;
					CustFormat.defaults.machine = DisplayPilotMachine;
					CustFormat.make();
				},
				onAfterInit: function(data){
					if (!$('#slotmachineAddOptsContainer').length){
						$('#genericConfiguratorMainBg').append(
							'<div id="slotmachineAddOptsContainer" class="slotmachineAddOptsContainer"></div>'
						);
					}
					var opts = {
						title: data.productTitle,
						data: data,
						target: $('#prdConfTopConfigXxl'),
						slot: this
					};
					QuickChoiceXxl.init(opts);
					ShoppingcartPrep.update(data);
					$(function(){
						var slots = self.slots;
						$(slots).each(function(i){
							var hasSelection = this.currentItem ? true : false;
							if (this.domel){
								this.domel.find('.slotBullet').toggleClass('slotBulletActive', hasSelection);
							}
						});
					});
				},
				onDataRequestSuccess: function(slot, data){
					var self = this, scHeightField = $('#prdConfTopWk_customerHeight'),
					scWidthField = $('#prdConfTopWk_customerWidth');
					updateDataTypes(data, 'displayPilotSelect');
					registerLockedSlots(this.urlParams, data);
					HandleOptions.defaults.data = data;
					HandleOptions.defaults.configurator = this;
					HandleOptions.make();
					AddOptions.makeShoppingCartOpts(data);
					$(function(){
						var slots = self.slots;
						$(slots).each(function(i){
							var hasSelection = this.currentItem ? true : false;
							if (this.domel){
								this.domel.find('.slotBullet').toggleClass('slotBulletActive', hasSelection);
							}
						});
					});
					// update auf_id.
					if (this.urlParams && this.urlParams.auf_id){
						this.urlParams.auf_id = data.auf_id;
					}
					QuickChoiceXxl.update(slot, data);
					ShoppingcartPrep.update(data);
					DpDownloads.update();
					CustFormat.update();
					if (data.auf_id && !Utils.isObject(data.freeFormatData.errorMessage) && data.freeformat){
						scHeightField.val(data.freeFormatData.height);
						scWidthField.val(data.freeFormatData.width);
					}else{
						scHeightField.val('');
						scWidthField.val('');
					}
					handleShippingTime(this, data, false);
					handleShippingMethodSelect(this, data);
					CustomerAdviseController.make();
					sendEcondaInfoIdAufId(data);
					MediaGallery.each(function(i){
						var pk, pkId, k, itemPk;
						if (slot){
							pk = slot.data.pk;
							pkId = slot.items[slot.currentItem].value;
							for (k in this.defaults.data.pks){
								itemPk = this.defaults.data.pks[k];
								if (pk === itemPk[0] && pkId == itemPk[1]){
									this.domel.trigger('click');
									return this;
								}
							}
						}
					});
				}
			});
		};
	// <

	// > Handle additional options
		DisplayPilotHandleAddOptions = $.extend(
			$.clone(LLObject),
			{
				create: function(opts){
					var o = LLObject.create.call(this);
					o.defaults = {
						data: null,
						configurator: null
					};
					if (Utils.isObject(opts)){
						$.extend(o.defaults, opts);
					}
					return o;
				},
				makeOptionsOuterLayout: function(){
					var lay = $(
						'<div class="display_pilot_add_options_outer">' +
							'<div class="headline">' +
								'<span class="bullet"></span>' +
								$.lang('displayPilotAddOptionsHeader') +
							'</div>' +
							'<div id="display_pilot_add_options" class="options">' +
							'</div>' +
						'</div>'
					);
					return lay;
				},
				makeOptionBaseLayout: function(){
					var lay = $(
						'<div class="display_pilot_option">' +
							'<div class="display_pilot_option_des1">' +
								'<div class="viewport">' +
									'<div class="posAbs image"></div>' +
									'<div class="posAbs help" style="z-index: 1000000;">' +
										'<div class="posAbs helpBubble"></div>' +
									'</div>' +
									'<div class="posAbs bullet"></div>' +
									'<div class="posAbs control"></div>' +
									'<div class="posAbs text"></div>' +
									'<div class="posAbs price"></div>' +
								'</div>' +
							'</div>' +
						'</div>'
					);
					return lay;
				},
				makeOptionControl: function(type, name, value, mandatory, overallItems, idx, here){
					var nodeName = 'input', iType = 'radio', node, self = this;
					if (type == 'select'){
						if (!mandatory && overallItems >= 2){
							iType = 'checkbox';
						}
					}else if (type == 'checkbox'){
						iType = 'checkbox';
					}
					idx = name + '_' + idx;
					node = $(['<',nodeName,' type="',iType,'" name="',name,'" value="',value,'" id="',idx,'"/>'].join(''));
					(function(here, idx, iType){
						Utils.busyWait(
							function(intervalObj){
								if ($('#' + idx).length){
									return true;
								}
								return false;
							},
							100,
							100,
							function(intervalObj){
								if (here){
									if (iType == 'checkbox'){
										$('#' + idx).attr('checked', 'checked');
									}else{
										$('#' + idx).attr('checked', 'checked');
									}
								}
							}
						);
					})(here, idx, iType);
					node.bind('click', function(e){
						var here, i, j, idx, value = $(this).attr('value'),
						name = $(this).attr('name'), option, type = $(this).attr('type'), item;
						for (i = 0; i < self.defaults.configurator.data.options.length; i+=1){
							option = self.defaults.configurator.data.options[i];
							if (option.name == name){
								idx = i;
								break;
							}
						}
						if (option.items && option.items.length){
							for (j = 0; j < option.items.length; j+=1){
								item = option.items[j];
								if (item.value == value){
									if ((type == 'radio' && $(this).attr('selected')) || $(this).attr('checked')){
										self.defaults.configurator.data.options[idx].items[j].here = true;
									}else{
										delete self.defaults.configurator.data.options[idx].items[j].here;
									}
								}else{
									delete self.defaults.configurator.data.options[idx].items[j].here;
								}
							}
						}else if (type == 'checkbox'){
							if ($(this).attr('checked')){
								self.defaults.configurator.data.options[idx].here = true;
							}else{
								delete self.defaults.configurator.data.options[idx].here;
							}
						}
						self.verifyData();
					});
					return node;
				},
				getOptId: function(id){
					return id.substring(id.lastIndexOf('_') + 1, id.length);
				},
				make: function(){
					var outer = this.makeOptionsOuterLayout(), optionLay, option, options = this.defaults.data.options,
					item, i, j, control, type, name, required, value, text, price, len,
					x1 = function(e){
						$(this).find('.helpBubble').show('fast');
					},
					x2 = function(e){
						$(this).find('.helpBubble').hide('fast');
					};
					$('#display_pilot_product_options').empty();
					if (options.length){
						for (i = 0; i < options.length; i+=1){
							len = 0;
							option = options[i];
							type = option.type;
							name = option.name;
							value = option.value;
							required = option.mandatory;
							text = option.prompt;
							price = option.price;
							if (option.items && option.items.length){
								len = option.items.length;
							}
							if (len){
								j = !required && len >= 2 ? 1 : 0;
								for (j; j < len; j+=1){
									item = option.items[j];
									if (type == 'select'){
										text = item.content;
									}else{
										text = item.prompt;
									}
									value = item.value;
									price = item.price;
									optionLay = this.makeOptionBaseLayout();
									optionLay.find('.image').addClass('display_pilot_default_option_image');
									control = this.makeOptionControl(type, name, value, required, len, j, item.here);
									if (Utils.isObject(item.img)){
										optionLay.find('.image').css({
											backgroundImage: 'url(' + item.img.src + ')'
										});
									}
									optionLay.find('.control').append(control);
									optionLay.find('.text').html(text);
									optionLay.find('.price').html(price);
									if (item.description){
										optionLay.find('.helpBubble').html(item.description);
										optionLay.find('.help').hover(x1, x2).show();
									}
									outer.find('.options').append(optionLay);
								}
							}else{
								optionLay = this.makeOptionBaseLayout();
								optionLay.find('.image').addClass('display_pilot_default_option_image');
								control = this.makeOptionControl(type, name, value, required, len, i, option.here);
								if (Utils.isObject(option.img)){
									optionLay.find('.image').css({
										backgroundImage: 'url(' + option.img.src + ')'
									});
								}
								optionLay.find('.control').append(control);
								optionLay.find('.text').html(text);
								optionLay.find('.price').html(price);
								if (option.description){
									optionLay.find('.helpBubble').html(option.description);
									optionLay.find('.help').hover(x1, x2).show();
								}
								outer.find('.options').append(optionLay);
							}
						}
						$('#display_pilot_product_options').append(outer);
						$('#display_pilot_product_options').find('.options').append('<div class="floatTerm"></div>');
					}
				},
				verifyData: function(){
					this.defaults.configurator.verifyData();
				}
			}
		);
	// <
// <<


// >> Configurator services like twitter, facebook and google+1
	ConfiguratorServices = $.extend(
		$.clone(LLObject),
		{
			create: function(opts){
				var o = LLObject.create.call(this);
				o.services = [];
				o.defaults = {
					target: []
				};
				if(Utils.isObject(opts)){
					$.extend(o.defaults, opts);
				}
				return o;
			},
			makeServiceShellLayout: function(){
				return $(
					'<div class="cs-serviceShell viewport"></div>'
				);
			},
			init: function(){
				var target = this.defaults.target;
				if (target.length){
					target.prepend(this.makeServiceShellLayout());
				}
				return this;
			},
			add: function(service){
				if (service.instanceOf(ConfiguratorServices_Twitter)){
					this.services.push(service);
					service.target = $('.cs-serviceShell');
					service.make();
				}
			}
		}
	);

	ConfiguratorServices_Twitter = $.extend(
		$.clone(LLObject),
		{
			create: function(opts){
				var o = LLObject.create.call(this);
				o.domel = [];
				o.target = [];
				o.defaults = {
					stylename: 'configuratorservices-twitter',
					params: {
						'data-url': '',
						'data-via': '',
						'data-text': '',
						'data-related': '',
						'data-count': 'horizontal'
					}
				};
				if(Utils.isObject(opts)){
					$.extend(o.defaults, opts);
				}
				return o;
			},
			makeScriptAndLayout: function(){
				var opts = this.defaults, k, ref, data,
				stylename = ['configuratorservices-item', opts.stylename].join(' '),
				lay = $(
					'<div class="' + stylename + '">' +
						'<script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script>' +
						'<a href="http://twitter.com/share" class="twitter-share-button">Tweet</a>' +
					'</div>'
				);
				opts.params['data-url'] = window.location.href;
				opts.params['data-text'] = 'Top-Produkt, kann ich nur weiter empfehlen!';
				ref = lay.find('a');
				for (k in opts.params){
					if (k.substring(0, k.indexOf('-')) == 'data'){
						if (opts.params[k]){
							ref.attr(k, opts.params[k]);
						}
					}
				}
				return lay;
			},
			make: function(){
				var lay = this.makeScriptAndLayout();
				this.domel = lay;
				if (this.target.length){
					this.target.append(lay);
				}
			},
			remake: function(params){
				if (typeof(params) == 'object' && this.domel.length){
					this.domel.remove();
				}
			}
		}
	);

	ConfiguratorServices_Facebook = $.extend(
		$.clone(ConfiguratorServices_Twitter),
		{
			create: function(opts){
				var o = ConfiguratorServices_Twitter.create.call(this, opts);
				o.defaults = {
					stylename: 'configuratorservices-facebook',
					params: {
						href: null,
						send: 'false',
						layout: 'button_count',
						width: 120,
						show_faces: 'false',
						action: 'like',
						colorscheme: 'light',
						font: null,
						height: 21
					}
				};
				if(Utils.isObject(opts)){
					$.extend(true, o.defaults, opts);
				}
				return o;
			},
			makeScriptAndLayout: function(){
				var opts = this.defaults, url = 'http://www.facebook.com/plugins/like.php',
				stylename = ['configuratorservices-item', opts.stylename].join(' '), lay;
				url = 'http://www.facebook.com/plugins/like.php';
				opts.params.href = window.location.href;
				url = url + Utils.getUrlParamsFromJson(opts.params);
				lay = $(
					'<div class="' + stylename + '">' +
						'<iframe src="' + url + '" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:' + opts.params.width + 'px; height:' + opts.params.height + 'px;" allowTransparency="true"></iframe>' +
					'</div>'
				);
				return lay;
			}
		}
	);

	ConfiguratorServices_GooglePlusOne = $.extend(
		$.clone(ConfiguratorServices_Twitter),
		{
			create: function(opts){
				var o = ConfiguratorServices_Twitter.create.call(this, opts);
				o.defaults = {
					stylename: 'configuratorservices-googleplusone'
				};
				if(Utils.isObject(opts)){
					$.extend(o.defaults, opts);
				}
				return o;
			},
			makeScriptAndLayout: function(){
				var opts = this.defaults,
				stylename = ['configuratorservices-item', opts.stylename].join(' '),
				lay = $(
					'<div class="' + stylename + '">' +
						'<g:plusone size="medium" count="true">' + window.location.href + '</g:plusone>' +
						'<script type="text/javascript">gapi.plusone.go();</script>' +
					'</div>'
				);
				if ($.browser.msie && $.browser.version <= 8) {
					lay = $('<div></div>');
				}
				return lay;
			}
		}
	);

	$(function(){
		if (FLYPI_CONFIGURATION_TYPE == 'sm' && $('#slotMachine').length){
			ConfServ = ConfiguratorServices.create({
				target: $('.prdConfTopShellSm')
			}).init();
		}else if (FLYPI_CONFIGURATION_TYPE == 'xxl' && $('#display_pilot_product_configurator').length){
			ConfServ = ConfiguratorServices.create({
				target: $('.twoCol_display_pilot_configurator_top_data')
			}).init();
		}
		if (typeof(ConfServ) !== 'undefined'){
			ConfServ.add(ConfiguratorServices_Twitter.create());
			ConfServ.add(ConfiguratorServices_Facebook.create());
			ConfServ.add(ConfiguratorServices_GooglePlusOne.create());
		}
	});
// <<



