// >> call the standard document print function (require MochiKit 1.4, StandardPopup) Version rel-1-0-0
	function printDocument(){
		var href = getElementsByTagAndClassName('td', 'printButton')[0].childNodes[0].href;
		window.open(href, 'printView', 'location=no,menubar=no,resizable=yes,scrollbars=yes,statusbar=no,toolbar=no,height=500,width=700');
		return false;
	}
// <<

if (typeof(lltools) === 'undefined'){
	window.lltools = {};
}
// Initialisation of global set info variable
window.SK_CURRENT_STEP = 0;
updateStepFromUrlParam = function(){
	var params = Utils.getUrlParamsAsJson();
}

AjaxURLManager.setMode('live');
AjaxURLManager.registerKey('configarticle', null, '../schlauchkonfigurator_testdata_tube.json', false, null);


/* >> 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,
						onBeforeEachSlot: null, // Attributes: "this" = Configurator | slot-data, index
						onAfterEachSlot: null, // Attributes: "this" = Configurator | slot-data, index
						onBeforeEachSlotItem: null, // Attributes: "this" = Configurator | item-data, index
						onAfterEachSlotItem: null, // Attributes: "this" = Configurator | item-data, index
						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){
									$(d.slots).each(function(i){
										var sType, slot, slotType;
										if (typeof self.defaults.onBeforeEachSlot === 'function'){
											self.defaults.onBeforeEachSlot.call(self, this, i);
										}
										slotType = self.defaults.slotType || null;
										if (!slotType || this.type == slotType){
											sType = slotType;
											if (!slotType){
												sType = this.type;
											}
											slot = window[sType].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){
												var siType, slotItemType;
												if (typeof self.defaults.onBeforeEachSlotItem === 'function'){
													self.defaults.onBeforeEachSlotItem.call(self, this, i);
												}
												slotItemType = self.defaults.slotItemType || null;
												if (!slotItemType || this.type == slotItemType){
													siType = slotItemType;
													if (!slotItemType){
														siType = this.type;
													}
													var slotItem = window[siType].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);
												}
												if (typeof self.defaults.onAfterEachSlotItem === 'function'){
													self.defaults.onAfterEachSlotItem.call(self, this, i);
												}
											});
											self.appendSlot(slot);
											self.calculateSlotWidth(slot);
										}
										if (typeof self.defaults.onAfterEachSlot === 'function'){
											self.defaults.onAfterEachSlot.call(self, this, i);
										}
									});
								}
								// 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);
				},
				getSlotsPrimaryKeys: function(){
					var k, pks = [];
					for (k in this.slots){
						pks.push(this.slots[k].data.pk);
					}
					return pks;
				},
				getSlotsWithPrimaryKeys: function(pks){
					var k, slots = [];
					if (Utils.isArray(pks)){
						for (k in this.slots){
							if ($.inArray(this.slots[k].data.pk, pks) > -1){
								slots.push(this.slots[k]);
							}
						}
					}
					return slots;
				},
				verifyData: function(slot){
					var 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,
						dataType: 'json',
						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;
						});
						// after the slot catch trigger a callback
						var cb = self.configurator.defaults.onAfterSlotCatch;
						if (cb && typeof cb == 'function'){
							cb.call(self.configurator, self);
						}
						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();
						var 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, siType;
					slotItemType = this.configurator.defaults.slotItemType || null;
					$(slotData.items).each(function(i){
						if (!slotItemType || this.type == slotItemType){
							siType = slotItemType;
							if (!slotItemType){
								siType = this.type;
							}
							var slotItem = window[siType].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();
						var 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) params = $.reduce(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;
						if (cfd && cfd.auf_id){
							params = $.extend(params, {'auf_id': cfd.auf_id, 'freeConfig': 'true'});
						}
					}
					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;
					if (button){
						if (button == 'up' || button == 'down'){
							var up = button == 'up' ? true : false;
							var down = button == 'down' ? true : false;
						}else{
							button = $(button);
							var up = button.hasClass('top');
							var 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');
						var 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));
					}
				}
			}
		);
	/* << */
/* << */


// >> Special implementations of GenericConfigurator parts
	GC_TubeConfigurator = $.extend(
		$.clone(GenericConfigurator),
		{
			create: function(){
				return GenericConfigurator.create.call(this);
			},
			makeShell: function(target){
				var shell = $(
					'<div id="genericConfiguratorOuter">' +
						'<div id="genericConfiguratorMainBg">' +
							'<div class="genericConfiguratorShell">' +
							'</div>' +
						'</div>' +
					'</div>'
				);
				target.append(shell);
			},
			verifyData: function(slot){
				var 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, {mode:'config'});
				//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,
					dataType: 'json',
					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);}
				});
			}
		}
	);

	GC_TubeSlot = $.extend(
		$.clone(GenericConfiguratorSlot),
		{
			create: function(title, currentItem){
				var o = GenericConfiguratorSlot.create.call(this, title, currentItem);
				return o;
			},
			makeSlotLayout: function(){
				var slot = $(
					'<div id="' + this.id + '" class="gc-sk-tubeOuter">' +
					'</div>'
				).hide();
				return slot;
			},
			appendItemsToSlot: function(){
				var target = $('#' + this.id), currentCompound, subtract = 0;
				$(this.items).each(function(i){
					var compound;
					if (this.value == -1){
						subtract++;
					}else{
						if ((i - subtract) % 2 == 0){
							currentCompound = compound = $('<div class="sk-tubeItemsOuter"></div>');
							target.append(compound);
						}
						this.make(currentCompound);
					}
				});
			},
			make: function(target){
				if (target){
					var slotLay = this.makeSlotLayout(),
					target = target.find('.genericConfiguratorShell');
					target.append(slotLay);
					this.appendItemsToSlot();
					this.selectCurrentItem();
				}
			},
			selectCurrentItem: function(clearall){
				var self = this;
				$(this.items).each(function(i){
					if (self.currentItem == i && !clearall){
						$('#' + self.id + '_slotItem_' + i).find('.gc-sk-tubeSelectedArrow').addClass('gc-sk-tubeSelectedArrow-selected');
					}else{
						$('#' + self.id + '_slotItem_' + i).find('.gc-sk-tubeSelectedArrow').removeClass('gc-sk-tubeSelectedArrow-selected');
					}
				});
			},
			update: function(slotData){
				this.items = [];
				this.initMode = true;
				this.data = slotData;
				this.currentItem = slotData.currentItem;
				$('.gc-sk-tubeOuter').empty();
				var self = this;
				var slotItemType, siType;
				slotItemType = this.configurator.defaults.slotItemType || null;
				$(slotData.items).each(function(i){
					if (!slotItemType || this.type == slotItemType){
						siType = slotItemType;
						if (!slotItemType){
							siType = this.type;
						}
						var slotItem = window[siType].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();
				this.selectCurrentItem();
			}
		}
	);
	
	GC_TubeSlotItem = $.extend(
		$.clone(GenericConfiguratorSlotItem),
		{
			create: function(title, value){
				return GenericConfiguratorSlotItem.create.call(this, title, value);
			},
			makeItemLayout: function(){
				var item, image = '', self = this, infoText, subtitle = '';
				if (this.data.image){
					image = $('<img/>');
					image.attr({
							src: this.data.image.src,
							width: this.data.image.width,
							height: this.data.image.height
					});
					image = $('<div></div>').append(image).html();
				}
				if (this.data.subtitle){
					subtitle = '<h3 class="gc-sk-tubeSubTitle sk-bold">' + this.data.subtitle + '</h3>';
				}
				item = $(
					'<div id="' + this.id + '" class="gc-sk-tubeItem sk-viewport">' +
						'<div class="gc-sk-tubeSelectedArrow"></div>' +
						'<div class="gc-sk-tubeTitle sk-bold sk-bgDarkGray sk-unselectable">' + this.data.title + '</div>' +
						'<div class="gc-sk-tubeContent sk-bgDarkGray">' +
							subtitle +
							'<div class="gc-sk-tubeImage">' + image + '</div>' +
							'<div class="gc-sk-tubeDesc">' + this.data.desc + '</div>' +
						'</div>' +
						'<div class="gc-sk-tubeControlsBar sk-viewport sk-bgLightGray">' +
							'<div class="gc-sk-detailInfo sk-unselectable sk-buttonBehaviour">' +
								'<span class="gc-sk-detailPlus sk-bold">+</span>&nbsp;' +
								'<span class="gc-sk-detail">Mehr Details</span>' +
							'</div>' +
							'<div class="sk-button gc-sk-button gc-sk-button-choose sk-bold sk-unselectable sk-buttonBehaviour">' +
								'<span>&raquo;&nbsp;Auswählen</span>' +
							'</div>' +
						'</div>' +
						'<div class="gc-sk-detailInfoText">' + this.data.longdesc || '' + '</div>' +
					'</div>'
				);
				if (this.slot.currentItem == this.itemCnt){
					item.find('.gc-sk-tubeSelectedArrow').addClass('gc-sk-tubeSelectedArrow-selected');
				}else{
					item.find('.gc-sk-tubeSelectedArrow').removeClass('gc-sk-tubeSelectedArrow-selected');
				}
				item.find('.gc-sk-button-choose').bind('click', function(e){
					var cb = self.configurator.defaults.onSlotAction, button, clearall = false;
					if (cb && typeof cb == 'function'){
						cb.call(self, self.slot);
					}
					button = $(this);
					if (self.slot.currentItem == self.itemCnt){
						clearall = true;
						self.slot.currentItem = 0;
					}else{
						self.slot.currentItem = self.itemCnt;
					}
					self.slot.selectCurrentItem(clearall);
					self.configurator.verifyData(self.slot);
				});
				infoText = item.find('.gc-sk-detailInfo');
				if (this.data.longdesc){
					infoText.toggle(
						function(e){
							$(this).find('.gc-sk-detailPlus').html('-').end().find('.gc-sk-detail').text('Weniger Details');
							$(this).parent().next('.gc-sk-detailInfoText').slideDown('fast');
						},
						function(e){
							$(this).find('.gc-sk-detailPlus').text('+').end().find('.gc-sk-detail').text('Mehr Details');
							$(this).parent().next('.gc-sk-detailInfoText').slideUp('fast');
						}
					);
				}else{
					
				}
				return item;
			}
		}
	);


	GC_DiameterSlot = $.extend(
		$.clone(GenericConfiguratorSlot),
		{
			create: function(title, currentItem){
				var o = GenericConfiguratorSlot.create.call(this, title, currentItem);
				return o;
			},
			makeOuterPanelLayout: function(){
				var lay = $(
					'<div class="gc-sk-panelOuter gc-sk-panelOuter-diameter">' +
						'<div class="gc-sk-outerPanelTitle sk-unselectable sk-bgDarkGray">Schlauch-Eigenschaften</div>' +
						'<div class="gc-sk-content">' +
							'<table cellpadding="0" cellspacing="0" border="0" class="gc-sk-dataTable"></table>' +
						'</div>' +
					'</div>'
				).hide();
				return lay;
			},
			makeSlotLayout: function(){
				var slot,
				image = Utils.pixel();
				image.addClass('sk-' + this.data.pk);
				slot = $(
					'<tr>' +
						'<td class="' + this.id + '_imageColumn imageColumn sk-unselectable">' + image.xhtml() + '</td>' +
						'<td class="' + this.id + '_titleColumn titleColumn sk-unselectable"><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;
						}
					});
					// after the slot catch trigger a callback
					var cb = self.configurator.defaults.onAfterSlotCatch;
					if (cb && typeof cb == 'function'){
						cb.call(self.configurator, self);
					}
					self.configurator.verifyData(self);
				});
				return slot;
			},
			make: function(target){
				if (target){
					var slotLay = this.makeSlotLayout(), outerPanel,
					target = target.find('.genericConfiguratorShell');
					if (!$('.gc-sk-panelOuter-diameter').length){
						outerPanel = this.makeOuterPanelLayout();
						target.append(outerPanel);
					}
					target = $('.gc-sk-panelOuter-diameter').find('.gc-sk-dataTable');
					target.append(slotLay);
					this.appendItemsToSlot();
					this.selectCurrentItem();
				}
			},
			update: function(slotData){
				var replLay = this.makeSlotLayout();
				this.items = [];
				this.initMode = true;
				this.data = slotData;
				this.currentItem = slotData.currentItem;
				$('#' + this.id + '_select').parents('td.selectColumn').parent('tr').replaceWith(replLay);
				$('#' + this.id + '_titleColumn').find('.slotTitle').text(slotData.title);
				var self = this;
				var slotItemType, siType;
				slotItemType = this.configurator.defaults.slotItemType || null;
				$(slotData.items).each(function(i){
					if (!slotItemType || this.type == slotItemType){
						siType = slotItemType;
						if (!slotItemType){
							siType = this.type;
						}
						var slotItem = window[siType].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();
			}
		}
	);

	GC_AddAttributesSlot = $.extend(
		$.clone(GC_DiameterSlot),
		{
			create: function(title, currentItem){
				return GC_DiameterSlot.create.call(this, title, currentItem);
			},
			makeOuterPanelLayout: function(){
				var lay = $(
					'<div class="gc-sk-panelOuter gc-sk-panelOuter-addAttributes">' +
						'<div class="gc-sk-outerPanelTitle sk-unselectable sk-bgDarkGray">Zusätzliche-Eigenschaften</div>' +
						'<div class="gc-sk-content">' +
							'<table cellpadding="0" cellspacing="0" border="0" class="gc-sk-dataTable"></table>' +
						'</div>' +
					'</div>'
				).hide();
				return lay;
			},
			makeSlotLayout: function(){
				var slot,
				image = Utils.pixel();
				image.addClass('sk-' + this.data.pk);
				slot = $(
					'<tr>' +
						'<td class="' + this.id + '_imageColumn imageColumn sk-unselectable">' + image.xhtml() + '</td>' +
						'<td class="' + this.id + '_titleColumn titleColumn sk-unselectable"><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;
						}
					});
					// after the slot catch trigger a callback
					var cb = self.configurator.defaults.onAfterSlotCatch;
					if (cb && typeof cb == 'function'){
						cb.call(self.configurator, self);
					}
					self.configurator.verifyData(self);
				});
				return slot;
			},
			make: function(target){
				if (target){
					var slotLay = this.makeSlotLayout(), outerPanel,
					target = target.find('.genericConfiguratorShell');
					if (!$('.gc-sk-panelOuter-addAttributes').length){
						outerPanel = this.makeOuterPanelLayout();
						target.append(outerPanel);
					}
					target = $('.gc-sk-panelOuter-addAttributes').find('.gc-sk-dataTable');
					target.append(slotLay);
					this.appendItemsToSlot();
					this.selectCurrentItem();
				}
			},
			update: function(slotData){
				var replLay = this.makeSlotLayout();
				this.items = [];
				this.initMode = true;
				this.data = slotData;
				this.currentItem = slotData.currentItem;
				$('#' + this.id + '_select').parents('td.selectColumn').parent('tr').replaceWith(replLay);
				$('#' + this.id + '_titleColumn').find('.slotTitle').text(slotData.title);
				var self = this;
				var slotItemType, siType;
				slotItemType = this.configurator.defaults.slotItemType || null;
				$(slotData.items).each(function(i){
					if (!slotItemType || this.type == slotItemType){
						siType = slotItemType;
						if (!slotItemType){
							siType = this.type;
						}
						var slotItem = window[siType].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.setDisplay();
			},
			setDisplay: function(){
				if (this.data.display){
					$('#' + this.id + '_select').attr({
						disabled: false
					});
					$('#' + this.id + '_select')
					.parent('div')
					.parent('td')
					.parent('tr')
					.find('img, .slotTitle').css({
						opacity: 1
					});
				}else{
					$('#' + this.id + '_select').attr({
						disabled: true
					});
					$('#' + this.id + '_select')
					.parent('div')
					.parent('td')
					.parent('tr')
					.find('img, .slotTitle').css({
						opacity: .3
					});
				}
			}
		}
	);


	GC_LengthAttribute = $.extend(
		$.clone(GenericConfiguratorSlot),
		{
			create: function(title, currentItem){
				var o = GenericConfiguratorSlot.create.call(this, title, currentItem);
				return o;
			},
			makeOuterPanelLayout: function(){
				var lay = $(
					'<div class="gc-sk-panelOuter gc-sk-panelOuter-length">' +
						'<div class="gc-sk-outerPanelTitle sk-unselectable sk-bgDarkGray">Gesamtlänge</div>' +
						'<div class="gc-sk-content">' +
							'<table cellpadding="0" cellspacing="0" border="0" class="gc-sk-dataTable"></table>' +
						'</div>' +
					'</div>'
				).hide();
				return lay;
			},
			makeSlotLayout: function(){
				var slot,
				image = Utils.pixel();
				image.addClass('sk-hose_length');
				slot = $(
					'<tr>' +
						'<td class="' + this.id + '_titleColumn titleColumn sk-unselectable">' +
							'<div class="slotTitle"><span>' + this.title + '</span>:</div>' +
						'</td>' +
						'<td class="' + this.id + '_column selectColumn">' +
							'<div class="slotSelect viewport">' +
								'<div class="sco-lengthErrorBubble">' +
									'Geben Sie nur Angaben in Millimeter und <b>ohne</b> Nachkommastellen ein.<br/>' +
									'Kleinste zulässige Länge: 20mm.' +
								'</div>' +
								'<input type="text" name="' + this.id + '_text" id="' + this.id + '_text" />' +
							'</div>' +
						'</td>' +
					'</tr>' +
					'<tr>' +
						'<td class="' + this.id + '_imageColumn imageColumn sk-unselectable" colspan="2">' + image.xhtml() + '</td>' +
					'</tr>'
				);
				if (this.data.tubeLength){
					slot.find(':input').val(this.data.tubeLength);
				}
				var self = this;
				slot.find(':input').bind('keyup', function(e){
					var rex = /^[1-9]+[0-9]*$/;
					if (rex.test($(this).val()) && parseInt($(this).val(), 10) >= 20){
						$(this).prev().hide();
						self.configurator.data.tubeLength = $(this).val() * 1;
						self.configurator.verifyData();
					}else{
						slot.find('.sco-lengthErrorBubble').show('fast').click(function(e){
							$(this).hide('fast');
						});
					}
				});
				return slot;
			},
			make: function(target){
				if (target){
					var slotLay = this.makeSlotLayout(), outerPanel,
					target = target.find('.genericConfiguratorShell');
					if (!$('.gc-sk-panelOuter-length').length){
						outerPanel = this.makeOuterPanelLayout();
						target.append(outerPanel);
					}
					target = $('.gc-sk-panelOuter-length').find('.gc-sk-dataTable');
					target.append(slotLay);
				}
			}
		}
	);

	GC_ArmatureSlot = $.extend(
		$.clone(GC_TubeSlot),
		{
			create: function(title, currentItemA, currentItemB){
				var o = GC_TubeSlot.create.call(this, title, 0);
				o.currentItemA = currentItemA;
				o.currentItemB = currentItemB;
				return o;
			},
			makeSlotLayout: function(){
				var slot = $(
					'<div id="' + this.id + '" class="gc-sk-armatureOuter">' +
					'</div>'
				).hide();
				return slot;
			},
			appendItemsToSlot: function(){
				var target = $('#' + this.id), currentCompound, subtract = 0;
				$(this.items).each(function(i){
					var compound;
					if (this.value == -1){
						subtract++;
					}else{
						if ((i - subtract) % 2 == 0){
							currentCompound = compound = $('<div class="sk-tubeItemsOuter sk-armatureItemsOuter"></div>');
							target.append(compound);
						}
						this.make(currentCompound);
					}
				});
			},
			selectCurrentItem: function(clearall_A, clearall_B){
				var self = this;
				$(this.items).each(function(i){
					if (self.currentItemA == i && !clearall_A){
						$('#' + self.id + '_slotItem_' + i)
						.find('.gc-sk-armatureSelectedArrowA')
						.addClass('gc-sk-armatureSelectedArrowA-selected');
					}else{
						$('#' + self.id + '_slotItem_' + i)
						.find('.gc-sk-armatureSelectedArrowA')
						.removeClass('gc-sk-armatureSelectedArrowA-selected');
					}
					if (self.currentItemB == i && !clearall_B){
						$('#' + self.id + '_slotItem_' + i)
						.find('.gc-sk-armatureSelectedArrowB')
						.addClass('gc-sk-armatureSelectedArrowB-selected');
					}else{
						$('#' + self.id + '_slotItem_' + i)
						.find('.gc-sk-armatureSelectedArrowB')
						.removeClass('gc-sk-armatureSelectedArrowB-selected');
					}
				});
			}
		}
	);

	GC_ArmatureSlotItem = $.extend(
		$.clone(GC_TubeSlotItem),
		{
			create: function(title, value){
				return GC_TubeSlotItem.create.call(this, title, value);
			},
			makeItemLayout: function(){
				var item, image = '', self = this, infoText, subtitle = '';
				if (this.data.image){
					image = $('<img/>');
					image.attr({
							src: this.data.image.src,
							width: this.data.image.width,
							height: this.data.image.height
					});
					image = $('<div></div>').append(image).html();
				}
				if (this.data.subtitle){
					subtitle = '<h3 class="gc-sk-tubeSubTitle gc-sk-armatureSubTitle sk-bold">' + this.data.subtitle + '</h3>';
				}
				item = $(
					'<div id="' + this.id + '" class="gc-sk-tubeItem gc-sk-armatureItem sk-viewport">' +
						'<div class="gc-sk-tubeTitle gc-sk-armatureTitle sk-bold sk-bgDarkGray sk-unselectable">' + this.data.title + '</div>' +
						'<div class="gc-sk-tubeContent gc-sk-armatureContent sk-bgDarkGray">' +
							subtitle +
							'<div class="gc-sk-tubeImage gc-sk-armatureImage">' + image + '</div>' +
							'<div class="gc-sk-tubeDesc gc-sk-armatureDesc">' + this.data.desc + '</div>' +
						'</div>' +
						'<div class="gc-sk-tubeControlsBar gc-sk-armatureControlsBar sk-viewport sk-bgLightGray">' +
							'<div class="gc-sk-detailInfo sk-unselectable sk-buttonBehaviour">' +
								'<span class="gc-sk-detailPlus sk-bold">+</span>&nbsp;' +
								'<span class="gc-sk-detail">Mehr Details</span>' +
							'</div>' +
							'<div class="sk-button gc-sk-button gc-sk-button-choose gc-sk-button-choose-A sk-bold sk-unselectable sk-buttonBehaviour">' +
								'<div class="gc-sk-tubeSelectedArrow gc-sk-armatureSelectedArrowA"></div>' +
								'<span>A</span>' +
							'</div>' +
							'<div class="sk-button gc-sk-button gc-sk-button-choose gc-sk-button-choose-B sk-bold sk-unselectable sk-buttonBehaviour">' +
								'<div class="gc-sk-tubeSelectedArrow gc-sk-armatureSelectedArrowB"></div>' +
								'<span>B</span>' +
							'</div>' +
						'</div>' +
						'<div class="gc-sk-detailInfoText">' + (this.data.longdesc || '') + '</div>' +
					'</div>'
				);
				if (this.slot.currentItemA == this.itemCnt){
					item.find('.gc-sk-armatureSelectedArrowA').addClass('gc-sk-armatureSelectedArrowA-selected');
				}else{
					item.find('.gc-sk-armatureSelectedArrowA').removeClass('gc-sk-armatureSelectedArrowA-selected');
				}
				if (this.slot.currentItemB == this.itemCnt){
					item.find('.gc-sk-armatureSelectedArrowB').addClass('gc-sk-armatureSelectedArrowB-selected');
				}else{
					item.find('.gc-sk-armatureSelectedArrowB').removeClass('gc-sk-armatureSelectedArrowB-selected');
				}
				item.find('.gc-sk-button-choose-A').bind('click', function(e){
					var cb = self.configurator.defaults.onSlotAction, k, button, clearall_A = false, clearall_B = false;
					if (cb && typeof cb == 'function'){
						cb.call(self, self.slot);
					}
					button = $(this);
					if (self.configurator.data.connectorSlot.currentItemA == self.itemCnt){
						clearall_A = true;
						self.configurator.data.connectorSlot.currentItemA = self.slot.currentItemA = 0;
					}else{
						self.configurator.data.connectorSlot.currentItemA = self.slot.currentItemA = self.itemCnt;
					}
					self.slot.selectCurrentItem(clearall_A, clearall_B);
					self.configurator.verifyData();
				});
				item.find('.gc-sk-button-choose-B').bind('click', function(e){
					var cb = self.configurator.defaults.onSlotAction, k, button, clearall_A = false, clearall_B = false;
					if (cb && typeof cb == 'function'){
						cb.call(self, self.slot);
					}
					button = $(this);
					if (self.configurator.data.connectorSlot.currentItemB == self.itemCnt){
						clearall_B = true;
						self.configurator.data.connectorSlot.currentItemB = self.slot.currentItemB = 0;
					}else{
						self.configurator.data.connectorSlot.currentItemB = self.slot.currentItemB = self.itemCnt;
					}
					self.slot.selectCurrentItem(clearall_A, clearall_B);
					self.configurator.verifyData();
				});
				infoText = item.find('.gc-sk-detailInfo');
				if (this.data.longdesc){
					infoText.toggle(
						function(e){
							$(this).find('.gc-sk-detailPlus').html('-').end().find('.gc-sk-detail').text('Weniger Details');
							$(this).parent().next('.gc-sk-detailInfoText').slideDown('fast');
						},
						function(e){
							$(this).find('.gc-sk-detailPlus').text('+').end().find('.gc-sk-detail').text('Mehr Details');
							$(this).parent().next('.gc-sk-detailInfoText').slideUp('fast');
						}
					);
				}else{
					
				}
				return item;
			}
		}
	);

	GC_OptionSlot = $.extend(
		$.clone(GC_TubeSlot),
		{
			create: function(title, currentItems){
				var o = GC_TubeSlot.create.call(this, title, 0);
				o.currentItems = currentItems;
				return o;
			},
			makeSlotLayout: function(){
				var slot = $(
					'<div id="' + this.id + '" class="gc-sk-optionOuter">' +
					'</div>'
				).hide();
				return slot;
			},
			appendItemsToSlot: function(){
				var target = $('#' + this.id);
				var self = this;
				$(this.items).each(function(i){
					this.make(target);
				});
			},
			selectCurrentItem: function(){
				var self = this;
				$(this.items).each(function(i){
					if ($.inArray(i, self.currentItems) > -1){
						$('#' + self.id + '_slotItem_' + i)
						.find('.gc-sk-optionSelectedArrow')
						.addClass('gc-sk-optionSelectedArrow-selected');
					}else{
						$('#' + self.id + '_slotItem_' + i)
						.find('.gc-sk-optionSelectedArrowA')
						.removeClass('gc-sk-optionSelectedArrowA-selected');
					}
				});
			}
		}
	);

	GC_OptionSlotItem = $.extend(
		$.clone(GC_TubeSlotItem),
		{
			create: function(title, value){
				return GC_TubeSlotItem.create.call(this, title, value);
			},
			makeItemLayout: function(){
				var item, image = '', self = this, infoText, subtitle = '';
				if (this.data.image){
					image = $('<img/>');
					image.attr({
							src: this.data.image.src,
							width: this.data.image.width,
							height: this.data.image.height
					});
					image = $('<div></div>').append(image).html();
				}
				if (this.data.subtitle){
					subtitle = '<h3 class="gc-sk-tubeSubTitle gc-sk-optionSubTitle sk-bold">' + this.data.subtitle + '</h3>';
				}
				item = $(
					'<div id="' + this.id + '" class="gc-sk-tubeItem gc-sk-optionItem sk-viewport">' +
						'<div class="gc-sk-tubeTitle gc-sk-optionTitle sk-bold sk-bgDarkGray sk-unselectable">' + this.data.title + '</div>' +
						'<div class="gc-sk-tubeContent gc-sk-optionContent sk-bgDarkGray">' +
							subtitle +
							'<div class="gc-sk-tubeImage gc-sk-optionImage">' + image + '</div>' +
							'<div class="gc-sk-tubeDesc gc-sk-optionDesc">' + this.data.desc + '</div>' +
						'</div>' +
						'<div class="gc-sk-tubeControlsBar gc-sk-optionControlsBar sk-viewport sk-bgLightGray">' +
							'<div class="gc-sk-tubeSelectedArrow gc-sk-optionSelectedArrow"></div>' +
							'<div class="gc-sk-detailInfo sk-unselectable sk-buttonBehaviour">' +
								'<span class="gc-sk-detailPlus sk-bold">+</span>&nbsp;' +
								'<span class="gc-sk-detail">Mehr Details</span>' +
							'</div>' +
							'<div class="sk-button gc-sk-button gc-sk-button-choose gc-sk-button-chooseOption sk-bold sk-unselectable sk-buttonBehaviour">' +
								'<span>&raquo;&nbsp;Auswählen</span>' +
							'</div>' +
						'</div>' +
						'<div class="gc-sk-detailInfoText">' + this.data.longdesc || '' + '</div>' +
					'</div>'
				);
				if ($.inArray(this.itemCnt, this.slot.currentItems) > -1){
					item.find('.gc-sk-optionSelectedArrow').addClass('gc-sk-optionSelectedArrow-selected');
				}else{
					item.find('.gc-sk-optionSelectedArrow').removeClass('gc-sk-optionSelectedArrow-selected');
				}
				item.find('.gc-sk-button-choose').bind('click', function(e){
					var cb = self.configurator.defaults.onSlotAction, k, realItems = [], dItem;
					if (cb && typeof cb == 'function'){
						cb.call(self, self.slot);
					}
					var button = $(this);
					if ($.inArray(self.itemCnt, self.slot.currentItems) == -1){
						self.slot.currentItems.push(self.itemCnt);
					}else{
						for (k in self.slot.currentItems){
							if (self.itemCnt != self.slot.currentItems[k]){
								realItems.push(self.slot.currentItems[k]);
							}
						}
						self.slot.currentItems = realItems;
					}
					for (k in self.slot.data){
						dItem = self.slot.data[k];
						if ($.inArray(parseInt(k), self.slot.currentItems) > -1){
							dItem.here = true;
						}else{
							dItem.here = false;
						}
					}
					self.configurator.verifyData();
					self.slot.selectCurrentItem();
				});
				infoText = item.find('.gc-sk-detailInfo');
				if (this.data.longdesc){
					infoText.toggle(
						function(e){
							$(this).find('.gc-sk-detailPlus').html('-').end().find('.gc-sk-detail').text('Weniger Details');
							$(this).parent().next('.gc-sk-detailInfoText').slideDown('fast');
						},
						function(e){
							$(this).find('.gc-sk-detailPlus').text('+').end().find('.gc-sk-detail').text('Mehr Details');
							$(this).parent().next('.gc-sk-detailInfoText').slideUp('fast');
						}
					);
				}else{
					
				}
				return item;
			}
		}
	);
// <<


// >> Attributes handling object
	SC_Attributes = {
		attrs: [
			'st_id',             // step 0  //
			'sc_innendurchm',    // step 1  //
			'sc_aussendurchm',   //.        //
			'sc_betrdruck20',    //.        //
			'sc_spitzendruck20', //.        //
			'sc_biegeradstat',   //.        // step 4, all attrs
			'sc_biegeraddyn',    //.        //
			'sc_length',         //.        //
			'sck_id',            // step 2  //
			'so_id'              // step 3  //
		],
		stepRanges: [
			[0,1],
			[1,8],
			[8,9],
			[9, 10],
			[0, 10] // last step
		],
		getAttrs: function(){
			return this.attrs;
		},
		getAttrsForStep: function(step){
			var s = this.stepRanges[step][0], e = this.stepRanges[step][1];
			return this.attrs.slice(s, e);
		},
		getStepIndexForPk: function(pk){
			var k, idx;
			for (idx in this.attrs){
				if (this.attrs[idx] === pk){
					for (k in this.stepRanges){
						if (idx >= this.stepRanges[k][0] && idx < this.stepRanges[k][1]){
							return (k / 1);
						}
					}
				}
			}
		}
	}
// <<


// >> Step trail handler
	UI_StepTrailController = $.extend(
		$.clone(LLObject),
		{
			create: function(opts){
				var o = LLObject.create.call(this);
				o.target = $('.sk-stepTrail');
				o.currentStep = 0;
				o.defaults = {
					activeItem: 0,
					stepCount: 3,
					actionBar: null
				};
				if(Utils.isObject(opts)){
					$.extend(o.defaults, opts);
				}
				return o;
			},
			next: function(){
				this.layoutForStep(this.currentStep++);
				this.update(lltools.GCPart1, null, lltools.GCPart1.data);
			},
			layoutForStep: function(step){
				var actionBar = this.defaults.actionBar;
				step = step.toString();
				switch (step){
					case '0':
						$('.gc-sk-tubeOuter').show();
						$('.gc-sk-panelOuter-diameter').hide();
						$('.gc-sk-panelOuter-addAttributes').hide();
						$('.gc-sk-panelOuter-length').hide();
						$('.gc-sk-armatureOuter').hide();
						$('.gc-sk-optionOuter').hide();
						$('.gc-sk-finishConfigurationOuter').hide();
						break;
					case '1':
						$('.gc-sk-tubeOuter').hide();
						$('.gc-sk-panelOuter-diameter').show();
						$('.gc-sk-panelOuter-addAttributes').show();
						$('.gc-sk-panelOuter-length').show();
						$('.gc-sk-armatureOuter').hide();
						$('.gc-sk-optionOuter').hide();
						$('.gc-sk-finishConfigurationOuter').hide();
						break;
					case '2':
						$('.gc-sk-tubeOuter').hide();
						$('.gc-sk-panelOuter-diameter').hide();
						$('.gc-sk-panelOuter-addAttributes').hide();
						$('.gc-sk-panelOuter-length').hide();
						$('.gc-sk-armatureOuter').show();
						$('.gc-sk-optionOuter').hide();
						$('.gc-sk-finishConfigurationOuter').hide();
						break;
					case '3':
						$('.gc-sk-tubeOuter').hide();
						$('.gc-sk-panelOuter-diameter').hide();
						$('.gc-sk-panelOuter-addAttributes').hide();
						$('.gc-sk-panelOuter-length').hide();
						$('.gc-sk-armatureOuter').hide();
						$('.gc-sk-optionOuter').show();
						$('.gc-sk-finishConfigurationOuter').hide();
						break;
					case '4':
						$('.gc-sk-tubeOuter').hide();
						$('.gc-sk-panelOuter-diameter').hide();
						$('.gc-sk-panelOuter-addAttributes').hide();
						$('.gc-sk-panelOuter-length').hide();
						$('.gc-sk-armatureOuter').hide();
						$('.gc-sk-optionOuter').hide();
						$('.gc-sk-finishConfigurationOuter').show();
						break;
				}
				if (actionBar){
					actionBar.update(lltools.GCPart1.data);
				}
			},
			update: function(configurator, data){
				var items = this.target.find('.sk-stepTrailItem'), self = this,
				params = Utils.getUrlParamsAsJson(),
				step = this.currentStep;
				if (step > -1){
					this.layoutForStep(step);
					items.each(function(i){
						if (i <= step){
							if (i < step){
								$(this).removeClass('sk-bgDarkGray');
								$(this).removeClass('sk-stepTrailItem-inpath');
								$(this).removeClass('sk-stepTrailItem-straight-inpath');
								$(this).removeClass('sk-stepTrailItem-here');
								$(this).find('a').unbind().bind('click', function(e){
									var step = Utils.getUrlParamsAsJson($(this).attr('href')).skst / 1;
									e.preventDefault();
									e.stopPropagation();
									var k;
									if (!step){ // step = 0
										for (i = 1; i < configurator.slots.length; i+=1){
											configurator.slots[i].currentItem = 0;
										}
										
									}
									self.currentStep = step;
									configurator.verifyData();
									self.layoutForStep(step);
								}).css({
									cursor: 'pointer'
								});
								$(this).addClass('sk-stepTrailItem-inpath');
								if (i + 1 == step){
									$(this).addClass('sk-stepTrailItem-straight-inpath');
								}
							}else{
								$(this).addClass('sk-bgDarkGray sk-stepTrailItem-here').find('a').unbind().bind('click', function(e){
									e.preventDefault();
									e.stopPropagation();
									self.layoutForStep(step);
								}).css({
									cursor: 'default'
								});
							}
						}else{
							$(this).removeClass('sk-bgDarkGray');
							$(this).removeClass('sk-stepTrailItem-inpath');
							$(this).removeClass('sk-stepTrailItem-straight-inpath');
							$(this).removeClass('sk-stepTrailItem-here');
							$(this).find('a').unbind().bind('click', function(e){
								e.preventDefault();
								e.stopPropagation();
							}).css({
								cursor: 'default'
							});
						}
					});
				}
			}
		}
	);
//<<


// >> Tube info panel controller
	UI_TubeInfoPanelController = $.extend(
		$.clone(LLObject),
		{
			create: function(opts){
				var o = LLObject.create.call(this);
				o.target = $('.sk-stepInfo');
				o.defaults = {
					stepController: null
				};
				if(Utils.isObject(opts)){
					$.extend(o.defaults, opts);
				}
				return o;
			},
			makeLayoutWithDataFor_st_id: function(data){
				var image = '', lay;
				if (data.image){
					image = $('<img/>');
					image.attr({
							src: data.image.src,
							width: data.image.width / 2,
							height: data.image.height / 2
					});
					image = $('<div></div>').append(image).html();
				}
				lay = $(
					'<div class="sk-stepInfoItemContent">' +
						image +
						'<p>' +
							'<span class="sk-bold sk-unselectable">Gewählter Schlauchtyp:</span> ' + data.title +
						'</p>' +
					'</div>'
				);
				return lay;
			},
			makeLayoutWithDataForOthers: function(slot){
				var slot, selectedItem, item;
				selectedItem = slot.items[slot.currentItem];
				item = $(
					'<p>' +
						'<span class="sk-bold sk-unselectable">' + slot.title + '</span>: ' + selectedItem.title +
					'</p>'
				);
				return item;
			},
			makeLayoutWithDataForStaticSlot: function(title, value, classname){
				var item, cn;
				cn = classname ? ' ' + classname : ''
				item = $(
					'<p class="sk-staticSlotInfoItem' + cn + '">' +
						'<span class="sk-bold sk-unselectable">' + title + '</span>: ' + value +
					'</p>'
				);
				return item;
			},
			makeLayoutArmatureInfoImage:function(connectorSlot){
				var imgA = [], imgB = [], lay, cs = connectorSlot, item, img;
				if (cs.currentItemA){
					item = cs.items[cs.currentItemA];
					if (!item.image){
						//img = item.image;
						//imgA = $('<img class="sk-infoPanelImgA sk-posAbs" src="' + img.src + '" alt="' + item.title + '" title="' + item.title + '"/>');
						imgA = $('<img class="sk-infoPanelImgA sk-posAbs" src="/xist4c/px/spc.gif" alt="gurkA" title="gurkA"/>');
					}
				}
				if (cs.currentItemB){
					item = cs.items[cs.currentItemB];
					if (!item.image){
						//img = item.image;
						//imgB = $('<img class="sk-infoPanelImgB sk-posAbs" src="' + img.src + '" alt="' + item.title + '" title="' + item.title + '"/>');
						imgB = $('<img class="sk-infoPanelImgB sk-posAbs" src="/xist4c/px/spc.gif" alt="hurzB" title="hurzB"/>');
					}
				}
				lay = $(
					'<div class="sk-armaturesImage sk-viewport">' +
					'</div>'
				);
				if (imgA.length){
					lay.append(imgA);
				}
				if (imgB.length){
					lay.append(imgB);
				}
				return lay;
			},
			updateStepDetailInfo: function(infoItem, infoData){
				if (infoData.longdesc){
					infoItem.find('.sk-stepInfoMoreDetail').html(infoData.longdesc);
					infoItem.find('.sk-stepInfoMoreDetailButton').toggle(
						function(e){
							$(this).find('.sk-stepInfoMoreDetailPlus').text('-');
							$(this).find('.sk-stepInfoMoreDetailText').text('Weniger Details anzeigen');
							$(this).parent().siblings('.sk-stepInfoMoreDetail').slideDown('fast');
						},
						function(e){
							$(this).find('.sk-stepInfoMoreDetailPlus').text('+');
							$(this).find('.sk-stepInfoMoreDetailText').text('Mehr Details anzeigen');
							$(this).parent().siblings('.sk-stepInfoMoreDetail').slideUp('fast');
						}
						).css({
							opacity: 1,
							cursor: 'pointer'
						});
				}
			},
			updateHoseInfo: function(data, step, infoItems){
				var item;
				if (data.hose_info){
					if (step == 1){
						if (data.hose_info.material){
							item = this.makeLayoutWithDataForStaticSlot('Material', data.hose_info.material, 'sk-hoseInfoMaterial');
							$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
						}
					}
				}
			},
			update: function(data){
				var infoItems = this.target.find('li'), item, slot, slotItem, k, emptyText, furtherStep, i,
				stepController = this.defaults.stepController, infoData = {
					longdesc: ''
				},
				step = stepController.currentStep, currentItems = [],
				stepAttrs = SC_Attributes.getAttrsForStep(step);
				for (i = step; i <= stepController.defaults.stepCount; i+=1){
					$('.sk-stepInfoItemContent, .sk-defaultEmptyText', infoItems.eq(i)).remove();
					infoItems.eq(i).append('<div class="sk-defaultEmptyText">Noch nicht gewählt</div>');
					$('.sk-stepInfoMoreDetail', infoItems.eq(i)).empty();
					$('.sk-stepInfoMoreDetailButton', infoItems.eq(i)).unbind().css({
						opacity: .5,
						cursor: 'default'
					});
				}
				for (k in data.slots){
					slot = data.slots[k];
					if(slot.currentItem && $.inArray(slot.pk, stepAttrs) > -1){
						if (step == 0){
							slotItem = slot.items[slot.currentItem];
							item = this['makeLayoutWithDataFor_' + slot.pk](slotItem);
							infoItems.eq(step).find('.sk-defaultEmptyText').replaceWith(item);
							infoData.longdesc = slotItem.longdesc;
						}else if (step == 1){
							if (!$('.sk-stepInfoItemContent', infoItems.eq(step)).length){
								infoItems.eq(step).find('.sk-defaultEmptyText')
									.replaceWith('<div class="sk-stepInfoItemContent"></div>');
							}
							item = this.makeLayoutWithDataForOthers(slot);
							$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
						}
					}
				}
				if (step == 1 && data.tubeLength){
					item = this.makeLayoutWithDataForStaticSlot('Länge inkl. Armaturen (mm)', data.tubeLength, 'sk-staticSlotTubeLength');
					$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
				}else if (step == 2){
					if (!$('.sk-stepInfoItemContent', infoItems.eq(step)).length){
						infoItems.eq(step).find('.sk-defaultEmptyText')
							.replaceWith('<div class="sk-stepInfoItemContent"></div>');
					}
					item = this.makeLayoutArmatureInfoImage(data.connectorSlot);
					$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
					if (data.connectorSlot.currentItemA){
						item = this.makeLayoutWithDataForStaticSlot(
							'Armatur A', 
							data.connectorSlot.items[data.connectorSlot.currentItemA].title, 
							'sk-staticSlotArmatureA'
						);
						$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
						infoData.longdesc += '<p><b>Armatur A:</b><br/>' + 
							data.connectorSlot.items[data.connectorSlot.currentItemA].longdesc + '</p>';
					}
					if (data.connectorSlot.currentItemB){
						item = this.makeLayoutWithDataForStaticSlot(
							'Armatur B', 
							data.connectorSlot.items[data.connectorSlot.currentItemB].title, 
							'sk-staticSlotArmatureB'
						);
						$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
						infoData.longdesc += '<p><b>Armatur B:</b><br/>' + 
							data.connectorSlot.items[data.connectorSlot.currentItemB].longdesc + '</p>';
					}
				}else if (step == 3){
					if (!$('.sk-stepInfoItemContent', infoItems.eq(step)).length){
						infoItems.eq(step).find('.sk-defaultEmptyText')
							.replaceWith('<div class="sk-stepInfoItemContent"></div>');
					}
					$('.sk-stepInfoItemContent', infoItems.eq(step)).empty();
					if (data.options && data.options.length){
						for (k in data.options){
							if (data.options[k].here){
								item = this.makeLayoutWithDataForStaticSlot(
									data.options[k].title,
									data.options[k].desc,
									'sk-staticSlotOption'
								);
								$('.sk-stepInfoItemContent', infoItems.eq(step)).append(item);
								infoData.longdesc += '<p><b>' + data.options[k].title +'</b>:<br/>' + data.options[k].longdesc + '</p>';
							}
						}
					}
				}
				this.updateHoseInfo(data, step, infoItems);
				this.updateStepDetailInfo(infoItems.eq(step), infoData);
			}
		}
	);
// <<


// >> Additional ui elements to handle configurator data
	UI_ArticleActionbar = $.extend(
		$.clone(LLObject),
		{
			create: function(opts){
				var o = LLObject.create.call(this);
				o.target = $('#sk-articleBar').empty();
				o.defaults = {
					stepController: null,
					infoPanelController: null
				};
				if (typeof opts === 'object'){
					$.extend(o.defaults, opts);
				}
				return o;
			},
			currentStep: function(){
				var params = Utils.getUrlParamsAsJson();
				if (params && typeof(params.skst) !== 'undefined'){
					return window.SK_CURRENT_STEP = params.skst;
				}
				return window.SK_CURRENT_STEP;
			},
			makeLayout: function(){
				var lay;
				lay = $(
					'<div class="sk-uiArticleActionbar sk-viewport sk-bgLightGray">' +
						'<div class="sk-ActionbarArticleNumber sk-posAbs">' +
							'<span class="sk-prompt sk-bold sk-unselectable">Artikelnummer:</span>' +
							'<span class="sk-articleNumber">----</span>' +
						'</div>' +
						'<div class="sk-ActionbarArticlePrice sk-posAbs">' +
							'<span class="sk-prompt sk-bold sk-unselectable">Stückpreis:</span>' +
							'<span class="sk-articlePrice"><span class="price">0,00 &euro;</span></span>' +
						'</div>' +
						'<div class="sk-ActionbarButton sk-posAbs sk-bold sk-unselectable sk-buttonBehaviour sk-buttonBehaviourPassive">' +
							'<span></span>' +
						'</div>' +
					'</div>'
				);
				return lay;
			},
			make: function(){
				var target = this.target, lay = this.makeLayout();
				target.append(lay);
			},
			updateHoseInfo: function(data){
				var actionBar = $('.sk-uiArticleActionbar'),
				price = actionBar.find('.price');
				articleNumber = actionBar.find('.sk-articleNumber');
				if (data.hose_info){
					if (data.hose_info.price){
						price.html(data.hose_info.price);
					}else{
						price.html('0,00 &euro;');
					}
					if (data.hose_info.articleNumber){
						articleNumber.html(data.hose_info.articleNumber);
					}else{
						articleNumber.html('----');
					}
				}else{
					price.html('0,00 &euro;');
					articleNumber.html('----');
				}
			},
			update: function(data){
				var target = this.target, button = target.find('.sk-ActionbarButton'), k, stepAttrs, stepIsValid,
				stepController = this.defaults.stepController, infoPanelController = this.defaults.infoPanelController,
				self = this;
				if (data.prd_id){
					target.find('.sk-articleNumber').text(data.prd_id);
				}
				if (data.meta && data.meta.price){
					target.find('.price').text(data.meta.price);
				}
				switch (stepController.currentStep.toString()){
					case '0':
						button.children('span').html('&raquo;&nbsp;Abmessungen festlegen');
						if (data.slots.length >= 3 && data.slots[0].currentItem != 0){
							button.removeClass('sk-buttonBehaviourPassive').unbind().bind('click', function(e){
								stepController.next();
							});
						}else{
							target.find('.sk-ActionbarButton').unbind().addClass('sk-buttonBehaviourPassive');
						}
						this.updateHoseInfo(data);
						break;
					case '1':
						button.children('span').html('&raquo;&nbsp;Armaturen auswählen');
						if (data.sc_id && data.tubeLength){
							button.removeClass('sk-buttonBehaviourPassive').unbind().bind('click', function(e){
								stepController.next();
								if (infoPanelController){
									infoPanelController.update(data, stepController);
								}
							});
						}else{
							target.find('.sk-ActionbarButton').unbind().addClass('sk-buttonBehaviourPassive');
						}
						this.updateHoseInfo(data);
						break;
					case '2':
						button.children('span').html('&raquo;&nbsp;Optionen wählen');
						if (data.sc_id && data.connectorSlot && data.connectorSlot.currentItemA && data.connectorSlot.currentItemB){
							button.removeClass('sk-buttonBehaviourPassive').unbind().bind('click', function(e){
								stepController.next();
								if (infoPanelController){
									infoPanelController.update(data, stepController);
								}
							});
						}else{
							target.find('.sk-ActionbarButton').unbind().addClass('sk-buttonBehaviourPassive');
						}
						this.updateHoseInfo(data);
						break;
					case '3':
						button.children('span').html('&raquo;&nbsp;Konfiguration abschließen');
						if (data.sc_id && data.connectorSlot && data.connectorSlot.currentItemA && data.connectorSlot.currentItemB){
							button.removeClass('sk-buttonBehaviourPassive').unbind().bind('click', function(e){
								stepController.next();
								if (infoPanelController){
									infoPanelController.update(data, stepController);
								}
							});
						}else{
							target.find('.sk-ActionbarButton').unbind().addClass('sk-buttonBehaviourPassive');
						}
						this.updateHoseInfo(data);
						break;
					case '4':
						button.children('span').html('&raquo;&nbsp;In den Warenkorb legen');
						if (data.sc_id && data.connectorSlot && data.connectorSlot.currentItemA && data.connectorSlot.currentItemB){
							button.removeClass('sk-buttonBehaviourPassive').unbind().bind('click', function(e){
								/* todo: Implement the shoppingcart logic */
							});
						}else{
							target.find('.sk-ActionbarButton').unbind().addClass('sk-buttonBehaviourPassive');
						}
						break;
				}
			}
		}
	);
// <<


// >> GC machine field connection config
	lltools.GC_FieldConnectionConfig = {
		optAttributesPrimaryKeys: [
			'sc_betrdruck20',
			'sc_spitzendruck20',
			'sc_biegeradstat',
			'sc_biegeraddyn'
		],
		handleConnectionForKey: function(key, configurator, slot){
			if (typeof this[key] !== 'undefined'){
				return this[key](configurator, slot);
			}
			return null;
		},
		sc_innendurchm: function(configurator, slot){
			var k, connectedSlots = configurator.getSlotsWithPrimaryKeys(this.optAttributesPrimaryKeys);
			if (slot.data.currentItem == 0){
				for (k in connectedSlots){
					connectedSlots[k].currentItem = 0;
				}
			}
		},
		sc_aussendurchm: function(configurator, slot){
			var k, connectedSlots = configurator.getSlotsWithPrimaryKeys(this.optAttributesPrimaryKeys);
			if (slot.data.currentItem == 0){
				for (k in connectedSlots){
					connectedSlots[k].currentItem = 0;
				}
			}
		}
	}
// <<


// >> GC initialization part one (tube)
	$(function(){
		if ($('#sk-machineElements').length){
			var handleStaticLengthSlot = function(configurator, data){
				var lengthSlot = GC_LengthAttribute.create('Länge inkl. Armaturen (mm)', 0);
				lengthSlot.configurator = configurator;
				lengthSlot.id = 100;
				lengthSlot.data = data;
				lengthSlot.make(configurator.defaults.target);
				lltools.UI_InfoPanelController.update(data, lltools.UI_StepController);
			},
			handleStaticArmatureSlot = function(configurator, data){
				$('.gc-sk-armatureOuter').remove();
				if (data.connectorSlot){
					var armatureSlot = GC_ArmatureSlot.create(null, data.connectorSlot.currentItemA, data.connectorSlot.currentItemB);
					armatureSlot.configurator = configurator;
					armatureSlot.id = '_200';
					armatureSlot.data = data;
					$(data.connectorSlot.items).each(function(i){
						var slotItem = GC_ArmatureSlotItem.create(this.title, this.value);
						slotItem.configurator = configurator;
						slotItem.id = armatureSlot.id + '_slotItem_' + i;
						slotItem.itemCnt = i;
						slotItem.data = this;
						slotItem.slot = armatureSlot;
						slotItem.width = armatureSlot.width;
						armatureSlot.appendItem(slotItem);
					});
					armatureSlot.make(configurator.defaults.target);
				}
			},
			handleStaticOptionSlot = function(configurator, data){
				var k, optionSlot, currentItems = [];
				$('.gc-sk-optionOuter').remove();
				if (data.options && data.options.length){
					for (k in data.options){
						if (data.options[k].here){
							currentItems.push(parseInt(k));
						}
					}
					optionSlot = GC_OptionSlot.create(null, currentItems);
					optionSlot.configurator = configurator;
					optionSlot.id = '_300';
					optionSlot.data = data.options;
					$(data.options).each(function(i){
						var slotItem = GC_OptionSlotItem.create(this.title, this.value);
						slotItem.configurator = configurator;
						slotItem.id = optionSlot.id + '_slotItem_' + i;
						slotItem.itemCnt = i;
						slotItem.data = this;
						slotItem.slot = optionSlot;
						slotItem.width = optionSlot.width;
						optionSlot.appendItem(slotItem);
					});
					optionSlot.make(configurator.defaults.target);
				}
			},
			handleFinishConfiguration = function(configurator){
				var msg = 'Bitte überprüfen Sie Ihre Konfiguration und legen Sie Ihr Produkt anschließend in den Warenkorb.',
				lay = $('<div class="gc-sk-finishConfigurationOuter">' + msg + '</div>');
				$('.gc-sk-finishConfigurationOuter').remove();
				configurator.defaults.target.append(lay);
				
			};
			lltools.UI_StepController = UI_StepTrailController.create();
			lltools.UI_InfoPanelController = UI_TubeInfoPanelController.create({
				stepController: lltools.UI_StepController
			});
			lltools.UI_Actionbar = UI_ArticleActionbar.create({
				infoPanelController: lltools.UI_InfoPanelController,
				stepController: lltools.UI_StepController
			});
			lltools.UI_Actionbar.make();
			lltools.UI_StepController.defaults.actionBar = lltools.UI_Actionbar;
			lltools.GCPart1 = GC_TubeConfigurator.create();
			lltools.GCPart1.init({
				target: $('#sk-machineElements'),
				slotType: '',
				slotItemType: '',
				ajaxHandler: 'configarticle',
				onBeforeInit: function(){
				},
				onInitDataReceive: function(data){
				},
				onBeforeEachSlot: function(slotData, index){
				},
				onBeforeEachSlotItem: function(itemData, index){
				},
				onAfterInit: function(data){
					handleStaticLengthSlot(this, data);
				},
				onAfterSlotCatch: function(slot){
					lltools.GC_FieldConnectionConfig.handleConnectionForKey(slot.data.pk, slot.configurator, slot);
				},
				onAfterSlotsUpdate: function(){},
				onSlotAction: function(eventElement){},
				onDataRequest: function(configurator, oldData){},
				onDataRequestSuccess: function(slot, data){
					handleStaticArmatureSlot(this, data);
					handleStaticOptionSlot(this, data);
					handleFinishConfiguration(this);
					lltools.UI_StepController.update(this, data);
					lltools.UI_Actionbar.update(data);
					lltools.UI_InfoPanelController.update(data);
				}
			});
		}
	});
// <<


// >> GC initialization part two (armature)
// <<


