Index: /trunk/phpgwapi/inc/class.common.inc.php
===================================================================
--- /trunk/phpgwapi/inc/class.common.inc.php	(revision 2009)
+++ /trunk/phpgwapi/inc/class.common.inc.php	(revision 2011)
@@ -1221,6 +1221,11 @@
 			} 
 
-			echo "<script type='text/javascript' src='".$GLOBALS['phpgw_info']['server']['webserver_url']."/phpgwapi/expressoAjax/expressoAjax.js'></script>";
-
+//			echo "<script type='text/javascript' src='".$GLOBALS['phpgw_info']['server']['webserver_url']."/phpgwapi/js/expressoAjax/expressoAjax.js'></script>";
+			if(!@is_object($GLOBALS['phpgw']->js))
+			{
+				$GLOBALS['phpgw']->js = CreateObject('phpgwapi.javascript');
+			}
+			$GLOBALS['phpgw']->js->validate_file('expressoAjax','expressoAjax');
+			echo $GLOBALS['phpgw']->js->get_script_links();
 		}
 
Index: /trunk/phpgwapi/js/expressoAjax/xtools.js
===================================================================
--- /trunk/phpgwapi/js/expressoAjax/xtools.js	(revision 1999)
+++ /trunk/phpgwapi/js/expressoAjax/xtools.js	(revision 1999)
@@ -0,0 +1,155 @@
+(function()
+{
+	var _FILES = [];
+
+	function _convert(pString)
+	{
+		if ( typeof pString != 'string' )
+			return false;
+
+		if ( window.ActiveXObject )
+		{
+			var _xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+			_xmlDoc.async = "false";
+			_xmlDoc.loadXML(pString);
+		}
+		else
+		{
+			var parser = new DOMParser();
+			var _xmlDoc = parser.parseFromString( pString, "text/xml" );
+		}
+
+		return _xmlDoc;
+	}
+
+	function _load(pFile)
+	{
+		pFile = this._PATH + 'xsl/' + pFile;
+		if ( !(_FILES[pFile]) )
+		{
+			var _data = null;
+			if ( document.implementation.createDocument )
+				_data = document.implementation.createDocument("", "", null);
+			else
+				_data = new ActiveXObject( "Msxml2.FreeThreadedDOMDocument" );
+
+			_data.async = false;
+			_data.load(pFile + '?' + Date.parse(new Date));
+			_FILES[pFile] = _data;
+		}
+		return _FILES[pFile];
+	}
+
+	function _parse()
+	{
+		if ( arguments.length == 1 )
+		{
+			pXML = _xml('root');
+			pXSL = arguments[0];
+		}
+		else
+		{
+			pXML = arguments[0];
+			pXSL = arguments[1];
+		}
+		
+		switch ( typeof pXML )
+		{
+			case 'object' :
+			break;
+			case 'string' :
+				if ( pXML.indexOf('<') == 0 )
+					pXML = _convert(pXML);
+				else
+					pXML = _load.call(this, pXML);
+			break;
+			default :
+				return { 'error' : 'invalid xml' } 
+		}
+		
+		switch ( typeof pXSL )
+		{
+			case 'object' :
+			break;
+			case 'string' :
+				pXSL = _load.call(this, pXSL);
+			break;
+			default :
+				return {'error':'invalid xsl'}
+		}
+
+		var fragment = null;
+		
+		if ( window.XSLTProcessor )
+		{
+			var xslProc = new XSLTProcessor();
+			xslProc.importStylesheet(pXSL);
+
+			if ( (arguments.length == 3) && (typeof arguments[2] == 'object') )
+			{
+				var params = arguments[2];
+				for (var i in params )
+					 xslProc.setParameter(null, i, params[i]);
+			}
+
+			fragment = xslProc.transformToFragment(pXML, document);
+
+			// para retornar valor igual ao ie.
+			var aux = document.createElement("div");
+			aux.appendChild(fragment);
+			fragment = aux.innerHTML;
+		}
+		else
+		{
+			var xslTemplate = new ActiveXObject("MSXML2.XSLTemplate");
+			xslTemplate.stylesheet = pXSL;
+
+			var xslProc = xslTemplate.createProcessor();
+			xslProc.input = pXML;
+
+			if ( (arguments.length == 3) && (typeof arguments[2] == 'object') )
+			{
+				var params = arguments[2];
+				for (var i in params )
+					 xslProc.addParameter(i, params[i], '');
+			}
+
+			xslProc.transform();
+			fragment = xslProc.output;
+		}
+		return fragment;
+	}
+
+	function _xml()
+	{
+		var a = false;
+		if ( document.implementation.createDocument )
+			a = document.implementation.createDocument("", "", null);
+		else if ( ActiveXObject )
+			a = new ActiveXObject("Msxml2.DOMDocument");
+
+		if ( arguments.length == 1 && typeof arguments[0] == 'string' )
+			a.appendChild(a.createElement(arguments[0]));
+		//with ( a )
+		//	appendChild(createProcessingInstruction("xml", "version='1.0'"));
+
+		return a;
+	}
+
+	function xtools()
+	{
+		var _argv = arguments;
+		this._PATH = ( _argv.length > 0 ) ? _argv[0] : '';
+
+		if ( this._PATH != '' && this._PATH.lastIndexOf('/') != (this._PATH.length - 1) )
+			this._PATH += '/';
+	}
+
+	xtools.prototype.convert	= _convert;
+	xtools.prototype.load		= _load;
+	xtools.prototype.parse		= _parse;
+	xtools.prototype.xml		= _xml;
+	
+	window.JITXtools = xtools;
+}
+)();
Index: /trunk/phpgwapi/js/expressoAjax/coder.js
===================================================================
--- /trunk/phpgwapi/js/expressoAjax/coder.js	(revision 1999)
+++ /trunk/phpgwapi/js/expressoAjax/coder.js	(revision 1999)
@@ -0,0 +1,300 @@
+
+// Constructor
+function coder(){
+
+}
+
+coder.prototype.url_encode = function (str){
+	var hex_chars = "0123456789ABCDEF";
+	var noEncode = /^([a-zA-Z0-9\_\-\.])$/;
+	var n, strCode, hex1, hex2, strEncode = "";
+
+	for(n = 0; n < str.length; n++) {
+		if (noEncode.test(str.charAt(n))) {
+			strEncode += str.charAt(n);
+		} else {
+			strCode = str.charCodeAt(n);
+			hex1 = hex_chars.charAt(Math.floor(strCode / 16));
+			hex2 = hex_chars.charAt(strCode % 16);
+			strEncode += "%" + (hex1 + hex2);
+		}
+	}
+	return strEncode;
+}
+
+coder.prototype.url_decode = function (str) {
+
+	var n, strCode, strDecode = "";
+	for (n = 0; n < str.length; n++) {
+		if (str.charAt(n) == "%") {
+			strCode = str.charAt(n + 1) + str.charAt(n + 2);
+			strDecode += String.fromCharCode(parseInt(strCode, 16));
+			n += 2;
+		} else {
+			strDecode += str.charAt(n);
+		}
+	}
+	return strDecode;
+}
+
+
+/*
+ * base64.js - Base64 encoding and decoding functions
+ *
+ * Copyright (c) 2007, David Lindquist <david.lindquist@gmail.com>
+ * Released under the MIT license
+ */
+
+coder.prototype.base64_encode = function (str){
+	var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+	var encoded = [];
+	var c = 0;
+	while (c < str.length) {
+		var b0 = str.charCodeAt(c++);
+		var b1 = str.charCodeAt(c++);
+		var b2 = str.charCodeAt(c++);
+		var buf = (b0 << 16) + ((b1 || 0) << 8) + (b2 || 0);
+		var i0 = (buf & (63 << 18)) >> 18;
+		var i1 = (buf & (63 << 12)) >> 12;
+		var i2 = isNaN(b1) ? 64 : (buf & (63 << 6)) >> 6;
+		var i3 = isNaN(b2) ? 64 : (buf & 63);
+		encoded[encoded.length] = chars.charAt(i0);
+		encoded[encoded.length] = chars.charAt(i1);
+		encoded[encoded.length] = chars.charAt(i2);
+		encoded[encoded.length] = chars.charAt(i3);
+	}
+	return encoded.join('');
+}
+
+coder.prototype.base64_decode = function (str) {
+	var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+	var invalid = {
+strlen: (str.length % 4 != 0),
+	chars:  new RegExp('[^' + chars + ']').test(str),
+	equals: (/=/.test(str) && (/=[^=]/.test(str) || /={3}/.test(str)))
+	};
+	if (invalid.strlen || invalid.chars || invalid.equals)
+		throw new Error('Invalid base64 data');
+	var decoded = [];
+	var c = 0;
+	while (c < str.length) {
+		var i0 = chars.indexOf(str.charAt(c++));
+		var i1 = chars.indexOf(str.charAt(c++));
+		var i2 = chars.indexOf(str.charAt(c++));
+		var i3 = chars.indexOf(str.charAt(c++));
+		var buf = (i0 << 18) + (i1 << 12) + ((i2 & 63) << 6) + (i3 & 63);
+		var b0 = (buf & (255 << 16)) >> 16;
+		var b1 = (i2 == 64) ? -1 : (buf & (255 << 8)) >> 8;
+		var b2 = (i3 == 64) ? -1 : (buf & 255);
+		decoded[decoded.length] = String.fromCharCode(b0);
+		if (b1 >= 0) decoded[decoded.length] = String.fromCharCode(b1);
+		if (b2 >= 0) decoded[decoded.length] = String.fromCharCode(b2);
+	}
+	return decoded.join('');
+}
+
+
+/**
+ * @author MD5 (Message-Digest Algorithm)
+ * *  http://www.webtoolkit.info/
+ *
+ */
+coder.prototype.md5_encode = function (string) {
+
+	function RotateLeft(lValue, iShiftBits) {
+		return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
+	}
+
+	function AddUnsigned(lX,lY) {
+		var lX4,lY4,lX8,lY8,lResult;
+		lX8 = (lX & 0x80000000);
+		lY8 = (lY & 0x80000000);
+		lX4 = (lX & 0x40000000);
+		lY4 = (lY & 0x40000000);
+		lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
+		if (lX4 & lY4) {
+			return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+		}
+		if (lX4 | lY4) {
+			if (lResult & 0x40000000) {
+				return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+			} else {
+				return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+			}
+		} else {
+			return (lResult ^ lX8 ^ lY8);
+		}
+	}
+
+	function F(x,y,z) { return (x & y) | ((~x) & z); }
+	function G(x,y,z) { return (x & z) | (y & (~z)); }
+	function H(x,y,z) { return (x ^ y ^ z); }
+	function I(x,y,z) { return (y ^ (x | (~z))); }
+
+	function FF(a,b,c,d,x,s,ac) {
+		a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+		return AddUnsigned(RotateLeft(a, s), b);
+	};
+
+	function GG(a,b,c,d,x,s,ac) {
+		a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+		return AddUnsigned(RotateLeft(a, s), b);
+	};
+
+	function HH(a,b,c,d,x,s,ac) {
+		a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+		return AddUnsigned(RotateLeft(a, s), b);
+	};
+
+	function II(a,b,c,d,x,s,ac) {
+		a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+		return AddUnsigned(RotateLeft(a, s), b);
+	};
+
+	function ConvertToWordArray(string) {
+		var lWordCount;
+		var lMessageLength = string.length;
+		var lNumberOfWords_temp1=lMessageLength + 8;
+		var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
+		var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
+		var lWordArray=Array(lNumberOfWords-1);
+		var lBytePosition = 0;
+		var lByteCount = 0;
+		while ( lByteCount < lMessageLength ) {
+			lWordCount = (lByteCount-(lByteCount % 4))/4;
+			lBytePosition = (lByteCount % 4)*8;
+			lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
+			lByteCount++;
+		}
+		lWordCount = (lByteCount-(lByteCount % 4))/4;
+		lBytePosition = (lByteCount % 4)*8;
+		lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
+		lWordArray[lNumberOfWords-2] = lMessageLength<<3;
+		lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
+		return lWordArray;
+	};
+
+	function WordToHex(lValue) {
+		var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
+		for (lCount = 0;lCount<=3;lCount++) {
+			lByte = (lValue>>>(lCount*8)) & 255;
+			WordToHexValue_temp = "0" + lByte.toString(16);
+			WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
+		}
+		return WordToHexValue;
+	};
+	function Utf8Encode(string) {
+		string = string.replace(/\r\n/g,"\n");
+		var utftext = "";
+
+		for (var n = 0; n < string.length; n++) {
+
+			var c = string.charCodeAt(n);
+
+			if (c < 128) {
+				utftext += String.fromCharCode(c);
+			}
+			else if((c > 127) && (c < 2048)) {
+				utftext += String.fromCharCode((c >> 6) | 192);
+				utftext += String.fromCharCode((c & 63) | 128);
+			}
+			else {
+				utftext += String.fromCharCode((c >> 12) | 224);
+				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+				utftext += String.fromCharCode((c & 63) | 128);
+			}
+
+		}
+
+		return utftext;
+	};
+	var x=Array();
+	var k,AA,BB,CC,DD,a,b,c,d;
+	var S11=7, S12=12, S13=17, S14=22;
+	var S21=5, S22=9 , S23=14, S24=20;
+	var S31=4, S32=11, S33=16, S34=23;
+	var S41=6, S42=10, S43=15, S44=21;
+
+	string = Utf8Encode(string);
+
+	x = ConvertToWordArray(string);
+
+	a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
+
+	for (k=0;k<x.length;k+=16) {
+		AA=a; BB=b; CC=c; DD=d;
+		a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
+		d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
+		c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
+		b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
+		a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
+		d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
+		c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
+		b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
+		a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
+		d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
+		c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
+		b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
+		a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
+		d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
+		c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
+		b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
+		a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
+		d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
+		c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
+		b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
+		a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
+		d=GG(d,a,b,c,x[k+10],S22,0x2441453);
+		c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
+		b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
+		a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
+		d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
+		c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
+		b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
+		a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
+		d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
+		c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
+		b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
+		a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
+		d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
+		c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
+		b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
+		a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
+		d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
+		c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
+		b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
+		a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
+		d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
+		c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
+		b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
+		a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
+		d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
+		c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
+		b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
+		a=II(a,b,c,d,x[k+0], S41,0xF4292244);
+		d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
+		c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
+		b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
+		a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
+		d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
+		c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
+		b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
+		a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
+		d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
+		c=II(c,d,a,b,x[k+6], S43,0xA3014314);
+		b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
+		a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
+		d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
+		c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
+		b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
+		a=AddUnsigned(a,AA);
+		b=AddUnsigned(b,BB);
+		c=AddUnsigned(c,CC);
+		d=AddUnsigned(d,DD);
+	}
+
+	var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
+
+	return temp.toLowerCase();
+}
+expresso.coder = new coder();
Index: /trunk/phpgwapi/js/expressoAjax/expressoAjax.js
===================================================================
--- /trunk/phpgwapi/js/expressoAjax/expressoAjax.js	(revision 2011)
+++ /trunk/phpgwapi/js/expressoAjax/expressoAjax.js	(revision 2011)
@@ -0,0 +1,656 @@
+var debug_controller =false;
+var files = new Array();
+var progressBar;
+var handlerExecuteForm = null;
+
+  if (document.all)
+	{
+		navigator.userAgent.toLowerCase().indexOf('msie 5') != -1 ? is_ie5 = true : is_ie5 = false;
+		is_ie = true;
+		is_moz1_6 = false;
+		is_mozilla = false;
+		is_ns4 = false;
+	}
+	else if (document.getElementById)
+	{
+		navigator.userAgent.toLowerCase().match('mozilla.*rv[:]1\.6.*gecko') ? is_moz1_6 = true : is_moz1_6 = false;
+		is_ie = false;
+		is_ie5 = false;
+		is_mozilla = true;
+		is_ns4 = false;
+	}
+	else if (document.layers)
+	{
+		is_ie = false;
+		is_ie5 = false
+		is_moz1_6 = false;
+		is_mozilla = false;
+		is_ns4 = true;
+	}
+
+/****************************************** Connector Class *************************************************/
+	// Constructor
+	function cConnector()
+	{
+		this.requests = new Array();
+		this.oxmlhttp = null;
+		this.isVisibleBar = false;
+		this.tid = 0;
+		this.progressBar = null;
+		this.oldX = 0;
+		this.oldY = 0;
+		this.updateVersion = "";
+		this.connectorCache = {
+				'valid' : [],
+				'result' : []
+		};
+		this.expurgatedCache = new Array(); // Data to purge from cache
+
+	}
+
+	cConnector.prototype.buildBar = function()
+		{
+			var div = document.getElementById('divProgressBar');
+
+			if(! div) {
+				div = document.createElement("DIV");
+				div.style.visibility	= "hidden";
+				div.style.width = "103px";
+				div.id = 'divProgressBar';
+				div.align = "center";
+				var loadingTitle = document.getElementById('txt_loading');
+				div.innerHTML = '&nbsp;&nbsp;<font face="Verdana" size="2" color="WHITE">'+loadingTitle.value+'...</font>&nbsp;';
+				div.style.background = "#cc4444";
+				div.style.position = 'fixed';
+				div.style.top = '0px';
+				div.style.right = '0px';
+				document.body.appendChild(div);
+
+				if(is_ie) {
+					var elem = document.all[div.id];
+					elem.style.position="absolute";
+					var root = document.body;
+					var posX = elem.offsetLeft-root.scrollLeft;
+					var posY = elem.offsetTop-root.scrollTop;
+					root.onscroll = function() {
+						elem.style.right = '0px';
+						elem.style.top = (posY + root.scrollTop) + "px";
+					};
+				}
+
+				if(debug_controller) {
+					div = document.createElement("DIV");
+					div.style.width	= "800px";
+					div.style.height= "400px";
+					div.id = "debug_controller";
+					div.align='right';
+					document.body.appendChild(div);
+				}
+			}
+	}
+//------------------------------------ BEGIN: Functions for Connector HTTPRequest  -------------------------------------------------//
+	// Serialize Data Method
+	cConnector.prototype.serialize = function(data)
+	{	var _thisObject = this;
+		var f = function(data)
+		{
+			var str_data;
+
+			if (data == null ||
+				(typeof(data) == 'string' && data == ''))
+			{
+				str_data = 'N;';
+			}
+
+			else switch(typeof(data))
+			{
+				case 'object':
+					var arrayCount = 0;
+
+					str_data = '';
+
+					for (i in data)
+					{
+						if (i == 'length')
+						{
+							continue;
+						}
+
+						arrayCount++;
+						switch (typeof(i))
+						{
+							case 'number':
+								str_data += 'i:' + i + ';' + f(data[i]);
+								break;
+
+							case 'string':
+								str_data += 's:' + i.length + ':"' + i + '";' + f(data[i]);
+								break;
+
+							default:
+								showMessage(Element('cc_msg_err_serialize_data_unknown').value);
+								break;
+						}
+					}
+
+					if (!arrayCount)
+					{
+						str_data = 'N;';
+					}
+					else
+					{
+						str_data = 'a:' + arrayCount + ':{' + str_data + '}';
+					}
+
+					break;
+
+				case 'string':
+					str_data = 's:' + data.length + ':"' + data + '";';
+					break;
+
+				case 'number':
+					str_data = 'i:' + data + ';';
+					break;
+
+				case 'boolean':
+					str_data = 'b:' + (data ? '1' : '0') + ';';
+					break;
+
+				default:
+					showMessage(Element('cc_msg_err_serialize_data_unknown').value);
+					return null;
+			}
+
+			return str_data;
+		}
+
+		return f(data);
+	}
+
+
+	//Unserialize Data Method
+	cConnector.prototype.unserialize = function(str)
+	{
+
+		_thisObject = this;
+		var matchB = function (str, iniPos)
+		{
+			var nOpen, nClose = iniPos;
+			do
+			{
+				nOpen = str.indexOf('{', nClose+1);
+				nClose = str.indexOf('}', nClose+1);
+
+				if (nOpen == -1)
+				{
+					return nClose;
+				}
+				if (nOpen < nClose )
+				{
+					nClose = matchB(str, nOpen);
+				}
+			} while (nOpen < nClose);
+
+			return nClose;
+		}
+
+		var f = function (str)
+		{
+			switch (str.toString().charAt(0))
+			{
+				case 'a':
+
+					var data = new Array();
+					var n = parseInt( str.substring( str.indexOf(':')+1, str.indexOf(':',2) ) );
+					var arrayContent = str.substring(str.indexOf('{')+1, str.lastIndexOf('}'));
+
+					for (var i = 0; i < n; i++)
+					{
+						var pos = 0;
+
+						/* Process Index */
+						var indexStr = arrayContent.substr(pos, arrayContent.indexOf(';')+1);
+						var index = f(indexStr);
+						pos = arrayContent.indexOf(';', pos)+1;
+
+						/* Process Content */
+						var part = null;
+						switch (arrayContent.charAt(pos))
+						{
+							case 'a':
+								var pos_ = matchB(arrayContent, arrayContent.indexOf('{', pos))+1;
+								part = arrayContent.substring(pos, pos_);
+								pos = pos_;
+								data[index] = f(part);
+								break;
+
+							case 's':
+								var pval = arrayContent.indexOf(':', pos+2);
+								var val  = parseInt(arrayContent.substring(pos+2, pval));
+								pos = pval + val + 4;
+								data[index] = arrayContent.substr(pval+2, val);
+								break;
+
+							default:
+								part = arrayContent.substring(pos, arrayContent.indexOf(';', pos)+1);
+								pos = arrayContent.indexOf(';', pos)+1;
+								data[index] = f(part);
+								break;
+						}
+						arrayContent = arrayContent.substr(pos);
+					}
+					break;
+
+				case 's':
+					var pos = str.indexOf(':', 2);
+					var val = parseInt(str.substring(2,pos));
+					var data = str.substr(pos+2, val);
+					str = str.substr(pos + 4 + val);
+					break;
+
+				case 'i':
+				case 'd':
+					var pos = str.indexOf(';');
+					var data = parseInt(str.substring(2,pos));
+					str = str.substr(pos + 1);
+					break;
+
+				case 'N':
+					var data = null;
+					str = str.substr(str.indexOf(';') + 1);
+					break;
+
+				case 'b':
+					var data = str.charAt(2) == '1' ? true : false;
+					break;
+			}
+			return data;
+		}
+
+		return f(str);
+	}
+
+	//Create XMLHTTP object Method
+	cConnector.prototype.createXMLHTTP = function ()
+	{
+		try
+		{
+			this.oxmlhttp = new XMLHttpRequest();
+			this.oxmlhttp.overrideMimeType('text/xml');
+		}
+		catch (e)
+		{
+			try
+			{
+				this.oxmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
+			}
+			catch (e1)
+			{
+				try
+				{
+					this.oxmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
+				}
+				catch (e2)
+				{
+					this.oxmlhttp = null;
+				}
+			}
+		}
+
+	}
+
+	// Request Constructor Connector
+	cConnector.prototype.newRequest = function (id, target, method, handler, data)
+	{
+		var params = data;
+		this.tid = id;
+		if (this.requests[id]) {
+			return false;
+		}
+
+		this.createXMLHTTP();
+		var oxmlhttp = this.oxmlhttp;
+		var _thisObject = this;
+
+		if (! oxmlhttp)
+			return false;
+
+		this.requests[id] = oxmlhttp;
+		this.buildBar();
+		this.showProgressBar();
+
+		var sub_handler = function ()
+		{
+			var progressBar = _thisObject.progressBar;
+
+			try
+			{
+				if (oxmlhttp.readyState == 4 )
+				{
+
+					switch (oxmlhttp.status)
+					{
+
+						case 200:
+							if (typeof(handler) == 'function')
+							{
+								_thisObject.hideProgressBar();
+								var data = _thisObject.unserialize(oxmlhttp.responseText);
+								if ( typeof data == 'undefined' )
+									data = oxmlhttp.responseText;
+								if(debug_controller) {
+									document.getElementById("debug_controller").innerHTML += oxmlhttp.responseText;
+									document.getElementById("debug_controller").innerHTML += "<br>-------------------------------------------------------------------------------------<br>";
+								}
+								handler(data);
+								_thisObject.addToCache(params?id+"&"+params:id,data);
+								delete _thisObject.requests[id];
+								_thisObject.requests[id] = null;
+							}
+
+							break;
+
+						case 404:
+
+							alert(get_lang('Page Not Found!'));
+							break;
+
+						default:
+					}
+				}
+			}
+			catch (e)
+			{
+				_thisObject.hideProgressBar();
+				if(debug_controller)
+					alert(e+"\n"+oxmlhttp.responseText);
+				// View Exception in Javascript Console
+				throw(e);
+			}
+
+		}
+
+		try
+		{
+
+			if (method == '' || method == 'GET')
+			{
+				oxmlhttp.open("GET",target,true);
+				if (typeof(handler) == 'function')
+				{
+					oxmlhttp.onreadystatechange =  sub_handler;
+					oxmlhttp.send(null);
+				}
+
+			}
+			else if (method == 'POST')
+			{
+				oxmlhttp.open("POST",target, true);
+				oxmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+				if (typeof(handler) == 'function')
+				{
+					oxmlhttp.onreadystatechange = sub_handler;
+					oxmlhttp.send(data);
+				}
+
+			}
+		}
+		catch(e)
+		{
+			_thisObject.hideProgressBar();
+			if(debug_controller)
+				alert(e);
+			// View Exception in Javascript Console
+			throw(e);
+		}
+
+		return true;
+	}
+	// Cancel Request Connector
+	cConnector.prototype.cancelRequest = function (){
+		if (!this.requests[this.tid]){
+			return false;
+		}
+		this.oxmlhttp.onreadystatechange = null;
+		this.requests[this.tid].abort();
+		this.hideProgressBar();
+	}
+//------------------------------------  END: Functions for Connector HTTPRequest  -------------------------------------------------//
+
+//	----------------------------------- BEGIN: Functions for build Bar Progress ---------------------------------------------------------//
+	cConnector.prototype.hideProgressBar = function ()
+	{
+		var div = document.getElementById('divProgressBar');
+		div.style.visibility = 'hidden';
+		this.isVisibleBar = false;
+	}
+
+	cConnector.prototype.showProgressBar = function(){
+		var div = document.getElementById('divProgressBar');
+		div.style.visibility = 'visible';
+
+		this.isVisibleBar = true;
+	}
+
+	cConnector.prototype.loadAllScripts = function(scripts) {
+		for(var i = 0; i < scripts.length; i++){
+			this.loadScript(scripts[i]);
+		}
+	}
+
+	cConnector.prototype.loadScript = function(scriptPath)	{
+      	if (document.getElementById('uploadscript_'+scriptPath)) {
+      		return;
+      	}
+		var head = document.getElementsByTagName("head")[0];
+		var script = document.createElement("SCRIPT");
+		script.id = 'uploadscript_'+scriptPath;
+		script.type = 'text/javascript';
+
+  		if(is_ie) {
+
+			this.oxmlhttp.open("GET", "js/"+scriptPath+".js?"+this.updateVersion, false);
+			this.oxmlhttp.setRequestHeader('Content-Type','text/plain');
+			this.oxmlhttp.send(null);
+			if(this.oxmlhttp.status != 0 && this.oxmlhttp.status != 200 || 	this.oxmlhttp.status == 0 && this.oxmlhttp.responseText.length == 0)
+				throw new Error("Error " + this.oxmlhttp.status + "("+this.oxmlhttp.statusText+") when loading script file '"+scriptPath+"'");
+			script.text = this.oxmlhttp.responseText;
+		}
+		else {
+			script.src =  "js/"+scriptPath+".js?"+this.updateVersion;
+		}
+
+		head.appendChild(script);
+		return;
+	}
+//------------------------------------  END: Functions for Progress Bar  -------------------------------------------------//
+	// Default Controller File
+	var DEFAULT_URL = 'controller.php?action=';
+	// connector object
+	var _onmouseup = document.onmouseup;
+	var isExecuteForm = false;
+	var id = null;
+
+	cConnector.prototype.queryConnectorCache = function(url,handler){
+		if (this.connectorCache.valid[url])
+		{
+			handler(this.connectorCache.result[url]);
+			return true;
+		}
+		else
+			return false;
+	}
+	cConnector.prototype.purgeCache= function(){
+		if (typeof(preferences) == "undefined" || preferences.use_cache != 'True')
+			return false;
+		var i;
+		for (i=0; i<= this.expurgatedCache.length; i++)
+		{
+			this.connectorCache.valid[this.expurgatedCache[i]] = false;
+			try {
+	   		delete this.connectorCache.result[this.expurgatedCache[i]];
+			}
+			catch (e) { };
+		}
+	}
+	cConnector.prototype.addToCache = function(id,data){
+		if (typeof(preferences) == "undefined" || preferences.use_cache != 'True')
+			return false;
+		var func = id.substr(id.lastIndexOf('.')+1);
+		if (func.indexOf('&') > 0)
+			func = func.substr(0,func.indexOf('&'));
+		switch (func){
+			// functions that enters in cache
+                        case 'get_info_msg':
+				data.cacheHit = true;
+			case 'get_preferences':
+			case 'getSharedUsersFrom':
+			case 'get_organizations':
+			case 'get_catalogs':
+			case 'get_dropdown_contacts':
+			case 'get_cc_contacts':
+			case 'get_cc_groups':
+			case 'getUsersByEmail':
+				this.connectorCache.valid[id] = true;
+				this.connectorCache.result[id] = data;
+				break;
+			// function that needs expire
+			case 'get_range_msgs2':
+			case 'quicksearch':
+			case 'get_folders_list':
+			case 'search_msg':
+			case 'search_for':
+				this.connectorCache.valid[id] = true;
+                                this.connectorCache.result[id] = data;
+				var i = this.expurgatedCache.length;
+				this.expurgatedCache[i+1] = id;
+				break;
+			//functions that expires the cache
+			case 'move_messages':
+			case 'delete_msgs':
+			case 'getReturnExecuteForm':
+			case 'set_messages_flag':
+			case 'empty_trash':
+				this.purgeCache();
+			default: // no cache
+				break;
+		}
+	}
+
+	// 	Function executes AJAX
+	// 	cExecute (url, handler, params)
+	//	url: 'module.class.method'
+	//  handle: function handle() receive response.
+	//  params: parameters for POST method
+	//	form: form element (for upload files)
+	function cExecute(url, handler, params, form) {
+		if(isExecuteForm){
+			isExecuteForm = false;
+			document.onmouseup = _onmouseup;
+		}
+		if(form) {
+			cExecuteForm(url, form);
+			return;
+		}
+
+		url = DEFAULT_URL + url;
+
+		if (expresso.connector.queryConnectorCache(params?url+"&"+params:url,handler))
+			return;
+
+		if(params)
+			method = "POST";
+		else
+			method = "GET";
+
+		id = url;
+		expresso.connector.newRequest(id, url, method, handler, params);
+	}
+
+// This function executes submit values to Controller (POST)
+	// The return is void.
+	// 	cExecuteForm (url, form)
+	//	url: 'module.class.method'
+	//	form: form element (for upload files)
+	function cExecuteForm(url, form, handler,id){
+		expresso.connector.buildBar();
+		isExecuteForm = true;
+
+		document.onmouseup = alertBut;
+
+		expresso.connector.showProgressBar();
+		if(! (divUpload = document.getElementById('divUpload'))) {
+			divUpload		= document.createElement('DIV');
+			divUpload.id	= 'divUpload';
+			document.body.appendChild(divUpload);
+		}
+
+		if(! (el = document.getElementById('_action'))) {
+			el			= document.createElement('input');
+			el.type	= 'hidden';
+			el.id		= '_action';
+			el.name	= '_action';
+			form.appendChild(el);
+		}
+
+		var divFiles = Element("divFiles_"+id);
+		if (divFiles && divFiles.firstChild) {
+			el			= document.createElement('input');
+			el.type	= 'hidden';
+			el.name	= 'countFiles';
+			var countDivFiles = 0;
+			try{
+				countDivFiles = parseInt(divFiles.lastChild.firstChild.id.split('_')[2]) + 1; // The id of last file
+				}
+			catch (e) { var countDivFiles = 0; };
+			el.value	= countDivFiles ;
+			form.appendChild(el);
+		}
+
+		form._action.value = url;
+		// Connector Bug fixing: Encapsulating returned handler function
+		handlerExecuteForm = handler;
+		var form_handler = function (data){
+			handlerExecuteForm(data);
+			handlerExecuteForm = null;
+		}
+		divUpload.innerHTML= "<iframe onload=\"cExecute('$this.functions.getReturnExecuteForm',"+form_handler+");\"  style='display:"+(debug_controller ? "" : "none")+";width:"+(debug_controller ? 400 : 0)+";height:"+(debug_controller ? 400 : 0)+";' name='uploadFile'></iframe>";
+		form.action ="controller.php";
+		form.target ="uploadFile";
+		form.submit();
+		// Connector Bug fixing: Exclude '_action' element after cExecuteForm execution
+		if(el && el.id == '_action'){
+			el.parentNode.removeChild(el);
+		}
+	}
+
+
+	function alertBut(e) {
+	   	if(!e)
+			e = window.event;
+
+	    if(_onmouseup)
+			_onmouseup(e);
+
+		if(isExecuteForm) {
+	    	if(confirm(get_lang("There's an action processing. Do you want abort it?"))) {
+		    	expresso.connector.hideProgressBar();
+		    	isExecuteForm = false;
+		    	delete expresso.connector.requests[id];
+				expresso.connector.requests[id] = null;
+	    		stop();
+	    		return;
+	    	}
+    		else
+    			return false;
+	    }
+	}
+
+function expressoAjax(){
+	this.connector = new cConnector();
+
+}
+expressoAjax.prototype.require = function (module){
+	expresso.connector.loadScript(module);
+}
+var expresso = new expressoAjax();
Index: /trunk/phpgwapi/js/expressoAjax/dom.js
===================================================================
--- /trunk/phpgwapi/js/expressoAjax/dom.js	(revision 1999)
+++ /trunk/phpgwapi/js/expressoAjax/dom.js	(revision 1999)
@@ -0,0 +1,283 @@
+dom.prototype.config_events = function (pObj, pEvent, pHandler)
+{
+    if( typeof pObj == 'object')
+    {
+        if( pEvent.substring(0, 2) == 'on')
+            pEvent = pEvent.substring(2, pEvent.length);
+
+        if ( pObj.addEventListener )
+            pObj.addEventListener(pEvent, pHandler, false);
+        else if( pObj.attachEvent )
+            pObj.attachEvent('on' + pEvent, pHandler );
+    }
+}
+
+
+var _beforeunload_ = window.onbeforeunload;
+
+window.onbeforeunload = function()
+{
+	return unloadMess();
+}
+
+dom.prototype.unloadMess = function (){
+	var mess = get_lang("All change you made has not been saved and will be discarted.");
+	for (var i = 0; i < BordersArray.length; i++) {
+		var body = Element('body_' + BordersArray[i].sequence);
+		if (body && body.contentWindow && body.contentWindow.document.designMode.toLowerCase() == 'on') {
+			return mess;
+		}
+	}
+}
+
+// Make decimal round, using in size message
+dom.prototype.round = function (value, decimal){
+	var return_value = Math.round( value * Math.pow( 10 , decimal ) ) / Math.pow( 10 , decimal );
+	return( return_value );
+}
+
+
+dom.prototype.removeAllById = function (id){
+	do
+	{
+		if (typeof(Element(id)) == 'undefined')
+			break;
+		Element(id).parentNode.removeChild(Element(id));
+	}
+	while(Element(id));
+}
+// Add Input File Dynamically.
+dom.prototype.addFile = function (id_border){
+	divFiles = document.getElementById("divFiles_"+id_border);
+	if (! divFiles)
+		return false;
+	
+	if (divFiles.lastChild)
+		var countDivFiles = parseInt(divFiles.lastChild.id.split('_')[2]) + 1;
+
+	if (! countDivFiles)
+		var countDivFiles = 1;
+	
+	divFile = document.createElement('DIV');
+	
+	
+	divFile.innerHTML = "<input type='file' id_border='"+id_border+"' size='50' maxLength='255' onchange=\"function () {validateFileExtension(this.value, this.id.replace('input','div'), this.getAttribute('id_border'));};\" id='"+"inputFile_"+id_border+"_"+countDivFiles+"' name='file_"+countDivFiles+"'>";
+
+	
+	var linkFile = document.createElement("A");
+	linkFile.id = "linkFile_"+id_border+"_"+countDivFiles;
+	linkFile.href='javascript:void(0)';
+	linkFile.onclick=function () {removeFile(this.id.replace("link","div")); return false;};
+	linkFile.innerHTML=get_lang("Remove");	
+	//divFile.innerHTML += "&nbsp;&nbsp;";
+	divFile.appendChild(linkFile);
+	divFile.id = "divFile_"+id_border+"_"+countDivFiles;	
+	divFiles.appendChild(divFile);
+
+	
+
+	return document.getElementById("inputFile_"+id_border+"_"+countDivFiles);
+}
+//	Remove Input File Dynamically.
+dom.prototype.removeFile = function (id){
+	var border_id = id.substr(8,1);
+	var el = Element(id);
+	el.parentNode.removeChild(el);
+}
+
+var denyFileExtensions = new Array('exe','com','reg','chm','cnf','hta','ins',
+					'jse','job','lnk','pif','src','scf','sct','shb',
+					'vbe','vbs','wsc','wsf','wsh','cer','its','mau',
+					'mda','mar','mdz','prf','pst');
+dom.prototype.validateFileExtension = function (fileName){
+	var error_flag = false;
+	var fileExtension = fileName.split(".");
+	fileExtension = fileExtension[(fileExtension.length-1)];
+	for(var i=0; i<denyFileExtensions.length; i++)
+	{
+		if(denyFileExtensions[i] == fileExtension)
+		{
+			error_flag = true;
+			break;
+		}
+
+	}
+
+	if ( error_flag == true )
+	{
+		write_error(get_lang('File extension forbidden or invalid file') + '.');
+		return false;
+	}
+	return true;
+}
+
+
+dom.prototype.validatePath = function (fileName, id, id_border){
+	
+	var error_flag  = false;
+
+	if ( fileName.indexOf('/') != -1 )
+	{
+		if (fileName[0] != '/'){ // file name is windows format?
+			var file = fileName.substr(fileName.lastIndexOf('\\') + 1, fileName.length);
+			if ((fileName.indexOf(':\\') != 1) && (fileName.indexOf('\\\\') != 0)) // Is stored in partition or a network file?
+				error_flag = true;	
+		}
+		else // is Unix
+			var file = fileName.substr(fileName.lastIndexOf('/') + 1, fileName.length);						
+	}
+	else  // is Firefox 3
+		var file = fileName;
+	return (validateFileExtension(file));
+}
+
+var setTimeout_write_msg = 0;
+var old_msg = false;
+// Funcao usada para escrever mensagem
+// notimeout = True : mensagem nao apaga
+dom.prototype.write_msg = function (msg, notimeout){	
+	
+	if (setTimeout_write_msg)
+		clearTimeout(setTimeout_write_msg);
+	
+	var msg_div = Element('em_div_write_msg');
+	var old_divStatusBar = Element("divStatusBar");
+
+	if(!msg_div) {
+		msg_div = document.createElement('DIV');
+		msg_div.id = 'em_div_write_msg';
+		msg_div.className = 'em_div_write_msg';
+		old_divStatusBar.parentNode.insertBefore(msg_div,old_divStatusBar);
+	}
+	
+	if( document.getElementById('JabberMessenger'))
+		loadscript.adIcon();
+
+	msg_div.innerHTML = '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tbody><tr><th width="40%"></th><th noWrap class="action_info_th">'+msg+'</th><th width="40%"></th></tr></tbody></table>';
+
+	old_divStatusBar.style.display = 'none';
+	msg_div.style.display = '';	
+	// Nao ponha var na frente!! jakjr
+	handle_write_msg = function(){
+		try{
+			if(!old_msg)
+				clean_msg();
+			else
+				write_msg(old_msg, true);			
+		}
+		catch(e){}
+	}
+	if(notimeout)
+		old_msg = msg;
+	else
+		setTimeout_write_msg = setTimeout("handle_write_msg();", 5000);
+}
+// Funcao usada para apagar mensagem sem timeout
+dom.prototype.clean_msg = function (){
+	old_msg = false;
+	var msg_div = Element('em_div_write_msg');
+	var old_divStatusBar = Element("divStatusBar");
+	if(msg_div)
+		msg_div.style.display = 'none';
+	old_divStatusBar.style.display = '';	
+}
+function Element (el) {
+	return	document.getElementById(el);
+}
+
+dom.prototype.trim = function (inputString) {
+   if (typeof inputString != "string") 
+   	return inputString;
+ 
+   var retValue = inputString;
+   var ch = retValue.substring(0, 1);
+   while (ch == " ") { 
+	  retValue = retValue.substring(1, retValue.length);
+	  ch = retValue.substring(0, 1);
+   }
+   ch = retValue.substring(retValue.length-1, retValue.length);
+   while (ch == " ") { 
+	  retValue = retValue.substring(0, retValue.length-1);
+	  ch = retValue.substring(retValue.length-1, retValue.length);
+   }
+   while (retValue.indexOf("  ") != -1) { 
+	  retValue = retValue.substring(0, retValue.indexOf("  ")) + retValue.substring(retValue.indexOf("  ")+1, retValue.length); 
+   }
+   return retValue; 
+}
+
+
+dom.prototype.LTrim = function (value){
+	var w_space = String.fromCharCode(32);
+	var strTemp = "";
+	var iTemp = 0;
+
+	var v_length = value ? value.length : 0;
+	if(v_length < 1)
+		return "";
+
+	while(iTemp < v_length){
+		if(value && value.charAt(iTemp) != w_space){
+			strTemp = value.substring(iTemp,v_length);
+			break;
+		}
+		iTemp++;
+	}
+	return strTemp;
+}
+
+
+dom.prototype.array_search = function (needle, haystack) {
+	var n = haystack.length;
+	for (var i=0; i<n; i++) {
+		if (haystack[i]==needle) {
+			return true;
+		}
+	}
+	return false;
+}
+
+
+dom.prototype.add_className = function (obj, className){
+	if (obj && !exist_className(obj, className))
+		obj.className = obj.className + ' ' + className;
+}
+
+dom.prototype.remove_className = function (obj, className){
+	var re = new RegExp("\\s*"+className);
+	if (obj)
+		obj.className = obj.className.replace(re, ' ');
+}
+
+dom.prototype.exist_className = function (obj, className){
+	return ( obj && obj.className.indexOf(className) != -1 )
+}
+
+
+dom.prototype.validate_date = function (date){
+    if (date.match(/^[0-3][0-9]\/[0-1][0-9]\/\d{4,4}$/))
+    {
+        tmp = date.split('/');
+
+        day = new Number(tmp[0]);
+        month = new Number(tmp[1]);
+        year = new Number(tmp[2]);
+        if (month >= 1 && month <= 12 && day >= 1 && day <= 31)
+        {
+            if (month == 02 && day <= 29)
+            {
+                return true;
+            }
+            return true;
+        }
+        else
+            {
+                return false;
+            }
+    }
+    else
+        {
+            return false;
+        }
+}
+
Index: /trunk/phpgwapi/js/expressoAjax/lang.js
===================================================================
--- /trunk/phpgwapi/js/expressoAjax/lang.js	(revision 1999)
+++ /trunk/phpgwapi/js/expressoAjax/lang.js	(revision 1999)
@@ -0,0 +1,13 @@
+function get_lang(_key){
+	var key = _key.toLowerCase();
+	if(array_lang[key])
+		var _value = array_lang[key];
+	else
+		var _value = _key+"*";
+
+	if(arguments.length > 1)
+		for(j = 1; typeof(arguments[j]) != 'undefined'; j++)
+			_value = _value.replace("%"+j,arguments[j]);
+	return _value;
+
+}
Index: /trunk/phpgwapi/js/expressoAjax/dragdrop.js
===================================================================
--- /trunk/phpgwapi/js/expressoAjax/dragdrop.js	(revision 1999)
+++ /trunk/phpgwapi/js/expressoAjax/dragdrop.js	(revision 1999)
@@ -0,0 +1,208 @@
+(function()
+{
+	var _element	= null;
+	var _elementA	= null;
+	var _elementB	= null;
+	var _parent		= null;
+
+	function _configEvent(pObj, pEvent, pHandler)
+	{
+		if ( typeof pObj == 'object' )
+		{
+			if ( pEvent.substring(0, 2) == 'on' )
+				pEvent = pEvent.substring(2, pEvent.length);
+	
+			if ( arguments.length == 3 )
+			{
+				if ( pObj.addEventListener )
+					pObj.addEventListener(pEvent, pHandler, false);
+				else if ( pObj.attachEvent )
+					pObj.attachEvent('on' + pEvent, pHandler);
+			}
+			else if ( arguments.length == 4 )
+			{
+				if ( pObj.removeEventListener && pObj.removeEventListener != 'undefined')
+					pObj.removeEventListener(pEvent, pHandler, false);
+				else if ( pObj.detachEvent )
+					pObj.detachEvent('on' + pEvent, pHandler);
+			}
+		}
+	}
+
+	function _drag(e)
+	{
+		if (typeof e.preventDefault != 'undefined')
+			e.preventDefault();
+		else
+			e.onselectstart = new Function("return false;");
+
+		_element = ( e.target ) ? e.target : e.srcElement;
+
+		if ( _element )
+		{
+			_configEvent(_element, 'onmousemove', _mouseMove);
+			_configEvent(top.document, 'onmousemove', _mouseMove);
+
+			_configEvent(_element, 'onmouseup', _mouseUp);
+			_configEvent(top.document, 'onmouseup', _mouseUp);
+		}
+	}
+
+	function _elementShadow( pId )
+	{
+		if( _elementA )
+		{
+			var _elShadow 			= document.createElement("div");
+			_elShadow.id 			= _elementA.id + "__Shadow";
+			_elShadow.setAttribute("onselectstart" , "return false");
+			_elShadow.style.width	= _elementA.style.width;
+			_elShadow.style.height	= _elementA.style.height;
+			_elShadow.style.top		= _elementA.style.top;
+			_elShadow.style.left	= _elementA.style.left;
+			_elShadow.style.zIndex	= _elementA.style.zIndex;
+			_elShadow.className		= "x-shadow_Div";
+			
+			return _elShadow;
+		}
+	}
+
+	function _load()
+	{
+		if( arguments.length > 0 )
+		{
+			var pId = arguments[0];
+			
+			_configEvent(document.getElementById( pId + "__draggable"), 'onmousedown', _mouseDownShadow);
+		}
+	}
+
+	function _getMouseOffset(e, el)
+	{
+		var docPos = _getPosition(el);
+		var mousePos = _mouseCoords(e);
+		return {
+			'x' : mousePos.x - docPos.x,
+			'y' : mousePos.y - docPos.y
+		};
+	}
+
+	function _getPosition(_pObject)
+	{
+		var left = 0;
+		var top  = 0;
+
+		while ( _pObject.offsetParent )
+		{
+			left += _pObject.offsetLeft;
+			top  += _pObject.offsetTop;
+			_pObject = _pObject.offsetParent;
+		}
+
+		left += _pObject.offsetLeft;
+		top  += _pObject.offsetTop;
+
+		return {
+			'x' : left,
+			'y' : top
+		};
+	}
+
+	function _mouseCoords(ev)
+	{
+		var CoordX = "";
+		var CoordY = "";
+
+		if ( ev.pageX || ev.pageY )
+			return {
+				'x' : ev.pageX,
+				'y' : ev.pageY
+			};
+
+		CoordX = ev.clientX + document.body.scrollLeft - document.body.clientLeft;
+		CoordY = ev.clientY + document.body.scrollTop  - document.body.clientTop;
+		
+		return {
+			'x' : CoordX,
+			'y' : CoordY
+		};
+	}
+
+	function _mouseMove(e)
+	{
+		if ( _element )
+		{
+			if ( _element.mouseOffset == null )
+				_element.mouseOffset = _getMouseOffset(e, _element);
+
+			var mousePos = _mouseCoords(e);
+
+			var x = mousePos.x - _element.mouseOffset.x;
+			var y = mousePos.y - _element.mouseOffset.y;
+			_element.style.left = (( x < 0 ) ? 0 : x) + 'px';
+			_element.style.top  = (( y < 0 ) ? 0 : y) + 'px';
+		}
+	}
+
+	function _mouseUp()
+	{
+		if ( _element )
+		{
+			_mouseUpShadow();
+			
+			_configEvent(_element, 'onmousemove', _mouseMove, 'remove');
+			_configEvent(top.document, 'onmousemove', _mouseMove, 'remove');
+
+			_configEvent(_element, 'onmouseup', _mouseUp, 'remove');
+			_configEvent(top.document, 'onmouseup', _mouseUp, 'remove');
+
+			_element.mouseOffset = null;
+			_element = null;
+		}
+	}
+
+	function _mouseDownShadow(e)
+	{
+		try
+		{
+			if( arguments.length > 0 )
+			{
+				var _el = ( e.target ) ? e.target : e.srcElement;
+				var _id = (_el.id.substring(0, _el.id.indexOf("__draggable")));	
+				
+				_elementA = document.getElementById( _id + "__parent");
+				_elementB = _elementShadow( _id + "__parent");
+				
+				_elementA.style.left = '-1500px';
+				_parent	  = _elementA.parentNode;
+				
+				var _B = _parent.appendChild(_elementB);
+				
+				_configEvent( _elementB, 'onmouseup', _mouseUpShadow);
+				_configEvent( _elementB, 'onmousemove', _drag);
+			}
+			
+		}catch(e){}
+	}
+
+	function _mouseUpShadow()
+	{
+		try
+		{
+			_elementA.style.top			= _elementB.style.top;
+			_elementA.style.left		= _elementB.style.left;
+			
+			var _B = _parent.removeChild(_elementB);
+
+			_elementA = null;
+			_elementB = null;
+			_element = null;
+		}
+		catch(e){}
+	}
+	
+	function dragdrop(){}
+
+	dragdrop.prototype.set 	= _load;
+	window.dragdrop = dragdrop;
+	
+})();
