/*
 * Name : ToolBox.js
 * Author: Patrick Heyer
 * Maintainer: Patrick Heyer
 * 
 * Current Version 0.7
 * 
 * Changelog
 * ---------------------
 * 
 * 0.1: Added NoteBox class to ToolBox
 * 
 * 0.2: Created ToolBox-Class, moved certain methods to class.
 * 
 * 0.3: Added GlobalTimer as class
 * 
 * 0.4: Finalized some stuff, made ToolBox compatible with other projects "plug&play"
 * 
 * 0.5: Added cursor-fix for clickable elements
 * 
 * 0.6: Using Milkbox by Luca Reghellin (http://www.reghellin.com) 
 * August 2009, MIT-style license.
 *
 * 0.7 Added graphical scrollbar class
 *
 */


var isIE = false /*@cc_on || true @*/;
var isIE6 = isIE && (document.implementation != null) && (document.implementation.hasFeature != null);

/* update cursor on add/remove click event */
Element.Events.click = { 
	base:'click',
	onAdd: function() {
		if(this.getStyle && this.get("tag") != "a" && !this.match("input[type=text]") && !this.match("input[type=password]")) {
			this.store('original-cursor',this.getStyle('cursor'));
			this.setStyle('cursor','pointer');
		}
	},
	onRemove: function() {
		if(this.setStyle && this.get("tag") != "a" && !this.match("input[type=text]") && !this.match("input[type=password]")) {
			this.setStyle('cursor',this.retrieve('original-cursor'));
		}
	}
};

var ToolBox = new Class({
	initialize: function() {
		this.myTimer = new GlobalTimer();
		this.onLoadFunctions = new Array();
		this.onLoadVars = new Array();
		this.dynContentCache = new Object();
		this.objectStore = new Object();
		this.jsonRequests = new Object();
	},
	getTimerObject: function() {
		return this.myTimer;
	},
	getContentCache: function() {
		return this.dynContentCache;
	},
	getObjectStore: function() {
		return this.objectStore;
	},
	registerOnLoadFunc: function(func, vars) {
		this.onLoadFunctions.push(func);
		this.onLoadVars.push(vars);
	},
	execOnLoadFuncs: function() {
		for (var i = 0; i < this.onLoadFunctions.length; i++) {
			this.onLoadFunctions[i].run(this.onLoadVars[i]);
		}
	}
});

var TopScroller = new Class({
	initialize: function() {
		this.topScrollBox = new Element("a", {
			id: "topScrollBox",
			text: "Top",
			href: "#top",
			styles: {
				position: "fixed",
				bottom: 5,
				right: 5,
				"z-index": 300,
				padding: "7px 7px 7px 20px" 
			}
		});

		if (isIE6) {
			this.topScrollBox.pin();
		}
		
		$(document.body).grab(this.topScrollBox);
		
		this.topScrollBox.fade("hide");
		
		window.addEvent("scroll", function(e) {
			$("topScrollBox").fade((document.body.getScroll().y > 200) ? "in" : "out")
		});
	},
	toElement: function() {
		return this.topScrollBox;
	}
});

var GlobalTimer = new Class({
	initialize: function() {
		this.numTimers = 0;
		this.timers = new Object();
	},
	addTimer: function(myTimer, myTimerName) {
		this.timers[myTimerName] = myTimer;
		this.numTimers++;
	},
	clearTimer: function(myTimerName) {
		this.timers[myTimerName] = $clear(this.timers[myTimerName]);
		this.numTimers--;
	}
});

var ScrollSlider = new Class({
	Implements: [Options], 
	options: {
		horizontal: false,
		ignoreMouse: false,
		smoothScroll: false,
		offsets: {x: 0, y:0}
	},
	initialize: function(content, options) {
		if (!$defined(content)) {
			return false;
		}
		
		this.setOptions(options);
		
		this.steps = (this.options.horizontal ? (content.getScrollSize().x - content.getSize().x) : (content.getScrollSize().y - content.getSize().y));
		this.content = content;
		
		this.scrollbar = new Element("div", {
			"class": "scroll" + (this.options.horizontal ? "Horizontal" : "Vertical")
		});
		
		this.handle = new Element("span", {
			"text": "Scroll me!"
		});
		
		this.scrollbar.grab(this.handle);
		this.scrollbar.fade("hide");
		
		this.content.getParent("li.blade").grab(this.scrollbar);
		
		this.enableSlider();
	},
	enableSlider: function(index) {
		if (this.steps <= 0) {
			return;
		}
		this.scrollbar.setStyle("height", this.content.getStyle("height") - 5);
		this.scrollbar.position({
			relativeTo: this.content,
			position: {x: "right", y: "top"},
			edge: {x: "center", y: "top"},
			offset: this.options.offsets
		});
		
		this.slider = new Slider(this.scrollbar, this.handle, {
			steps: this.steps,
			mode: (this.options.horizontal ? "horizontal" : "vertical"),
			onChange: function(step) {
				var x = (this.options.horizontal ? step : 0);
				var y = (this.options.horizontal ? 0 : step);
				this.content.scrollTo(x, y);
			}.bindWithEvent(this)
		}).set(0);
		
		if (!this.options.ignoreMouse) {
			$$(this.content, this.scrollbar).addEvent("mousewheel", function(e) {
				e.stop();
				var step = this.slider.step - e.wheel * 30;
				this.slider.set(step); 
			}.bindWithEvent(this));
		}

		$(document.body).addEvent("mouseleave", function() {this.slider.drag.stop()}.bindWithEvent(this));
		this.scrollbar.fade("show");
	}
});

var Throbber = new Class({
	initialize: function(element) {
		this.theElement = new Element("div", {
			"class": "throbberBox"
		});
		
		this.theThrobber = new Element("img", {
			src: "/images/toolbox/throbber.gif",
			alt: "ThrobberBox"
		});
		
		this.theElement.grab(this.theThrobber);
		
		$$("body").grab(this.theElement);

		if ($defined(element)) {
			this.theThrobber.position({
				relativeTo: element
			});
		} else {
			this.theThrobber.position({
				relativeTo: document.body,
				position: {x: "left", y: "top"},
				edge: {x: "left", y: "top"}
			});
		}
		this.theElement.fade("hide");
	},
	setElement: function(element) {
		if ($defined(element)) {
			this.theThrobber.position({
				relativeTo: element
			});
		}
	},
	fade: function(method) {
		this.theElement.fade(method);
	}
});

var NoteBox = new Class({
	initialize: function(skinType, instanceName) {
		this.skinType = (skinType == undefined) ? "dark" : skinType;
		this.instanceName = (instanceName == undefined) ? "noteBox" + new Date().getTime() : instanceName;
		this.timer = new GlobalTimer();

		this.theElement = new Element("div", {
			"class": "noteBox",
			styles: {
				"background": ((this.skinType == "dark") ? "#333" : "#fafafa"),
				"color": ((this.skinType == "dark") ? "#fff" : "#000"),
				"border": "1px solid " + ((this.skinType == "dark") ? "#777" : "#333"),
				"position": "absolute",
				"top": 0,
				"left": 0
			}
		});

		this.theElement.grab(new Element("span", {
			styles: {
				"background": "url(/images/toolbox/" + this.skinType + "_divotB.png) no-repeat top center"
			}
		}));
		this.theElement.grab(new Element("h2", {
			styles: {
				"border-bottom": ((skinType == "dark") ? "1px solid #fafafa" : "1px solid #333"),
				"color": ((this.skinType == "dark") ? "#fff" : "#000")
			}
		}).appendText("Note title here"));
		this.theElement.grab(new Element("a", {
			events: {
				"click": function(e) {
					this.getParent().fade("out");
				}
			},
			"class": "closer",
			styles: {
				"background": "url(/images/toolbox/" + this.skinType + "_x.png) no-repeat top left"
			}
		}));
		
		this.theElement.grab(new Element("a", {
			"class": "resizer",
			styles: {
				"background": "url(/images/toolbox/" + this.skinType + "_resizer.png) no-repeat top left"
			}
		}));
		
		this.theElement.grab(new Element("p", {
			"class": this.skinType
		}));
		this.theElement.getElement("p").appendText("Note text here!");
	
		$$("body").grab(this.theElement);
		
		this.theElement.fade("hide");
	},
	setText: function(newContent, isHTML) {
		if (isHTML || isIE6) {
			this.theElement.getElement("p").set("html", newContent);
		} else {
			this.theElement.getElement("p").set("text", newContent);
		}
	},
	setTitle: function(newContent, isHTML) {
		this.theElement.getElement("h2").setStyles({
			display: "block"
		});
		if (isHTML || isIE6) {
			this.theElement.getElement("h2").set("html", newContent);
		} else {
			this.theElement.getElement("h2").set("text", newContent);
		}
	},
	removeText: function(newContent) {
		this.theElement.getElement("p").set("text", "");
	},
	removeTitle: function(newContent) {
		this.theElement.getElement("h2").setStyle("display", "none");
	},
	setDimension: function(dimensions) {
		if ($defined(dimensions.width)) {
			this.theElement.setStyle("width", dimensions.width);
		}
		
		if ($defined(dimensions.height)) {
			this.theElement.setStyle("height", dimensions.height);
		}
	},
	setPosition: function(thePosition, whichBorder, margins, dockTo, showPointer, showCloser, isDraggable, isResizable) {
		if (whichBorder.x == "left" || whichBorder.x == "right") {
			var pointerStyles = {
				"width": 11,
				"height": 22,
				"background-position": whichBorder.y + " " + whichBorder.x
			};
		} else {
			var pointerStyles = {
				"width": 22,
				"height": 11,
				"background-position": whichBorder.y + " " + whichBorder.x
			};
		}

		this.theElement.getElement("span").setStyles(pointerStyles);

		this.theElement.position({
			relativeTo: dockTo,
			position: thePosition,
			edge: whichBorder,
			offset: margins
		});
		
		if (showPointer) {
			this.theElement.getElement("span").fade("show");
			this.theElement.getElement("span").position({
				relativeTo: this.theElement,
				position: whichBorder,
				edge: thePosition,
				ignoreMargins: true,
				offset: {
					x: ((whichBorder.x == "right") ? -2 : 2),
					y: ((whichBorder.y == "top") ? 1 : -1)
				}
			});
		} else {
			this.theElement.getElement("span").fade("hide");
		}
		
		if (showCloser) {
			this.theElement.getElement("a.closer").fade("show");
		} else {
			this.theElement.getElement("a.closer").fade("hide");
		}
		
		if (isDraggable) {
			this.theElement.makeDraggable({
				handle: this.theElement.getElement("h2"),
				snap: 5,
				precalculate: true,
				onStart: function(element) {
					element.setStyle("opacity", element.getStyle("opacity") - 0.4);
				},
				onComplete: function(element) {
					element.setStyle("opacity", element.getStyle("opacity") + 0.4);
				}
			});
			
			this.theElement.getElement("h2").setStyle("cursor", "move");
		}
		
		if (isResizable) {
			this.theElement.makeResizable({
				handle: this.theElement.getElement("a.resizer"),
				limit: {x: [this.theElement.getSize().x, 950], y: [this.theElement.getSize().y, 700]},
				onStart: function(element) {
					element.setStyle("opacity", element.getStyle("opacity") - 0.4);
				},
				onComplete: function(element) {
					element.setStyle("opacity", element.getStyle("opacity") + 0.4);
				}
			});
			this.theElement.getElement("a.resizer").setStyle("cursor", "nw-resize");
			this.theElement.getElement("a.resizer").fade("show");
			this.theElement.setStyle("padding-bottom: 20px;");
		} else {
			this.theElement.getElement("a.resizer").fade("hide");
			this.theElement.setStyle("padding-bottom: 6px;");
		}
	},
	fade: function(method, fadeOut, duration) {
		if (!$defined(fadeOut)) {
			var fadeOut = false;
		}
		
		if (!$defined(duration)) {
			var duration = 500;
		}
	
		if (fadeOut) {
			this.timer.clearTimer(this.instanceName);
			var myFader = function(){
				if (method == "show") {
					this.theElement.fade("hide");
				} else if (method == "in") {
					this.theElement.fade("out");
				}
			}.bind(this);
			
			this.timer.addTimer(myFader.delay(duration), this.instanceName);
		}

		this.theElement.fade(method);
	}
});


var FormMagic = new Class({
	Implements: [Options], 
	options: {
		fancify: false,
		checkPreSubmit: true,
		notifications: {
			display: true,
			fade: true,
			skinType: "dark",
			position: "bottom"
		},
		defaults: {},
		toggleNoEmpty: true
	},
	initialize: function(formElement, options) {
		if (!$defined(formElement)) {
			return false;
		}
		
		this.setOptions(options);

		this.myFormElement = formElement;
		this.myFormElement.grab(new Element("input", {
			type: "hidden",
			name: this.myFormElement.getElement("input[type=submit]").get("name"),
			value: this.myFormElement.getElement("input[type=submit]").get("value")
		}));
		
		this.myTextInputs = formElement.getElements("input[type=text]");
		var passFields = formElement.getElement("input[type=password]");
		if (passFields != null) {
			this.myTextInputs.push(passFields);
		}
		
		this.myTextInputs.each(function(item){
				if (!this.options.toggleNoEmpty) {
					return;
				}

				var defaultValue = this.options.defaults[item.get("name")];

				if ($defined(defaultValue)) {
					item.store("defaultValue", defaultValue);
				}
				else {
					item.store("defaultValue", item.get("value"));
				}
		}.bind(this));
		
		this.myNoteBox = new NoteBox(this.options.notifications.skinType);

		this.enableInputReset();
		this.enableFormCheck();
		this.fixIEbugs();
	},
	enableInputReset: function() {
		this.myTextInputs.addEvents({
			"click": function(e) {
				if (this.get("value") == this.retrieve("defaultValue")) {
					this.set("value", "");
				}
			},
			"blur": function(e) {
				if (this.get("value") == "") {
					this.set("value", this.retrieve("defaultValue"));
				}
			}
		});
	},
	enableFormCheck: function() {
		this.myFormElement.addEvent("submit", this.checkFormFields.bindWithEvent(this));
	},
	fixIEbugs: function() {
		if (isIE) {
			var myPassField = this.myFormElement.getElement("input[type=password]");
			myPassField.setStyle("font-family", "tahoma, verdana, arial, helvetica, sans-serif");
			this.myFormElement.getElement("input[type=submit]").set("value", "");

		}
	},
	checkFormFields: function(event) {
		event.stop();

		this.myFormElement.store("isClean", true);

		this.myTextInputs.each(function(item) {
			if (this.myFormElement.retrieve("isClean")) {
				if (item.get("value") == item.retrieve("defaultValue") || item.get("value").clean() == "") {
					var labelText = this.myFormElement.getElement("label[for=" + item.get("name") + "]");
					if (labelText != null) {
						this.myNoteBox.setTitle(labelText.get("text"));
					} else {
						this.myNoteBox.removeTitle();
					}
						
					this.myNoteBox.setText(langStrings.fieldCheck);
					this.myNoteBox.setDimension({width: item.getSize().x});

					switch (this.options.notifications.position) {
						case "top": {
							var positions = {
								x: "center",
								y: "top"
							};
							var edges = {
								x: "center",
								y: "bottom"
							};
							var offsets = {
								x: 0,
								y: -13
							};
						}
						break;
						case "bottom": {
							var positions = {
								x: "center",
								y: "bottom"
							};
							var edges = {
								x: "center",
								y: "top"
							};
							var offsets = {
								x: 0,
								y: 13
							};
						}
						break;
						case "left": {
							var positions = {
								x: "left",
								y: "center"
							};
							var edges = {
								x: "right",
								y: "center"
							};
							var offsets = {
								x: -13,
								y: -10
							};
						}
						break;
						case "right": {
							var positions = {
								x: "right",
								y: "center"
							};
							var edges = {
								x: "left",
								y: "center"
							};
							var offsets = {
								x: 13,
								y: -10
							};
						}
						break;

					}

					this.myNoteBox.setPosition(positions, edges, offsets, item, true, false, false, false);
					this.myFormElement.store("isClean", false);
				}
			}
		}.bind(this));

		if (this.myFormElement.retrieve("isClean")) {
			this.myFormElement.submit();
		} else {
			this.myNoteBox.fade("in", true, 2000);
			this.myFormElement.set("isClean", true);
		}
	}
});

var MilkBox = new Class({
	Implements:[Options,Events],
	options:{
		overlayOpacity:0.7,
		topPosition:50,
		initialWidth:250,
		initialHeight:250,
		canvasBorderWidth:'0px',
		canvasBorderColor:'#000000',
		canvasPadding:'0px',
		resizeDuration:500,
		resizeTransition:'sine:in:out',
		autoPlay:false,
		autoPlayDelay:7,
		removeTitle:false,
		autoSize:true,
		maxHeight:0,
		imageOfText:'of',
		onXmlGalleries:$empty,
		onClosed:$empty,
		onFileReady:$empty
	},
	initialize: function(options){
		this.setOptions(options);
		this.autoPlayBkup = {
			autoPlayDelay: this.options.autoPlayDelay,
			autoPlay: this.options.autoPlay
		};
		this.fullOptionsBkup = {};
		this.galleries = [];
		this.families = [];
		this.xmlFiles = [];
		this.loadedImages = [];
		this.currentFile = null;
		this.currentIndex = null;
		this.currentGallery = null;
		this.currentRequest = null;
		this.currentResponse = null;
		
		this.mode = null;
		this.closed = true;
		this.busy = true;
		this.paused = true;
		this.fileReady = false;
		this.eventsok = false;
		this.first = true;
		
		this.intObj = null;
		
		this.formtags = null;
		this.prepareGalleries();

		if(this.galleries.length == 0) {
			return;
		}
				
		this.initMilkbox();
		this.saveOptions();
	},
	initMilkbox: function(){
		this.prepareHTML();
		this.prepareEffects();
		this.prepareEvents();
		
		this.formtags = $$('select','textarea');
		this.activated = true;
	},
	openMilkbox: function(gallery,index) {
		this.closed = false;
		if (this.formtags.length != 0) {
			this.formtags.setStyle('display','none');
		};

		this.overlay.setStyles({
			'top': -$(window).getScroll().y,
			'height':$(window).getScrollSize().y+$(window).getScroll().y
		});
		this.center.setStyle('top',$(window).getScroll().y+this.options.topPosition);

		this.currentGallery = gallery;
		this.currentIndex = index;
		this.overlay.tween('opacity',this.options.overlayOpacity);
		
		if (gallery.length == 1) {
			this.mode = 'singleFile';
			this.loadFile(gallery[index],index);
		} else {
			this.mode = 'fileGallery';
			var playpauseWidth = 0;
			$$(this.prev, this.next, this.count).setStyle('display','block');

			if (this.options.autoPlay) { 
				this.playpause.setStyle('display','block');
				playpauseWidth = this.playpause.getSize().x;
			}

			var border = this.center.getStyle('border-right-width').toInt();
			var navWidth = this.prev.getSize().x + this.next.getSize().x + this.close.getSize().x + playpauseWidth+border;
			this.navigation.setStyle('width',navWidth);
			this.description.setStyle('margin-right',navWidth);

			var next = (index != gallery.length-1) ? gallery[index+1] : gallery[0];
			var prev = (index != 0) ? gallery[index-1] : gallery[gallery.length-1];
			var preloads = (prev == next) ? [prev] : [prev,next];
						
			this.loadFile(gallery[index],preloads);
		}
	},
	loadFile:function(fileObj,preloads){
		this.fileReady = false;
		var swf = this.checkFileType(fileObj,'swf');

		if (!swf) { 
			if (!this.loadedImages.contains(fileObj.retrieve('href'))){
				this.center.addClass('mbLoading');
			} 
			this.loadImage(fileObj.retrieve('href'));
		} else {
			this.loadSwf(fileObj);
		}
		
		if(preloads){
			this.preloadFiles(preloads);
		}
	},
	preloadFiles: function(preloads){
		preloads.each(function(fileObj,index){
			var swf = this.checkFileType(fileObj.retrieve('href'),"swf");
			if (!swf) {
				this.preloadImage(fileObj.retrieve('href'));
			}
		},this);
	},
	loadImage: function(file){
		var imageAsset = new Asset.image(file, {
			onload: function(img){
				if (!this.loadedImages.contains(file)) {
					this.loadedImages.push(file);
				};
			this.currentFile = img;
			this.loadAux(this.currentFile);
			}.bindWithEvent(this)
		});
	},
	preloadImage: function(file){
		if (!this.loadedImages.contains(file)) {
			var imageAsset = new Asset.image(file, {
				onload:function(img) {
					this.loadedImages.push(file);
				}.bindWithEvent(this)
			});
		}
	},
	loadSwf: function(swf){
		var swfObj = new Swiff(swf.retrieve('href'),{
			width: swf.retrieve('width').toInt(),
			height: swf.retrieve('height').toInt(),
			params: {
				wMode:'opaque',
				swLiveConnect:'false'
			}
		});
		
		this.currentFile = swfObj;
		this.loadAux(swf);
	},
	
	loadAux: function(file){
		this.fileReady = true;
		this.fireEvent('fileReady');
		$$(this.description,this.navigation).setStyle('visibility','hidden');
		this.navigation.setStyle('height','');
		$$(this.next,this.prev,this.close).setStyle('backgroundPosition','0 0');
		this.showFile(file);
	},
	showFile: function(file){
 		if (this.closed) {
			return;
		};
 		
 		var fileSize = new Hash();
 		var centerSize = new Hash();
 		var targetSize, canvasSize;
		var canvasAddSize, gap, b, p, d;
 		targetSize = canvasSize = {};
 		canvasAddSize = gap = b = p = d = 0;
 		
 		if(this.options.canvasBorderWidth.toInt() != 0 && this.canvas.getStyle('borderWidth').toInt() == 0){
 			b = this.options.canvasBorderWidth + ' solid ' + this.options.canvasBorderColor;
 			this.canvas.setStyle('border',b);
 		}
 		
 		if(this.options.canvasPadding.toInt() != 0 && this.canvas.getStyle('padding').toInt() == 0){
 			p = this.options.canvasPadding;
 			this.canvas.setStyle('padding',p);
 		}
 		
 		canvasSize = this.canvas.getSize();
 		canvasAddSize = this.canvas.getStyle('borderWidth').toInt()*2 + this.canvas.getStyle('padding').toInt()*2;
 		this.canvas.setStyles(
			{'opacity': 0,
			'width':'',
			'height':''
		});
 		
 		if (!file.retrieve('width')) {
 			fileSize = fileSize.extend(file.getProperties('width','height')).map(function(item){
				return item.toInt();
			});
 			
			if (this.options.autoSize) { 
 				fileSize = this.computeSize(fileSize);
 				file.setProperties({
					'width': fileSize.width,
					'height':fileSize.height
				});
 			}
 		} else {
 			fileSize.extend({
				'height': file.retrieve('height').toInt(),
				'width': file.retrieve('width').toInt()
			});
 		}
 				
 		centerSize = centerSize.extend(this.center.getStyles('width','height')).map(function(item){ 
			return item.toInt();
		});

 		if(fileSize.width != centerSize.width){ 
 			targetSize.width = fileSize.width + canvasAddSize;
 			targetSize.marginLeft = -(targetSize.width/2).round();
 		}
 		 		
 		gap = (canvasSize.y-canvasAddSize > 0) ? centerSize.height - canvasSize.y : 0; 

 	   targetSize.height = fileSize.height + canvasAddSize + gap;
 	   
		this.canvas.setStyles({
			'width': fileSize.width,
			'height':fileSize.height
		});

 		this.center.removeClass('mbLoading');
 		
 		if(this.first) {
			d = 500; this.first = false;
		}
		
 		(function() {
			this.center.morph(targetSize);
		}).delay(d,this)
	},
	computeSize:function(oSize){
		var size = oSize;
		var wSize = window.getSize();
		var baseSize = {
			width: wSize.x-60,
			height: wSize.y-68 - this.options.topPosition*2
		};
		
		var ratio;
		var check;
		
		var max = Math.max( baseSize.height, baseSize.width );

		if (max == baseSize.width) {
			ratio = max/size.width;
			check = 'height';
		} else {
			ratio = max/size.height;
			check = 'width';
		}
		ratio = (ratio <= 1) ? ratio : 1;
		size = size.map(function(item){
			return Math.floor(item*ratio);
		});
		
		ratio = (baseSize[check]/size[check] <= 1) ? baseSize[check]/size[check] : 1;
		size = size.map(function(item){
			return Math.floor(item*ratio);
		});
		
		if(this.options.maxHeight > 0){
			ratio = (this.options.maxHeight/size.height < 1) ? this.options.maxHeight/size.height : 1;
			size = size.map(function(item) {
				return Math.floor(item*ratio);
			});
		}
		
		return size;
	},
	showGallery: function(opt){
		if (!opt || !opt.gallery) {
			return;
		}
		
		var fileIndex = ($chk(opt.index)) ? opt.index : 0;
		var g = this.getGallery(opt.gallery);
		var auto = false;
		var d;

		if (opt.autoplay || (g['options'] && g['options'].autoplay)){
			auto = true;
		}
		
		if (g != -1 && !this.opened) {
			if (auto) {
				d = (opt && opt.delay) ? opt.delay : (g['options'] && g['options'].delay) ? g['options'].delay : this.autoPlayDelay;
				this.startAutoPlay({ gallery:g, index:fileIndex, delay:d });
			} else {
				this.openMilkbox(g,fileIndex);
			}
		}
	},
	addGalleries: function(xmlfile){
		this.currentRequest = new Request({
			method: 'get',
			autoCancel: true,
			url: xmlfile,
			onRequest: function() {
			}.bindWithEvent(this),
			onSuccess: function(text,xml){
				var t = text.replace(/(<a.+)\/>/gi,"$1></a>");
				this.setGalleries(new Element('div',{ html:t }),xmlfile);
			}.bindWithEvent(this),
			onFailure: function(transport) {
				alert('Milkbox :: addGalleries: XML file path error or local Ajax test: please test addGalleries() on-line');
			}
		});
		this.currentRequest.send();
	},
	setGalleries: function(container,xmlfile){
		if (!this.xmlFiles.contains(xmlfile)) {
			this.xmlFiles.push(xmlfile);
		}
		var c = container;
		var galleries = c.getElements('.gallery');
		var links = [];
		var aplist = [];

		galleries.each(function(gallery,i) {
			var obj = { 
				gallery:gallery.getProperty('name'), 
				autoplay:Boolean(gallery.getProperty('autoplay')),
				delay:Number(gallery.getProperty('delay'))
			}
			
			var l = gallery.getChildren('a');
			var lx = l.map(function(link) {
				return link.setProperty('rel','milkbox['+obj.gallery+']');
			});
			links.push(lx);
			if(obj.autoplay){ aplist.push(obj); }
		});
		
		this.prepareGalleries(links.flatten());
		this.setAutoPlay(aplist);
		
		if (!this.activated){
			this.initMilkbox();
		}
		this.fireEvent('xmlGalleries');
	},
	checkFileType: function(file,type){
		var href = null;
		if ($type(file) != 'string') {
			href = file.retrieve('href');
		} else {
			href = file;
		}
		var regexp = new RegExp("\.("+type+")$","i");
		return href.split('?')[0].test(regexp);
	},
	getGallery: function(gallery){
		var f = null;
		if (gallery.test(/^milkbox/i)) {
			f = this.families;
		} else {
			f = this.families.map(function(item){
				var trimmed = item.trim();
				var name = trimmed.slice(0,trimmed.length).substr(8);
				var cleanName = name.replace(/(.+)]$/,"$1");
				return cleanName;
			});
		}
		var i = f.indexOf(gallery);
		var g = (i != -1) ? this.galleries[i] : i;
		return g;
	},
	setFileProps: function(fileObj,propString){
		var s = propString.split(',');
		s.each(function(p,i){
			var clean = p.trim().split(':');
			fileObj.store(clean[0].trim(),clean[1].trim())
		},this);
	},
	changeOptions: function(obj){
		if(!obj){ return; }
		this.setOptions(obj);
 		this.center.get('morph').setOptions({ transition:this.options.resizeTransition,  duration:this.options.resizeDuration });
	},
	saveOptions: function(obj){
		if($chk(obj)){
			this.fullOptionsBkup = obj;
		} else {
			this.fullOptionsBkup = this.options;
		}
	},
	restoreOptions: function(){
		this.setOptions(this.fullOptionsBkup);
 		var b = this.options.canvasBorderWidth + ' solid ' + this.options.canvasBorderColor;
 		this.canvas.setStyles({ 'border':b, 'padding':this.options.canvasPadding});
 		this.center.get('morph').setOptions({ transition:this.options.resizeTransition,  duration:this.options.resizeDuration });
	},
	reloadGalleries: function(){
		this.galleries = [];
		this.families = [];
		this.formtags = $$('select','textarea');
		
		this.prepareGalleries();
		this.removeGalleriesEvents();
		this.setGalleriesEvents();
		
		if(this.xmlFiles.length == 0) {
			return;
		}

		this.xmlFiles.each(function(xmlfile,index){
			this.addGalleries(xmlfile);
		}.bind(this));
	},
	setAutoPlay: function(list){
		var l = ($type(list) == 'object') ? [list] : list;
		l.each(function(item){
			var g = this.getGallery(item.gallery);
			if(g == -1){ return; }
			var a = (item.autoplay == true) ? item.autoplay : false;
			var d = ($chk(item.delay) && a) ? item.delay : this.options.autoPlayDelay;
			g['options'] = { autoplay:a, delay:d }
		},this);
	},
	
	startAutoPlay: function(opt){
		var g = -1;
		var i,d;
		if(opt && opt.gallery){
			if($type(opt.gallery) == 'array'){ g = opt.gallery }
			else if($type(opt.gallery) == 'string'){ 
				g = this.getGallery(opt.gallery);
			}
		}
		
		if(g == -1){ g = this.galleries[0]; }
		
		d = (opt && opt.delay && ($type(opt.delay) == 'number')) ? opt.delay*1000 : (g['options'] && g['options'].delay) ? g['options'].delay*1000 : this.options.autoPlayDelay*1000;
		i = (opt && opt.index && ($type(opt.index) == 'number')) ? opt.index : 0;
		if(d < this.options.resizeDuration*2){ d = this.options.resizeDuration*2 };
		this.options.autoPlayDelay = d/1000;
		
		if (!this.options.autoPlay) {
			this.setOptions({ autoPlay:true, autoPlayDelay:this.options.autoPlayDelay });
		}
		
		if (this.closed) { 
			this.openMilkbox(g,i); 
			if(this.mode != 'fileGallery'){ return; }
			this.addEvent('fileReady',function(){
				this.intObj = this.next_prev_aux.periodical(d,this,[null,'next']);
				this.removeEvents('fileReady');
			}.bindWithEvent(this));
		} else {
			if(!this.closed){ this.next_prev_aux(null,'next'); }
			this.intObj = this.next_prev_aux.periodical(d,this,[null,'next']);
		}

		this.paused = false;
	},
	stopAutoPlay: function(){
		if(this.intObj){ $clear(this.intObj); this.intObj = null; }
		this.playpause.setStyle('backgroundPosition','0 -44px');
		this.paused = true;
	},
	removeGalleriesEvents: function(){
		this.galleries.each(function(gallery){
			$$(gallery).removeEvents('click');
		},this);
	},
	setGalleriesEvents: function(){
		this.galleries.each(function(gallery){
		
			$$(gallery).addEvent('click',function(e){
				var button=($(e.target).match('a')) ? $(e.target) : $(e.target).getParent('a');
				e.preventDefault();
				
				var g = this.getGallery(button.rel);
				if(g.options && g.options.autoplay){
					this.setOptions({ autoPlay:g.options.autoplay, autoPlayDelay:g.options.delay });
				}

				if(this.options.autoPlay){
					this.startAutoPlay({ gallery:gallery, index:gallery.indexOf(button) });
				} else { 
					this.openMilkbox(gallery, gallery.indexOf(button)); 
				}
				
			}.bindWithEvent(this));
		},this);
	},
	prepareEvents:function(xml){
		this.setGalleriesEvents();
		
		this.next.addEvent('click',this.next_prev_aux.bindWithEvent(this,'next'));
		this.prev.addEvent('click',this.next_prev_aux.bindWithEvent(this,'prev'));
		
		if (isIE6) {
			$$(this.next, this.prev, this.close).addEvents({
				'mouseover': function(){
					this.setStyle('backgroundPosition', '0 -22px');
				},
				'mouseout': function(){
					this.setStyle('backgroundPosition', '0 0');
				}
			});
		}

		$(window.document).addEvent('keydown',function(e){
			if(this.mode != 'fileGallery' || this.busy == true){ return; }
			if(e.key == 'right' || e.key == 'space'){ this.next_prev_aux(e,'next'); }
			else if(e.key == 'left'){ this.next_prev_aux(e,'prev'); }
			else if(e.key == 'esc'){ this.closeMilkbox(); }
		}.bindWithEvent(this));

		this.playpause.addEvents({
				'mouseover':function(e){ 
					if(this.paused == false){ this.playpause.setStyle('backgroundPosition','0 -22px'); } 
					else { this.playpause.setStyle('backgroundPosition','0 -66px'); }
				}.bindWithEvent(this),
				'mouseout':function(){ 
					if(this.paused == false){ this.playpause.setStyle('backgroundPosition','0 0'); } 
					else { this.playpause.setStyle('backgroundPosition','0 -44px'); }
				}.bindWithEvent(this),
				'click':function(){
					if(this.paused == false){ 
						this.stopAutoPlay();
						this.paused = true;
						this.playpause.setStyle('backgroundPosition','0 -66px');
					} else {
						var d = (this.currentGallery.options && this.currentGallery.options.delay) ? this.currentGallery.options.delay : this.options.autoPlayDelay;
						this.startAutoPlay({gallery:this.currentGallery, index:this.currentIndex+1, delay:d });
						this.paused = false;
						this.playpause.setStyle('backgroundPosition','0 0');
					}
				}.bindWithEvent(this)
		});
		
		this.overlay.get('tween').addEvent('onComplete',function(){
			if(this.overlay.getStyle('opacity') == this.options.overlayOpacity){ 
				this.center.tween('opacity',1);
			} else if(this.overlay.getStyle('opacity') == 0) {
				this.overlay.setStyles({'height':0,'top':''});
			};
		}.bindWithEvent(this));
		
		this.center.get('morph').addEvent('onComplete',function(){
						
			 if($type(this.currentFile) == "element"){//is image file
				this.canvas.grab(this.currentFile);
			 } else {//object: is swf file
			 	(function(){ this.canvas.grab(this.currentFile); }).delay(500,this);
			 }
 			 
			 this.canvas.tween('opacity',1);
			 			 
			 var d = (!(this.mode == 'showThisImage')) ? this.currentGallery[this.currentIndex].retrieve('title') : this.specialDescription;
			 if($chk(d)){ this.description.innerHTML = d; };
			 
			 if(this.mode == 'fileGallery'){
			 	this.count.appendText((this.currentIndex+1)+' '+this.options.imageOfText+' '+this.currentGallery.length); 
			 }
			 
			 var currentCenterHeight = this.center.getStyle('height').toInt();
			 
			 this.navigation.setStyle('height',this.bottom.getStyle('height').toInt());//to have the right-border height == total bottom height
			 var bottomSize = this.bottom.getSize().y;
			 
			 //after the 1st time, currentCenterHeight is always > this.canvas.getSize().y
			 var targetOffset = (currentCenterHeight > this.canvas.getSize().y) ? (this.bottom.getSize().y+this.canvas.getSize().y)-currentCenterHeight : bottomSize;
				
			 this.bottom.setStyle('display','none');//to avoid rendering problems during setFinalHeight

			 this.center.retrieve('setFinalHeight').start(currentCenterHeight,currentCenterHeight+targetOffset);
		}.bindWithEvent(this));
		
		this.center.retrieve('setFinalHeight').addEvent('onComplete',function(){
			this.bottom.setStyles({'visibility':'visible','display':'block'});
			$$(this.description,this.navigation).setStyle('visibility','visible');
			//reset overlay height based on position and height
			var scrollSize = $(window).getScrollSize().y;
			var scrollTop = $(window).getScroll().y;
			
			this.overlay.setStyles({'height':scrollSize+scrollTop, 'top':-scrollTop });
			this.busy = false;
		}.bindWithEvent(this));

		window.addEvent('resize',function(){
			if(this.overlay.getStyle('opacity') == 0){ return; };//resize only if visible
			var scrollSize = $(window).getScrollSize().y;
			var scrollTop = $(window).getScroll().y;
			this.overlay.setStyles({ 'height':scrollSize+scrollTop,'top':-scrollTop });
		}.bindWithEvent(this));

		$$(this.overlay,this.close).addEvent('click',this.closeMilkbox.bindWithEvent(this));

		this.eventsok = true;
	},
	next_prev_aux: function(e,direction){
		if(e){ 
			e.preventDefault();
			this.stopAutoPlay();
		} else { 
			if(this.busy || !this.fileReady){ return; }
		}

		this.busy = true;
		
		var i, _i;
		
		if(direction == "next"){
			i= (this.currentIndex != this.currentGallery.length-1) ? this.currentIndex += 1 : this.currentIndex = 0;
			_i= (this.currentIndex != this.currentGallery.length-1) ? this.currentIndex + 1 : 0;
		} else {
			i= (this.currentIndex != 0) ? this.currentIndex -= 1 : this.currentIndex = this.currentGallery.length-1;
			_i= (this.currentIndex != 0) ? this.currentIndex - 1 : this.currentGallery.length-1;		
		};
		
		this.canvas.empty();
		this.description.empty();
		this.count.empty();

		this.loadFile(this.currentGallery[i],[this.currentGallery[_i]]);
	},
	
	prepareEffects: function(){
		this.overlay.set('tween',{ duration:'short',link:'cancel' });
		this.center.set('tween',{ duration:'short',link:'chain' });
		this.center.set('morph',{ duration:this.options.resizeDuration,link:'chain',transition:this.options.resizeTransition });
		this.center.store('setFinalHeight',new Fx.Tween(this.center,{property:'height',duration:'short'}));
		this.canvas.set('tween',{ link:'chain' });
	},
	
	prepareGalleries: function(responseElements){
		var milkbox_a = [];
		var a_tags = (responseElements) ? responseElements : $$('a');
				
		a_tags.each(function(a){
			if(a.rel && a.rel.test(/^milkbox/i) && a.href.split('?')[0].test(/\.(gif|jpg|jpeg|png|swf)$/i)){
				if(a.rel.length>7 && !this.families.contains(a.rel)){ this.families.push(a.rel); };
				milkbox_a.push(a);
			}
		},this);

		milkbox_a.each(function(a){
			$(a).store('href',a.href);
			$(a).store('rel',a.rel);
			$(a).store('title',a.title);
			if(this.checkFileType(a.href,"swf")){ this.setFileProps($(a),a.rev); }

			if(this.options.removeTitle){ $(a).removeProperty('title'); }
			if(a.rel.length > 7){
				this.families.each(function(f,i){
					if(a.rel == f){
						var gMounted = false;
						var index;
						this.galleries.each(function(g,k){
							if(g[0].rel == f){ 
								gMounted = true;
								index = k;
								return;
							}
						});
						
						if(gMounted == true){ this.galleries[index].push($(a)); } 
						else { this.galleries.push([$(a)]); }
					};
				},this);
			} else { this.galleries.push([$(a)]); };
		},this);
	},
	prepareHTML: function(){		
		this.overlay = new Element('div', { 'id':'mbOverlay','styles':{ 'opacity':0,'visibility':'visible','height':0,'overflow':'hidden' }}).inject($(document.body));
		
		this.center = new Element('div', {'id':'mbCenter', 'styles':{'width':this.options.initialWidth,'height':this.options.initialHeight,'marginLeft':-(this.options.initialWidth/2),'opacity':0 }}).inject($(document.body));
		this.canvas = new Element('div', {'id':'mbCanvas'}).inject(this.center);
		
		this.bottom = new Element('div',{'id':'mbBottom'}).inject(this.center).setStyle('visibility','hidden');
		this.navigation = new Element('div',{'id':'mbNavigation'}).setStyle('visibility','hidden');
		this.description = new Element('div',{'id':'mbDescription'}).setStyle('visibility','hidden');

		this.bottom.adopt(this.navigation, this.description, new Element('div',{'class':'mbClear'}));
		
		this.close = new Element('a',{'id':'mbCloseLink'});
		this.next = new Element('a',{'id':'mbNextLink'});
		this.prev = new Element('a',{'id':'mbPrevLink'});
		this.playpause = new Element('a',{'id':'mbPlayPause'});
		this.count = new Element('span',{'id':'mbCount'});
		
		$$(this.next, this.prev, this.count, this.playpause).setStyle('display','none');
		
		this.navigation.adopt(this.close, this.next, this.prev, this.playpause, new Element('div',{'class':'mbClear'}), this.count);
	},
	closeMilkbox: function(){
		this.cancelAllEffects();
		this.stopAutoPlay();
		this.setOptions(this.autoPlayBkup);

		this.currentFile = null;
		this.currentIndex = null;
		this.currentGallery = null;
		this.currentRequest = null;
		this.currentResponse = null;
 		
		$$(this.prev, this.next, this.playpause, this.count).setStyle('display','none');
		this.playpause.setStyle('backgroundPosition','0 0');
		var border = this.center.getStyle('border-right-width').toInt();
		var navWidth = this.close.getSize().x+border;
		this.navigation.setStyles({'width':navWidth,'height':'','visibility':'hidden'});
		this.description.setStyle('margin-right',navWidth);
		this.description.empty();
		this.bottom.setStyles({'visibility':'hidden','display':''});
	   	this.canvas.setStyles({'opacity':0, 'width':'', 'height':''});
 		this.canvas.empty();
 		
 		this.count.empty();
		
		this.center.setStyles({'opacity':0,'width':this.options.initialWidth,'height':this.options.initialHeight,'marginLeft':-(this.options.initialWidth/2)});
		this.overlay.tween('opacity',0);//see onComplete in prepareEvents() 
		
		if(this.formtags.length != 0){ this.formtags.setStyle('display','') };
		
		this.mode = null;
		this.closed = true;
		this.first = true;
		this.fileReady = false;
		this.fireEvent('closed');
	},
	cancelAllEffects: function(){
		this.overlay.get('tween').cancel();
		this.center.get('morph').cancel();
		this.center.get('tween').cancel();
		this.center.retrieve('setFinalHeight').cancel();
		this.canvas.get('tween').cancel();
	}
});
