/**
 * Shorthand for document.getElementById($id)
 */
function $($id) {
  return (isString($id)) ? document.getElementById($id) : $id;
}

function $f($id) {
  if (isString($id)) {  
    $form = $($id);
    if (!$form) $form = document.forms[$id];
    return $form;
  } else
    return $id;
}

/**
 * Shorthand for document.getElementsByTagName($tag)
 *
function $tag($tag) {
  return document.getElementsByTagName($tag);
}
*/

/** console functions */
function list_property(obj) { for (property in obj) clog(property); }
function clog(message) { if (window.console && console.log) console.log(message); else if (window.opera) opera.postError(message); }
function cerror(message) { }//if (window.console && console.error) console.error(message); else if (window.opera) opera.postError(message); }
function cinfo(message) { }//if (window.console && console.info) console.info(message); else if (window.opera) opera.postError(message); }
function cdebug(message) { }//if (window.console && console.debug) console.debug(message); else if (window.opera) opera.postError(message); }
function ctrace() { }//if (window.console && console.trace) console.trace(); else if (window.opera) opera.postError('Trace not supported'); }

/**
 * Get style of given id or element.
 * Return null if style not found
 */
function styleOf(id) {
  var e = $(id);
  if (e) return e.style;
  else return null;
}

//function is_array(param) { return typeof(param)=="object" }
function isString(param) { return typeof(param)=="string" }
function trim($str) { return $str.replace(/^\s*|\s*$/g,"") }

/** An event handler that cancles the action */
function cancelAction(e) {
  if (e && e.preventDefault) e.preventDefault();
  else return false;
}


/************************************ Forms ******************************************/

/** Disable a form, preventing it from submitting */
function disableForm(id) {
  var form = $f(id);
  if (!form) { cerror('Form '+id+' not found, cannot disable'); return; }
  form.onsubmit = cancelAction;
  var list = form.elements;
  for (var i=0;i<list.length;i++) {
    var input=list[i];
    if (input.type == 'submit' || input.type=='image') input.disabled=true;
  }
}

/** Enable a form, optionally assigning onsubmit handler */
function enableForm(id, onsubmit) {
  var form = $f(id);
  if (!form) { cerror('Form '+id+' not found, cannot enable'); return; }
  form.onsubmit = (onsubmit) ? onsubmit : null;
  var list = form.elements;
  for (var i=0;i<list.length;i++) {
    var input=list[i];
    if ((input.type == 'submit' || input.type=='image') && input.disabled) input.disabled=null;
  }
}

/**
 * Generate get parameter from form of given id.
 * @param form string id of form
 */
function formToParam(id) {
  var list = $f(id).elements;
  var result = '';
  for (var i=0;i<list.length;i++) {
    var input=list[i];
    if (!input.name) continue;
    switch(input.type) {
      case 'text':
      case 'hidden':
      case 'password': result += escape(input.name)+'='+escape(input.value)+'&'; break;
      case 'checkbox':
      case 'radio': if (input.checked) result += escape(input.name)+'='+escape(input.value)+'&'; break;
      case 'select-one': result += escape(input.name)+'='+escape(input.options[input.selectedIndex].value)+'&'; break;
      case 'select-multiple': {
        var options = input.options;
        for (var j=0;j<options.length;j++) {
          var opt = options[j];
          if (!opt.selected) continue;
          result += escape(input.name)+'='+escape(opt.value)+'&';
        }
      } break;
      default:; // Button, image and reset ignored
    }
  }
  return result.substr(0, result.length-1);
}

/**
 * Get radio input value
 * $elem can be radio input name
 * $elem can be a form or id/name of a form
 * Return currently selected radio input
 */
function $radio($elem, $form) {
  if (!$elem || !isString($elem) || !$form) return null;
  // Find element if given id
  $form = $f($form);
  if (!$form) return null;

  var list = $form.elements;
  var result = '';
  for (var i=0;i<list.length;i++) {
    var input=list[i];
    if (!input.name) continue;
    if(input.type=='radio' && input.checked && input.name==$elem) return input;
  }
  return null;
}

/**
 * Select select item with given value attribute
 */
function setSelect($elem, $value, $form) {
  if (isString($elem)) {
    if ($form) $form = $f($form);
    $elem = $form[$elem];
  }
  if (!$elem) { cdebug('Select input not found'); return }
  var options = $elem.options;
  for (var j=0;j<options.length;j++) {
    var opt = options[j];
    if (!opt.value || opt.value != $value) continue;
    $elem.selectedIndex = j;
    return;
  }
}

/**
 * Uncheck everything with given id/name
 * $elem can be input name or comma separated input name, or element if $form is not set
 * $form can be null, a form, or id/name of a form
 * Return nothing.
 */
function uncheck($elem, $form) {
  if (!$elem) return;
  // Find element if given id
  if (isString($elem)) {
    $form = $f($form);
    if ($elem.indexOf(',')>=0) {
      $list = $elem.split(',');
      for (var $i=0;$i<$list.length;$i++)
        uncheck($list[$i], $form);
      return;
    } else {
      if ($form)
        $elem = $form[$elem];
      else
        $elem = document.getElementById($elem);
      if (!$elem) return;
    }
  }
  $elem.checked = false;
}


/************************************ Style ******************************************/

/**
 * Toggle the display style of given element between 'none' and default
 * $elem can be an Element, element id, or comma separated element id
 * Return nothing.
 */
function toggleHidden($elem) {
  if (!$elem) return;
  // Find element if given id
  if (isString($elem)) {
    if ($elem.indexOf(',')>=0) {
      $list = $elem.split(',');
      for (var $i=0;$i<$list.length;$i++)
        toggleHidden($list[$i]);
      return;
    } else {
      $elem = document.getElementById($elem);
      if (!$elem) return;
    }
  }
  if (!$elem.style) return;
  var $style = $elem.style;
  $style.display = ($style.display) ? '' : 'none';
}

/**
 * Hide given element.
 * Parameter can be an element, element id, or comma separated element id.
 * Return nothing.
 */
function hide($elem) {
  if (isString($elem))
    if ($elem.indexOf(',')>=0) {
      $list = $elem.split(',');
      for (var $i=0;$i<$list.length;$i++)
        hide($list[$i]);
    } else {
      $elem = document.getElementById(trim($elem));
      if (!$elem) return;
      
      $style = styleOf($elem);
      if ($style) $style.display='none';
    }
  else {
    $elem.style.display='none';
  }
}

/**
 * Show given element.
 * Parameter can be an element, element id, or comma separated element id.
 * Return nothing.
 */
function show($elem) {
  if (isString($elem))
    if ($elem.indexOf(',')>=0) {
      $list = $elem.split(',');
      for (var $i=0;$i<$list.length;$i++)
        show($list[$i]);
    } else {
      $style = styleOf(trim($elem));
      if ($style) $style.display='';
    }
  else
    $elem.style.display='';
}


/************************************ AJAX ******************************************/
function ajax_load(url, success, fail) {
  if (window.XMLHttpRequest)
    var req = new XMLHttpRequest();
  else if (window.ActiveXObject)
    var req = new ActiveXObject("Msxml2.XMLHTTP");
  var time = 0;
  req.open('GET',url,true);
  req.onreadystatechange = function(){
    if (req.readyState == 4) {
      // Fx throw exception on user abort, however we can't distinguish it from script error
      if (req.status == 200) {
        clog('AJAX loaded in '+(new Date().valueOf()-time)+'ms - '+url);
        success(req);
      } else if (fail) fail(req);
      else { cerror('AJAX request failed'); cerror(req); }
//      else window.defaultStatus = 'AJAX request failed - '+url;
      success = fail = time = null;
      req.onreadystatechange = null; // Have to delay until we finish important things due to IE 6 bug
      req = null;
    }
  }
  clog('AJAX load             - '+url);
  time = new Date().valueOf();
  req.send(null);
  return req;
}

