

var gRequestList = [];
var gRequestCount =0;

function addRequest(request) {
	gRequestList.push(request);
	gRequestCount++;
	requestModified();
}

function removeRequest(request) {
	for (var ii in gRequestList) {
		if (gRequestList[ii] === request) {
			gRequestList[ii] = null;
		}
	}
	requestModified();
}

function requestModified() {
	var nbr =0;
	for (var ii in gRequestList) {
		if (gRequestList[ii] !== null) {
			nbr++;
		}
	}
	
	var requestInfoWidget = gWidgets["requestInfo"];
	if (requestInfoWidget) {
		requestInfoWidget.updateInfo(nbr,gRequestCount);
	}
}


//*******************************

function actionDone(request) {
	if (request.readyState == 4) {
		if (request.status == 200) {
			//alert(request.responseText);
			var responseXML = request.responseXML;
			if (!responseXML) {
				if (!request.responseText) {
					alert("Empty response");
				} else {
					alert(request.responseText);
				}
			} else {
				var root = responseXML.documentElement;
				if (root.tagName == "error") {
					alert(root.getAttribute("message"));
				} else if (root.tagName != "ok") {
					alert("error unknown response: "+root.tagName);
				} else {
					//alert("root: "+root.tagName);
					var responseWidgetId = root.getAttribute("response_widget_id");
					var responseMethodName = root.getAttribute("response_method_name");
					if (responseWidgetId && responseMethodName) {
						var widget = gWidgets[responseWidgetId];
						if (widget && widget[responseMethodName]) {
							var isOK = widget[responseMethodName](root);
							if (!isOK) {
								alert("error in reaction");
							}
						}
					}
				}
			}
		} else {
			alert("status: "+request.statusText);
		}
		removeRequest(request);
	}
}



function DowAction() {
}

DowAction.prototype.doAction = function(controlElem) {
	alert("must override doAction");
}

DowAction.prototype.doReaction = function(element , responseXML) {
	return true;
}

DowAction.prototype.createDomDocument = function() {
	if (typeof DOMParser == "function") { //Firefox3 bug with createDocument (never UTF-8 even when document is) IE7 will fail with just if(DOMParser)
		var xmlStr = '<?xml version="1.0" encoding="UTF-8"?><dummy/>';
		var parser = new DOMParser();
		var domDocument = parser.parseFromString(xmlStr,"application/xml");
		domDocument.removeChild(domDocument.firstChild);
		return domDocument;
	} else if (document.implementation && document.implementation.createDocument) {
		return document.implementation.createDocument(null,null, null);
	} else if (window.ActiveXObject) {
		return new ActiveXObject("Microsoft.XMLDOM");
	}
}

DowAction.prototype.createEmptyAction = function(method,doc) {
	var outDoc;
	
	if (doc) {
		outDoc=doc;
	} else {
		outDoc = this.createDomDocument();
	}
	
	var action = outDoc.createElement("action");
	outDoc.appendChild(action);
	
	action.setAttribute("method",method);
	if (typeof player_id != "undefined") action.setAttribute("player_id",player_id);
	if (typeof login_id != "undefined") action.setAttribute("login_id",login_id);
	if (typeof page_path != "undefined") action.setAttribute("page_path",page_path);
	
	return action;
}

DowAction.prototype.sendAction = function(actionDoc,responseMethodName) {
	var request = new XMLHttpRequest();
	try {
		request.open("POST", "/php/action.php", true);
		request.onreadystatechange = function() {actionDone(request)};
		addRequest(request);
		
		if (responseMethodName) {
			actionDoc.documentElement.setAttribute("response_method_name",responseMethodName);
		}
		if (this.uid) {
			actionDoc.documentElement.setAttribute("response_widget_id",this.uid);
		}
	
		request.send(actionDoc);
	} catch (ex) {
		alert(ex);
	}
}




//*************************

function explodeURI(uriStr) {
	var regExp = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?")
	var match = regExp.exec(uriStr);
	return {'scheme':match[1] , 'authority':match[4] , 'path':match[5] , 'query':match[7] , 'fragment':match[9] }; 
}
	
function implodeURI(uriObject) {
	return uriObject.scheme + "://" + uriObject.authority + uriObject.path + "?" + uriObject.query + "#" + uriObject.fragment;
}

//*****

function DowUrl() {
}

DowUrl.prototype.setUrl = function(urlStr) {
	this.params = new Object();
	queryPos = urlStr.indexOf('?');
	if (queryPos == -1) {
		this.preQuery = urlStr;
	} else {
		this.preQuery = urlStr.substring(0,queryPos);
		query = urlStr.substring(queryPos+1);
	
		var keypairs = new Array();
		if (query.length > 0) {
			var index = 0;
			while (query.indexOf('&') > -1) {
				var pos = query.indexOf('&');
				keypairs[index] = query.substring(0,pos);
				query = query.substring(pos + 1);
				index++;
			}
			keypairs[index] = query;
		}
		
		var ii;
		for (ii in keypairs) {
			var keypair = keypairs[ii];
			var pos = keypair.indexOf('=');
			var key = keypair.substring(0,pos);
			var value = keypair.substring(pos + 1);
			//escape value
			this.params[key]=value;
		}
	}
}

DowUrl.prototype.getParam = function(key) {
	return this.params[key];
}

DowUrl.prototype.setParam = function(key,value) {
	this.params[key]=value;
}

DowUrl.prototype.getUrl = function() {
	var urlStr = this.preQuery;
	
	var keypairs = new Array();
	var index=0;
	for (var key in this.params) {
		keypairs[index++] = key+"="+this.params[key];
	}
	if (keypairs.length>=1) {
		urlStr+="?"+keypairs.join('&');
	}
	return urlStr;
}

//**************** DRAG DROP ***************

function DowDropper() {
	this.dropWidgets = [];
}

DowDropper.prototype.clear = function() {
	this.dropWidgets = [];
	if (this.selectedDrop) {
		this.selectedDrop.dropExit(this);
	}
	this.selectedDrop=null;
}

DowDropper.prototype.addDropWidget = function(dropWidget) {
	//alert("addDropWidget: "+dropWidget);
	this.dropWidgets.push(dropWidget);
}


DowDropper.prototype.getDropZone = function(dragArea) {
	var dropTarget;
	var maxArea = 0;
	var selectedDrop = null;
	var index;
	
	//window.status += "nbr: " +this.dropWidgets.length;
	
	for (index in this.dropWidgets) {
		//window.status += "index: " +index;
		var dropWidget = this.dropWidgets[index];
		var dropArea = dropWidget.getElementArea(dropWidget.getWidgetElement());
		//window.status = "uid: "+dropWidget.uid;
		var area = this.calcOverlapArea(dragArea,dropArea);
		//window.status = "("+area+"?>"+maxArea+")";
		if (area > maxArea) {
			selectedDrop = dropWidget;
			maxArea=area;
		}
	}
	
	//window.status = selectedDrop;
	
	return selectedDrop;
}


DowDropper.prototype.calcOverlapArea = function(a1 , a2) {
	//window.status = "("+a1.top+","+a1.left+","+a1.bottom+","+a1.right+"):("+a2.top+","+a2.left+","+a2.bottom+","+a2.right+")";

	var minR = a1.right<a2.right ? a1.right : a2.right;
	var maxL = a1.left>a2.left ? a1.left : a2.left;
	var minB = a1.bottom<a2.bottom ? a1.bottom : a2.bottom;
	var maxT = a1.top>a2.top ? a1.top : a2.top;
	
	var deltaX = minR-maxL;
	var deltaY= minB-maxT;
	
	var area = 0;
	if (deltaX>0 && deltaY>0) {
		area = deltaX*deltaY;
	}
	//window.status = "deltaY="+deltaY;
	return area;
}

DowDropper.prototype.onMousemove = function(dragger) {
	//window.status += "v";
	
	var dragArea = dragger.getDragArea();
	var selectedDrop = this.getDropZone(dragArea);
	if (selectedDrop != this.selectedDrop) {
		if (this.selectedDrop) this.selectedDrop.dropExit(this);
		this.selectedDrop = selectedDrop;
		if (this.selectedDrop) this.selectedDrop.dropEnter(dragger,this);
	}
	if (this.selectedDrop && this.selectedDrop.dropMove) {
		this.selectedDrop.dropMove(dragger,this);
	}
}

DowDropper.prototype.onMouseup = function(dragger) {
	if (this.selectedDrop && this.selectedDrop.drop) {
		this.selectedDrop.drop(dragger,this);
	}
}

//*******

function getDragReferenceElement() {
	if (document.body) {
		return document.body;
	} else {
		var docElem = document.documentElement;
		return docElem.getElementsByTagName("body")[0];
	}
}

function DowDragger() {
	this.dragWidget  = null;
	this.dragObject  = null;
	this.mouseOffset  = null;
}

DowDragger.prototype.attach = function(widget, ev) {
	var self = this;
	
	if (widget) {
		this.dragObject = widget.getWidgetElement();
		
		if (this.mouseupInfo) {
			gDOMHelper.unbindElementEvent(this.mouseupInfo);
			this.mouseupInfo = null;
		}
		this.mouseupInfo = gDOMHelper.bindElementEvent(document,"mouseup", function(event) {self.mouseupAction(event);});
		//document.onmouseup = function(event) {self.mouseupAction(event);}
		
		//window.status = "DRAG=>";
		document.onmousemove = function(event) {return self.mousemoveAction(event || window.event); }
		
		document.onselectstart = function(){return false;} //IE
	
		this.attachPos  = gDOMHelper.getEventMousePosition(ev);
	
		this.mouseOffset = this.getMouseOffset(widget , this.dragObject, ev);
		this.altKey = ev.altKey;
		this.shiftKey = ev.shiftKey;
		this.ctrlKey = ev.ctrlKey;
		
		if (widget && widget.dragStart) {
			widget.dragStart(this);
		}
		
		gDropper.clear();
		var widgetId;
		for (widgetId in gWidgets) {
			var curWidget = gWidgets[widgetId];
			if (curWidget.canDrop && curWidget.canDrop(widget)) {
				gDropper.addDropWidget(curWidget);
			}
		}
		
		ev.preventDefault();
		//ev.stopPropagation(); 

	} else {
		this.detachPos  = gDOMHelper.getEventMousePosition(ev);
		this.dragObject  = null;
		//document.onmouseup = null;
		if (this.mouseupInfo) {
			gDOMHelper.unbindElementEvent(this.mouseupInfo);
			this.mouseupInfo = null;
		}
		
		document.onmousemove = null;
		document.onselectstart = null; //IE
		if (this.dragWidget && this.dragWidget.dragEnd) {
			this.dragWidget.dragEnd(this);
		}
		if (this.dragElement) {
			getDragReferenceElement().removeChild(this.dragElement);
			this.dragElement = null;
		}
		gDropper.clear();
	}
	this.dragWidget = widget;
}

DowDragger.prototype.mouseupAction = function(event) {
	if (!event.ctrlKey) { //hack
		gDropper.onMouseup(this);
		this.attach(null,event);
	}
}

DowDragger.prototype.getDragPosition = function() {
	return {'x': this.left , 'y': this.top};
}

DowDragger.prototype.getDragArea = function() {
	return this.dragWidget.getElementArea(this.dragElement);
}

DowDragger.prototype.makeDragElement = function() {
	this.dragElement = null;
	if (this.dragObject) {
		if (this.dragWidget.makeDragElement) {
			this.dragElement = this.dragWidget.makeDragElement(this);
		} else {
			this.dragElement = this.dragObject.cloneNode(true);
			this.dragElement.id = "";
		}
		gDOMHelper.setElementClass(this.dragElement , 'dragging');
		this.dragElement.style.position = 'absolute';
		this.dragElement.style.display = 'block';
		getDragReferenceElement().appendChild(this.dragElement);
	}

}

DowDragger.prototype.mousemoveAction = function(event) {
	//window.status += "V";

	var mousePos = this.dragWidget.getEventMousePosition(event);
	//dump("B mousePos.x: "+mousePos.x);
	
	this.left = mousePos.x - this.mouseOffset.x;
	this.top = mousePos.y - this.mouseOffset.y;
		
	var leftPX = ""+this.left+"px";
	var topPX = ""+this.top+"px";
	
	if (!this.dragElement) {
		this.makeDragElement();
	}
	
	if(this.dragElement){
		this.dragElement.style.left      = leftPX;
		this.dragElement.style.top     = topPX;
	}
	
	if (this.dragWidget && this.dragWidget.dragMove) {
		this.dragWidget.dragMove(this);
	}
	
	gDropper.onMousemove(this);
	
	if (event.preventDefault) {
		event.preventDefault();
	}
	if (event.stopPropagation) {
		event.stopPropagation();
	}
	
	return false;
}

DowDragger.prototype.getMouseOffset = function (widget , target, ev){
	ev = ev || window.event;

	var docPos    = widget.getElementPosition(target);
	var mousePos  = widget.getEventMousePosition(ev);
	//dump("A mousePos.x: "+mousePos.x);
	
	return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}

//*****

function DowContextMenu() {
	this.menus = [];
}

DowContextMenu.prototype.clear = function() {
	this.menus = [];
}

DowContextMenu.prototype.addMenu = function(title , widget , action , param) {
	this.menus.push( {'title' :title , 'action' : action , 'widget' : widget , 'param':param});
}

DowContextMenu.prototype.addImageMenu = function(src , title , widget , action , param) {
	this.menus.push( {'src': src , 'title' :title , 'action' : action , 'widget' : widget , 'param':param});
}

DowContextMenu.prototype.popup = function(event) {
	this.stop();
	var self = this;
	
	var context_menu = document.createElement("div");
	context_menu.id = "context_menu";
	context_menu.className = "context_menu";
	var ii,menu;
	for (ii in this.menus) {
		menu = this.menus[ii];
		var menuItem = document.createElement("div");
		var subItem = null;
		if (menu.src) {
			subItem = document.createElement("img");
			subItem.src = menu.src;
			subItem.alt = menu.title;
			subItem.title = menu.title;
		} else {
			subItem = document.createTextNode(menu.title);
		}
		menuItem.appendChild(subItem);
		menuItem.id="context_menu_item_"+ii;
		menuItem.className = "context_menu_item";
		
		this.registerItemClick(menuItem,menu.action,menu.widget,menu.param);
		context_menu.appendChild(menuItem);
	}
	
	//document.onclick = function() {self.stop(); document.onclick = null; document.onmousedown=null;}
	//document.onmousedown = function() {return false;} //to do contextmenu on selection (without deselecting)
	document.onmouseup = function() {self.stop(); }

	var mousePos  = gDOMHelper.getEventMousePosition(event);
	context_menu.style.left = mousePos.x +"px";
	context_menu.style.top = mousePos.y +"px";
	
	document.body.appendChild(context_menu);
}

DowContextMenu.prototype.registerItemClick = function(menuItem,action,widget,param) {
	var self = this;
	//gDOMHelper.bindElementEvent(menuItem,"click", function(event) {widget[action](param);event.stopPropagation(); self.stop(); document.onmousedown=null;} );
	gDOMHelper.bindElementEvent(menuItem,"mouseup", function(event) {widget[action](param); self.stop(); } );
}


DowContextMenu.prototype.stop = function() {
	var context_menu = document.getElementById("context_menu");
	if (context_menu) {
		context_menu.parentNode.removeChild(context_menu);
	}
	document.onmouseup = null;
}

//******

function DowSelection() {
	this.selectedIds = {};
	this.menusIds = {};
}

DowSelection.prototype.informMenu = function (uid) {
	this.menusIds[uid] = true;
}

DowSelection.prototype.selectionModified = function () {
	var menu_id;
	var menu;
	
	for (menu_id in this.menusIds) {
		menu = gWidgets[menu_id];
		if (menu && menu.onSelectionChanged) {
			menu.onSelectionChanged(this);
		}
	}
}

DowSelection.prototype.clear = function () {
	this.selectedIds = {};
	this.selectionModified();
}

DowSelection.prototype.set = function (widget) {
	this.selectedIds = {};
	this.selectedIds[widget.uid ] =true;
	this.selectionModified();
}

DowSelection.prototype.addTo = function (widget) {
	this.selectedIds[widget.uid]=true;
	this.selectionModified();
}

DowSelection.prototype.toggle = function (widget) {
	if (this.selectedIds[widget.uid]) {
		delete this.selectedIds[widget.uid];
	} else {
		this.selectedIds[widget.uid]=true;
	}
	this.selectionModified();
}


DowSelection.prototype.getSelectedWidgets = function() {
	var widgets = [];
	var widget;
	
	for (id in this.selectedIds) {
		widget = gWidgets[id];
		if (widget) {
			widgets.push(widget);
		}
	}
	
	return widgets;
}

//*******

window.gSelection = new DowSelection();
window.gDragger = new DowDragger();
window.gDropper = new DowDropper();
window.gContextMenu = new DowContextMenu();//*******************************



function DomParser() {
	this.type="DomParser";
}
DomParser.prototype = new DowAction;

window.gDomParser = new DomParser();

DomParser.prototype.previousElement = function(rootElem) {
	var cur = rootElem.previousSibling;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE) {
			return cur;
		}
		cur = cur.previousSibling;
	}
	return null;
}

DomParser.prototype.nextElement = function(rootElem) {
	var cur = rootElem.nextSibling;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE) {
			return cur;
		}
		cur = cur.nextSibling;
	}
	return null;
}


DomParser.prototype.findElement = function(rootElem , tagName,className) {
	var cur = rootElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE && cur.tagName == tagName) {
			if (!className || this.hasElementClass(cur , className)) {
				return cur;
			}
		}
		cur = cur.nextSibling;
	}
	return null;
}


DomParser.prototype.childIterator = function(rootElem , tagName , callback) {
	var cur = rootElem.firstChild;
	var next;
	while (cur) {
		next = cur.nextSibling; //do be able to delete (or insert) while iterating
		if (cur.nodeType == Node.ELEMENT_NODE && cur.tagName.toLowerCase() == tagName) {
			callback(cur);
		}
		cur = next;
	}
}

DomParser.prototype.getChildElementItem = function(parentElem  , className , index) {
	var resultElem = null;
	var curIndex = 0;
	
	var cur = parentElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE && this.hasElementClass(cur,className)) {
			if (curIndex==index) {
				resultElem = cur;
			}
			curIndex++;
		}
		cur = cur.nextSibling;
	}
	return resultElem;
}

DomParser.prototype.childElements = function(rootElem , tagName,className) {
	var list = [];
	var cur = rootElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE && cur.tagName == tagName) {
			if (!className || this.hasElementClass(cur, className)) {
				list.push(cur);
			}
		}
		cur = cur.nextSibling;
	}
	return list;
}

DomParser.prototype.getAllSubElements = function(topElem , tagName , className) {
	var elements = [];
	var subElements = topElem.getElementsByTagName(tagName);
	var ii;
	var curElem;
	for (ii=0 ; ii< subElements.length ; ii++) {
		curElem = subElements.item(ii);
		if (!className || this.hasElementClass(curElem,className)) {
			elements.push(curElem);
		}
	}
	
	return elements;
}

DomParser.prototype.isAncestor = function(element , ancestor) {
	while (element) {
		if (element == ancestor) return true;
		element = element.parentNode;
	}
	return false;
}

DomParser.prototype.findAncestor = function(rootElem , tagName, className) {
	var cur = rootElem;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE && cur.tagName == tagName) {
			if (!className || this.hasElementClass(cur,className)) {
				return cur;
			}
		}
		cur=cur.parentNode;
	}
	return null;
}

DomParser.prototype.findParent = function(rootElem , tagName, className) {
	var cur = rootElem.parentNode;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE && cur.tagName == tagName) {
			if (!className || this.hasElementClass(cur,className)) {
				return cur;
			}
		}
		cur=cur.parentNode;
	}
	return null;
}



DomParser.prototype.findWidgetParent = function(rootElem) {
	return this.findWidgetParentIncludingSelf(rootElem.parentNode);
}


DomParser.prototype.getMultilineTextValue = function(rootElem) {
	var textValue="";
	var cur = rootElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.TEXT_NODE) {
			textValue += cur.data;
		} else if (cur.nodeType == Node.ELEMENT_NODE && cur.tagName=='BR' ) {
			textValue += "\n";
		}
		cur = cur.nextSibling;
	}
	return textValue;
}

DomParser.prototype.setMultilineTextValue = function(rootElem,textStr) {
	while (rootElem.firstChild) {
		rootElem.removeChild(rootElem.firstChild);
	}
	var curPos = 0;
	var foundPos;
	
	while ( (foundPos = textStr.indexOf("\n",curPos)) != -1 ) {
		rootElem.appendChild(document.createTextNode(textStr.substring(curPos,foundPos)));
		rootElem.appendChild(document.createElement("br"));
		curPos = foundPos+1;
	}

	rootElem.appendChild(document.createTextNode(textStr.substring(curPos)));
}

DomParser.prototype.setTextValue = function(rootElem,textStr) {
	while (rootElem.firstChild) {
		rootElem.removeChild(rootElem.firstChild);
	}
	rootElem.appendChild(document.createTextNode(textStr));
}

DomParser.prototype.getTextValue = function(rootElem) {
	var textValue="";
	var cur = rootElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.TEXT_NODE) {
			textValue += cur.data;
		} else if (cur.nodeType == Node.ELEMENT_NODE) {
			textValue += this.getTextValue(cur);
		}
		cur = cur.nextSibling;
	}
	return textValue;
}

DomParser.prototype.setStyleProperty = function(element,name,value) {
	if (element.style.setProperty) {
		element.style.setProperty("display","block","");
	} else {
		element.style[name] = value;
	}
}

DomParser.prototype.setTransparentBackgroundImage = function(element,src) {
	if (window.isIE6) {
		if (src) {
			element.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='scale')";
		} else {
			element.style.filter = "";
		}
	} else {
		if (src) {
			element.style.backgroundImage="url("+src+")";
		} else {
			element.style.backgroundImage="";
		}
	}
}

DomParser.prototype.getXMLData = function() {
	doc = this.createDomDocument();
	var root = doc.createElement("root");
	this.appendXMLData(root);
	return root;
}

DomParser.prototype.getData = function(data) {
	alert("must override getData: "+this.type);
}

DomParser.prototype.setData = function(data) {
	alert("must override setData: "+this.type);
}

DomParser.prototype.appendXMLData = function(root) {
	alert("must override appendXMLData: "+this.type);
}

DomParser.prototype.reorder = function(fromElem , toElem) {
	if (fromElem == toElem) return;
	var forward=false;
	var curElem = fromElem.nextSibling;
	while (curElem) {
		if (curElem == toElem) {
			forward=true;
			break;
		}
		curElem = curElem.nextSibling;
	}
	
	if (forward) {
		fromElem.parentNode.insertBefore(fromElem,toElem.nextSibling);
	} else {
		fromElem.parentNode.insertBefore(fromElem,toElem);
	}
}

DomParser.prototype.setElementOpacity = function (element , opacity) {
	element.style.opacity = opacity/100;
	if (element.style.filters) {
		element.style.filters.alpha.opacity = opacity;
	}
}

DomParser.prototype.getContentSize = function () {
	var width = document.documentElement.clientWidth;
	var height = document.documentElement.clientHeight;

	return {'width':width,'height':height};
}

DomParser.prototype.getScrollOffset = function () {
	var left = document.body.scrollLeft + document.documentElement.scrollLeft;
	var top = document.body.scrollTop + document.documentElement.scrollTop;
	return {'left':left,'top':top};

}

DomParser.prototype.getEventMousePosition = function (event){
	if(event.pageX || event.pageY){
		return {x:event.pageX, y:event.pageY};
	}
	
	//alert("event.clientY: "+event.clientY);
	//alert("document.body.scrollTop: "+document.body.scrollTop);
	//alert("event.clientY: "+event.clientY);
	return {
		//x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
		//y:ev.clientY + document.body.scrollTop  - document.body.clientTop
		x:event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
		y:event.clientY + document.body.scrollTop  + document.documentElement.scrollTop
	};
}

/*
DomParser.prototype.getPositionReferenceParent = function(element) {
	var parent = element.parentNode;
	var position;
	while (parent) {
		if (!parent.style) return parent;
		position = parent.style.position; //no needs computed
		if (position =="absolute" || position=="relative") {
			return parent;
		}
		parent = parent.parentNode;
	}
	return document; //body?
}

DomParser.prototype.getEventMouseLocalPosition = function (element , event){
	var reference = this.getPositionReferenceParent(element);
	return this.getElementEventMouseOffset(reference,event);
	
}
*/

DomParser.prototype.getElementEventMouseOffset = function (element , event){
	var elementPos    = this.getElementPosition(element);
	var mousePos  = this.getEventMousePosition(event);
	return {'x': mousePos.x - elementPos.x , 'y': mousePos.y - elementPos.y};
}



DomParser.prototype.getEventMouseFixedPosition = function (event){
	var pos = this.getEventMousePosition(event);
	
	return {x: pos.x - window.pageXOffset , y: pos.y - window.pageYOffset}
}


DomParser.prototype.getElementClasses = function(element) {
	var oldClass = element.className;
	if (!oldClass) return [];
	var classes = oldClass.split(' ');
	return classes;
}

DomParser.prototype.getElementPrefixedClass = function(element , prefix) {
	var classes = this.getElementClasses(element);
	for (var ii=0; ii< classes.length ; ii++) {
		var className = classes[ii];
		if (className.indexOf(prefix)==0) {
			result = className.substring(prefix.length);
			return result;
		}
	}
	return null;
}

DomParser.prototype.setElementPrefixedClass = function(element , prefix, value) {
	var oldName = this.getElementPrefixedClass(element , prefix);
	var newName = value;
	if (oldName != newName) {
		this.unsetElementClass(element,prefix+oldName);
		this.setElementClass(element,prefix+newName);
	}
}

DomParser.prototype.hasElementClass = function(element , className) {
	var classes = this.getElementClasses(element);
	var ii,curClass;
	var found = false;
	for (ii in classes) {
		curClass = classes[ii];
		if (curClass == className) {
			//alert("found: "+curClass);
			found=true;
		}
	}
	return found;
}

DomParser.prototype.setElementClass = function(element , className) {
	if (!this.hasElementClass(element , className)) {
		element.className += ' ' + className;
	}
}

DomParser.prototype.unsetElementClass = function(element , className) {
	var oldArray = this.getElementClasses(element);
	var newArray = [];
	for (var ii in oldArray) {
		var curClass = oldArray[ii];
		if (curClass != className) {
			newArray.push(curClass);
		}
	}
	element.className=newArray.join(" ");
}

//*****

DomParser.prototype.getElementActionName = function(element) {
	var classes = this.getElementClasses(element);
	var regExp = new RegExp("^do_(.*?)( |$)");
	var actionName = null;
	
	for (var ii in classes) {
		var curClass = classes[ii];
		var match = regExp.exec(curClass);
		if (match) {
			actionName = match[1];
			break; //first one
		}
	}
	
	return actionName;
}


//*****

DomParser.prototype.setSelectionToElement = function(element , aWindow) {
	if (!aWindow) aWindow=window;
	var body = aWindow.document.body;
	if (body.createTextRange) {
		var ieRange = body.createTextRange();
		ieRange.moveToElementText(element);
		ieRange.select();
	} else if (aWindow.getSelection) {
		aWindow.getSelection().selectAllChildren(element);
	}
}



DomParser.prototype.setSelectionHTML = function(html , aWindow) {
	if (!aWindow) aWindow=window;
	var ieSelection = aWindow.document.selection;

	if (ieSelection && ieSelection.createRange) {
		var ieRange = ieSelection.createRange();
		ieRange.pasteHTML(html); 
		ieRange.collapse(false);
		ieRange.select();
	} else {
		aWindow.document.execCommand('insertHTML', false, html);
	}
}

DomParser.prototype.getSelectionHTML = function(aWindow) {
	if (!aWindow) aWindow=window;
	
	//aWindow.focus();
	var ieSelection = aWindow.document.selection;
	var html=null;
	
	if (ieSelection && ieSelection.createRange) {
		var ieRange = ieSelection.createRange();
		html = ieRange.htmlText; 
	} else if (aWindow.getSelection) {
		var selObj = aWindow.getSelection(); 
		if (!selObj.rangeCount) {
			return "";
		}
		var selRange = selObj.getRangeAt(0);
		var fragment = selRange.cloneContents();
		var aDiv = aWindow.document.createElement("div");
		aDiv.appendChild(fragment);
		html = aDiv.innerHTML;
	}
	
	return html;
}

DomParser.prototype.insertElementAfterSelection = function(aWindow , element) {
	if (!aWindow) aWindow=window;

	var ieSelection = aWindow.document.selection;
	if (ieSelection && ieSelection.createRange) { //IE
		var ieRange = ieSelection.createRange();
		ieRange.collapse(false);
		var htmlText = element.outerHTML;
		ieRange.pasteHTML(htmlText); 
		ieRange.select();
	} else {
		var selObj = aWindow.getSelection(); 
		selObj.collapseToEnd();
		var selRange = selObj.getRangeAt(0);
		selRange.insertNode(element);
		selObj.selectAllChildren(element)
	}
}


DomParser.prototype.getSelectionRange = function(aWindow) {
	var selRange;
	
	if (!aWindow) aWindow=window;
	
	
	if (aWindow.getSelection) {
		var selObj = aWindow.getSelection(); 
		selRange = selObj.getRangeAt(0);

	} else if (aWindow.document.selection) {
		selRange = aWindow.document.selection.createRange(); 
	}
	
	return selRange;
}


DomParser.prototype.getRangeFragment = function(range) {
	var documentFragment=null;
	
	if (range.cloneContents) {
		documentFragment = range.cloneContents();
	} else {
		var parentElement = range.parentElement();
		if (parentElement && parentElement.ownerDocument) {
			documentFragment = parentElement.ownerDocument.createDocumentFragment();
			var htmlText = range.htmlText;
			
			var aDiv = parentElement.ownerDocument.createElement("DIV");
			aDiv.innerHTML = htmlText;
			
			var curElem = aDiv.firstChild;
			while(curElem) {
				if (curElem.nodeType == Node.ELEMENT_NODE) {
					documentFragment.appendChild(curElem);
				} else if (curElem.nodeType == Node.TEXT_NODE) {
					documentFragment.appendChild(curElem);
				}
				curElem=curElem.nextSibling;
			}
		}
	}
	return documentFragment;
}


DomParser.prototype.setRangeFragment = function(range , frag) {
	if (range.insertNode) {
		//alert("setRangeFragment1: "+range);
		range.deleteContents();
		range.insertNode(frag);
		

	} else {
		var htmlText = frag.innerHTML;
		range.pasteHTML(htmlText);
	}
}

DomParser.prototype.getSelectionFragment = function(aWindow) {
	return this.getRangeFragment(this.getSelectionRange(aWindow));
}


DomParser.prototype.getFragmentHTML = function(fragment) {
	var aDoc = fragment.ownerDocument;
	
	var aDiv = aDoc.createElement("div");
	aDiv.appendChild(fragment);
	var html = aDiv.innerHTML;
	
	return html;
}

DomParser.prototype.setSelectionFragment = function(aWindow , fragment) {
	this.setSelectionHTML(this.getFragmentHTML(fragment),aWindow);
}

DomParser.prototype.getSelectionHTML2 = function(aWindow) {
	var fragment = this.getSelectionFragment(aWindow);
	var html ="";
	if (fragment) {
		html = this.getFragmentHTML(fragment);
	}
	return html;
}


DomParser.prototype.setSelectionStyle = function(aWindow , styleName , styleValue) {
	var fragment = this.getSelectionFragment(this.frameElem.contentWindow);
	if (fragment) {
		this.setFragmentStyle(fragment , styleName , styleValue);
		this.setSelectionFragment(this.frameElem.contentWindow,fragment);
	}
}


DomParser.prototype.getRangeContainer = function(range) {
	var container = range.commonAncestorContainer;
	
	if (!container && range.parentElement) {
		container = range.parentElement()
	} else {
		while (container && container.nodeType != Node.ELEMENT_NODE) {
			container = container.parentNode;
		}
	}
	return container;
}

DomParser.prototype.setElementStyle = function(element , styleName , styleValue) { 
	if (element.style[styleName] != styleValue) {
		element.style[styleName] = styleValue;
	}
}

DomParser.prototype.unsetElementStyle = function(element , styleName) { 
	if (element.style[styleName]) {
		element.style[styleName] = "";
	}
}

DomParser.prototype.setFragmentStyle = function(fragment , styleName , styleValue) { 
	var curElem = fragment.firstChild;
	while(curElem) {
		var nextElem = curElem.nextSibling;
		if (curElem.nodeType == Node.ELEMENT_NODE) {
			this.removeChildrenElementStyleRecursive(curElem,styleName);
			this.setElementStyle(curElem,styleName , styleValue);
		} else if (curElem.nodeType == Node.TEXT_NODE) {
			if (curElem.nodeValue != "") {
				var newSpan = fragment.ownerDocument.createElement("SPAN");
				fragment.replaceChild(newSpan,curElem);
				newSpan.appendChild(curElem);
				this.setElementStyle(newSpan,styleName , styleValue);
			} else {
				fragment.removeChild(curElem); //reason for var nextElem 
			}
		}
		curElem=nextElem;
	}

}


DomParser.prototype.removeChildrenElementStyleRecursive = function(element , styleName) { 
	var curElem = element.firstChild;
	while(curElem) {
		if (curElem.nodeType == Node.ELEMENT_NODE) {
			this.unsetElementStyle(curElem , styleName);
			this.removeChildrenElementStyleRecursive(curElem,styleName);
		} 
		curElem=curElem.nextSibling;
	}
}



DomParser.prototype.getEventChar = function(event) {
	return String.fromCharCode(event.charCode ? event.charCode : event.keyCode);
}


DomParser.prototype.bindElementEvent = function (element,eventName,callback) {
	var self = this;
	
	function eventCaught(event) {
		
		if (!event) event=window.event; //IE6
		if (!event.target && event.srcElement) { //IE6
			event.target = event.srcElement;
		}
		if (!event.preventDefault) {//IE6
			event.preventDefault = function() {event.returnValue=false;}
		}
		if (!event.stopPropagation) {//IE6
			event.stopPropagation = function() {event.cancelBubble=true;}
		}
		
		if (event.toElement && !event.relatedTarget) event.relatedTarget=event.toElement;
		if (event.fromElement && !event.relatedTarget) event.relatedTarget=event.fromElement;
		
		//alert("eventCaught: "+ event.target.id + " -> " + event.target.parentNode.id);
		callback(event);
	}
	
	if (element) {
		if (element.addEventListener) { //DOM
			element.addEventListener(eventName, eventCaught , false);
		} else if (element.attachEvent) { //IE
			element.attachEvent('on'+eventName, eventCaught );
		}
	}
	return {'func':eventCaught , 'name':eventName , 'element':element};
}

DomParser.prototype.unbindElementEvent = function(bindInfo) {
	if (bindInfo.element.removeEventListener) { //DOM
		bindInfo.element.removeEventListener(bindInfo.name, bindInfo.func , false);
	} else if (bindInfo.element.detachEvent) { //IE
		bindInfo.element.detachEvent('on'+bindInfo.name, bindInfo.func );
	}
	return null;
}


DomParser.prototype.getElementPosition = function (e ){
	var left = 0;
	var top  = 0;

	while (e.offsetParent){
		left += e.offsetLeft;
		top  += e.offsetTop;
		e     = e.offsetParent;
	}

	left += e.offsetLeft;
	top  += e.offsetTop;

	var pos = {x:left, y:top};
	//window.status = "("+pos.x+","+pos.y+")";

	return pos;
}

DomParser.prototype.getElementSize = function (element) {
	var width,height;
	
	if (document.defaultView && document.defaultView.getComputedStyle) {
		var computedStyleBuffer = document.defaultView.getComputedStyle(element, null);
		
		widthValue = computedStyleBuffer.getPropertyCSSValue("width");
		heightValue = computedStyleBuffer.getPropertyCSSValue("height");

		try {
			width = widthValue.getFloatValue(CSSPrimitiveValue.CSS_PX);
			height = heightValue.getFloatValue(CSSPrimitiveValue.CSS_PX);
		} catch(ex) {
			//alert("type: "+widthValue.primitiveType);
			//alert("value: "+widthValue.getStringValue());
		
			//alert("widthValue: "+widthValue);
			//alert("heightValue: "+heightValue);
			alert(element.id +" -> "+ex);
		}
		
		//height = computedStyleBuffer.getPropertyValue("height");
	} else {
		width = element.offsetWidth;
		height = element.offsetHeight;
	}
	
	//window.status = "("+width+","+height+"): "+element.id;
	
	return {'width':width , 'height':height};
}

DomParser.prototype.getElementArea = function (element) {
	var pos = this.getElementPosition(element);
	var size = this.getElementSize(element);
	var bottom = pos.y + size.height;
	var right = pos.x + size.width;
	
	var area = {'left': pos.x , 'top': pos.y , 'bottom': bottom , 'right': right};
	
	//window.status = "("+area.top+","+area.left+","+area.bottom+","+area.right+")";
	return area;
}


window.gDOMHelper = new DomParser();

//****************************

function DowWidget() {
}

DowWidget.prototype = new DomParser;

DowWidget.newWidget = function(widgetId , widgetName) {
	var widgetConstructor = eval (widgetName); //Is eval EVIL here ????
	var newWidget = new widgetConstructor(widgetId);
	newWidget.uid = widgetId; 
	newWidget.widgetName = widgetName; 
	newWidget.preInit();
	newWidget.initParams();
	return newWidget;
}

DowWidget.prototype.preInit = function() {
}

DowWidget.prototype.initParams = function(params) {
	this.params={};

	var params = gWidgetParams[this.uid];
	if (params) {
		for(var key in params) {
			this.params[key] = getAndClearWidgetParam(this.uid , key);
		}
	}
	//delete gWidgetParams[this.uid]; not now needs to be used later in registerAllSubWidgets
}


						
DowWidget.prototype.clone = function(newUid) {
	gWidgetParams[newUid] = this.params; //could also be a deep copy
	var newWidget = DowWidget.newWidget(newUid , this.widgetName);
	return newWidget;
}

DowWidget.prototype.getWidgetElement = function() {
	var hookElem = document.getElementById(this.uid);
	return hookElem;
}

DowWidget.prototype.toString = function() {
	return '<widget id="' + this.uid + '" widgetName="' + this.widgetName + '"/>';
}


DowWidget.prototype.appendChildrenXMLData = function(root) {
	function doSubWidget(subWidget) {
		subWidget.appendXMLData(root);
	}
	
	this.getTopDescendantWidgets(doSubWidget);
}


DowWidget.prototype.findFirstChildWidget = function(parentElem) {
	var cur = parentElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE) {
			var curId = cur.id;
			if (curId) {
				var curWidget = gWidgets[curId];
				if (curWidget) {
					return curWidget;
				}
			}
		}
		cur = cur.nextSibling;
	}
	return null;
}


DowWidget.prototype.findParentWidget = function() {
	var hookElem = document.getElementById(this.uid);
	var widget = this.findWidgetParent(hookElem);
	return widget;
}

DowWidget.prototype.getFirstParentWidget = function(baseElem , tagName , className) {
	var curElem = baseElem;
	while (curElem) {
		if (curElem.tagName==tagName && (!className || this.hasElementClass(curElem,className))) {
			widget = gWidgets[curElem.id];
			if (widget) {
				return widget;
			}
		}
		curElem = curElem.parentNode;
	}
	return null;
}

DowWidget.prototype.getAllSubWidgets = function(topElem , tagName , className) {
	var widgets = [];
	var subElements = topElem.getElementsByTagName(tagName);
	var ii;
	var curElem,widget;
	for (ii=0 ; ii< subElements.length ; ii++) {
		curElem = subElements.item(ii);
		if (this.hasElementClass(curElem,className)) {
			widget = gWidgets[curElem.id];
			if (widget) {
				widgets.push(widget);
			}
		}
	}
	
	return widgets;
}

DowWidget.prototype.getChildrenWidgets = function(topElem  , className) {
	var widgets = [];
	
	var cur = topElem.firstChild;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE) {
			var curId = cur.id;
			if (curId) {
				var curWidget = gWidgets[curId];
				if (curWidget) {
					if (className) {
						if (this.hasElementClass(cur,className)) {
							widgets.push(curWidget);
						}
					} else {
						widgets.push(curWidget);
					}
				}
			}
		}
		cur = cur.nextSibling;
	}
	
	return widgets;
}

DowWidget.prototype.findWidgetParentIncludingSelf = function(rootElem) {
	var cur = rootElem;
	while (cur) {
		if (cur.nodeType == Node.ELEMENT_NODE && cur.id) {
			var widget = gWidgets[cur.id];
			if (widget) return widget;
		}
		cur=cur.parentNode;
	}
	return null;

}

DowWidget.prototype.getTopDescendantWidgets = function(callback,topElem) {
	if (!topElem) {
		topElem = document.getElementById(this.uid);
	}
	
	function _childWidgets(parentElem) {
		var cur = parentElem.firstChild;
		var widget;
		
		while (cur) {
			widget = null;
			if (cur.nodeType == Node.ELEMENT_NODE) {
				var curId = cur.id;
				if (curId) {
					var curWidget = gWidgets[curId];
					if (curWidget) {
						widget = curWidget;
					}
				}
			}
			
			if (widget) callback(widget); else _childWidgets(cur);
			cur = cur.nextSibling;
		}
	}
	
	_childWidgets(topElem);
}

DowWidget.prototype.sendEventDown = function(who,what,rootElem) {
	function _sendEventDown(widget) {
		var onMethod = widget["on_"+what];
		if (onMethod) {
			onMethod.call(widget,who);
		} else {
			widget.sendEventDown(who,what);
		}
	}
	
	this.getTopDescendantWidgets(_sendEventDown , rootElem);
}


DowWidget.prototype.sendEventUp = function(who,what,param) {
	var parentWidget = this.findParentWidget();
	if (parentWidget) {
		var onMethod = parentWidget["on_"+what];
		if (onMethod) {
			onMethod.call(parentWidget,who,param);
		} else {
			parentWidget.sendEventUp(who,what,param);
		}
	} else {
		alert("end of sendEventUp rope: "+what );
	}
}


DowWidget.prototype.getActionName = function() {
	return this.getElementActionName(this.getWidgetElement());
}

DowWidget.prototype.getFirstActionName = function(startElement , stopElement) {
	var actionName = null;
	var target = startElement;
	while (target && !actionName && target!=stopElement) {
		actionName = this.getElementActionName(target);
		target = target.parentNode;
	}
	return actionName;
}


DowWidget.prototype.widgetModified = function(widget,what) {
	var parentWidget = this.findParentWidget();
	
	if (parentWidget) {
		if (parentWidget.onWidgetModified) parentWidget.onWidgetModified(widget);
		else if (parentWidget.widgetModified) parentWidget.widgetModified(widget);
		else alert("Not a widget "+widget.uid+" : "+widget.widgetName+ " at "+ this.uid + " : " +this.widgetName);
	} else {
		alert("End of rope for "+widget.uid+" : "+widget.widgetName+ " at "+ this.uid + " : " +this.widgetName);
	}
}




DowWidget.prototype.cloneWidget = function() {
	var myElem = this.getWidgetElement();
	var clonedElem = this.cloneSubtree(myElem , true);
	
	var myUid = myElem.id;
	var clonedUid = clonedElem.id;
	
	var clonedWidget = this.clone(clonedUid);
	gWidgets[clonedUid] = clonedWidget;

	if (clonedWidget.postInit) { //subs done by this.cloneSubtree(myElem , true);
		clonedWidget.postInit(); 
	}
	
	return clonedElem;
}

DowWidget.prototype.cloneSubtree = function (rootElem , doWidgets) {
	var newUid = generateUid();
	var oldUid = rootElem.id;
	var newElem;
	
	var outerHTML = rootElem.outerHTML;
	if (outerHTML) { //IE copies attachEvent when using cloneNode
		var holder = document.createElement("DIV");
		holder.innerHTML = outerHTML;
		newElem = holder.firstChild;
	} else {
		newElem = rootElem.cloneNode(true);
	}
	newElem.setAttribute("id",newUid);
	
	var regExp = new RegExp("^"+oldUid+"(.*)");
	var newWidgets = [];
	
	var divList = newElem.getElementsByTagName("*");
	for (var ii=0 ; ii<divList.length ; ii++) {
		var curElem = divList.item(ii);
		var curId = curElem.id;
		if (curId) {
			var match = regExp.exec(curId);
			if (match) {
				var postfix = match[1];
				var newCurId = newUid+postfix;
				//alert("newCurId: "+newCurId);
				curElem.setAttribute("id",newCurId);
				
				if (doWidgets) { //NEW BETTER INCOMPATIBLE
					var curWidget = gWidgets[curId];
					if (curWidget) {
						var  newWidget = curWidget.clone(newCurId);
						gWidgets[newCurId] = newWidget;
						newWidgets.push(newWidget);
					}
				}
			}
		}
	}
	
	if (doWidgets) { //NEW BETTER INCOMPATIBLE
		rootElem.parentNode.insertBefore(newElem,rootElem);
		
		for (var index=0 ; index<newWidgets.length ; index++) {
			var curWidget = newWidgets[index];
			if (curWidget.postInit) {
				curWidget.postInit(); //for when you need the other widgets already initialized
			}
		}
	}
	
	return newElem;
}

DowWidget.prototype.unbindEvent = function (domElement,domEventName) {
	domElement.removeAttribute('on'+domEventName);
}

DowWidget.prototype.bindEvent = function (domElement,domEventName,widgetMethod) {
	var self = this;
	function callback(event) {
		gWidgets[self.uid][widgetMethod](event);
	}
	this.bindElementEvent(domElement,domEventName,callback);
}

DowWidget.prototype.dragStart = function (dragger) {
	window.status = "dragging";
}

DowWidget.prototype.dragMove = function (dragger) {
	//var pos = dragger.getDragPosition();  
	//window.status = "("+pos.x +","+pos.y+") : "; 
	//window.status = "drag move";
}

DowWidget.prototype.dragEnd = function (dragger) {
	window.status = "NOT dragging";
}

DowWidget.prototype.canDrop = function (dragWidget) {
	return false;
}





function FileUpload() {
}
FileUpload.prototype = new DowWidget;

FileUpload.prototype.postInit = function () {
	this.callbackName = null;
	this.browseElem =  document.getElementById(this.uid+"_file");
	this.formElem =  document.getElementById(this.uid+"_form");
	this.submitElem =  document.getElementById(this.uid+"_submit");
	this.bindEvent(this.formElem,"submit","submitAction");
}

FileUpload.prototype.setFileType = function (fileType) {
	switch(fileType) {
		case "image":
			this.submitElem.value = "Upload Image";
			//this.browseElem.setAttribute("accept","image/jpeg,image/gif,image/png");
			break;
		case "pdf":
			this.submitElem.value = "Upload PDF";
			//this.browseElem.setAttribute("accept","application/pdf");
			break;
		case "doc":
			this.submitElem.value = "Upload Word";
			//this.browseElem.setAttribute("accept","application/msword");
			break;
		case "xls":
			this.submitElem.value = "Upload Excel";
			//this.browseElem.setAttribute("accept","application/vnd.ms-excel");
			break;
	}
	
	this.formElem.setAttribute("action","/php/upload.php?file_type="+fileType);
}

FileUpload.prototype.setCallback = function (widget , methodName) {
	this.callbackWidget = widget;
	this.callbackName=methodName;
}


FileUpload.prototype.progress = function (percent) {
	var progressElem = document.getElementById(this.uid+"_progress");
	this.setTextValue(progressElem , percent+"%");
}

FileUpload.prototype.submitAction = function () {
	this.bindEvent(this.iframeElem,"load","loadAction");
	var formElem =  document.getElementById(this.uid+"_form");
	//formElem.submit();
	if (this.callerWidget.uploading) {
		this.callerWidget.uploading(this.params.error_msgs['upload_uploading']);
	}
}

/*
FileUpload.prototype.blurAction = function () {
	this.stopEditing();
}
*/

FileUpload.prototype.loadAction = function (event) {	
	var contentDoc = this.iframeElem.contentDocument;
	
	if (!contentDoc && document.frames) { //IE6
		contentDoc = document.frames(this.iframeElem.name).document;
	}
	
	if (contentDoc) {
		var responseObject = {};
		
		var responseList = this.getAllSubElements(contentDoc , "SPAN" , "response")
		for (var ii=0; ii< responseList.length ; ii++) {
			var responseElem = responseList[ii];
			responseObject[responseElem.id] = this.getTextValue(responseElem);
		}
		
		
		if (responseObject['error_code'] == 0) {
			if (this.callbackName) {
				this.callbackWidget[this.callbackName](responseObject['file_id'] ,responseObject['orig_url'], responseObject['file_type']);
			} else if (this.callerWidget.setImageData) {
				this.callerWidget.setImageData(responseObject['thumb_url'] , responseObject['web_url']  , responseObject['file_id'] , responseObject['file_name'] , this.params.error_msgs['upload_uploaded']);
			} else {
				this.callerWidget.setData(responseObject['thumb_url'] );
			}
		} else {
			if (this.callerWidget.uploadError) {
				this.callerWidget.uploadError(responseObject['error_code'] , responseObject['file_name'] , this.getErrorMessage(responseObject));
			}
		}
		this.stopEditing();
	}
	//this.stopEditing();
}


FileUpload.prototype.startEditing = function (callerWidget , left , top) {
	var editorElem = this.getWidgetElement();
	if (left) editorElem.style.left=left;
	if (top) editorElem.style.top=top;
	this.callerWidget=callerWidget;
	editorElem.style.display="block";
	
	this.browseElem.value="";
	
	if (this.iframeElem) {
		editorElem.removeChild(this.iframeElem);
		this.iframeElem = null;
	}
	
	if (!this.iframeElem) {
		if (document.all) {
			//this.iframeElem = document.createElement('<iframe name="uploadWindow" allowTransparency style="display: none">') ;
			this.iframeElem = document.createElement('<iframe name="uploadWindow">') ;
		} else {
			this.iframeElem = document.createElement("iframe");
			this.iframeElem.name = "uploadWindow";
			}
		this.iframeElem.id = this.uid+"_iframe";
		this.iframeElem.className = "upload";
		//this.iframeElem.allowTransparency=true; //IE
		editorElem.appendChild(this.iframeElem);
		//this.bindEvent(this.iframeElem,"load","loadAction");
	}
	
	var formElem =  document.getElementById(this.uid+"_form");
	formElem.target = this.iframeElem.name;

/*	
	this.canStop = false;
	this.browseElem.focus();
*/
	this.canStop = true;
}

FileUpload.prototype.stopEditing = function () {
	if (this.canStop) {
		var editorElem = this.getWidgetElement();
		editorElem.style.display="none";
		if (this.callerWidget.hideForm) {
			this.callerWidget.hideForm();
		}
	}
}

FileUpload.prototype.getErrorMessage = function (responseObject) {
	function substitute(matchStr, subMatch1 , offset, origStr) {
		//alert("matchStr: "+matchStr+ " subMatch1: "+subMatch1+" offset: "+offset);
		return responseObject[subMatch1];
	}
	
	var errorMsg = this.params.error_msgs[responseObject['code']];
	if (!errorMsg) {
		errorMsg = this.params.error_msgs['upload_unknown_error'];
	} 
	errorMsg = errorMsg.replace(/\{\$(\w+)\}/g , substitute );
	
	return errorMsg;
}





function DowInteractiveAction() {
}

DowInteractiveAction.prototype = new DowWidget;

DowInteractiveAction.prototype.postInit = function () {
	this.smileyElem = document.getElementById(this.uid+"_smiley");
	this.bindEvent(this.smileyElem,"mousedown","smileyAction"); 
	this.updateSmiley();
}

DowInteractiveAction.prototype.updateSmiley = function () {
	if (this.smileyElem) {
		var name = "icon_neutral";
		if (this.params.rank) {
			name = "icon_smile";
		} 
		this.smileyElem.src = "/images/smiley_icons/"+name+".gif";
	}
}

DowInteractiveAction.prototype.smileyAction = function (event) {
	this.params.rank=this.params.rank ? 0 : 1;
	this.doRanking(this.params.rank);
	this.updateSmiley();
}

DowInteractiveAction.prototype.doRanking = function(value) {
	var action = this.createEmptyAction("ranking");
	var doc = action.ownerDocument;
	var rankingElem = doc.createElement("rank");
	rankingElem.setAttribute("value",value);
	action.appendChild(rankingElem);
	this.sendAction(action.ownerDocument);
}


DowInteractiveAction.prototype.doFavorite = function(isChecked,isDow) {
	var methodName = "favorite";
	if (isDow) {
		//methodName += "Dow";
	}
	var action = this.createEmptyAction(methodName);
	var doc = action.ownerDocument;
	if (isDow) {
		action.setAttribute("login_id",0);
	}
	var favoriteElem;
	if (isChecked) {
		favoriteElem = doc.createElement("on");
	} else {
		favoriteElem = doc.createElement("off");
	}
	action.appendChild(favoriteElem);
	this.sendAction(action.ownerDocument);
}

DowInteractiveAction.prototype.doEditable = function(isEditable) {
	var editableStyleElem = document.getElementById("editable_css_link");
	editableStyleElem.disabled = !isEditable;
	//alert("isEditable: "+ isEditable + " : " +editableStyleElem);
}

DowInteractiveAction.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_favorite") {
		this.doFavorite(widget.getData(),false);
	} else if (widget.uid == this.uid+"_dowFavorite") {
		this.doFavorite(widget.getData(),true);
	} else if (widget.uid == this.uid+"_editable") {
		this.doEditable(widget.getData());
	} else {
		alert("DowInteractiveAction.onWidgetModified: "+ this.uid + " -> " + widget.uid);
	}
}


//*******************************


function CheckBoxWidget(uid) {
	this.uid = uid;
	this.type="CheckBoxWidget";
	this.checkbox = document.getElementById(this.uid+"_checkbox");
	this.registerListeners();
	
	this.checkbox.checked = this.checkbox.defaultChecked; //for no shift refresh on firefox
}
CheckBoxWidget.prototype = new DowWidget;

CheckBoxWidget.prototype.registerListeners = function () {
	this.bindEvent(this.checkbox,"change","checkboxAction");
}

CheckBoxWidget.prototype.getData = function() {
	return this.checkbox.checked;
}

CheckBoxWidget.prototype.checkboxAction = function(event) {
	this.widgetModified(this);
}

//*******


function ImageEditor(uid) {
	this.uid = uid;
	this.browseElem =  document.getElementById(this.uid+"_file");
	this.bindEvent(this.browseElem,"change","changeAction");
}
ImageEditor.prototype = new DowWidget;


ImageEditor.prototype.progress = function (percent) {
	var progressElem = document.getElementById(this.uid+"_progress");
	this.setTextValue(progressElem , percent+"%");
}

ImageEditor.prototype.changeAction = function () {
	var formElem =  document.getElementById(this.uid+"_form");
	formElem.submit();
	this.callerWidget.setData("/up/icons/empty.png");
	//this.checkForProgress();
}

ImageEditor.prototype.loadAction = function (event) {	
	//var formElem =  document.getElementById(this.uid+"_form");
	//formElem.target = this.iframeElem.name;

	
	var contentDoc = this.iframeElem.contentDocument;
	
	if (!contentDoc && document.frames) { //IE6
		contentDoc = document.frames(this.iframeElem.name).document;
	}
	
	if (contentDoc) {
		var nameElem = contentDoc.getElementById("file_name");
		if (nameElem) {
			var name = this.getTextValue(nameElem);
			this.callerWidget.name = name;
		}

		var urlElem = contentDoc.getElementById("thumb_url");
		if (urlElem) {
			//var width = this.getTextValue(contentDoc.getElementById("width"));
			//var height = this.getTextValue(contentDoc.getElementById("height"));
			var fileUrl = this.getTextValue(urlElem);
			var file_id = 0;
			var fileIdElem = contentDoc.getElementById("file_id");
			if (fileIdElem) {
				file_id = this.getTextValue(fileIdElem);
			}
			
			if (this.callerWidget.setImageData) {
				var zoomElem = contentDoc.getElementById("web_url");
				var zoom_url = this.getTextValue(zoomElem);
				this.callerWidget.setImageData(fileUrl, zoom_url , file_id);
			} else {
				this.callerWidget.setData(fileUrl );
			}
			this.stopEditing();
		}

	}
	//this.stopEditing();
}

/*
ImageEditor.prototype.checkForProgress = function () {
	var progressElem =  document.getElementById(this.uid+"_progress");

	var action = this.createEmptyAction("checkFileUpload");
	action.setAttribute("progress_key",progressElem.value);
	this.sendAction(action.ownerDocument,"receiveStatus");
}

ImageEditor.prototype.receiveStatus = function (xmlResponse) {
	var statusElem = xmlResponse.getElementsByTagName("status").item(0);
	
	var current = statusElem.getAttribute("current");
	var total = statusElem.getAttribute("total");
	var percent = ((0+current)*100.0)/(0+total);
	var progressElem =  document.getElementById(this.uid+"_percent");
	this.setTextValue(progressElem,percent);
		
	var isDone = statusElem.getAttribute("done");
	if (isDone && isDone != 1) {
		setTimeout("gWidgets["+this.uid+"].checkForProgress()",1000);
	}
	return true;
}
*/

ImageEditor.prototype.startEditing = function (callerWidget , left , top) {
	var editorElem = this.getWidgetElement();
	editorElem.style.left=left;
	editorElem.style.top=top;
	this.callerWidget=callerWidget;
	editorElem.style.display="block";
	
	gWidgets['body'].darkenPage();

	if (!this.iframeElem) {
	
		if (document.all) {
			this.iframeElem = document.createElement('<iframe name="uploadWindow">') ;
		} else {
			this.iframeElem = document.createElement("iframe");
			this.iframeElem.name = "uploadWindow";
			}
		this.iframeElem.id = this.uid+"_iframe";
		this.iframeElem.className = "upload";
		editorElem.appendChild(this.iframeElem);
		this.bindEvent(this.iframeElem,"load","loadAction");
	}
	
	var formElem =  document.getElementById(this.uid+"_form");
	formElem.target = this.iframeElem.name;
}

ImageEditor.prototype.stopEditing = function () {
	var editorElem = this.getWidgetElement();
	editorElem.style.display="none";
	gWidgets['body'].undarkenPage();
}


ImageEditor.prototype.style = function () {
	var styleWidget = gWidgets[this.uid+"_style"];
	var style = styleWidget.getData();
	
	//this.imageElem.setAttribute("class",style);
}

ImageEditor.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_style") {
		this.style();
	} else if (widget.uid == this.uid+"_ok") {
		this.stopEditing();
	} else {
		alert("ImageEditor.onWidgetModified: "+ this.uid + " -> " + widget.uid);
	}
}

//****

function ImageWidget() {
}
ImageWidget.prototype = new DowWidget;

ImageWidget.prototype.postInit = function () {
	this.divElem = this.getWidgetElement();
	this.imageElem = document.getElementById(this.uid + "_img");
	this.bindEvent(this.divElem,"click","zoomAction");
	this.bindEvent(this.imageElem,"load","loadAction");
}

//********

ImageWidget.prototype.getData = function () {
	return this.params.src;
}

ImageWidget.prototype.setData = function (src) {
	this.params.src=src;
	this.imageElem.src=src;
	this.widgetModified(this);
}

ImageWidget.prototype.setImageData = function (fileUrl , zoom_url , file_id) {
	this.params.file_id = file_id;
	this.params.zoom_src = zoom_url;
	this.setData(fileUrl);
}

ImageWidget.prototype.cleanSrc = function (src) {
	return src;
}

ImageWidget.prototype.appendXMLData = function (root) {
	var doc = root.ownerDocument;
	var myElem = doc.createElement("dow_image");
	
	var src = this.cleanSrc(this.getData());
	var zoom_src = this.cleanSrc(this.params.zoom_src);
	var file_id = this.params.file_id;
	
	if (!src || !zoom_src || !file_id) {
		return false;
	}
	
	myElem.setAttribute("src", src );
	myElem.setAttribute("file_id", file_id);
	myElem.setAttribute("zoom_src", zoom_src);
	root.appendChild(myElem);
	
	return true;
}


//********

ImageWidget.prototype.loadAction = function (event) {
	this.sendEventUp(this,"load" );
}

ImageWidget.prototype.zoomAction = function (event) {
	this.sendEventUp(this,"zoom", this.params.zoom_src );
}

ImageWidget.prototype.selectAction = function () {
	if (this.hasElementClass(this.divElem,"selectable")) {
		this.sendEventUp(this,"willselect");
		this.setElementClass(this.divElem,"selected");
		window.gSelection.set(this);
		this.sendEventUp(this,"hasselected");
	}
}

ImageWidget.prototype.unselectAction = function (who) {
	if (this.hasElementClass(this.divElem,"selectable")) {
		this.unsetElementClass(this.divElem,"selected");
	}
}

ImageWidget.prototype.on_unselect = function (who) {
	this.unselectAction();
}

ImageWidget.prototype.do_edit = function (event) {
	var baseElem =this.getWidgetElement();
	var pos = this.getElementPosition(baseElem);
	var uploadWidget = gWidgets["file_upload"];
	
	uploadWidget.setFileType("image");
	uploadWidget.startEditing(this, pos.x+"px" , pos.y+"px");
}

/*
ImageWidget.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_edit") {
		this.do_edit();
	} else {
		alert("ImageWidget.onWidgetModified: "+ this.uid + " -> " + widget.uid);
	}
}
*/

//*************************

function ImageWithCaptionWidget(uid) {
	this.uid = uid;
	this.widgetElem = document.getElementById(this.uid);
	this.imageUid = uid+"_image";
	this.captionUid = uid+"_caption";
}
ImageWithCaptionWidget.prototype = new DowWidget;

ImageWithCaptionWidget.prototype.postInit = function () {
	//this.editElem = document.getElementById(this.uid + "_edit");
}

//***

ImageWithCaptionWidget.prototype.getCaptionWidget = function () {
	return  gWidgets[this.captionUid];
}

ImageWithCaptionWidget.prototype.toggleCaption = function () {
	var captionWidget = this.getCaptionWidget();
	if (captionWidget.isEditing()) {
		captionWidget.stopEdit();
	} else {
		captionWidget.startEdit();
	}
	this.updateEditIcon();
}

ImageWithCaptionWidget.prototype.updateEditIcon = function () {
	var captionWidget = this.getCaptionWidget();
	if (captionWidget.isEditing()) {
		this.setElementClass(this.widgetElem , "editing");
	} else {
		this.unsetElementClass(this.widgetElem , "editing");
	}
}

ImageWithCaptionWidget.prototype.getData = function () {
	var captionWidget = this.getCaptionWidget();
	var imageWidget = gWidgets[this.imageUid];

	var src =  imageWidget.getData();
	var caption = captionWidget.getData();
	
	return {'src': src , 'caption': caption};
}


ImageWithCaptionWidget.prototype.appendXMLData = function (root) {
	var doc = root.ownerDocument;
	var myData = doc.createElement("image_with_caption");
	
	if (gWidgets[this.uid+"_image"].appendXMLData(myData) === false) {
		return false;
	}
	
	gWidgets[this.uid+"_caption"].appendXMLData(myData);
	
	root.appendChild(myData);
	return true;
}


ImageWithCaptionWidget.prototype.setData = function (dataObject) {
//url = "/lang/french/images/picto_4-trans.png";
	
	var imageElem = document.getElementById(this.uid+"_image");
	var captionWidget = gWidgets[this.uid+"_caption"];

	imageElem.setAttribute("src",dataObject.src);
}

ImageWithCaptionWidget.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_edit") {
		this.edit();
	} else if (widget.uid == this.uid+"_removeItem") {
		var listWidget = this.findParentWidget();
		listWidget.removeItem(document.getElementById(this.uid));
	} else if (widget.uid == this.uid+"_caption") {
		this.updateEditIcon();
		//this.widgetModified(this);
		this.sendEventUp(this,"caption");
	} else if (widget.uid == this.uid+"_image") {
		if (widget.name) {
			var captionWidget = gWidgets[this.uid+"_caption"];
			captionWidget.setData(widget.name);
			delete widget.name;
		}
		this.widgetModified(this);
	} else {
		alert("ImageWithCaptionWidget.onWidgetModified: "+ this.uid + " -> " + widget.uid);
	}
}


ImageWithCaptionWidget.prototype.edit = function (actionElem) {
	var iframeElem = document.createElement("iframe");
	iframeElem.setAttribute("width","100%");
	iframeElem.setAttribute("height","400");
	iframeElem.setAttribute("scrolling","no");
	iframeElem.setAttribute("frameborder","0");
	
	var src = "/"+language+"/upload_frame_generic?uploadParamStr="+this.uid;
	iframeElem.setAttribute("src",src);

	this.widgetElem.appendChild(iframeElem);
}

ImageWithCaptionWidget.prototype.endEdit = function (url) {
	var dataObject = this.getData();
	dataObject.src = url;
	this.setData(dataObject);
	this.widgetModified(this);

	var editElem = this.findElement(this.getWidgetElement(),"IFRAME","");
	if (editElem) {
		editElem.parentNode.removeChild(editElem);
	}
}

//******************

function ZoomedImage(uid) {
	this.imageElem = document.getElementById(uid+"_image");
	this.loaderElem = document.getElementById(uid+"_loader");
}
ZoomedImage.prototype = new DowWidget;

ZoomedImage.prototype.postInit = function(event) {
	this.bindEvent(this.getWidgetElement(),"click","clickAction");
	this.bindEvent(this.imageElem,"load","loadAction");
}

ZoomedImage.prototype.clickAction = function(event) {
	var widgetElem = this.getWidgetElement();
	this.imageElem.style.visibility = "hidden";
	this.loaderElem.style.visibility = "hidden";
	widgetElem.style.display = "none";
}

ZoomedImage.prototype.loadAction = function (event) {
	var size = this.getContentSize();
	var offset = this.getScrollOffset();
	
	var left = offset.left +  size.width/2 - this.imageElem.width/2;
	var top = offset.top + size.height/2- this.imageElem.height/2;
	
	if (left<0) left=0;
	if (top<0) top=0;
	
	this.imageElem.style.left = left + "px";
	this.imageElem.style.top = top + "px";

	this.loaderElem.style.visibility = "hidden";
	this.imageElem.style.visibility = "visible";
}

ZoomedImage.prototype.showZoom = function(src) {
	var widgetElem = this.getWidgetElement();
	//widgetElem.style.width = document.body.clientWidth + "px";

	var size = this.getContentSize();

	var width = document.body.clientWidth;
	if (size.width > width) width=size.width;
	
	var height = document.body.clientHeight;
	if (size.height > height) height=size.height;
	
	widgetElem.style.width = width + "px";
	widgetElem.style.height = height + "px";
	
	var size = this.getContentSize();
	var offset = this.getScrollOffset();
	
	this.loaderElem.style.left = (offset.left + size.width/2) + "px";
	this.loaderElem.style.top = (offset.top + size.height/2) + "px";
	this.loaderElem.style.visibility = "visible";

	this.imageElem.src=src;
	
	widgetElem.style.display = "block";
}


//*************



function DowWelcomeAction() {
}
DowWelcomeAction.prototype = new DowAction;

DowWelcomeAction.prototype.doAction = function(welcomeText) {
	var action = this.createEmptyAction("setGenericXML");
	action.setAttribute("what_key","welcome");
	var doc = action.ownerDocument;
	var simpleTextElem = doc.createElement("simpleText");
	simpleTextElem.appendChild(doc.createTextNode(welcomeText));

	action.appendChild(simpleTextElem);
	this.sendAction(action.ownerDocument,null);
}



function WelcomeBehavior(uid) {
	this.uid = uid;
	this.type="WelcomeBehavior";
}
WelcomeBehavior.prototype = new DowWidget;

WelcomeBehavior.prototype.widgetModified = function () {
	var messageWidget = gWidgets['message_welcomeBehavior'];
	var text = messageWidget.getData().text;
	
	var welcomeAction = new DowWelcomeAction();
	welcomeAction.doAction(text);
}



function BookmarkWidget(uid) {
	this.uid = uid;
	this.type="BookmarkWidget";
}
BookmarkWidget.prototype = new DowWidget;


BookmarkWidget.prototype.getData = function () {
	var widgetElem = this.getWidgetElement();
	var anchorElem = this.findElement(widgetElem,"A","bookmark");
	var name = this.getTextValue(anchorElem);
	var href = anchorElem.getAttribute("HREF");
	return {'name':name , 'href':href};
}

BookmarkWidget.prototype.getXMLData = function (doc) {
	var data = this.getData();
	
	var bookmark = doc.createElement("bookmark");
	bookmark.setAttribute("href", data.href);
	bookmark.appendChild(doc.createTextNode(data.name));
	return bookmark;
}

BookmarkWidget.prototype.setData = function (dataObject) {
	if (!dataObject) {
		dataObject = {'name':'Days of Wonder' , 'href':'http://wwww.daysofwonder.com' };
	}
	
	var widgetElem = this.getWidgetElement();
	var anchorElem = this.findElement(widgetElem,"A","bookmark");
	anchorElem.setAttribute("href",dataObject.href);
	this.setTextValue(anchorElem,dataObject.name);
}


BookmarkWidget.prototype.onWidgetModified = function(widget) {
	if (widget.uid == this.uid + "_edit") {
		this.edit();
	} else if (widget.uid == this.uid + "_editor_ok") {
		this.okedit();
	} else if (widget.uid == this.uid + "_removeItem") {
		var listWidget = this.findParentWidget();
		listWidget.removeItem(document.getElementById(this.uid));
	}

}


BookmarkWidget.prototype.okedit = function () {
	var editor_uid = this.uid+"_editor";

	var dataObject = {};
	
	var nameElem = document.getElementById(editor_uid+"_name");
	dataObject['name']=nameElem.value;
		
	var urlElem = document.getElementById(editor_uid+"_href");
	dataObject['href']=urlElem.value;
	this.setData(dataObject);

	var editElem = document.getElementById(editor_uid);
	editElem.setAttribute("class","editor");
	this.widgetModified(this);
}

BookmarkWidget.prototype.edit = function () {
	var editor_uid = this.uid+"_editor";
	var data = this.getData();
	
	var nameElem = document.getElementById(editor_uid+"_name");
	nameElem.value = data.name;
	
	var urlElem = document.getElementById(editor_uid+"_href");
	urlElem.value = data.href;
	
	
	var editElem = document.getElementById(editor_uid);
	editElem.setAttribute("class","editing");
}

//*************************

//********************************

function ChooseWidget(uid) {
	this.uid = uid;
	this.type="ChooseWidget";
	var selectElem = document.getElementById(this.uid);
	this.bindEvent(selectElem,"change","selectAction");
}
ChooseWidget.prototype = new DowWidget;

ChooseWidget.prototype.getData = function() {
	var selectElem = document.getElementById(this.uid);
	return selectElem.value;
}

ChooseWidget.prototype.selectAction = function(event) {
	//alert("CheckBoxWidget.selectAction");
	this.widgetModified(this);
}



//********************************

function FreeFlowWidget(uid) {
	this.uid = uid;
	this.type="FreeFlowWidget";
}
FreeFlowWidget.prototype = new DowWidget;

FreeFlowWidget.prototype.appendXMLData = function (root) {
	var doc = root.ownerDocument;
	var myElem = doc.createElement("free_flow");
	
	var listElem = document.getElementById(this.uid + "_list");

	function doSubWidget(subWidget) {
		subWidget.appendXMLData(myElem);
	}
	
	this.getTopDescendantWidgets(doSubWidget,listElem);

	root.appendChild(myElem);
}

FreeFlowWidget.prototype.on_willselect = function (who) {
	this.sendEventDown(this,"unselect");
	this.selected = who;
}

FreeFlowWidget.prototype.on_hasselected= function (who) {

}


FreeFlowWidget.prototype.deleteBlock = function(blockWidget) {
	if (blockWidget) {
		var elem = blockWidget.getWidgetElement();
		elem.parentNode.removeChild(elem);
		this.widgetModified(this);
	}
}

FreeFlowWidget.prototype.newFreeElement = function (templateId) {
	var listElem = document.getElementById(this.uid + "_list");
	var templateElem = document.getElementById(templateId);
	
	var newFreeElement = this.cloneSubtree(templateElem);
	listElem.appendChild(newFreeElement);

	registerAllSubWidgets(newFreeElement);
	
	this.widgetModified(this);
}


FreeFlowWidget.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_newSpan") {
		this.newFreeElement(this.uid + "_spanTemplate");
	} else if (widget.uid == this.uid+"_newLink") {
		this.newFreeElement(this.uid + "_linkTemplate");
	} else if (widget.uid == this.uid+"_newPicture") {
		this.newFreeElement(this.uid + "_imageTemplate");
	} else if (widget.uid == this.uid+"_newDowPageLink") {
		this.newFreeElement(this.uid + "_dowPageLinkTemplate");
	} else {
		//alert("FreeFlowWidget.onWidgetModified: "+ this.uid + " -> " + widget.uid);
		this.widgetModified(this);
	}
}

//********************************

function DowPageLink(uid) {
	this.uid = uid;
	this.type="DowPageLink";
}
DowPageLink.prototype = new DowWidget;

DowPageLink.prototype.getXMLData = function (doc) {
	var dowPageLink = doc.createElement("dowPageLink");
	return dowPageLink;
}

DowPageLink.prototype.edit = function () {
	var editorWidget = gWidgets[this.uid+"_editor"];
	editorWidget.fillEditor();

	var editElem = document.getElementById(this.uid+"_editor_toggle");
	editElem.setAttribute("class","editing");
}

DowPageLink.prototype.ok = function () {
	var editElem = document.getElementById(this.uid+"_editor_toggle");
	editElem.setAttribute("class","editor");
	this.widgetModified(this);
}

DowPageLink.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_edit") {
		this.edit();
	} else if (widget.uid == this.uid+"_ok") {
		this.ok();
	} else {
		alert("DowPageLink.onWidgetModified: "+ this.uid + " -> " + widget.uid);
	}
}

//********************************
function DowPageLinkEditor(uid) {
	this.uid = uid;
	this.type="DowPageLinkEditor";
	this.bindEvent(document.getElementById(this.uid+"_player"),"change","selectPlayerAction");
}
DowPageLinkEditor.prototype = new DowWidget;


DowPageLinkEditor.prototype.doGetFavorites = function() {
	var action = this.createEmptyAction("getFavorites");
	//action.setAttribute("what_key","bookmarks");
	//var doc = action.ownerDocument;
	this.sendAction(action.ownerDocument);
}

DowPageLinkEditor.prototype.doGetPages = function(player_id) {
	var action = this.createEmptyAction("getPages");
	action.setAttribute("player_id",player_id);
	this.sendAction(action.ownerDocument);
}


DowPageLinkEditor.prototype.extractPlayerData = function(responseXML) {
	var playerData = [];
	var players = responseXML.getElementsByTagName('player');
	var ii;
	
	for (ii=0; ii<players.length; ii++) {
		var player = players.item(ii);
		var player_id = player.getAttribute('player_id');
		var login = player.getAttribute('login');
		
		playerData.push({'player_id' : player_id , 'login' : login});
	}
	
	return playerData;
}

DowPageLinkEditor.prototype.fillPlayerData = function(playerData) {
	var playerSelect =  document.getElementById(this.uid+"_player");
	while(playerSelect.length) {
		playerSelect.remove(0);
	}
	
	for (var index in playerData) {
		var option1 = document.createElement("option");
		option1.value = playerData[index].player_id;
		option1.appendChild(document.createTextNode(playerData[index].login));
		playerSelect.add(option1,null);
	}
}

DowPageLinkEditor.prototype.doReaction = function(element , responseXML) {
	var playerData = this.extractPlayerData(responseXML);
	this.fillPlayerData(playerData);
	return true;
}

DowPageLinkEditor.prototype.getPlayerId = function () {
	var playerSelect =  document.getElementById(this.uid+"_player");
	return playerSelect.value;
}

DowPageLinkEditor.prototype.selectPlayerAction = function () {
	this.doGetPages(this.getPlayerId());
}


DowPageLinkEditor.prototype.fillEditor = function () {
	var playerSelect =  document.getElementById(this.uid+"_player");
	
	var option1 = document.createElement("option");
	option1.value = "14";
	option1.appendChild(document.createTextNode("john"));
	
	playerSelect.add(option1,null);
	
	var pageSelect =  document.getElementById(this.uid+"_page");
	
	var option1 = document.createElement("option");
	option1.value = "3234";
	option1.appendChild(document.createTextNode("galley"));
	
	pageSelect.add(option1,null);
	
	this.doGetFavorites();

}

//******************

function PlayerWidget(uid) {
	this.uid = uid;
	this.dataElem = document.getElementById(uid+"_data");
}
PlayerWidget.prototype = new DowWidget;

PlayerWidget.prototype.getData = function () {
	var login = this.getTextValue(this.dataElem);
	var player_id = this.getElementPrefixedClass(this.getWidgetElement() , "player_id_");
	return {'player_id': player_id , 'login': login};
}

PlayerWidget.prototype.on_editAction = function (who) {
	this.startEditor();
}

PlayerWidget.prototype.getLoginName = function(login_id) {
	var action = this.createEmptyAction("getLoginName");
	action.setAttribute("request_id",login_id);
	this.sendAction(action.ownerDocument,"receiveLoginName");
}

PlayerWidget.prototype.receiveLoginName = function(xmlResponse) {
	var loginName = xmlResponse.getAttribute("login");
	var player_id = xmlResponse.getAttribute("login_id");
	
	if (!player_id) {
		var request = xmlResponse.getAttribute("request");
		alert("User: '"+request+"' does not exist. USE THE LOGIN ID!!!");
		this.setTextValue(this.dataElem,"unknown");
		this.widgetModified(this);
	} else {
		this.setElementPrefixedClass(this.getWidgetElement(),"player_id_",player_id);
		this.setTextValue(this.dataElem,loginName);
		this.dataElem.href = "/"+language+"/mypage/"+player_id+"/m44";
		this.widgetModified(this);
	}
	return true;
}


PlayerWidget.prototype.startEditor = function () {
	var data = this.getData();
	var login_id = prompt("enter login id of the player: ", data.login);
	if (login_id) {
		this.setTextValue(this.dataElem,login_id);
		this.getLoginName(login_id);
	}
}


//*********************

function TabsWidget(uid) {
	this.uid = uid;
	this.tabNamesElem = document.getElementById(uid+"_tabNames");
	this.tabcontentElem = document.getElementById(uid+"_tabcontent");
	
	this.bindEvent(this.tabNamesElem,"click","clickTabAction");
}
TabsWidget.prototype = new DowWidget;

TabsWidget.prototype.clickTabAction = function (event) {
	var dataElem =  document.getElementById(event.target.id+"_content");
	this.selectTab(event.target,dataElem);
}

TabsWidget.prototype.selectTab = function (selectTagElem ,selectedDataElem) {
	var self= this;
	
	this.childIterator(this.tabNamesElem , 'div' , function(childElem) {self.unsetElementClass(childElem,"selected");} );
	this.childIterator(this.tabcontentElem , 'div' , function(childElem) {childElem.style.display="none";} );
	
	this.setElementClass(selectTagElem,"selected");
	selectedDataElem.style.display = "block";

	this.sendEventDown(this,"tabSelected",selectedDataElem);
}

//*****************
window.gCommands = {};

function DowMenu(uid) {
	this.uid = uid;
	window.gSelection.informMenu(uid);
}
DowMenu.prototype = new DowWidget;


DowMenu.prototype.onSelectionChanged = function (selection) {
	var menuElem = this.getWidgetElement();
	var self = this;
	this.childIterator(menuElem , 'div' , function(elem) {if (gDOMHelper.hasElementClass(elem,"widget_DowMenuItem")) self.selectionChanged(selection,elem.id);} );
}

DowMenu.prototype.selectionChanged = function (selection , menuItemId) {
	var is_enabled = gCommands["is_enabled_"+menuItemId];
	if (is_enabled) {
		this.enableItem(is_enabled(selection),menuItemId);
	}

	var contextualize = gCommands["contextualize_"+menuItemId];
	if (contextualize) {
		this.contextualizeItem(contextualize(selection),menuItemId);
	}

}

DowMenu.prototype.contextualizeItem = function (context , menuItemId) {
	var menuElem = document.getElementById(menuItemId);
	this.childIterator(menuElem , 'span' , function(elem) {if (gDOMHelper.hasElementClass(elem,"selected")) {gDOMHelper.setElementClass(elem,"item_hidden");}} );
	var contextElem = document.getElementById(context);
	this.setElementClass(contextElem,"selected");
}

DowMenu.prototype.enableItem = function (is_enabled , menuItemId) {
	//alert(menuItemId + " : "+ is_enabled);
}

//***

function DowMenuItem(uid) {
	this.uid = uid;
	this.bindEvent(this.getWidgetElement(),"click","clickAction");
	this.bindEvent(this.getWidgetElement(),"mousedown","mousedownAction");
}
DowMenuItem.prototype = new DowWidget;

DowMenuItem.prototype.mousedownAction = function (event) {
	//alert("DowMenuItem.prototype.mousedownAction");
	event.stopPropagation();
	event.preventDefault();
	//window.status += "M"; 
	
	//alert("stop");
}

DowMenuItem.prototype.clickAction = function (event) {
	event.stopPropagation();
	
	var actionName = this.getActionName();
	if (actionName) {
		this.sendEventUp(this, actionName);
	} else {
		alert("no command for: "+event);
	}
}

	

//*******************************

function ButtonWidget() {
}
ButtonWidget.prototype = new DowWidget;

ButtonWidget.prototype.postInit = function() {
//alert("ButtonWidget. .postInit: "+ this.uid);
	this.bindEvent(this.getWidgetElement(),"click","buttonAction");
}
	
ButtonWidget.prototype.buttonAction = function(event) {
//alert("buttonAction: "+ this.uid);
	var actionName = this.getActionName();
	if (actionName) {
		this.sendEventUp(this, actionName);
	} else {
		this.widgetModified(this);
	}
}


//*******************************

function PromptWidget(uid) {
	this.type="PromptWidget";
	this.uid = uid;
	this.data = "";
}

PromptWidget.prototype = new DowWidget;

PromptWidget.prototype.getData = function() {
	return this.data;
}

PromptWidget.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid + "_prompt") {
		this.newPage();
	} else if (widget.uid == this.uid + "_promptOK") {
		this.promptOK();
	}
 }

PromptWidget.prototype.newPage = function() {
	var promptElem = this.findElement(this.getWidgetElement(),"DIV","promptUI");
	promptElem.setAttribute("style","display: block");
}

PromptWidget.prototype.promptOK = function() {
	var promptElem = this.findElement(this.getWidgetElement(),"DIV","promptUI");
	var inputElem = this.findElement(promptElem,"INPUT","");
	var pagePath = inputElem.value;
	this.data = pagePath;
	promptElem.setAttribute("style","display: none");
	this.widgetModified(this);
}


//********

function DowScroller() {
	this.lastTop=0;
}
DowScroller.prototype = new DowWidget;

DowScroller.prototype.postInit = function(event) {
	this.bindEvent(this.getWidgetElement(),"scroll","scrollAction");
}

DowScroller.prototype.scrollAction = function(event) {
	var oldPos = event.target.scrollTop;
	
	var newPos = Math.floor(oldPos/25)*25;
	if (newPos == this.lastTop && oldPos > this.lastTop) { //canceled a modif
		newPos += 25;
	}
	
	event.target.scrollTop = newPos;
	this.lastTop = newPos;
}






//****

//*******  simple ****

function SimpleTextWidget(uid) {
	this.uid = uid; //for bindEvent
	this.spanElem = this.getWidgetElement();
	this.bindEvent(this.spanElem,"dblclick","dblclickAction");
}

SimpleTextWidget.prototype = new DowWidget;

SimpleTextWidget.prototype.getData = function () {
	return this.getTextValue(this.spanElem);
}

SimpleTextWidget.prototype.setData = function (data) {
	this.setTextValue(this.spanElem,data);
}


SimpleTextWidget.prototype.dblclickAction = function (event) {
	this.startEdit();
}

SimpleTextWidget.prototype.blurAction = function (event) {
	this.stopEdit();
}

SimpleTextWidget.prototype.mousedownAction = function (event) {
	event.stopPropagation();
}


SimpleTextWidget.prototype.keypressAction = function (event) {
	if (this.editElem && event.which == 13) {
		this.editElem.blur();
	}
}

SimpleTextWidget.prototype.appendXMLData = function (root) {
	var doc = root.ownerDocument;
	var captionElem = doc.createElement("span_text");
	var text = this.getData();
	captionElem.appendChild(doc.createTextNode(text));
	root.appendChild(captionElem);
}

SimpleTextWidget.prototype.isEditing = function() {
	return this.editElem!=null;
}

SimpleTextWidget.prototype.startEdit = function() {
	var width = this.spanElem.parentNode.clientWidth;
	var height = this.spanElem.parentNode.clientHeight;
	this.setElementClass(this.spanElem , "editing");
	if (!this.isEditing()) { //safety check
		//var size = this.getElementSize(this.spanElem);
		
		var editElem = document.createElement("input");
		editElem.type = "text";
		editElem.style.width = width+"px";
		editElem.style.height = height+"px";
		this.bindEvent(editElem,"blur","blurAction");
		this.bindEvent(editElem,"keypress","keypressAction");
		this.bindEvent(editElem,"mousedown","mousedownAction");
		this.spanElem.parentNode.appendChild(editElem);
		this.editElem = editElem;
	}
	
	this.editElem.value = this.getData();
	this.editElem.focus();
}

SimpleTextWidget.prototype.stopEdit = function() {
	if (this.isEditing()) { //safety
		this.setData(this.editElem.value);
		this.spanElem.parentNode.removeChild(this.editElem);
		this.editElem = null;
		
		this.unsetElementClass(this.spanElem , "editing");
		this.widgetModified(this);
	}
	
}



//*********** textarea *****

function MessageWidget() {
}
MessageWidget.prototype = new DowWidget;

MessageWidget.prototype.postInit = function() {
	this.divElem = this.getWidgetElement();
	this.dataElem = document.getElementById(this.uid+"_data");
	
	this.bindEvent(this.divElem,"dblclick","dblclickAction");
}

MessageWidget.prototype.getData = function () {
	var text = this.getMultilineTextValue(this.dataElem);
	return text;
}

MessageWidget.prototype.setData = function (text) {
	this.setMultilineTextValue(this.dataElem,text);
	this.widgetModified(this);
}


MessageWidget.prototype.appendXMLData = function (root) {
	var doc = root.ownerDocument;
	var captionElem = doc.createElement("span_text");
	var text = this.getData();
	captionElem.appendChild(doc.createTextNode(text));
	root.appendChild(captionElem);
}

MessageWidget.prototype.dblclickAction = function (event) {
	this.toggle_edit();
}

MessageWidget.prototype.toggle_edit = function() {
	var display = this.dataElem.style.display;
	if (display == "none") {
		this.end_edit();
	} else {
		this.do_edit();
	}
}

MessageWidget.prototype.do_edit = function () {
	var baseElem =this.getWidgetElement();
	var pos = this.getElementPosition(baseElem);
	var size = this.getElementSize(baseElem);

	var templateEditor = gWidgets["message_editor"];
	var myEditorElem = templateEditor.cloneWidget();
	myEditorElem.style.position="static";
	baseElem.appendChild(myEditorElem);
	var myEditorId = myEditorElem.id;
	registerAllSubWidgets(myEditorElem);
	this.myEditorElem=myEditorElem;
	this.myEditorWidget = gWidgets[myEditorId];
	this.myEditorWidget.attachEditor(this, 0 , 0 , size.width , size.height);
	this.dataElem.style.display = "none";
}

MessageWidget.prototype.end_edit = function () {
	if (this.myEditorWidget) {
		this.myEditorWidget.attachEditor(null);
		this.myEditorWidget = null;
	}
	if (this.myEditorElem) {
		var baseElem =this.getWidgetElement();
		baseElem.removeChild(this.myEditorElem);
		this.myEditorElem = null;
	}
	this.dataElem.style.display = "";
}

//**************  

function MessageEditor() {
}
MessageEditor.prototype = new DowWidget;

MessageEditor.prototype.postInit = function() {
	this.editorElem = this.getWidgetElement();
	this.textAreaElem = document.getElementById(this.uid+"_textarea");
	
	//this.bindEvent(this.textAreaElem,"blur","blurAction");
}

/*
MessageEditor.prototype.blurAction = function(event) {
	this.attachEditor(null);
}
*/

MessageEditor.prototype.getData = function() {	
	return this.textAreaElem.value;
}

MessageEditor.prototype.setData = function(text) {	
	this.textAreaElem.value = text;
}

MessageEditor.prototype.attachEditor = function (widget,left,top , width , height) {

	if (widget) {	
		if (this.ownerWidget) {
			this.attachEditor(null);
		}

		this.editorElem.style.left=left+"px";
		this.editorElem.style.top=top+"px";
		this.editorElem.style.width=width+"px";
		this.editorElem.style.height=height+"px";
		//this.setElementClass(this.textAreaElem , "editing");
		this.setData(widget.getData());
		this.editorElem.style.display = "block";
		//this.textAreaElem.focus();
	} else {
		if (this.ownerWidget) {
			this.ownerWidget.setData(this.getData());
			this.ownerWidget = null;
		}
		//this.unsetElementClass(this.textAreaElem , "editing");
		this.editorElem.style.display ="";
	}
	this.ownerWidget = widget;
}



//***

function RichButtonWidget() {
}
RichButtonWidget.prototype = new ButtonWidget;

RichButtonWidget.prototype._postInit = RichButtonWidget.prototype.postInit;
RichButtonWidget.prototype.postInit = function() {
	this.bindEvent(this.getWidgetElement(),"mousedown","mousedownAction");
	RichButtonWidget.prototype._postInit.call(this);
}
	
RichButtonWidget.prototype._buttonAction = RichButtonWidget.prototype.buttonAction;
RichButtonWidget.prototype.buttonAction = function(event) {
	RichButtonWidget.prototype._buttonAction.call(this,event);
	event.stopPropagation();
	event.preventDefault();
	//alert("buttonAction");
}


RichButtonWidget.prototype.mousedownAction = function(event) {
	event.stopPropagation();
	event.preventDefault();
}


//********


function DowListWidget() {
}
DowListWidget.prototype = new DowWidget;

DowListWidget.prototype.preInit = function() {
	this.listElem = document.getElementById(this.uid+"_list");
}

DowListWidget.prototype.postInit = function() {
	//var self = this;
	//window.setTimeout(function() {self.recalcAllSubPositions();} , 1000);
	
	this.recalcAllSubPositions();
}

DowListWidget.prototype.appendXMLData = function (root) {
	this.widgetIterator(function(subWidget) {subWidget.appendXMLData(root);});
}


DowListWidget.prototype.itemIterator = function (callback) {
	this.childIterator(this.listElem,"div",callback);
}
	
	
DowListWidget.prototype.getWidgetItem = function (index) {
	var widget = null;
	var curIndex = 0;
	
	function doWidget(element) {
		var curWidget = gWidgets[element.id];
		if (curWidget && curIndex==index) {
			widget=curWidget;
		}
		curIndex++;
	}
	this.childIterator(this.listElem,"div", doWidget);
	return widget;
}


DowListWidget.prototype.widgetIterator = function (callback) {
	function doWidget(element) {
		var widget = gWidgets[element.id];
		if (widget) {
			callback(widget);
		}
	}
	this.childIterator(this.listElem,"div", doWidget);
}



DowListWidget.prototype.onWidgetModified = function (widget) {
	if (widget.uid == this.uid+"_appendItem") {
		this.appendItem();
	}/* else if (widget.uid == this.uid+"_removeItem") {
		alert("actionElem: "+actionElem);
		this.removeItem(actionElem);
	}*/ else {
		//alert("DowListWidget.onWidgetModified: "+widget.uid);
		//alert("DowListWidget.onWidgetModified: "+this.uid);
		this.widgetModified(this);
	}
}

DowListWidget.prototype.removeItem = function (actionElem) {
	var itemElem = this.findParent(actionElem,"DIV","widget_DowListItemWidget");

	itemElem.parentNode.removeChild(itemElem);
	this.recalcAllSubPositions();
	this.widgetModified(this);
}


DowListWidget.prototype.appendItem = function () {
	var templateElem = document.getElementById(this.uid+"_template");
	var listElem = document.getElementById(this.uid+"_list");
	var clonedElem = this.cloneSubtree(templateElem);
	listElem.appendChild(clonedElem);
	this.unsetElementClass(clonedElem,"template");
	registerAllSubWidgets(clonedElem);
	//this.recalcAllSubPositions(); too early item not correctly initialized yet
	this.widgetModified(this);
	return gWidgets[clonedElem.id];
}

DowListWidget.prototype.recalcAllSubPositions = function () {

}

DowListWidget.prototype.on_willselect = function (who) {
	this.sendEventDown(this,"unselect");
	this.selected = who;
}
DowListWidget.prototype.on_hasselected = function (who) {
}

DowListWidget.prototype.canDrop = function (dragWidget) {
	return true;
}

DowListWidget.prototype.dropEnter = function (dragger , dropper) {
	var self=this;
	this.itemIterator(function(itemElem) {self.unsetElementClass(itemElem,"item_drop");});
	//window.status = "dropEnter";
	this.dropModified = false;
}

DowListWidget.prototype.dropMove = function (dragger , dropper) {
	var maxarea = 0;
	var area;
	var bestItem = null;
	var self = this;
	
	function doItem(itemElem) {
		self.unsetElementClass(itemElem,"item_drop");
		area = dropper.calcOverlapArea(dragger.getDragArea() , self.getElementArea(itemElem));
		//window.status = area;
		if (area > maxarea) {
			maxarea = area;
			bestItem = itemElem;
		}
	}
	
	//window.status += "d";
	
	this.itemIterator(doItem);

	if (bestItem) {
		this.setElementClass(bestItem,"item_drop");
		this.reorder(this.draggingWidget.widgetElem,bestItem);
		this.recalcAllSubPositions();
		this.dropModified = true;
		//window.status = "drop: "+ bestItem.id;
	}
}

DowListWidget.prototype.dropExit = function (dragger) {
	var self=this;
	this.itemIterator(function(itemElem) {self.unsetElementClass(itemElem,"item_drop");});
	//window.status = "dropExit";
	if (this.dropModified) {
		//this.widgetModified(this); 
		this.sendEventUp(this,"reorder");
	}
}

DowListWidget.prototype.getSubWidgets = function() {
	var subWidgets = [];
	this.itemIterator(function(itemElem) {subWidgets.push(gWidgets[itemElem.id]);});
	return subWidgets;
}



//******

function DowListItemWidget() {
}
DowListItemWidget.prototype = new DowWidget;

DowListItemWidget.prototype.postInit = function() {
	this.widgetElem = document.getElementById(this.uid);
	this.bindEvent(this.widgetElem,"mousedown","mousedownAction");
	this.listWidget = this.findWidgetParent(this.widgetElem);
}

DowListItemWidget.prototype.mousedownAction = function (event) {
	if (event.button != 2) {
		gDragger.attach(this ,event);
	}
}

DowListItemWidget.prototype.dragStart = function (dragger) {
	//this.widgetElem.style.display = "none";
	this.listWidget.draggingWidget = this;
	this.dragging = true;
}

DowListItemWidget.prototype.dragMove = function (dragger) {
}

DowListItemWidget.prototype.dragEnd = function (dragger) {
	//this.widgetElem.style.display = "block";
	this.listWidget.draggingWidget = null;
	this.dragging = false;
	//this.widgetModified(this); //not the dragger, the drop
}

DowListItemWidget.prototype.getSubWidget = function () {
	return this.findFirstChildWidget(this.widgetElem);
}

DowListItemWidget.prototype.appendXMLData = function (root) {
	var subWidget = this.getSubWidget();
	if (subWidget && subWidget.appendXMLData)  {
		subWidget.appendXMLData(root);
	}
}

// ***************




function SlideShow(uid) {
	this.uid = uid;
	this.slideShowElem = this.getWidgetElement();
	this.prevElem = document.getElementById(uid+"_prev");
	this.nextElem = document.getElementById(uid+"_next");
	this.endElem = document.getElementById(uid+"_end");
	this.loopElem = document.getElementById(uid+"_loop");
	this.imageElem = document.getElementById(uid+"_image");
	this.captionElem = document.getElementById(uid+"_caption");
	this.bindEvent(this.prevElem,"click","prevAction");
	this.bindEvent(this.nextElem,"click","nextAction");
	this.bindEvent(this.endElem,"click","endAction");
	this.bindEvent(this.loopElem,"click","loopAction");
	this.bindEvent(this.imageElem,"load","loadAction");
}
SlideShow.prototype = new DowWidget;

SlideShow.prototype.loadAction = function (event) {
	this.imageElem.removeAttribute("width");
	this.imageElem.removeAttribute("height");
	
	var naturalWidth = this.imageElem.width;
	var naturalHeight = this.imageElem.height;
	
	
	//alert("("+naturalWidth+","+naturalHeight+")");
	this.imageElem.className = "slide_image";
	this.imageElem.width = naturalWidth;
	this.imageElem.height = naturalHeight;
}

SlideShow.prototype.loopAction = function (event) {
	this.looping = !this.looping;
	if (this.looping) {
		this.prevElem.style.display = "none";
		this.nextElem.style.display = "none";
		this.loopElem.style.display = "none";
		this.initTimeMachine();
		this.runTimeMachine(0);
	}
}

SlideShow.prototype.pushTimeElement = function (delay,methodName,param) {
	this.timeMachine.push({'delay': delay , 'methodName': methodName , 'param': param });
}

SlideShow.prototype.initTimeMachine = function () {
	this.timeMachine = [];
	var opacity;
	
	for (var slideIndex = 0 ; slideIndex<this.data.childNodes.length ; slideIndex++) {
		var slideData = this.data.childNodes.item(slideIndex);
		
		this.pushTimeElement(0 , "preloadImage" , slideData);
		
		for (opacity=100 ; opacity>=0 ; opacity-=5) {
			this.pushTimeElement(50 , "setOpacity" , opacity);
		}
		this.pushTimeElement(0 , "swapSlide" );
		for (opacity=0 ; opacity<=100 ; opacity+=5) {
			this.pushTimeElement(50 , "setOpacity" , opacity);
		}
		this.pushTimeElement(2000 );
	}
}

SlideShow.prototype.runTimeMachine = function (index) {
	var self = this;
	
	function stepTimeMachine() {
		var methodName = self.timeMachine[index].methodName;
		if (methodName) {
			self[methodName](self.timeMachine[index].param);
		}
		self.runTimeMachine(index+1);
	}
	
	//window.status ="runTimeMachine: "+index;
	if (index >= this.timeMachine.length) {
		index = 0;
	}
	this.timeoutId=setTimeout(stepTimeMachine , this.timeMachine[index].delay);
}

SlideShow.prototype.setOpacity = function (opacity) {
	this.setElementOpacity(this.imageElem,opacity);
}


SlideShow.prototype.prevAction = function (event) {
	this.index--;
	if (this.index < 0) this.index=0; //safety
	this.displaySlide(this.index);
}

SlideShow.prototype.nextAction = function (event) {
	this.index++;
	if (this.index >= this.data.childNodes.length) this.index=this.data.childNodes.length-1; //safety
	this.displaySlide(this.index);
}

SlideShow.prototype.endAction = function (event) {
	this.stop();
}

SlideShow.prototype.run = function (data) {
	this.data = data;
	this.index =0;
	
	gWidgets['body'].darkenPage();
	this.setElementClass(this.slideShowElem , "slide_show");
	this.slideShowElem.style.left = document.documentElement.scrollLeft + "px";
	this.slideShowElem.style.top = document.documentElement.scrollTop + "px";
	this.slideShowElem.style.width = document.documentElement.clientWidth + "px";
	this.slideShowElem.style.height = document.documentElement.clientHeight + "px";
	
	this.slideShowElem.style.display = "block";
	//this.displaySlide(this.index);
	this.loopAction();
}

SlideShow.prototype.stop = function () {
	if (this.timeoutId) {
		clearTimeout(this.timeoutId);
		this.timeoutId=null;
	}
	
	this.looping = false;
	this.data = null;
	this.unsetElementClass(this.slideShowElem , "slide_show");
	this.slideShowElem.style.display = "none";
	gWidgets['body'].undarkenPage();
}

SlideShow.prototype.preloadImage = function (slideData) {
	var zoom_src = slideData.getElementsByTagName("dow_image").item(0).getAttribute("zoom_src");
	var captionElem = slideData.getElementsByTagName("span_text").item(0);
	var caption = this.getTextValue(captionElem);
	
	var preloadImage = new Image();
	var self = this;
	
	function onloadAction() {
		var naturalWidth = preloadImage.width;
		var naturalHeight = preloadImage.height;
		preloadImage.setAttribute("width",naturalWidth);
		preloadImage.setAttribute("height",naturalHeight);
		self.setElementOpacity(preloadImage,0);
		preloadImage.className="slide_image";
		self.preloaded(preloadImage);
	}
	preloadImage.onload = onloadAction;
	preloadImage.src = zoom_src; 
	preloadImage.caption = caption;
}

SlideShow.prototype.preloaded = function (image) {
	this.preloadedImage = image;
	if (this.readyToSwap) {
		this.swapSlide();
	}
}

SlideShow.prototype.swapSlide = function () {
	if (!this.preloadedImage) {
		this.readyToSwap = true;
		return;
	} else {
		this.readyToSwap = false;
	}
	
	this.setTextValue(this.captionElem,this.preloadedImage.caption);

	this.imageElem.style.display = "none";
	this.preloadedImage.style.display = "none";
	
	this.imageElem.parentNode.replaceChild(this.preloadedImage,this.imageElem);
	this.imageElem = this.preloadedImage;
	this.preloadedImage = null;
	this.imageElem.style.display = "block";
	

}

SlideShow.prototype.displaySlide = function (slideIndex) {
	var slideData = this.data.childNodes.item(slideIndex);
	
	if (this.index <= 0) {
		this.prevElem.style.display = "none";
	} else {
		this.prevElem.style.display = "block";
	}
	
	if (this.index >= this.data.childNodes.length-1) {
		this.nextElem.style.display = "none";
	} else {
		this.nextElem.style.display = "block";
	}

	
	var src = slideData.getElementsByTagName("dow_image").item(0).getAttribute("src");
	var file_id = slideData.getElementsByTagName("dow_image").item(0).getAttribute("file_id");
	var caption = slideData.getElementsByTagName("multiline_text").item(0).firstChild.data;
	
	this.setTextValue(this.captionElem,caption);
	
	src = "/uploads/userpages/"+login_id+"/_"+file_id+".data";
	
	this.imageElem.className = "hidden";
	this.imageElem.src = src;
	this.imageElem.alt = "file_id: "+file_id;
}

//*******************************

function RequestInfo(uid) {
	this.type="RequestInfo";
	this.uid = uid;
	this.spanElem = document.getElementById(this.uid+"_data");
	this.textElem = this.spanElem.firstChild;
	this.totalText = document.getElementById(this.uid+"_total").firstChild;
}

RequestInfo.prototype = new DowWidget;

RequestInfo.prototype.updateInfo = function(nbr,total) {
	this.textElem.data = nbr;
	this.totalText.data = total;
}

//**********

function BodyWidget(uid) {
	this.uid = uid;
	
	this.darkenElem = document.getElementById("darken");
	var xmlElem = document.getElementById('dow_top_xml');
	if (xmlElem) xmlElem.target="xml";
	
	var piElem = document.getElementById('dow_top_withpi');
	if (piElem) piElem.target="withpi";
	
	//this.bindEvent(document.body,"keypress","keypressAction");
	this.bindEvent(document.body,"click","clickAction");
	this.bindEvent(document.body,"mousedown","mousedownAction");
}
BodyWidget.prototype = new DowWidget;

BodyWidget.prototype.darkenPage = function() {
	this.darkenElem.style.left = 0;
	this.darkenElem.style.top = 0;
	this.darkenElem.style.width =document.documentElement.scrollWidth+"px";
	this.darkenElem.style.height =  document.documentElement.scrollHeight+"px";
	
	this.setElementClass(this.darkenElem , "darken");
}

BodyWidget.prototype.undarkenPage = function() {
	this.unsetElementClass(this.darkenElem , "darken");
}

BodyWidget.prototype.mousedownAction = function(event) {
	//window.status += "m";
}

BodyWidget.prototype.on_dataModified = function (who) {
	var action = this.createEmptyAction("setGenericXML");
	action.setAttribute("what_key" , who.uid);
	var doc = action.ownerDocument;
	who.appendXMLData(action);
	this.sendAction(action.ownerDocument);
}

window.onfocus = function(event) {
	//var multiline_text_editor = gWidgets["rich_text_editor"];
	//if (multiline_text_editor) multiline_text_editor.attachEditor(null);
}

window.onblur = function(event) {
	//var multiline_text_editor = gWidgets["rich_text_editor"];
	//if (multiline_text_editor) multiline_text_editor.attachEditor(null);
}

BodyWidget.prototype.clickAction = function(event) {
	//var multiline_text_editor = gWidgets["rich_text_editor"];
	//if (multiline_text_editor) multiline_text_editor.attachEditor(null);
	gContextMenu.stop();
	//window.status = window.status +"A";
	//alert("BodyWidget.prototype.clickAction: "+event.target.id +" : "+event.target.className);
}

/*
BodyWidget.prototype.keypressAction = function(event) {
		alert("keypressAction");
	if (!event.ctrlKey) {
		var selObj;
		
		var selRange = this.getSelectionRange();
		var container = this.getRangeContainer(selRange);
		
		var keyChar = this.getEventChar(event);
		switch (keyChar) {
			case 'b': {
				var widget = gDOMHelper.findWidgetParentIncludingSelf(container);
				if (widget && widget.do_bold) {
					widget.do_bold(selRange);
				}
			} break;
			case 'u': {
				var widget = gDOMHelper.findWidgetParentIncludingSelf(container);
				if (widget && widget.do_underline) {
					widget.do_underline(selRange);
				}
			} break;
			case 'i': {
				var widget = gDOMHelper.findWidgetParentIncludingSelf(container);
				if (widget && widget.do_italic) {
					widget.do_italic(selRange);
				}
			} break;
		}
	}

}
*/


function DowBlock() {
}
DowBlock.prototype = new DowWidget;

DowBlock.prototype.postInit = function () {
	this.toggleElem = document.getElementById(this.uid+"_toggle");
	this.contentElem = document.getElementById(this.uid+"_content");
	this.titleElem = document.getElementById(this.uid+"_title");
	this.editElem = document.getElementById(this.uid+"_edit");
	this.deleteElem = document.getElementById(this.uid+"_delete");
	
	this.bindEvent(this.toggleElem,"click","toggleAction");
	this.bindEvent(this.editElem,"click","editAction");
	this.bindEvent(this.deleteElem,"click","deleteAction");
}


DowBlock.prototype.toggleAction = function (event) {
	this.collapse(!this.is_collapsed());
}

DowBlock.prototype.editAction = function (event) {
	this.sendEventUp(this, "editAction");
}

DowBlock.prototype.deleteAction = function (event) {
	var deleteMessage = "Do you really want to delete this block?";
	var messageElem = document.getElementById(this.uid+"_delete_message");
	if (messageElem) {
		deleteMessage = this.getTextValue(messageElem);
	}
	
	if (confirm(deleteMessage)) {
		this.sendEventUp(this, "deleteAction");
	}
}

DowBlock.prototype.appendXMLData = function (root) {
	var doc = root.ownerDocument;
	var myData = doc.createElement("dow_block_title");
	
	var title = this.getTextValue(this.titleElem);
	myData.appendChild(doc.createTextNode(title));
	
	root.appendChild(myData);
}

DowBlock.prototype.is_collapsed = function() {
	return this.hasElementClass(this.toggleElem,"block_banner_collapsed");
}

DowBlock.prototype.collapse = function(do_collapse) {
	var blockElem = this.getWidgetElement().parentNode;
	
	if (do_collapse) {
		this.setElementClass(this.toggleElem , "block_banner_collapsed");
		this.unsetElementClass(this.toggleElem , "block_banner_expanded");
		this.setElementClass(this.contentElem , "block_content_collapsed");
		this.unsetElementClass(this.contentElem , "block_content_expanded");
	} else {
		this.setElementClass(this.toggleElem , "block_banner_expanded");
		this.unsetElementClass(this.toggleElem , "block_banner_collapsed");
		this.setElementClass(this.contentElem , "block_content_expanded");
		this.unsetElementClass(this.contentElem , "block_content_collapsed");
	}
	
	var refresh = document.createTextNode("R");
	
	blockElem.appendChild(refresh); //IE6 Refresh layout BUG (this forces refresh)
	blockElem.removeChild(refresh);
}

//*****************

