function selectByText(sel, text)
{
   for (var i = 0 ; i < sel.options.length ; i++)
      if (sel.options[i].text == text)
      {
         sel.selectedIndex = i;
         return true;
      }
   return false;
}

// input type=file, input type=image are not supported
// input type=reset, input type=button, input type=submit and equiv buttons are not submitted
// only POST forms and application/x-www-form-urlencoded enctype is supported
// form targets are not supported
// all data is submitted in UTF-8, in sync mode (async = false)
// returns XMLHttpRequest.responseText or false on error
function ajaxSubmit(form, req)
{
   // check form
   if (!/post/i.test(form.method)) return false;
   if (form.enctype != '' && form.enctype != 'application/x-www-form-urlencoded') return false;

   // 
   var send = '';
   var loopThru = function(tag)
   {
      var inp = form.getElementsByTagName(tag);
      for (var i = 0 ; i < inp.length ; i++)
      {
         // unsupported
         if (inp[i].type == 'reset') continue;
         if (inp[i].type == 'button') continue;
         if (inp[i].type == 'submit') continue;
         if (inp[i].type == 'file') continue;
         if (inp[i].type == 'image') continue;
         // nameless
         if (!inp[i].name) continue;
         // checkboxes & radios
         if (inp[i].type == 'checkbox' || inp[i].type == 'radio')
         {
            if (inp[i].checked) // send only if checked
            {
               var val = inp[i].value ? inp[i].value : 'on'; // if value=='' then 'on' is sent
               send += (send ? '&' : '') + inp[i].name + '=' + encodeURIComponent(val);
            }
            continue;
         }
         // selects
         if (inp[i].type == 'select-one')
         {
            send += (send ? '&' : '') + inp[i].name + '=' + encodeURIComponent(inp[i].options[inp[i].selectedIndex].value);
            continue;
         }
         if (inp[i].type == 'select-multiple')
         {
            for (var j = 0 ; j < inp[i].options.length ; j++)
               if (inp[i].options[j].selected)
                  send += (send ? '&' : '') + inp[i].name + '=' + encodeURIComponent(inp[i].options[inp[i].options[j].index].value);
            continue;
         }
         // other
         send += (send ? '&' : '') + inp[i].name + '=' + encodeURIComponent(inp[i].value);
      }	
   }
   
   // inputs
   loopThru('input');
   // buttons
   loopThru('button');
   // textareas
   loopThru('textarea');
   // selects
   loopThru('select');

   //
   Post(req, form.action, false, send);
   if (req.status != 200) return false;
   return req.responseText;
}

function insertAfter(what, after)
{
   if (after.parentNode)
   {
    	if (after.nextSibling)
		after.parentNode.insertBefore(what, after.nextSibling);
    	else
   		after.parentNode.appendChild(what);
   }
}

function addOption(sel, val, text, pos, className)
{
	var o = document.createElement('OPTION');
	o.value = val;
	o.text = text;
	o.className = className;
	if (pos === undefined)
		sel.options.add(o);
	else
		sel.options.add(o, pos);
}

function print_r(x)
{
	var res = new String();
	for (key in x) {
		res += '['+key+'] => '+x[key]+'\n';		
	}
	return res;
}

//usage: getSender(e ? e : event)
function getSender(event)
{
	if (event.target)
        	return event.target;
        else
        	return event.srcElement;
}

function getXY(elem)
{
	var ret = {x:elem.offsetLeft, y:elem.offsetTop}
	
	while (elem = elem.offsetParent)
	{
		ret.x += elem.offsetLeft;
		ret.y += elem.offsetTop;
	}
	return ret;
}

// FIXME: document.documentElement.scrollLeft & scrollTop are wrong in IE & FF
function getEventPageXY(event)
{           
	var ret = null;
	/*if (event.pageX) // NS4
		return {x:event.pageX, y:event.pageY};
	else */ if (event.clientX) // IE  /* and DOM2 :) */
		ret = {x:event.clientX, y:event.clientY};
	else
		return false;
	ret.x += document.documentElement.scrollLeft;
	ret.y += document.documentElement.scrollTop;
	return ret;
}

function getEventWindowXY(event)
{           
	var ret = null;
	if (event.clientX) // IE  /* and DOM2 :) */
		ret = {x:event.clientX, y:event.clientY};
	else
		return false;
	return ret;
}


function attachEvent(elem, event, handler)
{
	if (elem.attachEvent)	// IE
		elem.attachEvent('on'+event, handler);
	else if (elem.addEventListener)	// DOM2
		elem.addEventListener(event, handler, false);	// FIXME: why false? what is bubbling/capture phase???
}

function detachEvent(elem, event, handler)
{
	if (elem.detachEvent)	// IE
		elem.detachEvent('on'+event, handler);
	else if (elem.addEventListener)	// DOM2
		elem.removeEventListener(event, handler, false);	// FIXME: why false? what is bubbling/capture phase???
}


g_onload = new Array();
function attachOnLoad(handler)
{
	g_onload[g_onload.length] = handler;
}                                                                                

window.onload = function() {
	for (var i = 0 ; i < g_onload.length ; i++)
		g_onload[i]();
}

g_onresize = new Array();
function attachOnResize(handler)
{
	g_onresize[g_onresize.length] = handler;
}                                                                                

window.onresize = function() {
	for (var i = 0 ; i < g_onresize.length ; i++)
		g_onresize[i]();
}