r997 - in xwiki/trunk/src/main/web/skins/default: . ajax rico scriptaculous

Ludovic Dubost ludovic at users.forge.objectweb.org
Tue Mar 28 12:10:40 CEST 2006


Author: ludovic
Date: 2006-03-28 12:10:39 +0200 (Tue, 28 Mar 2006)
New Revision: 997

Added:
   xwiki/trunk/src/main/web/skins/default/Thumbs.db
   xwiki/trunk/src/main/web/skins/default/ajax/
   xwiki/trunk/src/main/web/skins/default/ajax/Drag.js
   xwiki/trunk/src/main/web/skins/default/ajax/ieemu.js
   xwiki/trunk/src/main/web/skins/default/ajax/toolTip.js
   xwiki/trunk/src/main/web/skins/default/prototype.js
   xwiki/trunk/src/main/web/skins/default/rico/
   xwiki/trunk/src/main/web/skins/default/rico/prototype.js
   xwiki/trunk/src/main/web/skins/default/rico/rico.js
   xwiki/trunk/src/main/web/skins/default/scriptaculous/
   xwiki/trunk/src/main/web/skins/default/scriptaculous/controls.js
   xwiki/trunk/src/main/web/skins/default/scriptaculous/dragdrop.js
   xwiki/trunk/src/main/web/skins/default/scriptaculous/effects.js
   xwiki/trunk/src/main/web/skins/default/scriptaculous/prototype.js
   xwiki/trunk/src/main/web/skins/default/scriptaculous/util.js
   xwiki/trunk/src/main/web/skins/default/xwiki.js
Log:
Added prototype.js to skin as it should be there

Added: xwiki/trunk/src/main/web/skins/default/Thumbs.db
===================================================================
(Binary files differ)


Property changes on: xwiki/trunk/src/main/web/skins/default/Thumbs.db
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: xwiki/trunk/src/main/web/skins/default/ajax/Drag.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/ajax/Drag.js	2006-03-28 10:10:11 UTC (rev 996)
+++ xwiki/trunk/src/main/web/skins/default/ajax/Drag.js	2006-03-28 10:10:39 UTC (rev 997)
@@ -0,0 +1,53 @@
+var Drag={
+        "obj":null,
+	"init":function(a, aRoot){
+			a.onmousedown=Drag.start;
+			a.root = aRoot;
+			if(isNaN(parseInt(a.root.style.left)))a.root.style.left="0px";
+			if(isNaN(parseInt(a.root.style.top)))a.root.style.top="0px";
+			a.root.onDragStart=new Function();
+			a.root.onDragEnd=new Function();
+			a.root.onDrag=new Function();
+		},
+	"start":function(a){	
+			var b=Drag.obj=this;
+			a=Drag.fixE(a);
+			var c=parseInt(b.root.style.top);
+			var d=parseInt(b.root.style.left);
+			b.root.onDragStart(d,c,a.clientX,a.clientY);
+			b.lastMouseX=a.clientX;
+			b.lastMouseY=a.clientY;
+			document.onmousemove=Drag.drag;
+			document.onmouseup=Drag.end;
+			return false;
+		},	
+	"drag":function(a){
+			a=Drag.fixE(a);
+			var b=Drag.obj;
+			var c=a.clientY;
+			var d=a.clientX;
+			var e=parseInt(b.root.style.top);
+			var f=parseInt(b.root.style.left);
+			var h,g;
+			h=f+d-b.lastMouseX;
+			g=e+c-b.lastMouseY;
+			b.root.style.left=h+"px";
+			b.root.style.top=g+"px";			
+			b.lastMouseX=d;
+			b.lastMouseY=c;
+			b.root.onDrag(h,g,a.clientX,a.clientY);
+			return false;
+		},
+	"end":function(){			
+			document.onmousemove=null;
+			document.onmouseup=null;
+			Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style.left),parseInt(Drag.obj.root.style.top));
+			Drag.obj=null;
+		},
+	"fixE":function(a){
+			if(typeof a=="undefined")a=window.event;
+			if(typeof a.layerX=="undefined")a.layerX=a.offsetX;
+			if(typeof a.layerY=="undefined")a.layerY=a.offsetY;
+			return a;
+		}
+};
\ No newline at end of file

Added: xwiki/trunk/src/main/web/skins/default/ajax/ieemu.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/ajax/ieemu.js	2006-03-28 10:10:11 UTC (rev 996)
+++ xwiki/trunk/src/main/web/skins/default/ajax/ieemu.js	2006-03-28 10:10:39 UTC (rev 997)
@@ -0,0 +1,304 @@
+/*----------------------------------------------------------------------------\
+|                                   IE Emu                                    |
+|-----------------------------------------------------------------------------|
+|                         Created by Erik Arvidsson                           |
+|                  (http://webfx.eae.net/contact.html#erik)                   |
+|                      For WebFX (http://webfx.eae.net/)                      |
+|-----------------------------------------------------------------------------|
+| A emulation of Internet Explorer DHTML Object Model for Mozilla  |
+|-----------------------------------------------------------------------------|
+|                  Copyright (c) 1999 - 2004 Erik Arvidsson                   |
+|-----------------------------------------------------------------------------|
+*/
+
+if (Browser.isMozilla) { // set up ie environment for Moz
+	
+	extendEventObject();
+	emulateAttachEvent();
+	emulateEventHandlers(["click", "dblclick", "mouseover", "mouseout",
+							"mousedown", "mouseup", "mousemove",
+							"keydown", "keypress", "keyup"]);
+	emulateCurrentStyle();
+	emulateHTMLModel();
+	/*emulateDocumentAll();
+	emulateElement()
+	*/
+
+	// It is better to use a constant for event.button
+	Event.LEFT = 0;
+	Event.MIDDLE = 1;
+	Event.RIGHT = 2;
+}
+else {
+	Event = {};
+	// IE is returning wrong button number
+	Event.LEFT = 1;
+	Event.MIDDLE = 4;
+	Event.RIGHT = 2;
+}
+
+
+
+/*
+ * Extends the event object with srcElement, cancelBubble, returnValue,
+ * fromElement and toElement
+ */
+function extendEventObject() {
+	Event.prototype.__defineSetter__("returnValue", function (b) {
+		if (!b) this.preventDefault();
+		return b;
+	});
+
+	Event.prototype.__defineSetter__("cancelBubble", function (b) {
+		if (b) this.stopPropagation();
+		return b;
+	});
+
+	Event.prototype.__defineGetter__("srcElement", function () {
+		var node = this.target;
+		while (node.nodeType != 1) node = node.parentNode;
+		return node;
+	});
+
+	Event.prototype.__defineGetter__("fromElement", function () {
+		var node;
+		if (this.type == "mouseover")
+			node = this.relatedTarget;
+		else if (this.type == "mouseout")
+			node = this.target;
+		if (!node) return;
+		while (node.nodeType != 1) node = node.parentNode;
+		return node;
+	});
+
+	Event.prototype.__defineGetter__("toElement", function () {
+		var node;
+		if (this.type == "mouseout")
+			node = this.relatedTarget;
+		else if (this.type == "mouseover")
+			node = this.target;
+		if (!node) return;
+		while (node.nodeType != 1) node = node.parentNode;
+		return node;
+	});
+
+	Event.prototype.__defineGetter__("offsetX", function () {
+		return this.layerX;
+	});
+	Event.prototype.__defineGetter__("offsetY", function () {
+		return this.layerY;
+	});
+}
+
+/*
+ * Emulates element.attachEvent as well as detachEvent
+ */
+function emulateAttachEvent() {
+	HTMLDocument.prototype.attachEvent =
+	HTMLElement.prototype.attachEvent = function (sType, fHandler) {
+		var shortTypeName = sType.replace(/on/, "");
+		fHandler._ieEmuEventHandler = function (e) {
+			window.event = e;
+			return fHandler();
+		};
+		this.addEventListener(shortTypeName, fHandler._ieEmuEventHandler, false);
+	};
+
+	HTMLDocument.prototype.detachEvent =
+	HTMLElement.prototype.detachEvent = function (sType, fHandler) {
+		var shortTypeName = sType.replace(/on/, "");
+		if (typeof fHandler._ieEmuEventHandler == "function")
+			this.removeEventListener(shortTypeName, fHandler._ieEmuEventHandler, false);
+		else
+			this.removeEventListener(shortTypeName, fHandler, true);
+	};
+}
+
+/*
+ * This function binds the event object passed along in an
+ * event to window.event
+ */
+function emulateEventHandlers(eventNames) {
+	for (var i = 0; i < eventNames.length; i++) {
+		document.addEventListener(eventNames[i], function (e) {
+			window.event = e;
+		}, true);	// using capture
+	}
+}
+
+/*
+ * Simple emulation of document.all
+ * this one is far from complete. Be cautious
+ */
+
+function emulateAllModel() {
+	var allGetter = function () {
+		var a = this.getElementsByTagName("*");
+		var node = this;
+		a.tags = function (sTagName) {
+			return node.getElementsByTagName(sTagName);
+		};
+		return a;
+	};
+	HTMLDocument.prototype.__defineGetter__("all", allGetter);
+	HTMLElement.prototype.__defineGetter__("all", allGetter);
+}
+
+function extendElementModel() {
+	HTMLElement.prototype.__defineGetter__("parentElement", function () {
+		if (this.parentNode == this.ownerDocument) return null;
+		return this.parentNode;
+	});
+
+	HTMLElement.prototype.__defineGetter__("children", function () {
+		var tmp = [];
+		var j = 0;
+		var n;
+		for (var i = 0; i < this.childNodes.length; i++) {
+			n = this.childNodes[i];
+			if (n.nodeType == 1) {
+				tmp[j++] = n;
+				if (n.name) {	// named children
+					if (!tmp[n.name])
+						tmp[n.name] = [];
+					tmp[n.name][tmp[n.name].length] = n;
+				}
+				if (n.id)		// child with id
+					tmp[n.id] = n
+			}
+		}
+		return tmp;
+	});
+
+	HTMLElement.prototype.contains = function (oEl) {
+		if (oEl == this) return true;
+		if (oEl == null) return false;
+		return this.contains(oEl.parentNode);
+	};
+}
+
+function emulateCurrentStyle() {
+	HTMLElement.prototype.__defineGetter__("currentStyle", function () {
+		return this.ownerDocument.defaultView.getComputedStyle(this, null);
+		/*
+		var cs = {};
+		var el = this;
+		for (var i = 0; i < properties.length; i++) {
+			cs.__defineGetter__(properties[i], encapsulateObjects(el, properties[i]));
+		}
+		return cs;
+		*/
+	});
+}
+
+function emulateHTMLModel() {
+
+	// This function is used to generate a html string for the text properties/methods
+	// It replaces '\n' with "<BR"> as well as fixes consecutive white spaces
+	// It also repalaces some special characters
+	function convertTextToHTML(s) {
+		s = s.replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<BR>");
+		while (/\s\s/.test(s))
+			s = s.replace(/\s\s/, "&nbsp; ");
+		return s.replace(/\s/g, " ");
+	}
+
+	HTMLElement.prototype.insertAdjacentHTML = function (sWhere, sHTML) {
+		var df;	// : DocumentFragment
+		var r = this.ownerDocument.createRange();
+
+		switch (String(sWhere).toLowerCase()) {
+			case "beforebegin":
+				r.setStartBefore(this);
+				df = r.createContextualFragment(sHTML);
+				this.parentNode.insertBefore(df, this);
+				break;
+
+			case "afterbegin":
+				r.selectNodeContents(this);
+				r.collapse(true);
+				df = r.createContextualFragment(sHTML);
+				this.insertBefore(df, this.firstChild);
+				break;
+
+			case "beforeend":
+				r.selectNodeContents(this);
+				r.collapse(false);
+				df = r.createContextualFragment(sHTML);
+				this.appendChild(df);
+				break;
+
+			case "afterend":
+				r.setStartAfter(this);
+				df = r.createContextualFragment(sHTML);
+				this.parentNode.insertBefore(df, this.nextSibling);
+				break;
+		}
+	};
+
+	HTMLElement.prototype.__defineSetter__("outerHTML", function (sHTML) {
+	   var r = this.ownerDocument.createRange();
+	   r.setStartBefore(this);
+	   var df = r.createContextualFragment(sHTML);
+	   this.parentNode.replaceChild(df, this);
+
+	   return sHTML;
+	});
+
+	HTMLElement.prototype.__defineGetter__("canHaveChildren", function () {
+		switch (this.tagName) {
+			case "AREA":
+			case "BASE":
+			case "BASEFONT":
+			case "COL":
+			case "FRAME":
+			case "HR":
+			case "IMG":
+			case "BR":
+			case "INPUT":
+			case "ISINDEX":
+			case "LINK":
+			case "META":
+			case "PARAM":
+				return false;
+		}
+		return true;
+	});
+
+	HTMLElement.prototype.__defineGetter__("outerHTML", function () {
+		var attr, attrs = this.attributes;
+		var str = "<" + this.tagName;
+		for (var i = 0; i < attrs.length; i++) {
+			attr = attrs[i];
+			if (attr.specified)
+				str += " " + attr.name + '="' + attr.value + '"';
+		}
+		if (!this.canHaveChildren)
+			return str + ">";
+
+		return str + ">" + this.innerHTML + "</" + this.tagName + ">";
+	});
+
+
+	HTMLElement.prototype.__defineSetter__("innerText", function (sText) {
+		this.innerHTML = convertTextToHTML(sText);
+		return sText;
+	});
+
+	var tmpGet;
+	HTMLElement.prototype.__defineGetter__("innerText", tmpGet = function () {
+		var r = this.ownerDocument.createRange();
+		r.selectNodeContents(this);
+		return r.toString();
+	});
+
+	HTMLElement.prototype.__defineSetter__("outerText", function (sText) {
+		this.outerHTML = convertTextToHTML(sText);
+		return sText;
+	});
+	HTMLElement.prototype.__defineGetter__("outerText", tmpGet);
+
+	HTMLElement.prototype.insertAdjacentText = function (sWhere, sText) {
+		this.insertAdjacentHTML(sWhere, convertTextToHTML(sText));
+	};
+}

Added: xwiki/trunk/src/main/web/skins/default/ajax/toolTip.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/ajax/toolTip.js	2006-03-28 10:10:11 UTC (rev 996)
+++ xwiki/trunk/src/main/web/skins/default/ajax/toolTip.js	2006-03-28 10:10:39 UTC (rev 997)
@@ -0,0 +1,70 @@
+/***********************************************
+* Cool DHTML tooltip script- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
+* This notice MUST stay intact for legal use
+* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code
+***********************************************/
+
+var offsetxpoint=-60 //Customize x offset of tooltip
+var offsetypoint=20 //Customize y offset of tooltip
+var ie=document.all
+var ns6=document.getElementById && !document.all
+var enabletip=false
+if (ie||ns6)
+var tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : ""
+
+function ietruebody(){
+	return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
+}
+
+function showtip(node, txt, w, align){
+	document.onmousemove=positiontip;
+	node.onmouseout = hideddrivetip;
+	//node.onclick = hideddrivetip;
+	if (ns6||ie){		
+		tipobj.style.textAlign=align;
+		tipobj.innerHTML=txt;
+		if (tipobj.offsetWidth>w) tipobj.style.width=w+"px";
+		enabletip=true;
+		return false
+	}
+}
+
+function positiontip(e){
+	if (enabletip){
+		var curX=(ns6)?e.pageX : event.x+ietruebody().scrollLeft;
+		var curY=(ns6)?e.pageY : event.y+ietruebody().scrollTop;
+		//Find out how close the mouse is to the corner of the window
+		var rightedge=ie&&!window.opera? ietruebody().clientWidth-event.clientX-offsetxpoint : window.innerWidth-e.clientX-offsetxpoint-20
+		var bottomedge=ie&&!window.opera? ietruebody().clientHeight-event.clientY-offsetypoint : window.innerHeight-e.clientY-offsetypoint-20
+		
+		var leftedge=(offsetxpoint<0)? offsetxpoint*(-1) : -1000
+		
+		//if the horizontal distance isn't enough to accomodate the width of the context menu
+		if (rightedge<tipobj.offsetWidth)
+		//move the horizontal position of the menu to the left by it's width
+		tipobj.style.left=ie? ietruebody().scrollLeft+event.clientX-tipobj.offsetWidth+"px" : window.pageXOffset+e.clientX-tipobj.offsetWidth+"px"
+		else if (curX<leftedge)
+		tipobj.style.left="5px"
+		else
+		//position the horizontal position of the menu where the mouse is positioned
+		tipobj.style.left=curX+offsetxpoint+"px"
+		
+		//same concept with the vertical position
+		if (bottomedge<tipobj.offsetHeight)
+		tipobj.style.top=ie? ietruebody().scrollTop+event.clientY-tipobj.offsetHeight-offsetypoint+"px" : window.pageYOffset+e.clientY-tipobj.offsetHeight-offsetypoint+"px"
+		else
+		tipobj.style.top=curY+offsetypoint+"px"
+		tipobj.style.visibility="visible"
+	}
+}
+
+function hideddrivetip(){
+	document.onmousemove=null;
+	if (ns6||ie){
+		enabletip=false
+		tipobj.style.visibility="hidden"
+		tipobj.style.left="-1000px"
+		tipobj.style.backgroundColor=''
+		tipobj.style.width=''
+	}
+}

Added: xwiki/trunk/src/main/web/skins/default/prototype.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/prototype.js	2006-03-28 10:10:11 UTC (rev 996)
+++ xwiki/trunk/src/main/web/skins/default/prototype.js	2006-03-28 10:10:39 UTC (rev 997)
@@ -0,0 +1,1039 @@
+/*  Prototype JavaScript framework, version 1.3.1
+ *  (c) 2005 Sam Stephenson <sam at conio.net>
+ *
+ *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
+ *  against the source tree, available from the Prototype darcs repository.
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+/*--------------------------------------------------------------------------*/
+
+
+var Prototype = {
+  Version: '1.3.1',
+  emptyFunction: function() {}
+}
+
+var Class = {
+  create: function() {
+    return function() {
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.prototype.extend = function(object) {
+  return Object.extend.apply(this, [this, object]);
+}
+
+Function.prototype.bind = function(object) {
+  var __method = this;
+  return function() {
+    __method.apply(object, arguments);
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this;
+  return function(event) {
+    __method.call(object, event || window.event);
+  }
+}
+
+Number.prototype.toColorPart = function() {
+  var digits = this.toString(16);
+  if (this < 16) return '0' + digits;
+  return digits;
+}
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0; i < arguments.length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.callback();
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+function $() {
+  var elements = new Array();
+
+  for (var i = 0; i < arguments.length; i++) {
+    var element = arguments[i];
+    if (typeof element == 'string')
+      element = document.getElementById(element);
+
+    if (arguments.length == 1)
+      return element;
+
+    elements.push(element);
+  }
+
+  return elements;
+}
+
+if (!Array.prototype.push) {
+  Array.prototype.push = function() {
+		var startLength = this.length;
+		for (var i = 0; i < arguments.length; i++)
+      this[startLength + i] = arguments[i];
+	  return this.length;
+  }
+}
+
+if (!Function.prototype.apply) {
+  // Based on code from http://www.youngpup.net/
+  Function.prototype.apply = function(object, parameters) {
+    var parameterStrings = new Array();
+    if (!object)     object = window;
+    if (!parameters) parameters = new Array();
+
+    for (var i = 0; i < parameters.length; i++)
+      parameterStrings[i] = 'parameters[' + i + ']';
+
+    object.__apply__ = this;
+    var result = eval('object.__apply__(' +
+      parameterStrings.join(', ') + ')');
+    object.__apply__ = null;
+
+    return result;
+  }
+}
+
+String.prototype.extend({
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  escapeHTML: function() {
+    var div = document.createElement('div');
+    var text = document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0].nodeValue;
+  }
+});
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
+      function() {return new XMLHttpRequest()}
+    ) || false;
+  }
+}
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      parameters:   ''
+    }.extend(options || {});
+  },
+
+  responseIsSuccess: function() {
+    return this.transport.status == undefined
+        || this.transport.status == 0
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  responseIsFailure: function() {
+    return !this.responseIsSuccess();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = (new Ajax.Base()).extend({
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    var parameters = this.options.parameters || '';
+    if (parameters.length > 0) parameters += '&_=';
+
+    try {
+      if (this.options.method == 'get')
+        url += '?' + parameters;
+
+      this.transport.open(this.options.method, url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) {
+        this.transport.onreadystatechange = this.onStateChange.bind(this);
+        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
+      }
+
+      this.setRequestHeaders();
+
+      var body = this.options.postBody ? this.options.postBody : parameters;
+      this.transport.send(this.options.method == 'post' ? body : null);
+
+    } catch (e) {
+    }
+  },
+
+  setRequestHeaders: function() {
+    var requestHeaders =
+      ['X-Requested-With', 'XMLHttpRequest',
+       'X-Prototype-Version', Prototype.Version];
+
+    if (this.options.method == 'post') {
+      requestHeaders.push('Content-type',
+        'application/x-www-form-urlencoded');
+
+      /* Force "Connection: close" for Mozilla browsers to work around
+       * a bug where XMLHttpReqeuest sends an incorrect Content-length
+       * header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType)
+        requestHeaders.push('Connection', 'close');
+    }
+
+    if (this.options.requestHeaders)
+      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+
+    for (var i = 0; i < requestHeaders.length; i += 2)
+      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState != 1)
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  respondToReadyState: function(readyState) {
+    var event = Ajax.Request.Events[readyState];
+
+    if (event == 'Complete')
+      (this.options['on' + this.transport.status]
+       || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+       || Prototype.emptyFunction)(this.transport);
+
+    (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
+
+    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+    if (event == 'Complete')
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+  }
+});
+
+Ajax.Updater = Class.create();
+Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
+
+Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
+  initialize: function(container, url, options) {
+    this.containers = {
+      success: container.success ? $(container.success) : $(container),
+      failure: container.failure ? $(container.failure) :
+        (container.success ? null : $(container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function() {
+      this.updateContent();
+      onComplete(this.transport);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.responseIsSuccess() ?
+      this.containers.success : this.containers.failure;
+
+    var match    = new RegExp(Ajax.Updater.ScriptFragment, 'img');
+    var response = this.transport.responseText.replace(match, '');
+    var scripts  = this.transport.responseText.match(match);
+
+    if (receiver) {
+      if (this.options.insertion) {
+        new this.options.insertion(receiver, response);
+      } else {
+        receiver.innerHTML = response;
+      }
+    }
+
+    if (this.responseIsSuccess()) {
+      if (this.onComplete)
+        setTimeout((function() {this.onComplete(
+          this.transport)}).bind(this), 10);
+    }
+
+    if (this.options.evalScripts && scripts) {
+      match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
+      setTimeout((function() {
+        for (var i = 0; i < scripts.length; i++)
+          eval(scripts[i].match(match)[1]);
+      }).bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = 1;
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this),
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+
+document.getElementsByClassName = function(className) {
+  var children = document.getElementsByTagName('*') || document.all;
+  var elements = new Array();
+
+  for (var i = 0; i < children.length; i++) {
+    var child = children[i];
+    var classNames = child.className.split(' ');
+    for (var j = 0; j < classNames.length; j++) {
+      if (classNames[j] == className) {
+        elements.push(child);
+        break;
+      }
+    }
+  }
+
+  return elements;
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element) {
+  var ss = new Object();
+}
+
+Object.extend(Element, {
+  toggle: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display =
+        (element.style.display == 'none' ? '' : 'none');
+    }
+  },
+
+  hide: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = 'none';
+    }
+  },
+
+  show: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = '';
+    }
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+  },
+
+  getHeight: function(element) {
+    element = $(element);
+    return element.offsetHeight;
+  },
+
+  hasClassName: function(element, className) {
+    element = $(element);
+    if (!element)
+      return;
+    var a = element.className.split(' ');
+    for (var i = 0; i < a.length; i++) {
+      if (a[i] == className)
+        return true;
+    }
+    return false;
+  },
+
+  addClassName: function(element, className) {
+    element = $(element);
+    Element.removeClassName(element, className);
+    element.className += ' ' + className;
+  },
+
+  removeClassName: function(element, className) {
+    element = $(element);
+    if (!element)
+      return;
+    var newClassName = '';
+    var a = element.className.split(' ');
+    for (var i = 0; i < a.length; i++) {
+      if (a[i] != className) {
+        if (i > 0)
+          newClassName += ' ';
+        newClassName += a[i];
+      }
+    }
+    element.className = newClassName;
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    var element = $(element);
+    for (var i = 0; i < element.childNodes.length; i++) {
+      var node = element.childNodes[i];
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        Element.remove(node);
+    }
+  }
+});
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content;
+
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      this.element.insertAdjacentHTML(this.adjacency, this.content);
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.fragment = this.range.createContextualFragment(this.content);
+      this.insertContent();
+    }
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+
+  insertContent: function() {
+    this.element.parentNode.insertBefore(this.fragment, this.element);
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+
+  insertContent: function() {
+    this.element.insertBefore(this.fragment, this.element.firstChild);
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+
+  insertContent: function() {
+    this.element.appendChild(this.fragment);
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+
+  insertContent: function() {
+    this.element.parentNode.insertBefore(this.fragment,
+      this.element.nextSibling);
+  }
+});
+
+var Field = {
+  clear: function() {
+    for (var i = 0; i < arguments.length; i++)
+      $(arguments[i]).value = '';
+  },
+
+  focus: function(element) {
+    $(element).focus();
+  },
+
+  present: function() {
+    for (var i = 0; i < arguments.length; i++)
+      if ($(arguments[i]).value == '') return false;
+    return true;
+  },
+
+  select: function(element) {
+    $(element).select();
+  },
+
+  activate: function(element) {
+    $(element).focus();
+    $(element).select();
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Form = {
+  serialize: function(form) {
+    var elements = Form.getElements($(form));
+    var queryComponents = new Array();
+
+    for (var i = 0; i < elements.length; i++) {
+      var queryComponent = Form.Element.serialize(elements[i]);
+      if (queryComponent)
+        queryComponents.push(queryComponent);
+    }
+
+    return queryComponents.join('&');
+  },
+
+  getElements: function(form) {
+    var form = $(form);
+    var elements = new Array();
+
+    for (tagName in Form.Element.Serializers) {
+      var tagElements = form.getElementsByTagName(tagName);
+      for (var j = 0; j < tagElements.length; j++)
+        elements.push(tagElements[j]);
+    }
+    return elements;
+  },
+
+  getInputs: function(form, typeName, name) {
+    var form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name)
+      return inputs;
+
+    var matchingInputs = new Array();
+    for (var i = 0; i < inputs.length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) ||
+          (name && input.name != name))
+        continue;
+      matchingInputs.push(input);
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.blur();
+      element.disabled = 'true';
+    }
+  },
+
+  enable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.disabled = '';
+    }
+  },
+
+  focusFirstElement: function(form) {
+    var form = $(form);
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      if (element.type != 'hidden' && !element.disabled) {
+        Field.activate(element);
+        break;
+      }
+    }
+  },
+
+  reset: function(form) {
+    $(form).reset();
+  }
+}
+
+Form.Element = {
+  serialize: function(element) {
+    var element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+
+    if (parameter)
+      return encodeURIComponent(parameter[0]) + '=' +
+        encodeURIComponent(parameter[1]);
+  },
+
+  getValue: function(element) {
+    var element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+
+    if (parameter)
+      return parameter[1];
+  }
+}
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'submit':
+      case 'hidden':
+      case 'password':
+      case 'text':
+        return Form.Element.Serializers.textarea(element);
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+    }
+    return false;
+  },
+
+  inputSelector: function(element) {
+    if (element.checked)
+      return [element.name, element.value];
+  },
+
+  textarea: function(element) {
+    return [element.name, element.value];
+  },
+
+  select: function(element) {
+    var value = '';
+    if (element.type == 'select-one') {
+      var index = element.selectedIndex;
+      if (index >= 0)
+        value = element.options[index].value || element.options[index].text;
+    } else {
+      value = new Array();
+      for (var i = 0; i < element.length; i++) {
+        var opt = element.options[i];
+        if (opt.selected)
+          value.push(opt.value || opt.text);
+      }
+    }
+    return [element.name, value];
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    var elements = Form.getElements(this.element);
+    for (var i = 0; i < elements.length; i++)
+      this.registerCallback(elements[i]);
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          element.target = this;
+          element.prev_onclick = element.onclick || Prototype.emptyFunction;
+          element.onclick = function() {
+            this.prev_onclick();
+            this.target.onElementEvent();
+          }
+          break;
+        case 'password':
+        case 'text':
+        case 'textarea':
+        case 'select-one':
+        case 'select-multiple':
+          element.target = this;
+          element.prev_onchange = element.onchange || Prototype.emptyFunction;
+          element.onchange = function() {
+            this.prev_onchange();
+            this.target.onElementEvent();
+          }
+          break;
+      }
+    }
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {
+      event.preventDefault();
+      event.stopPropagation();
+    } else {
+      event.returnValue = false;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0; i < Event.observers.length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        ((navigator.appVersion.indexOf('AppleWebKit') > 0)
+        || element.attachEvent))
+      name = 'keydown';
+
+    this._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        ((navigator.appVersion.indexOf('AppleWebKit') > 0)
+        || element.detachEvent))
+      name = 'keydown';
+
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      element.detachEvent('on' + name, observer);
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+Event.observe(window, 'unload', Event.unloadCache, false);
+
+var Position = {
+
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  clone: function(source, target) {
+    source = $(source);
+    target = $(target);
+    target.style.position = 'absolute';
+    var offsets = this.cumulativeOffset(source);
+    target.style.top    = offsets[1] + 'px';
+    target.style.left   = offsets[0] + 'px';
+    target.style.width  = source.offsetWidth + 'px';
+    target.style.height = source.offsetHeight + 'px';
+  }
+}

Added: xwiki/trunk/src/main/web/skins/default/rico/prototype.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/rico/prototype.js	2006-03-28 10:10:11 UTC (rev 996)
+++ xwiki/trunk/src/main/web/skins/default/rico/prototype.js	2006-03-28 10:10:39 UTC (rev 997)
@@ -0,0 +1,1047 @@
+<script type="text/javascript">
+<!--
+/*  Prototype JavaScript framework, version 1.3.1
+ *  (c) 2005 Sam Stephenson <sam at conio.net>
+ *
+ *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
+ *  against the source tree, available from the Prototype darcs repository. 
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+/*--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.3.1',
+  emptyFunction: function() {}
+}
+
+var Class = {
+  create: function() {
+    return function() { 
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.prototype.extend = function(object) {
+  return Object.extend.apply(this, [this, object]);
+}
+
+Function.prototype.bind = function(object) {
+  var __method = this;
+  return function() {
+    __method.apply(object, arguments);
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this;
+  return function(event) {
+    __method.call(object, event || window.event);
+  }
+}
+
+Number.prototype.toColorPart = function() {
+  var digits = this.toString(16);
+  if (this < 16) return '0' + digits;
+  return digits;
+}
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0; i < arguments.length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try { 
+        this.currentlyExecuting = true;
+        this.callback(); 
+      } finally { 
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+function $() {
+  var elements = new Array();
+
+  for (var i = 0; i < arguments.length; i++) {
+    var element = arguments[i];
+    if (typeof element == 'string')
+      element = document.getElementById(element);
+
+    if (arguments.length == 1) 
+      return element;
+
+    elements.push(element);
+  }
+
+  return elements;
+}
+
+if (!Array.prototype.push) {
+  Array.prototype.push = function() {
+		var startLength = this.length;
+		for (var i = 0; i < arguments.length; i++)
+      this[startLength + i] = arguments[i];
+	  return this.length;
+  }
+}
+
+if (!Function.prototype.apply) {
+  // Based on code from http://www.youngpup.net/
+  Function.prototype.apply = function(object, parameters) {
+    var parameterStrings = new Array();
+    if (!object)     object = window;
+    if (!parameters) parameters = new Array();
+    
+    for (var i = 0; i < parameters.length; i++)
+      parameterStrings[i] = 'parameters[' + i + ']';
+    
+    object.__apply__ = this;
+    var result = eval('object.__apply__(' + 
+      parameterStrings.join(', ') + ')');
+    object.__apply__ = null;
+    
+    return result;
+  }
+}
+
+String.prototype.extend({
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  escapeHTML: function() {
+    var div = document.createElement('div');
+    var text = document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0].nodeValue;
+  }
+});
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
+      function() {return new XMLHttpRequest()}
+    ) || false;
+  }
+}
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      parameters:   ''
+    }.extend(options || {});
+  },
+
+  responseIsSuccess: function() {
+    return this.transport.status == undefined
+        || this.transport.status == 0 
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  responseIsFailure: function() {
+    return !this.responseIsSuccess();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events = 
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = (new Ajax.Base()).extend({
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    var parameters = this.options.parameters || '';
+    if (parameters.length > 0) parameters += '&_=';
+
+    try {
+      // changes for handling ?xpage=rdf
+      if (this.options.method == 'get')
+      {
+	var urlSeparator = url.indexOf('?') ? '&' : '?'
+        url += urlSeparator + parameters;
+      }
+
+      this.transport.open(this.options.method, url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) {
+        this.transport.onreadystatechange = this.onStateChange.bind(this);
+        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
+      }
+
+      this.setRequestHeaders();
+
+      var body = this.options.postBody ? this.options.postBody : parameters;
+      this.transport.send(this.options.method == 'post' ? body : null);
+
+    } catch (e) {
+      alert (e);
+    }
+  },
+
+  setRequestHeaders: function() {
+    var requestHeaders = 
+      ['X-Requested-With', 'XMLHttpRequest',
+       'X-Prototype-Version', Prototype.Version];
+
+    if (this.options.method == 'post') {
+      requestHeaders.push('Content-type', 
+        'application/x-www-form-urlencoded');
+
+      /* Force "Connection: close" for Mozilla browsers to work around
+       * a bug where XMLHttpReqeuest sends an incorrect Content-length
+       * header. See Mozilla Bugzilla #246651. 
+       */
+      if (this.transport.overrideMimeType)
+        requestHeaders.push('Connection', 'close');
+    }
+
+    if (this.options.requestHeaders)
+      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+
+    for (var i = 0; i < requestHeaders.length; i += 2)
+      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState != 1)
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  respondToReadyState: function(readyState) {
+    var event = Ajax.Request.Events[readyState];
+
+    if (event == 'Complete')
+      (this.options['on' + this.transport.status]
+       || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+       || Prototype.emptyFunction)(this.transport);
+
+    (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
+
+    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+    if (event == 'Complete')
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+  }
+});
+
+Ajax.Updater = Class.create();
+Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
+
+Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
+  initialize: function(container, url, options) {
+    this.containers = {
+      success: container.success ? $(container.success) : $(container),
+      failure: container.failure ? $(container.failure) :
+        (container.success ? null : $(container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function() {
+      this.updateContent();
+      onComplete(this.transport);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.responseIsSuccess() ?
+      this.containers.success : this.containers.failure;
+
+    var match    = new RegExp(Ajax.Updater.ScriptFragment, 'img');
+    var response = this.transport.responseText.replace(match, '');
+    var scripts  = this.transport.responseText.match(match);
+
+    if (receiver) {
+      if (this.options.insertion) {
+        new this.options.insertion(receiver, response);
+      } else {
+        receiver.innerHTML = response;
+      }
+    }
+
+    if (this.responseIsSuccess()) {
+      if (this.onComplete)
+        setTimeout((function() {this.onComplete(
+          this.transport)}).bind(this), 10);
+    }
+
+    if (this.options.evalScripts && scripts) {
+      match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
+      setTimeout((function() {
+        for (var i = 0; i < scripts.length; i++)
+          eval(scripts[i].match(match)[1]);
+      }).bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = 1;
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ? 
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this), 
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+
+document.getElementsByClassName = function(className) {
+  var children = document.getElementsByTagName('*') || document.all;
+  var elements = new Array();
+  
+  for (var i = 0; i < children.length; i++) {
+    var child = children[i];
+    var classNames = child.className.split(' ');
+    for (var j = 0; j < classNames.length; j++) {
+      if (classNames[j] == className) {
+        elements.push(child);
+        break;
+      }
+    }
+  }
+  
+  return elements;
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element) {
+  var Element = new Object();
+}
+
+Object.extend(Element, {
+  toggle: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = 
+        (element.style.display == 'none' ? '' : 'none');
+    }
+  },
+
+  hide: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = 'none';
+    }
+  },
+
+  show: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = '';
+    }
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+  },
+   
+  getHeight: function(element) {
+    element = $(element);
+    return element.offsetHeight; 
+  },
+
+  hasClassName: function(element, className) {
+    element = $(element);
+    if (!element)
+      return;
+    var a = element.className.split(' ');
+    for (var i = 0; i < a.length; i++) {
+      if (a[i] == className)
+        return true;
+    }
+    return false;
+  },
+
+  addClassName: function(element, className) {
+    element = $(element);
+    Element.removeClassName(element, className);
+    element.className += ' ' + className;
+  },
+
+  removeClassName: function(element, className) {
+    element = $(element);
+    if (!element)
+      return;
+    var newClassName = '';
+    var a = element.className.split(' ');
+    for (var i = 0; i < a.length; i++) {
+      if (a[i] != className) {
+        if (i > 0)
+          newClassName += ' ';
+        newClassName += a[i];
+      }
+    }
+    element.className = newClassName;
+  },
+  
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    var element = $(element);
+    for (var i = 0; i < element.childNodes.length; i++) {
+      var node = element.childNodes[i];
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 
+        Element.remove(node);
+    }
+  }
+});
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content;
+    
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      this.element.insertAdjacentHTML(this.adjacency, this.content);
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.fragment = this.range.createContextualFragment(this.content);
+      this.insertContent();
+    }
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+  
+  insertContent: function() {
+    this.element.parentNode.insertBefore(this.fragment, this.element);
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+  
+  insertContent: function() {  
+    this.element.insertBefore(this.fragment, this.element.firstChild);
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+  
+  insertContent: function() {
+    this.element.appendChild(this.fragment);
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+  
+  insertContent: function() {
+    this.element.parentNode.insertBefore(this.fragment, 
+      this.element.nextSibling);
+  }
+});
+
+var Field = {
+  clear: function() {
+    for (var i = 0; i < arguments.length; i++)
+      $(arguments[i]).value = '';
+  },
+
+  focus: function(element) {
+    $(element).focus();
+  },
+  
+  present: function() {
+    for (var i = 0; i < arguments.length; i++)
+      if ($(arguments[i]).value == '') return false;
+    return true;
+  },
+  
+  select: function(element) {
+    $(element).select();
+  },
+   
+  activate: function(element) {
+    $(element).focus();
+    $(element).select();
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Form = {
+  serialize: function(form) {
+    var elements = Form.getElements($(form));
+    var queryComponents = new Array();
+    
+    for (var i = 0; i < elements.length; i++) {
+      var queryComponent = Form.Element.serialize(elements[i]);
+      if (queryComponent)
+        queryComponents.push(queryComponent);
+    }
+    
+    return queryComponents.join('&');
+  },
+  
+  getElements: function(form) {
+    var form = $(form);
+    var elements = new Array();
+
+    for (tagName in Form.Element.Serializers) {
+      var tagElements = form.getElementsByTagName(tagName);
+      for (var j = 0; j < tagElements.length; j++)
+        elements.push(tagElements[j]);
+    }
+    return elements;
+  },
+  
+  getInputs: function(form, typeName, name) {
+    var form = $(form);
+    var inputs = form.getElementsByTagName('input');
+    
+    if (!typeName && !name)
+      return inputs;
+      
+    var matchingInputs = new Array();
+    for (var i = 0; i < inputs.length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) ||
+          (name && input.name != name)) 
+        continue;
+      matchingInputs.push(input);
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.blur();
+      element.disabled = 'true';
+    }
+  },
+
+  enable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.disabled = '';
+    }
+  },
+
+  focusFirstElement: function(form) {
+    var form = $(form);
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      if (element.type != 'hidden' && !element.disabled) {
+        Field.activate(element);
+        break;
+      }
+    }
+  },
+
+  reset: function(form) {
+    $(form).reset();
+  }
+}
+
+Form.Element = {
+  serialize: function(element) {
+    var element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+    
+    if (parameter)
+      return encodeURIComponent(parameter[0]) + '=' + 
+        encodeURIComponent(parameter[1]);                   
+  },
+  
+  getValue: function(element) {
+    var element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+    
+    if (parameter) 
+      return parameter[1];
+  }
+}
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'submit':
+      case 'hidden':
+      case 'password':
+      case 'text':
+        return Form.Element.Serializers.textarea(element);
+      case 'checkbox':  
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+    }
+    return false;
+  },
+
+  inputSelector: function(element) {
+    if (element.checked)
+      return [element.name, element.value];
+  },
+
+  textarea: function(element) {
+    return [element.name, element.value];
+  },
+
+  select: function(element) {
+    var value = '';
+    if (element.type == 'select-one') {
+      var index = element.selectedIndex;
+      if (index >= 0)
+        value = element.options[index].value || element.options[index].text;
+    } else {
+      value = new Array();
+      for (var i = 0; i < element.length; i++) {
+        var opt = element.options[i];
+        if (opt.selected)
+          value.push(opt.value || opt.text);
+      }
+    }
+    return [element.name, value];
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+    
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+  
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+  
+  onTimerEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+    
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+  
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+  
+  registerFormCallbacks: function() {
+    var elements = Form.getElements(this.element);
+    for (var i = 0; i < elements.length; i++)
+      this.registerCallback(elements[i]);
+  },
+  
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':  
+        case 'radio':
+          element.target = this;
+          element.prev_onclick = element.onclick || Prototype.emptyFunction;
+          element.onclick = function() {
+            this.prev_onclick(); 
+            this.target.onElementEvent();
+          }
+          break;
+        case 'password':
+        case 'text':
+        case 'textarea':
+        case 'select-one':
+        case 'select-multiple':
+          element.target = this;
+          element.prev_onchange = element.onchange || Prototype.emptyFunction;
+          element.onchange = function() {
+            this.prev_onchange(); 
+            this.target.onElementEvent();
+          }
+          break;
+      }
+    }    
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX + 
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY + 
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) { 
+      event.preventDefault(); 
+      event.stopPropagation(); 
+    } else {
+      event.returnValue = false;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+  
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+  
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0; i < Event.observers.length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+    
+    if (name == 'keypress' &&
+        ((navigator.appVersion.indexOf('AppleWebKit') > 0) 
+        || element.attachEvent))
+      name = 'keydown';
+    
+    this._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+    
+    if (name == 'keypress' &&
+        ((navigator.appVersion.indexOf('AppleWebKit') > 0) 
+        || element.detachEvent))
+      name = 'keydown';
+    
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      element.detachEvent('on' + name, observer);
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+Event.observe(window, 'unload', Event.unloadCache, false);
+
+var Position = {
+
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false, 
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset 
+                || document.documentElement.scrollLeft 
+                || document.body.scrollLeft 
+                || 0;
+    this.deltaY =  window.pageYOffset 
+                || document.documentElement.scrollTop 
+                || document.body.scrollTop 
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0; 
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] && 
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] && 
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {  
+    if (!mode) return 0;  
+    if (mode == 'vertical') 
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 
+        element.offsetWidth;
+  },
+
+  clone: function(source, target) {
+    source = $(source);
+    target = $(target);
+    target.style.position = 'absolute';
+    var offsets = this.cumulativeOffset(source);
+    target.style.top    = offsets[1] + 'px';
+    target.style.left   = offsets[0] + 'px';
+    target.style.width  = source.offsetWidth + 'px';
+    target.style.height = source.offsetHeight + 'px';
+  }
+}
+// -->
+</script>

Added: xwiki/trunk/src/main/web/skins/default/rico/rico.js
===================================================================
--- xwiki/trunk/src/main/web/skins/default/rico/rico.js	2006-03-28 10:10:11 UTC (rev 996)
+++ xwiki/trunk/src/main/web/skins/default/rico/rico.js	2006-03-28 10:10:39 UTC (rev 997)
@@ -0,0 +1,2666 @@
+/**
+  *
+  *  Copyright 2005 Sabre Airline Solutions
+  *
+  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+  *  file except in compliance with the License. You may obtain a copy of the License at
+  *
+  *         http://www.apache.org/licenses/LICENSE-2.0
+  *
+  *  Unless required by applicable law or agreed to in writing, software distributed under the
+  *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+  *  either express or implied. See the License for the specific language governing permissions
+  *  and limitations under the License.
+  **/
+
+
+//-------------------- rico.js
+var Rico = {
+  Version: '1.1-beta2'
+}
+
+Rico.ArrayExtensions = new Array();
+
+if (Object.prototype.extend) {
+   // in prototype.js...
+   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
+}
+
+if (Array.prototype.push) {
+   // in prototype.js...
+   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
+}
+
+if (!Array.prototype.remove) {
+   Array.prototype.remove = function(dx) {
+      if( isNaN(dx) || dx > this.length )
+         return false;
+      for( var i=0,n=0; i<this.length; i++ )
+         if( i != dx )
+            this[n++]=this[i];
+      this.length-=1;
+   };
+  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
+}
+
+if (!Array.prototype.removeItem) {
+   Array.prototype.removeItem = function(item) {
+      for ( var i = 0 ; i < this.length ; i++ )
+         if ( this[i] == item ) {
+            this.remove(i);
+            break;
+         }
+   };
+  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
+}
+
+if (!Array.prototype.indices) {
+   Array.prototype.indices = function() {
+      var indexArray = new Array();
+      for ( index in this ) {
+         var ignoreThis = false;
+         for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
+            if ( this[index] == Rico.ArrayExtensions[i] ) {
+               ignoreThis = true;
+               break;
+            }
+         }
+         if ( !ignoreThis )
+            indexArray[ indexArray.length ] = index;
+      }
+      return indexArray;
+   }
+  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
+}
+
+// Create the loadXML method and xml getter for Mozilla
+if ( window.DOMParser &&
+	  window.XMLSerializer &&
+	  window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
+
+   if (!Document.prototype.loadXML) {
+      Document.prototype.loadXML = function (s) {
+         var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
+         while (this.hasChildNodes())
+            this.removeChild(this.lastChild);
+
+         for (var i = 0; i < doc2.childNodes.length; i++) {
+            this.appendChild(this.importNode(doc2.childNodes[i], true));
+         }
+      };
+	}
+
+	Document.prototype.__defineGetter__( "xml",
+	   function () {
+		   return (new XMLSerializer()).serializeToString(this);
+	   }
+	 );
+}
+
+document.getElementsByTagAndClassName = function(tagName, className) {
+  if ( tagName == null )
+     tagName = '*';
+
+  var children = document.getElementsByTagName(tagName) || document.all;
+  var elements = new Array();
+
+  if ( className == null )
+    return children;
+
+  for (var i = 0; i < children.length; i++) {
+    var child = children[i];
+    var classNames = child.className.split(' ');
+    for (var j = 0; j < classNames.length; j++) {
+      if (classNames[j] == className) {
+        elements.push(child);
+        break;
+      }
+    }
+  }
+
+  return elements;
+}
+
+
+//-------------------- ricoAccordion.js
+
+Rico.Accordion = Class.create();
+
+Rico.Accordion.prototype = {
+
+   initialize: function(container, options) {
+      this.container            = $(container);
+      this.lastExpandedTab      = null;
+      this.accordionTabs        = new Array();
+      this.setOptions(options);
+      this._attachBehaviors();
+
+      this.container.style.borderBottom = '1px solid ' + this.options.borderColor;
+
+      // set the initial visual state...
+      for ( var i=1 ; i < this.accordionTabs.length ; i++ )
+      {
+         this.accordionTabs[i].collapse();
+         this.accordionTabs[i].content.style.display = 'none';
+      }
+      this.lastExpandedTab = this.accordionTabs[0];
+      this.lastExpandedTab.content.style.height = this.options.panelHeight + "px";
+      this.lastExpandedTab.showExpanded();
+      this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
+   },
+
+   setOptions: function(options) {
+      this.options = {
+         expandedBg          : '#63699c',
+         hoverBg             : '#63699c',
+         collapsedBg         : '#6b79a5',
+         expandedTextColor   : '#ffffff',
+         expandedFontWeight  : 'bold',
+         hoverTextColor      : '#ffffff',
+         collapsedTextColor  : '#ced7ef',
+         collapsedFontWeight : 'normal',
+         hoverTextColor      : '#ffffff',
+         borderColor         : '#1f669b',
+         panelHeight         : 200,
+         onHideTab           : null,
+         onShowTab           : null
+      }.extend(options || {});
+   },
+
+   showTabByIndex: function( anIndex, animate ) {
+      var doAnimate = arguments.length == 1 ? true : animate;
+      this.showTab( this.accordionTabs[anIndex], doAnimate );
+   },
+
+   showTab: function( accordionTab, animate ) {
+
+      var doAnimate = arguments.length == 1 ? true : animate;
+
+      if ( this.options.onHideTab )
+         this.options.onHideTab(this.lastExpandedTab);
+
+      this.lastExpandedTab.showCollapsed(); 
+      var accordion = this;
+      var lastExpandedTab = this.lastExpandedTab;
+
+      this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px';
+      accordionTab.content.style.display = '';
+
+      accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
+
+      if ( doAnimate ) {
+         new Effect.AccordionSize( this.lastExpandedTab.content,
+                                   accordionTab.content,
+                                   1,
+                                   this.options.panelHeight,
+                                   100, 10,
+                                   { complete: function() {accordion.showTabDone(lastExpandedTab)} } );
+         this.lastExpandedTab = accordionTab;
+      }
+      else {
+         this.lastExpandedTab.content.style.height = "1px";
+         accordionTab.content.style.height = this.options.panelHeight + "px";
+         this.lastExpandedTab = accordionTab;
+         this.showTabDone(lastExpandedTab);
+      }
+   },
+
+   showTabDone: function(collapsedTab) {
+      collapsedTab.content.style.display = 'none';
+      this.lastExpandedTab.showExpanded();
+      if ( this.options.onShowTab )
+         this.options.onShowTab(this.lastExpandedTab);
+   },
+
+   _attachBehaviors: function() {
+      var panels = this._getDirectChildrenByTag(this.container, 'DIV');
+      for ( var i = 0 ; i < panels.length ; i++ ) {
+
+         var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV');
+         if ( tabChildren.length != 2 )
+            continue; // unexpected
+
+         var tabTitleBar   = tabChildren[0];
+         var tabContentBox = tabChildren[1];
+         this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) );
+      }
+   },
+
+   _getDirectChildrenByTag: function(e, tagName) {
+      var kids = new Array();
+      var allKids = e.childNodes;
+      for( var i = 0 ; i < allKids.length ; i++ )
+         if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
+            kids.push(allKids[i]);
+      return kids;
+   }
+
+};
+
+Rico.Accordion.Tab = Class.create();
+
+Rico.Accordion.Tab.prototype = {
+
+   initialize: function(accordion, titleBar, content) {
+      this.accordion = accordion;
+      this.titleBar  = titleBar;
+      this.content   = content;
+      this._attachBehaviors();
+   },
+
+   collapse: function() {
+      this.showCollapsed();
+      this.content.style.height = "1px";
+   },
+
+   showCollapsed: function() {
+      this.expanded = false;
+      this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
+      this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
+      this.titleBar.style.fontWeight      = this.accordion.options.collapsedFontWeight;
+      this.content.style.overflow = "hidden";
+   },
+
+   showExpanded: function() {
+      this.expanded = true;
+      this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
+      this.titleBar.style.color           = this.accordion.options.expandedTextColor;
+      this.content.style.overflow         = "visible";
+   },
+
+   titleBarClicked: function(e) {
+      if ( this.accordion.lastExpandedTab == this )
+         return;
+      this.accordion.showTab(this);
+   },
+
+   hover: function(e) {
+		this.titleBar.style.backgroundColor = this.accordion.options.hoverBg;
+		this.titleBar.style.color           = this.accordion.options.hoverTextColor;
+   },
+
+   unhover: function(e) {
+      if ( this.expanded ) {
+         this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
+         this.titleBar.style.color           = this.accordion.options.expandedTextColor;
+      }
+      else {
+         this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
+         this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
+      }
+   },
+
+   _attachBehaviors: function() {
+      this.content.style.border = "1px solid " + this.accordion.options.borderColor;
+      this.content.style.borderTopWidth    = "0px";
+      this.content.style.borderBottomWidth = "0px";
+      this.content.style.margin            = "0px";
+
+      this.titleBar.onclick     = this.titleBarClicked.bindAsEventListener(this);
+      this.titleBar.onmouseover = this.hover.bindAsEventListener(this);
+      this.titleBar.onmouseout  = this.unhover.bindAsEventListener(this);
+   }
+
+};
+
+
+//-------------------- ricoAjaxEngine.js
+
+Rico.AjaxEngine = Class.create();
+
+Rico.AjaxEngine.prototype = {
+
+   initialize: function() {
+      this.ajaxElements = new Array();
+      this.ajaxObjects  = new Array();
+      this.requestURLS  = new Array();
+   },
+
+   registerAjaxElement: function( anId, anElement ) {
+      if ( arguments.length == 1 )
+         anElement = $(anId);
+      this.ajaxElements[anId] = anElement;
+   },
+
+   registerAjaxObject: function( anId, anObject ) {
+      this.ajaxObjects[anId] = anObject;
+   },
+
+   registerRequest: function (requestLogicalName, requestURL) {
+      this.requestURLS[requestLogicalName] = requestURL;
+   },
+
+   sendRequest: function(requestName) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 1 )
+         queryString = this._createQueryString(arguments, 1);
+
+      new Ajax.Request(requestURL, this._requestOptions(queryString));
+   },
+
+   sendRequestWithData: function(requestName, xmlDocument) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 2 )
+         queryString = this._createQueryString(arguments, 2);
+
+      new Ajax.Request(requestURL + "?" + queryString, this._requestOptions(null,xmlDocument));
+   },
+
+   sendRequestAndUpdate: function(requestName,container,options) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 3 )
+         queryString = this._createQueryString(arguments, 3);
+
+      var updaterOptions = this._requestOptions(queryString);
+      updaterOptions.onComplete = null;
+      updaterOptions.extend(options);
+
+      new Ajax.Updater(container, requestURL, updaterOptions);
+   },
+
+   sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 4 )
+         queryString = this._createQueryString(arguments, 4);
+
+
+      var updaterOptions = this._requestOptions(queryString,xmlDocument);
+      updaterOptions.onComplete = null;
+      updaterOptions.extend(options);
+
+      new Ajax.Updater(container, requestURL + "?" + queryString, updaterOptions);
+   },
+
+   // Private -- not part of intended engine API --------------------------------------------------------------------
+
+   _requestOptions: function(queryString,xmlDoc) {
+      var self = this;
+
+      var requestHeaders = ['X-Rico-Version', Rico.Version ];
+      var sendMethod = "post"
+      if ( arguments[1] )
+         requestHeaders.push( 'Content-type', 'text/xml' );
+      else
+         sendMethod = "get";
+
+      return { requestHeaders: requestHeaders,
+               parameters:     queryString,
+               postBody:       arguments[1] ? xmlDoc : null,
+               method:         sendMethod,
+               onComplete:     self._onRequestComplete.bind(self) };
+   },
+
+   _createQueryString: function( theArgs, offset ) {
+      var queryString = ""
+      for ( var i = offset ; i < theArgs.length ; i++ ) {
+          if ( i != offset )
+            queryString += "&";
+
+          var anArg = theArgs[i];
+
+          if ( anArg.name != undefined && anArg.value != undefined ) {
+            queryString += anArg.name +  "=" + escape(anArg.value);
+          }
+          else {
+             var ePos  = anArg.indexOf('=');
+             var argName  = anArg.substring( 0, ePos );
+             var argValue = anArg.substring( ePos + 1 );
+             queryString += argName + "=" + escape(argValue);
+          }
+      }
+
+      return queryString;
+   },
+
+   _onRequestComplete : function(request) {
+
+      //!!TODO: error handling infrastructure?? 
+      if (request.status != 200)
+        return;
+
+      var response = request.responseXML.getElementsByTagName("ajax-response");
+      if (response == null || response.length != 1)
+         return;
+      this._processAjaxResponse( response[0].childNodes );
+   },
+
+   _processAjaxResponse: function( xmlResponseElements ) {
+      for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
+         var responseElement = xmlResponseElements[i];
+
+         // only process nodes of type element.....
+         if ( responseElement.nodeType != 1 )
+            continue;
+
+         var responseType = responseElement.getAttribute("type");
+         var responseId   = responseElement.getAttribute("id");
+
+         if ( responseType == "object" )
+            this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
+         else if ( responseType == "element" )
+            this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
+         else
+            alert('unrecognized AjaxResponse type : ' + responseType );
+      }
+   },
+
+   _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
+      ajaxObject.ajaxUpdate( responseElement );
+   },
+
+   _processAjaxElementUpdate: function( ajaxElement, responseElement ) {
+      ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement);
+   }
+
+}
+
+var ajaxEngine = new Rico.AjaxEngine();
+
+
+//-------------------- ricoColor.js
+Rico.Color = Class.create();
+
+Rico.Color.prototype = {
+
+   initialize: function(red, green, blue) {
+      this.rgb = { r: red, g : green, b : blue };
+   },
+
+   setRed: function(r) {
+      this.rgb.r = r;
+   },
+
+   setGreen: function(g) {
+      this.rgb.g = g;
+   },
+
+   setBlue: function(b) {
+      this.rgb.b = b;
+   },
+
+   setHue: function(h) {
+
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.h = h;
+
+      // convert back to RGB...
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+   },
+
+   setSaturation: function(s) {
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.s = s;
+
+      // convert back to RGB and set values...
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+   },
+
+   setBrightness: function(b) {
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.b = b;
+
+      // convert back to RGB and set values...
+      this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
+   },
+
+   darken: function(percent) {
+      var hsb  = this.asHSB();
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
+   },
+
+   brighten: function(percent) {
+      var hsb  = this.asHSB();
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
+   },
+
+   blend: function(other) {
+      this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
+      this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
+      this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
+   },
+
+   isBright: function() {
+      var hsb = this.asHSB();
+      return this.asHSB().b > 0.5;
+   },
+
+   isDark: function() {
+      return ! this.isBright();
+   },
+
+   asRGB: function() {
+      return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
+   },
+
+   asHex: function() {
+      return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
+   },
+
+   asHSB: function() {
+      return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
+   },
+
+   toString: function() {
+      return this.asHex();
+   }
+
+};
+
+Rico.Color.createFromHex = function(hexCode) {
+
+   if ( hexCode.indexOf('#') == 0 )
+      hexCode = hexCode.substring(1);
+   var red   = hexCode.substring(0,2);
+   var green = hexCode.substring(2,4);
+   var blue  = hexCode.substring(4,6);
+   return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
+}
+
+/**
+ * Factory method for creating a color from the background of
+ * an HTML element.
+ */
+Rico.Color.createColorFromBackground = function(elem) {
+
+   var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color");
+
+   if ( actualColor == "transparent" && elem.parent )
+      return Rico.Color.createColorFromBackground(elem.parent);
+
+   if ( actualColor == null )
+      return new Rico.Color(255,255,255);
+
+   if ( actualColor.indexOf("rgb(") == 0 ) {
+      var colors = actualColor.substring(4, actualColor.length - 1 );
+      var colorArray = colors.split(",");
+      return new Rico.Color( parseInt( colorArray[0] ),
+                            parseInt( colorArray[1] ),
+                            parseInt( colorArray[2] )  );
+
+   }
+   else if ( actualColor.indexOf("#") == 0 ) {
+      var redPart   = parseInt(actualColor.substring(1,3), 16);
+      var greenPart = parseInt(actualColor.substring(3,5), 16);
+      var bluePart  = parseInt(actualColor.substring(5), 16);
+      return new Rico.Color( redPart, greenPart, bluePart );
+   }
+   else
+      return new Rico.Color(255,255,255);
+}
+
+Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
+
+   var red   = 0;
+	var green = 0;
+	var blue  = 0;
+
+   if (saturation == 0) {
+      red = parseInt(brightness * 255.0 + 0.5);
+	   green = red;
+	   blue = red;
+	}
+	else {
+      var h = (hue - Math.floor(hue)) * 6.0;
+      var f = h - Math.floor(h);
+      var p = brightness * (1.0 - saturation);
+      var q = brightness * (1.0 - saturation * f);
+      var t = brightness * (1.0 - (saturation * (1.0 - f)));
+
+      switch (parseInt(h)) {
+         case 0:
+            red   = (brightness * 255.0 + 0.5);
+            green = (t * 255.0 + 0.5);
+            blue  = (p * 255.0 + 0.5);
+            break;
+         case 1:
+            red   = (q * 255.0 + 0.5);
+            green = (brightness * 255.0 + 0.5);
+            blue  = (p * 255.0 + 0.5);
+            break;
+         case 2:
+            red   = (p * 255.0 + 0.5);
+            green = (brightness * 255.0 + 0.5);
+            blue  = (t * 255.0 + 0.5);
+            break;
+         case 3:
+            red   = (p * 255.0 + 0.5);
+            green = (q * 255.0 + 0.5);
+            blue  = (brightness * 255.0 + 0.5);
+            break;
+         case 4:
+            red   = (t * 255.0 + 0.5);
+            green = (p * 255.0 + 0.5);
+            blue  = (brightness * 255.0 + 0.5);
+            break;
+          case 5:
+            red   = (brightness * 255.0 + 0.5);
+            green = (p * 255.0 + 0.5);
+            blue  = (q * 255.0 + 0.5);
+            break;
+	    }
+	}
+
+   return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
+}
+
+Rico.Color.RGBtoHSB = function(r, g, b) {
+
+   var hue;
+   var saturaton;
+   var brightness;
+
+   var cmax = (r > g) ? r : g;
+   if (b > cmax)
+      cmax = b;
+
+   var cmin = (r < g) ? r : g;
+   if (b < cmin)
+      cmin = b;
+
+   brightness = cmax / 255.0;
+   if (cmax != 0)
+      saturation = (cmax - cmin)/cmax;
+   else
+      saturation = 0;
+
+   if (saturation == 0)
+      hue = 0;
+   else {
+      var redc   = (cmax - r)/(cmax - cmin);
+    	var greenc = (cmax - g)/(cmax - cmin);
+    	var bluec  = (cmax - b)/(cmax - cmin);
+
+    	if (r == cmax)
+    	   hue = bluec - greenc;
+    	else if (g == cmax)
+    	   hue = 2.0 + redc - bluec;
+      else
+    	   hue = 4.0 + greenc - redc;
+
+    	hue = hue / 6.0;
+    	if (hue < 0)
+    	   hue = hue + 1.0;
+   }
+
+   return { h : hue, s : saturation, b : brightness };
+}
+
+
+//-------------------- ricoCorner.js
+
+Rico.Corner = {
+
+   round: function(e, options) {
+      var e = $(e);
+      this._setOptions(options);
+
+      var color = this.options.color;
+      if ( this.options.color == "fromElement" )
+         color = this._background(e);
+
+      var bgColor = this.options.bgColor;
+      if ( this.options.bgColor == "fromParent" )
+         bgColor = this._background(e.offsetParent);
+
+      this._roundCornersImpl(e, color, bgColor);
+   },
+
+   _roundCornersImpl: function(e, color, bgColor) {
+      if(this.options.border)
+         this._renderBorder(e,bgColor);
+      if(this._isTopRounded())
+         this._roundTopCorners(e,color,bgColor);
+      if(this._isBottomRounded())
+         this._roundBottomCorners(e,color,bgColor);
+   },
+
+   _renderBorder: function(el,bgColor) {
+      var borderValue = "1px solid " + this._borderColor(bgColor);
+      var borderL = "border-left: "  + borderValue;
+      var borderR = "border-right: " + borderValue;
+      var style   = "style='" + borderL + ";" + borderR +  "'";
+      el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"
+   },
+
+   _roundTopCorners: function(el, color, bgColor) {
+      var corner = this._createCorner(bgColor);
+      for(var i=0 ; i < this.options.numSlices ; i++ )
+         corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
+      el.style.paddingTop = 0;
+      el.insertBefore(corner,el.firstChild);
+   },
+
+   _roundBottomCorners: function(el, color, bgColor) {
+      var corner = this._createCorner(bgColor);
+      for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- )
+         corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
+      el.style.paddingBottom = 0;
+      el.appendChild(corner);
+   },
+
+   _createCorner: function(bgColor) {
+      var corner = document.createElement("div");
+      corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
+      return corner;
+   },
+
+   _createCornerSlice: function(color,bgColor, n, position) {
+      var slice = document.createElement("span");
+
+      var inStyle = slice.style;
+      inStyle.backgroundColor = color;
+      inStyle.display  = "block";
+      inStyle.height   = "1px";
+      inStyle.overflow = "hidden";
+      inStyle.fontSize = "1px";
+
+      var borderColor = this._borderColor(color,bgColor);
+      if ( this.options.border && n == 0 ) {
+         inStyle.borderTopStyle    = "solid";
+         inStyle.borderTopWidth    = "1px";
+         inStyle.borderLeftWidth   = "0px";
+         inStyle.borderRightWidth  = "0px";
+         inStyle.borderBottomWidth = "0px";
+         inStyle.height            = "0px"; // assumes css compliant box model
+         inStyle.borderColor       = borderColor;
+      }
+      else if(borderColor) {
+         inStyle.borderColor = borderColor;
+         inStyle.borderStyle = "solid";
+         inStyle.borderWidth = "0px 1px";
+      }
+
+      if ( !this.options.compact && (n == (this.options.numSlices-1)) )
+         inStyle.height = "2px";
+
+      this._setMargin(slice, n, position);
+      this._setBorder(slice, n, position);
+
+      return slice;
+   },
+
+   _setOptions: function(options) {
+      this.options = {
+         corners : "all",
+         color   : "fromElement",
+         bgColor : "fromParent",
+         blend   : true,
+         border  : false,
+         compact : false
+      }.extend(options || {});
+
+      this.options.numSlices = this.options.compact ? 2 : 4;
+      if ( this._isTransparent() )
+         this.options.blend = false;
+   },
+
+   _whichSideTop: function() {
+      if ( this._hasString(this.options.corners, "all", "top") )
+         return "";
+
+      if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 )
+         return "";
+
+      if (this.options.corners.indexOf("tl") >= 0)
+         return "left";
+      else if (this.options.corners.indexOf("tr") >= 0)
+          return "right";
+      return "";
+   },
+
+   _whichSideBottom: function() {
+      if ( this._hasString(this.options.corners, "all", "bottom") )
+         return "";
+
+      if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 )
+         return "";
+
+      if(this.options.corners.indexOf("bl") >=0)
+         return "left";
+      else if(this.options.corners.indexOf("br")>=0)
+         return "right";
+      return "";
+   },
+
+   _borderColor : function(color,bgColor) {
+      if ( color == "transparent" )
+         return bgColor;
+      else if ( this.options.border )
+         return this.options.border;
+      else if ( this.options.blend )
+         return this._blend( bgColor, color );
+      else
+         return "";
+   },
+
+
+   _setMargin: function(el, n, corners) {
+      var marginSize = this._marginSize(n);
+      var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+      if ( whichSide == "left" ) {
+         el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
+      }
+      else if ( whichSide == "right" ) {
+         el.style.marginRight = marginSize + "px"; el.style.marginLeft  = "0px";
+      }
+      else {
+         el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
+      }
+   },
+
+   _setBorder: function(el,n,corners) {
+      var borderSize = this._borderSize(n);
+      var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+      if ( whichSide == "left" ) {
+         el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
+      }
+      else if ( whichSide == "right" ) {
+         el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth  = "0px";
+      }
+      else {
+         el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
+      }
+   },
+
+   _marginSize: function(n) {
+      if ( this._isTransparent() )
+         return 0;
+
+      var marginSizes          = [ 5, 3, 2, 1 ];
+      var blendedMarginSizes   = [ 3, 2, 1, 0 ];
+      var compactMarginSizes   = [ 2, 1 ];
+      var smBlendedMarginSizes = [ 1, 0 ];
+
+      if ( this.options.compact && this.options.blend )
+         return smBlendedMarginSizes[n];
+      else if ( this.options.compact )
+         return compactMarginSizes[n];
+      else if ( this.options.blend )
+         return blendedMarginSizes[n];
+      else
+         return marginSizes[n];
+   },
+
+   _borderSize: function(n) {
+      var transparentBorderSizes = [ 5, 3, 2, 1 ];
+      var blendedBorderSizes     = [ 2, 1, 1, 1 ];
+      var compactBorderSizes     = [ 1, 0 ];
+      var actualBorderSizes      = [ 0, 2, 0, 0 ];
+
+      if ( this.options.compact && (this.options.blend || this._isTransparent()) )
+         return 1;
+      else if ( this.options.compact )
+         return compactBorderSizes[n];
+      else if ( this.options.blend )
+         return blendedBorderSizes[n];
+      else if ( this.options.border )
+         return actualBorderSizes[n];
+      else if ( this._isTransparent() )
+         return transparentBorderSizes[n];
+      return 0;
+   },
+
+   _hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) return true; return false; },
+   _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; },
+   _background: function(el) { try { return Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
+   _isTransparent: function() { return this.options.color == "transparent"; },
+   _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
+   _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
+   _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
+}
+
+
+//-------------------- ricoDragAndDrop.js
+Rico.DragAndDrop = Class.create();
+
+Rico.DragAndDrop.prototype = {
+
+   initialize: function() {
+      this.dropZones                = new Array();
+      this.draggables               = new Array();
+      this.currentDragObjects       = new Array();
+      this.dragElement              = null;
+      this.lastSelectedDraggable    = null;
+      this.currentDragObjectVisible = false;
+      this.interestedInMotionEvents = false;
+   },
+
+   registerDropZone: function(aDropZone) {
+      this.dropZones[ this.dropZones.length ] = aDropZone;
+   },
+
+   deregisterDropZone: function(aDropZone) {
+      var newDropZones = new Array();
+      var j = 0;
+      for ( var i = 0 ; i < this.dropZones.length ; i++ ) {
+         if ( this.dropZones[i] != aDropZone )
+            newDropZones[j++] = this.dropZones[i];
+      }
+
+      this.dropZones = newDropZones;
+   },
+
+   clearDropZones: function() {
+      this.dropZones = new Array();
+   },
+
+   registerDraggable: function( aDraggable ) {
+      this.draggables[ this.draggables.length ] = aDraggable;
+      this._addMouseDownHandler( aDraggable );
+   },
+
+   clearSelection: function() {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].deselect();
+      this.currentDragObjects = new Array();
+      this.lastSelectedDraggable = null;
+   },
+
+   hasSelection: function() {
+      return this.currentDragObjects.length > 0;
+   },
+
+   setStartDragFromElement: function( e, mouseDownElement ) {
+      this.origPos = RicoUtil.toDocumentPosition(mouseDownElement);
+      this.startx = e.screenX - this.origPos.x
+      this.starty = e.screenY - this.origPos.y
+      //this.startComponentX = e.layerX ? e.layerX : e.offsetX;
+      //this.startComponentY = e.layerY ? e.layerY : e.offsetY;
+      //this.adjustedForDraggableSize = false;
+
+      this.interestedInMotionEvents = this.hasSelection();
+      this._terminateEvent(e);
+   },
+
+   updateSelection: function( draggable, extendSelection ) {
+      if ( ! extendSelection )
+         this.clearSelection();
+
+      if ( draggable.isSelected() ) {
+         this.currentDragObjects.removeItem(draggable);
+         draggable.deselect();
+         if ( draggable == this.lastSelectedDraggable )
+            this.lastSelectedDraggable = null;
+      }
+      else {
+         this.currentDragObjects[ this.currentDragObjects.length ] = draggable;
+         draggable.select();
+         this.lastSelectedDraggable = draggable;
+      }
+   },
+
+   _mouseDownHandler: function(e) {
+      if ( arguments.length == 0 )
+         e = event;
+
+      // if not button 1 ignore it...
+      var nsEvent = e.which != undefined;
+      if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
+         return;
+
+      var eventTarget      = e.target ? e.target : e.srcElement;
+      var draggableObject  = eventTarget.draggable;
+
+      var candidate = eventTarget;
+      while (draggableObject == null && candidate.parentNode) {
+         candidate = candidate.parentNode;
+         draggableObject = candidate.draggable;
+      }
+   
+      if ( draggableObject == null )
+         return;
+
+      this.updateSelection( draggableObject, e.ctrlKey );
+
+      // clear the drop zones postion cache...
+      if ( this.hasSelection() )
+         for ( var i = 0 ; i < this.dropZones.length ; i++ )
+            this.dropZones[i].clearPositionCache();
+
+      this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() );
+   },
+
+
+   _mouseMoveHandler: function(e) {
+      var nsEvent = e.which != undefined;
+      if ( !this.interestedInMotionEvents ) {
+         this._terminateEvent(e);
+         return;
+      }
+
+      if ( ! this.hasSelection() )
+         return;
+
+      if ( ! this.currentDragObjectVisible )
+         this._startDrag(e);
+
+      if ( !this.activatedDropZones )
+         this._activateRegisteredDropZones();
+
+      //if ( !this.adjustedForDraggableSize )
+      //   this._adjustForDraggableSize(e);
+
+      this._updateDraggableLocation(e);
+      this._updateDropZonesHover(e);
+
+      this._terminateEvent(e);
+   },
+
+   _makeDraggableObjectVisible: function(e)
+   {
+      if ( !this.hasSelection() )
+         return;
+
+      var dragElement;
+      if ( this.currentDragObjects.length > 1 )
+         dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects);
+      else
+         dragElement = this.currentDragObjects[0].getSingleObjectDragGUI();
+
+      // go ahead and absolute position it...
+      if ( RicoUtil.getElementsComputedStyle(dragElement, "position")  != "absolute" )
+         dragElement.style.position = "absolute";
+
+      // need to parent him into the document...
+      if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 )
+         document.body.appendChild(dragElement);
+
+      this.dragElement = dragElement;
+      this._updateDraggableLocation(e);
+
+      this.currentDragObjectVisible = true;
+   },
+
+   /**
+   _adjustForDraggableSize: function(e) {
+      var dragElementWidth  = this.dragElement.offsetWidth;
+      var dragElementHeight = this.dragElement.offsetHeight;
+      if ( this.startComponentX > dragElementWidth )
+         this.startx -= this.startComponentX - dragElementWidth + 2;
+      if ( e.offsetY ) {
+         if ( this.startComponentY > dragElementHeight )
+            this.starty -= this.startComponentY - dragElementHeight + 2;
+      }
+      this.adjustedForDraggableSize = true;
+   },
+   **/
+
+   _updateDraggableLocation: function(e) {
+      var dragObjectStyle = this.dragElement.style;
+      dragObjectStyle.left = (e.screenX - this.startx) + "px"
+      dragObjectStyle.top  = (e.screenY - this.starty) + "px";
+   },
+
+   _updateDropZonesHover: function(e) {
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ ) {
+         if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) )
+            this.dropZones[i].hideHover();
+      }
+
+      for ( var i = 0 ; i < n ; i++ ) {
+         if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
+            if ( this.dropZones[i].canAccept(this.currentDragObjects) )
+               this.dropZones[i].showHover();
+         }
+      }
+   },
+
+   _startDrag: function(e) {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].startDrag();
+
+      this._makeDraggableObjectVisible(e);
+   },
+
+   _mouseUpHandler: function(e) {
+      if ( ! this.hasSelection() )
+         return;
+
+      var nsEvent = e.which != undefined;
+      if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
+         return;
+
+      this.interestedInMotionEvents = false;
+
+      if ( this.dragElement == null ) {
+         this._terminateEvent(e);
+         return;
+      }
+
+      if ( this._placeDraggableInDropZone(e) )
+         this._completeDropOperation(e);
+      else {
+         this._terminateEvent(e);
+         new Effect.Position( this.dragElement,
+                              this.origPos.x,
+                              this.origPos.y,
+                              200,
+                              20,
+                              { complete : this._doCancelDragProcessing.bind(this) } );
+      }
+   },
+
+   _completeDropOperation: function(e) {
+      if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
+         if ( this.dragElement.parentNode != null )
+            this.dragElement.parentNode.removeChild(this.dragElement);
+      }
+
+      this._deactivateRegisteredDropZones();
+      this._endDrag();
+      this.clearSelection();
+      this.dragElement = null;
+      this.currentDragObjectVisible = false;
+      this._terminateEvent(e);
+   },
+
+   _doCancelDragProcessing: function() {
+      this._cancelDrag();
+
+      if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
+         if ( this.dragElement.parentNode != null ) {
+            this.dragElement.parentNode.removeChild(this.dragElement);
+         }
+      }
+
+      this._deactivateRegisteredDropZones();
+      this.dragElement = null;
+      this.currentDragObjectVisible = false;
+   },
+
+   _placeDraggableInDropZone: function(e) {
+      var foundDropZone = false;
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ ) {
+         if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
+            if ( this.dropZones[i].canAccept(this.currentDragObjects) ) {
+               this.dropZones[i].hideHover();
+               this.dropZones[i].accept(this.currentDragObjects);
+               foundDropZone = true;
+               break;
+            }
+         }
+      }
+
+      return foundDropZone;
+   },
+
+   _cancelDrag: function() {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].cancelDrag();
+   },
+
+   _endDrag: function() {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].endDrag();
+   },
+
+   _mousePointInDropZone: function( e, dropZone ) {
+
+      var absoluteRect = dropZone.getAbsoluteRect();
+
+      return e.clientX  > absoluteRect.left  &&
+             e.clientX  < absoluteRect.right &&
+             e.clientY  > absoluteRect.top   &&
+             e.clientY  < absoluteRect.bottom;
+   },
+
+   _addMouseDownHandler: function( aDraggable )
+   {
+      var htmlElement = aDraggable.getMouseDownHTMLElement();
+      if ( htmlElement != null ) {
+         htmlElement.draggable = aDraggable;
+         this._addMouseDownEvent( htmlElement );
+      }
+   },
+
+   _activateRegisteredDropZones: function() {
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ ) {
+         var dropZone = this.dropZones[i];
+         if ( dropZone.canAccept(this.currentDragObjects) )
+            dropZone.activate();
+      }
+
+      this.activatedDropZones = true;
+   },
+
+   _deactivateRegisteredDropZones: function() {
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ )
+         this.dropZones[i].deactivate();
+      this.activatedDropZones = false;
+   },
+
+   _addMouseDownEvent: function( htmlElement ) {
+      if ( typeof document.implementation != "undefined" &&
+         document.implementation.hasFeature("HTML",   "1.0") &&
+         document.implementation.hasFeature("Events", "2.0") &&
+         document.implementation.hasFeature("CSS",    "2.0") ) {
+         htmlElement.addEventListener("mousedown", this._mouseDownHandler.bindAsEventListener(this), false);
+      }
+      else {
+         htmlElement.attachEvent( "onmousedown", this._mouseDownHandler.bindAsEventListener(this) );
+      }
+   },
+
+   _terminateEvent: function(e) {
+      if ( e.stopPropagation != undefined )
+         e.stopPropagation();
+      else if ( e.cancelBubble != undefined )
+         e.cancelBubble = true;
+
+      if ( e.preventDefault != undefined )
+         e.preventDefault();
+      else
+         e.returnValue = false;
+   },
+
+   initializeEventHandlers: function() {
+      if ( typeof document.implementation != "undefined" &&
+         document.implementation.hasFeature("HTML",   "1.0") &&
+         document.implementation.hasFeature("Events", "2.0") &&
+         document.implementation.hasFeature("CSS",    "2.0") ) {
+         document.addEventListener("mouseup",   this._mouseUpHandler.bindAsEventListener(this),  false);
+         document.addEventListener("mousemove", this._mouseMoveHandler.bindAsEventListener(this), false);
+      }
+      else {
+         document.attachEvent( "onmouseup",   this._mouseUpHandler.bindAsEventListener(this) );
+         document.attachEvent( "onmousemove", this._mouseMoveHandler.bindAsEventListener(this) );
+      }
+   }
+}
+
+var dndMgr = new Rico.DragAndDrop();
+dndMgr.initializeEventHandlers();
+
+
+//-------------------- ricoDraggable.js
+Rico.Draggable = Class.create();
+
+Rico.Draggable.prototype = {
+
+   initialize: function( type, htmlElement ) {
+      this.type          = type;
+      this.htmlElement   = $(htmlElement);
+      this.selected      = false;
+   },
+
+   /**
+    *   Returns the HTML element that should have a mouse down event
+    *   added to it in order to initiate a drag operation
+    *
+    **/
+   getMouseDownHTMLElement: function() {
+      return this.htmlElement;
+   },
+
+   select: function() {
+      this.selected = true;
+
+      if ( this.showingSelected )
+         return;
+
+      var htmlElement = this.getMouseDownHTMLElement();
+
+      var color = Rico.Color.createColorFromBackground(htmlElement);
+      color.isBright() ? color.darken(0.033) : color.brighten(0.033);
+
+      this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
+      htmlElement.style.backgroundColor = color.asHex();
+      this.showingSelected = true;
+   },
+
+   deselect: function() {
+      this.selected = false;
+      if ( !this.showingSelected )
+         return;
+
+      var htmlElement = this.getMouseDownHTMLElement();
+
+      htmlElement.style.backgroundColor = this.saveBackground;
+      this.showingSelected = false;
+   },
+
+   isSelected: function() {
+      return this.selected;
+   },
+
+   startDrag: function() {
+   },
+
+   cancelDrag: function() {
+   },
+
+   endDrag: function() {
+   },
+
+   getSingleObjectDragGUI: function() {
+      return this.htmlElement;
+   },
+
+   getMultiObjectDragGUI: function( draggables ) {
+      return this.htmlElement;
+   },
+
+   getDroppedGUI: function() {
+      return this.htmlElement;
+   },
+
+   toString: function() {
+      return this.type + ":" + this.htmlElement + ":";
+   }
+
+}
+
+
+//-------------------- ricoDropzone.js
+Rico.Dropzone = Class.create();
+
+Rico.Dropzone.prototype = {
+
+   initialize: function( htmlElement ) {
+      this.htmlElement  = $(htmlElement);
+      this.absoluteRect = null;
+   },
+
+   getHTMLElement: function() {
+      return this.htmlElement;
+   },
+
+   clearPositionCache: function() {
+      this.absoluteRect = null;
+   },
+
+   getAbsoluteRect: function() {
+      if ( this.absoluteRect == null ) {
+         var htmlElement = this.getHTMLElement();
+         var pos = RicoUtil.toViewportPosition(htmlElement);
+
+         this.absoluteRect = {
+            top:    pos.y,
+            left:   pos.x,
+            bottom: pos.y + htmlElement.offsetHeight,
+            right:  pos.x + htmlElement.offsetWidth
+         };
+      }
+      return this.absoluteRect;
+   },
+
+   activate: function() {
+      var htmlElement = this.getHTMLElement();
+      if (htmlElement == null  || this.showingActive)
+         return;
+
+      this.showingActive = true;
+      this.saveBackgroundColor = htmlElement.style.backgroundColor;
+
+      var fallbackColor = "#ffea84";
+      var currentColor = Rico.Color.createColorFromBackground(htmlElement);
+      if ( currentColor == null )
+         htmlElement.style.backgroundColor = fallbackColor;
+      else {
+         currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
+         htmlElement.style.backgroundColor = currentColor.asHex();
+      }
+   },
+
+   deactivate: function() {
+      var htmlElement = this.getHTMLElement();
+      if (htmlElement == null || !this.showingActive)
+         return;
+
+      htmlElement.style.backgroundColor = this.saveBackgroundColor;
+      this.showingActive = false;
+      this.saveBackgroundColor = null;
+   },
+
+   showHover: function() {
+      var htmlElement = this.getHTMLElement();
+      if ( htmlElement == null || this.showingHover )
+         return;
+
+      this.saveBorderWidth = htmlElement.style.borderWidth;
+      this.saveBorderStyle = htmlElement.style.borderStyle;
+      this.saveBorderColor = htmlElement.style.borderColor;
+
+      this.showingHover = true;
+      htmlElement.style.borderWidth = "1px";
+      htmlElement.style.borderStyle = "solid";
+      //htmlElement.style.borderColor = "#ff9900";
+      htmlElement.style.borderColor = "#ffff00";
+   },
+
+   hideHover: function() {
+      var htmlElement = this.getHTMLElement();
+      if ( htmlElement == null || !this.showingHover )
+         return;
+
+      htmlElement.style.borderWidth = this.saveBorderWidth;
+      htmlElement.style.borderStyle = this.saveBorderStyle;
+      htmlElement.style.borderColor = this.saveBorderColor;
+      this.showingHover = false;
+   },
+
+   canAccept: function(draggableObjects) {
+      return true;
+   },
+
+   accept: function(draggableObjects) {
+      var htmlElement = this.getHTMLElement();
+      if ( htmlElement == null )
+         return;
+
+      n = draggableObjects.length;
+      for ( var i = 0 ; i < n ; i++ )
+      {
+         var theGUI = draggableObjects[i].getDroppedGUI();
+         if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
+         {
+            theGUI.style.position = "static";
+            theGUI.style.top = "";
+            theGUI.style.top = "";
+         }
+         htmlElement.appendChild(theGUI);
+      }
+   }
+}
+
+
+//-------------------- ricoEffects.js
+
+/**
+  *  Use the Effect namespace for effects.  If using scriptaculous effects
+  *  this will already be defined, otherwise we'll just create an empty
+  *  object for it...
+ **/
+if ( window.Effect == undefined )
+   Effect = {};
+
+Effect.SizeAndPosition = Class.create();
+Effect.SizeAndPosition.prototype = {
+
+   initialize: function(element, x, y, w, h, duration, steps, options) {
+      this.element = $(element);
+      this.x = x;
+      this.y = y;
+      this.w = w;
+      this.h = h;
+      this.duration = duration;
+      this.steps    = steps;
+      this.options  = arguments[7] || {};
+
+      this.sizeAndPosition();
+   },
+
+   sizeAndPosition: function() {
+      if (this.isFinished()) {
+         if(this.options.complete) this.options.complete(this);
+         return;
+      }
+
+      if (this.timer)
+         clearTimeout(this.timer);
+
+      var stepDuration = Math.round(this.duration/this.steps) ;
+
+      // Get original values: x,y = top left corner;  w,h = width height
+      var currentX = this.element.offsetLeft;
+      var currentY = this.element.offsetTop;
+      var currentW = this.element.offsetWidth;
+      var currentH = this.element.offsetHeight;
+
+      // If values not set, or zero, we do not modify them, and take original as final as well
+      this.x = (this.x) ? this.x : currentX;
+      this.y = (this.y) ? this.y : currentY;
+      this.w = (this.w) ? this.w : currentW;
+      this.h = (this.h) ? this.h : currentH;
+
+      // how much do we need to modify our values for each step?
+      var difX = this.steps >  0 ? (this.x - currentX)/this.steps : 0;
+      var difY = this.steps >  0 ? (this.y - currentY)/this.steps : 0;
+      var difW = this.steps >  0 ? (this.w - currentW)/this.steps : 0;
+      var difH = this.steps >  0 ? (this.h - currentH)/this.steps : 0;
+
+      this.moveBy(difX, difY);
+      this.resizeBy(difW, difH);
+
+      this.duration -= stepDuration;
+      this.steps--;
+
+      this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
+   },
+
+   isFinished: function() {
+      return this.steps <= 0;
+   },
+
+   moveBy: function( difX, difY ) {
+      var currentLeft = this.element.offsetLeft;
+      var currentTop  = this.element.offsetTop;
+      var intDifX     = parseInt(difX);
+      var intDifY     = parseInt(difY);
+
+      var style = this.element.style;
+      if ( intDifX != 0 )
+         style.left = (currentLeft + intDifX) + "px";
+      if ( intDifY != 0 )
+         style.top  = (currentTop + intDifY) + "px";
+   },
+
+   resizeBy: function( difW, difH ) {
+      var currentWidth  = this.element.offsetWidth;
+      var currentHeight = this.element.offsetHeight;
+      var intDifW       = parseInt(difW);
+      var intDifH       = parseInt(difH);
+
+      var style = this.element.style;
+      if ( intDifW != 0 )
+         style.width   = (currentWidth  + intDifW) + "px";
+      if ( intDifH != 0 )
+         style.height  = (currentHeight + intDifH) + "px";
+   }