/**
 * 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 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'); }

/**
 * Shorthand for document.getElementById($id).style
 * Return null if style not found
 */
function styleOf($elem) {
  var $e = $($elem);
  if ($e && $e.style) 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,"") }



/**
 * Generate get parameter from form of given id.
 * @param form string id of form
 */
function formToParam(id) {
  var list = document.getElementById(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);
}

/**
 * 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 {
      $style = styleOf(trim($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='';
}

/**
 * Setup javascript css class, initialise hsrc image rollover.
 */
function addiah_init() {
  window.onload = null;
  var sl = document.styleSheets.length;
  var css_count = 0;
  // Set dynamic style
  for (i=0; i < sl; i++) {
    var style = document.styleSheets[i];
    // Get stylesheet
    if (style.cssRules) style = style.cssRules;
    else if (style.rules) style = style.rules;
    else continue;
    // Find rule
    var rl = style.length;
    for (j=0; j < rl; j++) {
      var rule = style[j];
      if (rule.selectorText == '.js_show') {
        // Reveal .js_show
        rule.style.display = 'none';
        rule.style.display = '';
        if (++css_count >= 2) { i = sl; break; } // Continue if found all rules
      } else if (rule.selectorText == '.js_hide') {
        // Hide .js_hide
        rule.style.display = '';
        rule.style.display = 'none';
        if (++css_count >= 2) { i = sl; break; } // Continue if found all rules
      }
    }
  }
  // Set hsrc hover from www.youngpup.net
  var img,sh,sn,sd;
  var il = document.images.length;
  for(var i=0; i < il; i++) {
    var img = document.images[i];
    sh = img.getAttribute("hsrc");
    if (!img.n && img.src && sh){
      if (img.getAttribute("realSrc")) sn = img.getAttribute("realSrc"); // IE 6 png hover fix
      else sn = img.getAttribute("src");
      img.n = new Image();
      img.h = new Image();
      img.n.src = sn;
      img.h.src = sh;
      img.onmouseover = hsrcHoverOn;
      img.onmouseout = hsrcHoverOff;
    }
  }
}
function hsrcHoverOn() { this.src = this.h.src; }
function hsrcHoverOff() { this.src = this.n.src; }

/**
 * Fetch a url and invoke function on success or failure
 *
 * @param string url URL to request
 * @param function success Function to invoke on success, with request object as parameter
 * @param function success Function to invoke on failure, with request object as parameter
 */
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;
}

/**
 * An event handler that cancles the action.  Always return false.
 * Example: return cancelAction(e)
 */
function cancelAction(e) {
  if (e && e.preventDefault) e.preventDefault();
  else return false;
}

/** Set height of iframe to equals to its content.  Width is not affected. */
function iframeFit(id) {
  if (!frames[id]) { cerror('Iframe '+id+' not found, cannot fit'); return; }
  var body = frames[id].document.body;
  if (body.scrollHeight)
    document.getElementById(id).style.height = (body.scrollHeight)+'px';
  else if (body.offsetHeight)
    document.getElementById(id).style.height = (body.offsetHeight)+'px';
}






/************************************ Forms ******************************************/


/** Disable submit button of a form, preventing it from submitting */
function disableForm(id) {
  var form = document.getElementById(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 submit button of a form, optionally assigning onsubmit handler */
function enableForm(id, onsubmit) {
  var form = document.getElementById(id);
  if (!form) { cerror('Form '+id+' not found, cannot enable'); return; }
  if (onsubmit) form.onsubmit = onsubmit;
  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;
  }  
}

/**
 * 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
 * @return true if success, false otherwise
 */
function setSelect($elem, $value, $form) {
  if (isString($elem)) {
    if ($form) {
      $form = $($form); 
      if (!$form) { cdebug('Form not specified'); return false; }
      if ($form.elements[$elem]) $elem = $form.elements[$elem]; else $elem = null;
    } else {
      $elem = $($elem);
    }
  }
  if (!$elem) { cdebug('Radio input not found'); return false; }
  var options = $elem.options;
  $selected = false;
  for (var j=0;j<options.length;j++) {
    var opt = options[j];
    if (opt.value != $value) continue;
    $elem.selectedIndex = j;
  }
  return $selected;
}

/**
 * Select (mutliple) select item with given value attribute
 * @return true if success, false otherwise
 */
function addSelect($elem, $value, $form) {
  if (isString($elem)) {
    if ($form) {
      $form = $($form); 
      if (!$form) { cdebug('Form not specified'); return false; }
      if ($form.elements[$elem]) $elem = $form.elements[$elem]; else $elem = null;
    } else {
      $elem = $($elem);
    }
  }
  if (!$elem) { cdebug('Radio input not found'); return false; }
  if (isString($elem))
    if ($form) $form = $f($form); else { cdebug('Form not specified'); return false; }
  if ($form[$elem]) $elem = $form[$elem]; else { cdebug('Radio input not found'); return false; }
  var options = $elem.options;
  for (var j=0;j<options.length;j++) {
    var opt = options[j];
    options[i].selected = opt.value != $value;
    return true;
  }
  return false;
}

/**
 * Select radio item with given value attribute
 * @return true if success, false otherwise
 */
function setRadio($elem, $value, $form) {
  if (isString($elem)) {
    if ($form) {
      $form = $($form); 
      if (!$form) { cdebug('Form not specified'); return false; }
      if ($form.elements[$elem]) $elem = $form.elements[$elem]; else $elem = null;
    } else {
      $elem = $($elem);
    }
  }
  if (!$elem) { cdebug('Radio input not found'); return false; }
  if ($elem.length) {
    for (var i=0; i<$elem.length; i++)
      if ($elem[i].value && $elem[i].value == $value) {
        $elem[i].checked = 'checked';
        return true;
      }
  } else {
    if ($elem.value && $elem.value == $value) {
      $elem.checked = 'checked';
      return true;
    }
  }
  return false;
}

