// 文字列の前後の空白を取り除く
function strTrim(str)
{
  return String(str).replace(/^\s+|\s$/, "");
}

// 二つの文字列を大文字小文字を区別せずに等しいかどうか調べる
function caseEqual(str1, str2)
{
  str1 = String(str1).toUpperCase();
  str2 = String(str2).toUpperCase();
  return str1 == str2;
}

// 整数を指定した長さに整形する
function formatInt(number, length, padding, plus)
{
  var num, dig, pad, str, i, sig;
  num = Number(number) | 0 || 0;
  len = Number(length) | 0 || 0;
  pad = String(padding || " ").charAt(0);
  str = number.toString(10);
  if (str.charAt(0) == "-")
  {
    sig = "-";
    str = str.substring(1);
  }
  else
    sig = plus ? "+" : "";
  for (i = str.length; i < len; ++i)
    str = pad + str;
  return sig + str;
}

// イベントリスナを設定する
function pushEventListener(target, type, listener, useCapture)
{
  if (target)
    if (target.addEventListener)
      target.addEventListener(String(type), listener, Boolean(useCapture));
    else
      if (target.attachEvent)
        target.attachEvent("on" + type, listener);
  return;
}

// className に token が含まれるかどうかを調べる
function classContains(className, token)
{
  var list, i;
  list = String(className).split(/(\s|,)+/);
  token = strTrim(token);
  if (token != "")
    for (i = 0; i < list.length; ++i)
      if (list[i] == token)
        return true;
  return false;
}

// 正規表現で特殊な意味を持つ文字をエスケープする
function quoteMeta(str)
{
  return String(str).replace(/[$()*+\-.?\[\\\]\^{|}]/g,
      function(match)
      {
        return "\\" + match[0];
      }
  );
}

// name=value 形式のクラス名の value の値を返す
function getNamedClassValue(className, name)
{
  var list, i, regex, match;
  list = String(className).split(/(\s|,)+/);
  name = strTrim(name);
  if (name != "")
  {
    regex = new RegExp("^" + quoteMeta(name) + "=(.*)");
    for (i = 0; i < list.length; ++i)
      if ((match = list[i].match(regex)))
        return match[1];
  }
  return "";
}

// DOM NodeList の各ノードを単純な配列にする
function nodeListToArray(nodeList)
{
  var result, i;
  result = new Array();
  if (nodeList && nodeList.item)
    for (i = 0; i < nodeList.length; ++i)
      result[result.length++] = nodeList.item(i);
  return result;
}

// NodeList から指定された名前の要素を取り出す
function getNamedItem(nodeList, name)
{
  if (nodeList)
    if (nodeList.namedItem)
      return nodeList.namedItem(name);
    else if (nodeList.item)
      return nodeList.item(name);
  return null;
}

// 下位要素のすべての配列を得る (IE5 対策)
function getAllElements(target)
{
  var result, element, i;
  if (target && target.getElementsByTagName && target.ownerDocument)
    return nodeListToArray(target.getElementsByTagName("*"));
  else
  {
    result = new Array();
    if (target && target.all)
      for (i = 0; i < target.all.length; ++i)
        if ((element = target.all(i)) && element.nodeType == 1)
          result[result.length++] = element;
    return result;
  }
}

// INPUT 要素を作成する
function createInputElement(ownerDocument, type, name, value)
{
  var input, source;
  input = null;
  if (ownerDocument && ownerDocument.createElement)
  {
    type = String(type) || "TEXT";
    name = String(name);
    if (ownerDocument.all) // IE
    {
      source = "<INPUT TYPE=\"" + type + "\"";
      if (name)
        source += " NAME=\"" + name + "\"";
      source += ">";
      input = ownerDocument.createElement(source);
    }
    else
      if ((input = ownerDocument.createElement("INPUT")))
      {
        input.type = type;
        if (name)
          input.name = name;
      }
    if (input && typeof value != "undefined")
      input.defaultValue = input.value = String(value);
  }
  return input;
}

// SELECT 要素を作成する
function createSelectElement(ownerDocument, multiple, name)
{
  var select, source;
  select = null;
  if (ownerDocument && ownerDocument.createElement)
  {
    // multiple が省略されている
    if (typeof name == "undefined" && typeof multiple == "string")
    {
      name = multiple;
      multiple = false;
    }
    if (ownerDocument.all) // IE
    {
      source = "<SELECT";
      if (multiple)
        source += " MULTIPLE";
      if (name)
        source += " NAME=\"" + name + "\"";
      source += "></SELECT>";
      select = ownerDocument.createElement(source);
    }
    else
      if ((select = ownerDocument.createElement("SELECT")))
      {
        if (multiple)
          select.multiple = true;
        if (name)
          select.name = name;
      }
  }
  return select;
}

// 配列 haystack の中から needle に一致するものの最初の序数を返す
function arraySearch(needle, haystack)
{
  var i;
  if (typeof haystack == "object" /*|| haystack instanceof Array*/)
    for (i in haystack)
      if (haystack[i] == needle)
        return i;
  return false;
}

// ↑が一致するかどうかを調べる
function inArray(needle, haystack)
{
  return typeof (arraySearch(needle, haystack)) == "number";
}

// <select> に含まれる <option> を削除する
function deleteOptions(select, start)
{
  var i;
  if (select && select.options && select.remove)
  {
    if (typeof start != "number" || isNaN(start) || start < 0)
      start = 0;
    for (i = select.options.length; i >= start; --i)
      select.remove(i);
  }
  return;
}

// <select> の末尾に <option> を追加する
function addOption(select, text, value)
{
  var doc, ie, option;
  if (select && select.add && (doc = (ie = select.document) ||
      select.ownerDocument) && doc.createElement &&
      (option = doc.createElement("OPTION")))
  {
    option.text = text;
    option.value = value || text;
    if (ie)
      select.add(option, -1);
    else
      select.add(option, null);
    return option;
  }
  return null;
}

// 指定された値を持つ <option> を選択する
function selectValue(select, value)
{
  var i, option;
  if (select && select.options && select.options.item)
  {
    for (i = 0; i < select.options.length; ++i)
      if ((option = select.options.item(i)) &&
          (option.value || option.text) == value)
      {
        option.selected = true;
        return option.index;
      }
    select.selectedIndex = -1;
  }
  return -1;
}

// 選択されている <option> の値を取得する
function getSelectedValue(select)
{
  var option;
  if (select && select.options && select.options.item &&
      select.selectedIndex >= 0 &&
      (option = select.options.item(select.selectedIndex)))
    return option.value || option.text;
  return "";
}

// element の内容テキストを返す
function getTextContent(element)
{
  var text, child;
  text = "";
  if (element)
  {
    if (element.nodeType == 1)
      for (child = element.firstChild; child; child = child.nextSibling)
        text += getTextContent(child);
    else if (element.nodeType == 3)
      text = element.nodeValue;
  }
  return text;
}

// element に内容テキストを設定する
function setTextContent(element, text)
{
  var doc, children, child, i;
  if (element && (doc = element.document || element.ownerDocument) &&
      doc.createTextNode)
  {
    if (element.removeChild &&
        (children = nodeListToArray(element.childNodes)))
      for (i = 0; i < children.length; ++i)
        if ((child = children[i]) && child.nodeType == 3)
          element.removeChild(child);
    if (element.appendChild && (child = doc.createTextNode(text)))
      return element.appendChild(child);
  }
  return null;
}

// イベントのターゲットの親を辿って指定されたノード名のノードを返す
function getTargetElement(evt, nodeName)
{
  var target;
  if (evt || (evt = window.event))
    for (target = evt.target || evt.srcElement; target; target = target.parentNode)
      if (caseEqual(target.nodeName, nodeName) ||
          nodeName == "*" && target.nodeType == 1)
        return target;
  return null;
}

// preventDefault() を呼び出す
function prohibitDefaultEvent(evt)
{
  if (evt || (evt = window.event))
  {
    if (evt.preventDefault)
      evt.preventDefault();
    else
      evt.returnValue = false;
    return true;
  }
  return false;
}

// 呼び出し元のドキュメントの絶対 URL を得る
function getScriptBaseURI(doc)
{
  var heads, head, metas, meta, i, j;
  if (doc || (doc = window.document))
  {
    if (doc.getElementsByTagName &&
       (heads = doc.getElementsByTagName("HEAD")) && heads.item)
      for (i = 0; i < heads.length; ++i)
        if ((head = heads.item(i)) && head.getElementsByTagName &&
            (metas = head.getElementsByTagName("META")) && metas.item)
          for (j = 0; j < metas.length; ++j)
            if ((meta = metas.item(j)) && meta.name &&
                meta.name == "SCRIPT-BASE-URI")
              return meta.content;
    return String(document.URL).replace(/\?.*/, "");
  }
  return "";
}

// URL パスの一つ上の階層を得る
function parentPath(path)
{
  var part;
  if ((part = String(path).match(/^([^#\/:?]+:)?(\/\/[^#\/?]*)?([^#?]*)/)))
  {
    path = String(part[3]);
    if (path.search(/\//) >= 0)
    {
      path += ".";
      path = path.replace(/\/[^\/]*$/, "");
    }
    else
      path = ".";
    return String(part[1]) + String(part[2]) + path + "/";
  }
  return "";
}

// URL に接続するクエリー文字列を作成する
function encodeURIQuery(name1, value1 /*, name2, value2, ...*/)
{
  var names, values, pairs, func, i;
  names = new Array();
  values = new Array();
  for (i = 0; i < (arguments.length + 1) >> 1; ++i)
  {
    names[names.length++] = String(arguments[i << 1]);
    values[values.length++] = String(arguments[(i << 1) + 1]);
  }
  if (names.length > 0)
  {
    pairs = new Array();
    if (window.encodeURIComponent)
    {
      func = window.encodeURIComponent;
      pairs[pairs.length++] = "encoding=UTF-8";
    }
    else
    {
      func = window.escape;
      pairs[pairs.length++] = "encoding=" + (window.ActiveXObject ? "UTF-16" : "unknown");
    }
    for (i = 0; i < names.length; ++i)
      pairs[pairs.length++] = func(names[i]) + "=" + func(values[i]);
    return "?" + pairs.join("&");
  }
  return "";
}

// setTimeout をパラメータ付きで呼び出せるようにする (MSIE 対応)
function setTimeoutParam(callback, msec, param)
{
  var timer, func;
  timer = 0;
  if (window.setTimeout && typeof callback == "function")
  {
    if (window.ActiveXObject)
    {
      func = function()
      {
        callback(param);
      };
      timer = window.setTimeout(func, msec);
    }
    else
      timer = window.setTimeout(callback, msec, param);
  }
  return timer;
}

// setInterval をパラメータ付きで呼び出せるようにする (MSIE 対応)
function setIntervalParam(callback, msec /*, ... param[] */)
{
  var timer, self, args, func, i;
  timer = 0;
  if (window.setInterval && typeof callback == "function")
  {
    self = this;
    args = new Array();
    if (window.ActiveXObject)
    {
      for (i = 2; i < arguments.length; ++i)
        args[args.length++] = arguments[i];
      func = function()
      {
        callback.apply(this, args);
      };
      timer = window.setInterval(func, msec);
    }
    else
    {
      for (i = 0; i < arguments.length; ++i)
        args[args.length++] = arguments[i];
      timer = window.setInterval.apply(window, args);
    }
  }
  return timer;
}

// XMLHttpRequest のインスタンスを作成して完了後にコールバック関数を呼び出す
// コールバック関数の第一引数は XMLHttpRequest のインスタンス
function xmlHttpGet(url, callback, param)
{
  var http;
  http = null;
  if (window.ActiveXObject)
    http = new ActiveXObject("Microsoft.XMLHTTP");
  else if (window.XMLHttpRequest)
    http = new XMLHttpRequest();
  if (http)
  {
    if (typeof callback == "function")
    {
      http.onreadystatechange = function()
        {
          if (http.readyState == 4)
            callback(http, param);
        };
    }
    http.open("GET", String(url), true);
    http.send(null);
  }
  return http;
}

function xmlHttpPost(url, data, callback, param)
{
  var http, pairs, func, body;
  http = null;
  if (window.ActiveXObject)
    http = new ActiveXObject("Microsoft.XMLHTTP");
  else if (window.XMLHttpRequest)
    http = new XMLHttpRequest();
  if (http)
  {
    if (typeof callback == "function")
    {
      http.onreadystatechange = function()
        {
          if (http.readyState == 4)
            callback(http, param);
        };
    }
    body = "";
    if (data)
    {
      pairs = new Array();
      if (window.encodeURIComponent)
      {
        func = window.encodeURIComponent;
        pairs[pairs.length++] = "encoding=UTF-8";
      }
      else
      {
        func = window.escape;
        pairs[pairs.length++] = "encoding=" + (window.ActiveXObject ? "UTF-16" : "unknown");
      }
      for (key in data)
        pairs[pairs.length++] = func(key) + "=" + func(data[key]);
      if (pairs.length >= 2)
        body = pairs.join("&");
    }
    http.open("POST", String(url), true);
    http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    http.setRequestHeader("Content-Length", String(body.length));
    http.send(body);
  }
  return http;
}

function getAbsolutePoint(element)
{
  var e, left, top;
  left = top = 0;
  for (e = element; e; e = e.offsetParent)
  {
    left += e.offsetLeft || 0;
    top += e.offsetTop || 0;
  }
  return {left: left, top: top};
}
