//[http://www.pseliger.de/jsExtendedApi/jsApi.bundles.DOM.getters.js]
/*
	- due to dynapi namespace collidition bugs it is not able to implement a prototype method [Array.prototype.forEach]
	- therefore every possible usecase for "[array object].forEach" got changed to a static "Array.forEach([array object], ...)"
*/
Array.forEach = function (obj, fct) {if(typeof fct=="function"){var i,l=(((obj instanceof Array)||((typeof obj.length=="number")&&((typeof obj.item=="function")||(typeof obj.item=="object")||(typeof obj.item=="string")||(obj instanceof window.NodeList)||(obj instanceof window.HTMLCollection))))?(obj.length):(0));for(i=0;i<l;++i){fct.call(null,(obj[i]||obj.item(i)),i,obj);}}};

//[http://www.pseliger.de/jsExtendedApi/jsApi.EventDispatcher.packer.compressed.js] - see also: [http://www.pseliger.de/jsExtendedApi/jsApi.EventDispatcher.js] as well as [http://www.pseliger.de/jsExtendedApi/jsApi.EventDispatcher.dev.js] and [http://www.pseliger.de/jsExtendedApi/jsApi.EventDispatcher.hybrid.js]
var EventDispatcher = new(function(){this.constructor=Object;var Event=function(target,type){this.constructor=arguments.callee;this.initEvent=function(target,type){this.target=target;this.type=type;this.timeStamp=new Date()};this.initEvent.apply(this,arguments)};var EventListener=function(thisTarget,type,handler){this.constructor=arguments.callee;var defaultEvent=new Event(thisTarget,type);this.handleEvent=function(evt){if(typeof evt==="string"){evt={target:defaultEvent.target,type:defaultEvent.type,timeStamp:defaultEvent.timeStamp}}else{evt.target=((evt.target&&(typeof evt.target==="object")&&(evt.target instanceof EventTarget))?(evt.target):(defaultEvent.target));evt.type=((evt.type&&((typeof evt.type==="string")||(evt.type instanceof String)))?(evt.type):(defaultEvent.type));evt.timeStamp=defaultEvent.timeStamp}handler(evt)}};var EventTarget=function(){this.constructor=arguments.callee;var events={};this.addEventListener=function(type,handler){if(type&&handler&&((typeof type==="string")||(type instanceof String))&&(typeof handler==="function")){var listener=new EventListener(this,type,handler);if(events[type]){var handlers=events[type].handlers;var listeners=events[type].listeners;if(!handlers.contains(handler)){handlers.push(handler);listeners.push(listener)}}else{var event=events[type]={};event.handlers=[];event.listeners=[];event.handlers.push(handler);event.listeners.push(listener)}listener=null;delete listener}};this.removeEventListener=function(type,handler){if(type&&handler&&((typeof type==="string")||(type instanceof String))&&(typeof handler==="function")){if(events[type]){var handlers=events[type].handlers;var listeners=events[type].listeners;var idx=handlers.indexOf(handler);handlers.remove(handler);listeners.remove(listeners[idx])}}};this.dispatchEvent=function(evt){var successfully=false;var type;type=((evt)?((typeof evt==="object")?((typeof evt.type==="string")?(evt.type):(type)):((typeof evt==="string")?(evt):(type))):(type));if(type){Array.forEach(events[type].listeners, (function(elm){elm.handleEvent(evt)}));successfully=true}return successfully}};this.register=function(obj){EventTarget.call(obj)};this.unsubscribe=function(obj){if(typeof obj.addEventListener==="function"){delete obj.addEventListener}if(typeof obj.removeEventListener==="function"){delete obj.removeEventListener}if(typeof obj.dispatchEvent==="function"){delete obj.dispatchEvent}}})();



(function (isSelfIntroducing) { // [[MiniSilhouetteNavigation]] could also be achived as [[Singleton]] *constructor* pattern


	var regXRangeClass = (/^(mini\s+clubman|mini\s+cabrio|mini\s+convertible|mini\s+cabriolet|mini)(?:\s|\b)/);
	var regXWhiteSpace = (/\s+/);

	var images = {}; // to be assigned by an outside preloader object


	var Model = function (/*elm:[HTMLLIElement]*/) { // *private* constructor - [en] model / [de] Modell


		this.constructor = arguments.callee;
		var self = this;

		EventDispatcher.register(this); // DOM2AlikeEventDispatcher


		var node, nodeLeft, nodeWidth;

		var timeoutId, timeout = 20, inkrement = 15, stopAt;
		var sliding = function () {

			clearTimeout(timeoutId);

			if (nodeLeft >= stopAt) {
				node.getElementsByTagName("a")[0].style.visibility = "visible";
				node.style.background = "none";
				node.style.left = (stopAt + "px");
				nodeLeft = stopAt;
			} else {
				nodeLeft += inkrement;
				node.style.left = (nodeLeft + "px");

				timeoutId = setTimeout(sliding, timeout);
			}
		};


		this.slideIn = function () {

			clearTimeout(this.timeoutId);

			node.getElementsByTagName("a")[0].style.visibility = "hidden";
			node.style.background = ("transparent url(" + images.backgroundCopies[node.id].src + ") no-repeat scroll 0 3px");
			node.style.left = ("-" + nodeWidth + "px");
			node.style.visibility = "visible";

			nodeLeft = -nodeWidth;
			stopAt = 0;

			sliding();
		};
		this.slideOut = function () {

			node.getElementsByTagName("a")[0].style.visibility = "hidden";
			node.style.background = ("transparent url(" + images.backgroundCopies[node.id].src + ") no-repeat scroll 0 3px");

			nodeLeft = 0;
			stopAt = (nodeWidth + 1);

			sliding();
		};


		this.compile = function (elm/*:[HTMLLIElement]*/) {

			node = elm;

			node.style.position = "relative";
			node.style.left = "0px";
			node.style.top = "0px";

			nodeLeft = node.offsetLeft;
			nodeWidth = node.offsetWidth;

			node.style.visibility = "hidden"; // due to msie 6.x

			node.onmouseover = function () {
				self.onRollOver(this);
			};
			node.onmouseout = function () {
				self.onRollOut(this);
			};
		};

		this.compile.apply(this, arguments);
	};
	Model.prototype.onRollOver = function (elm) {

		this.dispatchEvent({type: "onModelRollOver", target: this, targetNode: elm/*, even more key:value pairs */}); // DOM2AlikeEventDispatcher
	};
	Model.prototype.onRollOut = function (elm) {

		this.dispatchEvent({type: "onModelRollOut", target: this, targetNode: elm/*, even more key:value pairs */}); // DOM2AlikeEventDispatcher
	};


	var ModelRange = function (/*elm:[HTMLLIElement]*/) { // *private* constructor - [en] model range / [de] Baureihe


		this.constructor = arguments.callee;
		var self = this;

		EventDispatcher.register(this); // DOM2AlikeEventDispatcher


		var imgLeft, imgTop, imgWidth, nodeWidth, forcedRefresh = false;


		var timeoutId, timeout = 20, inkrement = 13, stopAt;
		var acting = function () {

			clearTimeout(timeoutId);

			if (imgLeft >= stopAt) {
				self.node.style.backgroundPosition = (stopAt + "px " + imgTop + "px");
				imgLeft = stopAt;

				self.fadeOut(forcedRefresh);
			} else {
				imgLeft += inkrement;
				self.node.style.backgroundPosition = (imgLeft + "px " + imgTop + "px");

				timeoutId = setTimeout(acting, timeout);
			}
		};
		this.enterStage = function (doRefresh) {

			clearTimeout(this.timeoutId);

			forcedRefresh = !!doRefresh;

			this.node.style.backgroundImage = "url(" + images.blurs[this.rangeClass].src + ")";
			this.node.style.backgroundPosition = ("-" + imgWidth + "px " + imgTop + "px");
			this.node.style.visibility = "visible";
			imgLeft= -imgWidth;
			stopAt = 0;
			acting();
		};
		this.leaveStage = function () {

			clearTimeout(this.timeoutId);

			this.node.style.backgroundImage = "url(" + images.blurs[this.rangeClass].src + ")";
			imgLeft = 0;
			stopAt = (nodeWidth + 1);
			acting();
		};
		this.appearSuddenly = function () {

			this.node.style.backgroundImage = "url(" + images.strokes[this.rangeClass].src + ")";
			this.node.style.backgroundPosition = ("0px " + imgTop + "px");
			this.node.style.visibility = "visible";
		};


		this.compile = function (elm/*:[HTMLLIElement]*/) {

			this.node = elm;
			this.node.style.visibility = "hidden";

			this.node.onclick = function () {
				self.onRelease(this);
			};
			this.node.onmouseover = function () {
				self.onRollOver(this);
			};
			this.node.onmouseout = function () {
				self.onRollOut(this);
			};

			this.rolloverState = "left";

			this.models = [];

			this.rangeClass = this.getRangeClass();

			if (this.rangeClass !== "") { // completly compiles for a properly classified html/css based [ModelRange]-object pendant only

				var img = images.blurs[this.rangeClass];

			//imgLeft = 0; // unfortunaltely no browser but opera can calculate this information
			//imgTop = 3;  // unfortunaltely no browser but opera can calculate this information

			// the above 2 commented out values are likely to differ for each model range - 
			// therefore those data needs to be maintained within the local [images] *hashtable* object:
				var positions = images.CSSBackgroundPositions[this.rangeClass].split(/\s+/);
				imgLeft = Number(parseInt(positions[0], 10));
				imgTop = Number(parseInt(positions[1], 10));

				imgLeft = ((isNaN(imgLeft)) ? (0) : (imgLeft));
				imgTop = ((isNaN(imgTop)) ? (0) : (imgTop));
				imgWidth = img.width;
				nodeWidth = this.node.offsetWidth;

				this.node.style.background = ("transparent url(" + img.src + ") no-repeat scroll " + imgLeft + "px " + imgTop + "px");

				var navElm = elm.getElementsByTagName("ul")[0];
				if (navElm) {

					var obj; // model;

					Array.forEach(navElm.childNodes, (function (elm/*, idx, arr*/) {
						if (elm.nodeType && (elm.nodeType === 1) && elm.nodeName && (elm.nodeName.toLowerCase() === "li")) {

							obj = new Model(elm);

							obj.addEventListener("onModelRollOver", self.onModelRollOver); // DOM2AlikeEventDispatcher
							obj.addEventListener("onModelRollOut", self.onModelRollOut);   // DOM2AlikeEventDispatcher

							self.models.push(obj);
						}
					}));
				}
			}
		};

		this.compile.apply(this, arguments);

	};
	ModelRange.prototype.getRangeClass = function () {

		return (((regXRangeClass.test(this.node.className)) ? (regXRangeClass.exec(this.node.className)[1]) : ("")).replace(regXWhiteSpace, " "));
	};
	ModelRange.prototype.fadeIn = function (forceRefresh) {

		this.node.style.backgroundImage = "url(" + images.colours[this.rangeClass].src + ")";
	};
	ModelRange.prototype.fadeOut = function (forceRefresh) {/* no fadeout animation anymore:

		if (window.attachEvent && !window.addEventListener && (typeof XMLHttpRequest == "undefined")) {
			this.node.style.backgroundImage = "url(" + images.strokes[this.rangeClass].src + ")";
		} else { // not figured out yet, what msie 6.x prevents from properly behaving here - though it successfully runs within msie 7 - test of msie 7: ((typeof XMLHttpRequest == "object") && !!XMLHttpRequest)
			this.node.style.backgroundImage = "url(" + images.animations.fadeOuts[this.rangeClass].src + ((!!forceRefresh) ? ("?refresh" + (new Date().getTime())) : ("")) + ")";
		}*/
		this.node.style.backgroundImage = "url(" + images.strokes[this.rangeClass].src + ")";
	};
	ModelRange.prototype.introduceYourself = function () { // introduce yourself once in the beginning

		clearTimeout(this.timeoutId);
		if (this.rangeClass !== "") {

			this.enterStage();
		}
	};
	ModelRange.prototype.onRelease = function (elm) {

	//due to "click-strict"-behavior:
		this.dispatchEvent({type: "onModelRangeFocused", target: this, targetNode: elm/*, even more key:value pairs */}); // DOM2AlikeEventDispatcher

	//this.node.focus(); // commented out - did cause errors within a tested mozilla 1.7.6

		if (this.rolloverState === "entered") {

			var self = this;
			this.timeoutId = setTimeout((function () {self.leaveStage();}), 210);

		//this.models.forEach(function (model, idx/*, arr*/) { // due to dynapi namespace collidition bugs
			Array.forEach(this.models, (function (model, idx/*, arr*/) { // due to dynapi namespace collidition bugs

				model.timeoutId = setTimeout((function () {model.slideIn();}), ((idx+3) * 60));
			}));
		}
		this.rolloverState = "focused";
	};
	ModelRange.prototype.onRollOver = function (elm) {

	//due to "click-strict"-behavior:
		this.dispatchEvent({type: "onModelRangeRollover", target: this, targetNode: elm/*, even more key:value pairs */}); // DOM2AlikeEventDispatcher

		clearTimeout(this.timeoutIdState);

		if (this.rolloverState === "left") {

			this.rolloverState = "entered";
			this.fadeIn(true);
		}
	};
	ModelRange.prototype.onRollOut = function (elm) {

	//clearTimeout(this.timeoutIdState);
		var self = this;

		if (this.rolloverState === "entered") {

			this.timeoutIdState = setTimeout((function () {

				self.rolloverState = "left";
				self.fadeOut(true);
			}), 100); // 300

		}
	};
	ModelRange.prototype.onModelRollOver = function (evt) {

		clearTimeout(this.timeoutIdState);
		this.rolloverState = "focused";
	};
	ModelRange.prototype.onModelRollOut = function (evt) {

		var self = this;
		this.timeoutIdState = setTimeout((function () {self.rolloverState = "left";}), 100);
	};


	var modelRanges = [];

	var onModelRangeFocused = function () {

	//due to "click-strict"-behavior:
	//modelRanges.forEach(function (modelRange/*, idx, arr*/) { // due to dynapi namespace collidition bugs
		Array.forEach(modelRanges, (function (modelRange/*, idx, arr*/) { // due to dynapi namespace collidition bugs

			if (modelRange.rolloverState == "focused") {

				modelRange.timeoutIdState = setTimeout((function () {

					modelRange.timeoutId = setTimeout((function () {modelRange.enterStage(true);}), 280); // 210

				//modelRange.models.forEach(function (model, idx/*, arr*/) { // due to dynapi namespace collidition bugs
					Array.forEach(modelRange.models, (function (model, idx/*, arr*/) { // due to dynapi namespace collidition bugs

						model.timeoutId = setTimeout((function () {model.slideOut();}), ((idx+1) * 60));
					}));
					modelRange.rolloverState = "left";
				}), 500);
			}
		}));
	};

	var timoutIdRestore;

	var onModelRangeRollover = function () {

		clearTimeout(timoutIdRestore);
	};


	var initialized = false;

	var initialize = function () {

		if (!initialized) {

			initialized = true;
			modelRanges = [];

			var navElm = document.getElementsByTagName("ul")["miniSilhouetteNavigation"];
			if (navElm) {

				if (silhoutteNavigationImages && (typeof silhoutteNavigationImages == "object")) {

					images = silhoutteNavigationImages;

					silhoutteNavigationImages = null;
					delete silhoutteNavigationImages;
				}

				Array.forEach(navElm.childNodes, (function (elm/*, idx, arr*/) {
					if (elm.nodeType && (elm.nodeType === 1) && elm.nodeName && (elm.nodeName.toLowerCase() === "li")) {

						modelRanges.push(new ModelRange(elm));
					}
				}));

				navElm.onmouseout = function () {
					timoutIdRestore = setTimeout((function () {onModelRangeFocused();}), 500);
				};
			}


			if (!!isSelfIntroducing) {

				setTimeout((function () {
					//modelRanges.forEach(function (modelRange, idx/*, arr*/) { // introduce yourself once in the beginning
						Array.forEach(modelRanges, (function (modelRange, idx/*, arr*/) { // due to dynapi namespace collidition bugs

					//due to "click-strict"-behavior:
						modelRange.addEventListener("onModelRangeRollover", onModelRangeRollover); // DOM2AlikeEventDispatcher
						modelRange.addEventListener("onModelRangeFocused", onModelRangeFocused); // DOM2AlikeEventDispatcher

						modelRange.timeoutId = setTimeout((function () {modelRange.introduceYourself();}), ((idx+1) * 300));
					}));
				}), 300);

			} else {

			//modelRanges.forEach(function (modelRange, idx/*, arr*/) { // no introduction - be right in place from beginning
				Array.forEach(modelRanges, (function (modelRange, idx/*, arr*/) { // due to dynapi namespace collidition bugs

				//due to "click-strict"-behavior:
					modelRange.addEventListener("onModelRangeRollover", onModelRangeRollover); // DOM2AlikeEventDispatcher
					modelRange.addEventListener("onModelRangeFocused", onModelRangeFocused); // DOM2AlikeEventDispatcher
					modelRange.appearSuddenly();
				}));
			}

			regXRangeClass = null; regXWhiteSpace = null;
			delete regXRangeClass; delete regXWhiteSpace;

			delete arguments.callee; // method terminates itself after execution
		}
	};


	if (window.addEventListener) {
		window.addEventListener("load", initialize, false);
	} else if (window.attachEvent) {
		window.attachEvent("onload", initialize);
	}
})(); // apply parameter [true] for starting with method [introduceYourself] or leave it as is to work with [appearSuddenly]
