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

Ludovic Dubost ludovic at xwiki.com
Tue Mar 28 13:47:54 CEST 2006


Hi,

Oops I also commited ajax, rico and scriptaculous. This will probably 
not work.
The main problem with putting it in /xwiki/ is that this will create 
some absolute links again.
Or we need an API to access these resources.

Maybe:

$xwiki.getJSFile("scriptaculous", "file.js") -> 
/xwiki/js/scriptaculous/file.js

Ludovic

jeremi joslin a écrit :
> Hi,
> Don't you think we can put scriptaculous and prototype.js as a
> resource, and not as a skin because some applications can depend on
> it.
>
> This library can be useful when you create an application.
>
>
> Jérémi
>
> On 3/28/06, Ludovic Dubost <ludovic at users.forge.objectweb.org> wrote:
>   
>> 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) {
&