function inspect(object) {
  var a = [];
  for (var p in object) {
    a.push(p.name, p);
  }
  return a.join(' ');
}

/*
  例外を発生させる
  superClass: 継承元クラス
*/
function abort(msg) {
  throw msg;
}

function dateToString(date) {
  return date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
}

function timeToString(time) {
  return ('0'+time.getHours()).slice(-2) + ":" + ('0'+time.getMinutes()).slice(-2);
}

/*
  必須項目が入力されているかどうかチェック
  入力されていなければ例外処理
  element: チェックする要素
  name: 空白の場合に表示する名前
*/
function CheckRequired(element, name) {
  var n = name;
  with (element) {
    if (type!='select-one' && value=='' ||
        type=='select-one' && options[selectedIndex].text=='') {
      focus();
      throw n+'は必ず入力してください';
    }
  }
}

/*
　obusolute
  数値が入力されているかどうかチェック
  入力されていなければ例外処理
　SetNumberCheckも参照、
  element: チェックする要素
*/
function CheckNumber(element) {
  with (element) {
    if (value>'' && isNaN(value)) {
      alert('数値を入力してください');
      select();
      return false;
    }
    return true;
  }
}

/*
  例外をトラップするコンテキストを提供
  func: 例外をトラップした状態で実行するブロック
*/
function TrapExceptionBlock(func) {
  try {
    func();
  } catch(e) {
    if (e>'') alert(e);
    return false;
  }
}

/*
  オブジェクトを継承する
  superClass: 継承元クラス
*/
Function.prototype.inherit = function(superClass) {
  var Temp = new Function();
  Temp.prototype = superClass.prototype;
  this.prototype = new Temp;
  this.prototype.constructor = this;
  this.prototype.superclass = superClass.prototype;
}

/*
  Arrayにeachメソッドを定義
*/
Array.prototype.each = function(func) {
  for(var i=0; i<this.length; i++) {
    func(this[i]);
  }
}

/*
  document.getElementByIdの代替ルーチン
*/
function $() {
  var elements = new Array();
  for (var i=0; i<arguments.length; i++) {
    var element = arguments[i];
    if (typeof element == 'string')
      element = this.document.getElementById(element);
    if (arguments.length == 1) return element;
    elements.push(element);
  }
  return elements;
}


/*
  thisを含め、子ノードを再帰的に巡回する
  node: 巡回するノード(nullの場合は巡回しない)
  block: ノード毎に実行するブロック function(node) {}
*/
function eachNode(node, block) {
  if (node) {
    block(node);
    with (node) {
      if (node.innerHTML) {
        /* Geckoはロード中にcolgroupにアクセスするとテーブルの表示が動的に更新されなくなる */
        var skip = -1;
        if (node.innerHTML.match(/^<colgroup>/)) skip = 0
          else if (node.innerHTML.match(/^[^<]+<colgroup>/)) skip = 1
        for (var i=0; i<childNodes.length; i++) {
          if (i!=skip) eachNode(childNodes[i], block);
        }
      }
    }
  }
}

/*
  hidden属性INPUTタグを作成する
  name: 名前
  value: 値
*/
function CreateHidden(name, value) {
  elm = document.createElement('input');
  elm.type = 'hidden';
  elm.name = name;
  elm.value = value;
  return elm;
}

/*
  FORMタグを作成する
  action: アクション
  method: メソッド(省略時はget)
*/
function CreateForm(action, method) {
  var form = document.createElement('form');
  form.action = action || '';
  form.method = method || 'get';
  return form;
}

/*
  Hiddenタグを作成して、thisの子要素として追加する
  このルーチンをFormのメソッドに登録して使用する
  name: 名前
  value: 値
*/
function AppendHidden(name, value) {
  this.appendChild(CreateHidden(name, value));
}

/*
  イベントハンドラを追加する
  object: イベントを追加する対象
  eventName: イベントの名前
  handler: イベントハンドラ function(source)
*/
function AddEventHandler(object, eventName, handler)
{
  if (object) {
    if (!object.GetEventHandlers) {
      object.GetEventHandlers = function(eventName) {
        var handlers = object['_handler_'+eventName];
        if (!handlers) {
          handlers = object['_handler_'+eventName] = [];
          object[eventName] = function() {
            return TrapExceptionBlock(function(event) {
              //if (window.event) event = window.event
              for (var i=0; i<handlers.length; i++)
//                handlers[i](event); //実行する
                handlers[i](object); //実行する
            });
          }
        }
        return handlers;
      }
    }
    object.GetEventHandlers(eventName).push(handler);
  }
}


/*
  数値チェックを行うonchangeイベントハンドラをセットする
  source: 入力要素
*/
function SetNumberCheck(source) {
  AddEventHandler(source, 'onchange', function() {
    with (source) {
      if (value>'' && isNaN(value)) {
        source.value = '';
        abort('数値を入力してください');
      }
    }
  });
}

/*
  日付入力要素に、日付正規化を施す
  source: 入力要素
*/
function SetDateNormalize(source) {
  AddEventHandler(source, 'onchange', function() {
    var value;
    if (source.value) {
      if (source.value.match(/^[^\/]+\/[^\/]+$/)) {
        var year = (new Date()).getFullYear()
        value = new Date(year+'/'+source.value)
      } else {
        value = new Date(source.value);
      }
      with (value) {
        if (isNaN(getFullYear())) {
          source.value = '';
          abort('日付を入力してください.');
          return false
        } else {
          source.value = getFullYear()+'/'+(getMonth()+1)+'/'+getDate()
        }
      }
    }
  });
}

/*
  時刻入力要素に、時刻正規化を施す
  source: 入力要素
*/
function SetTimeNormalize(source) {
  AddEventHandler(source, 'onchange', function() {
    var value;
    if (source.value) {
      source.value = source.value.replace('.', ':');
      if (source.value.match(/^\d+$/)) source.value = source.value+':0';
      if (!source.value.match(/^(\d{1,2}):(\d{1,2})$/)) {
        source.value = '';
        abort('時刻を入力してください.');
        return false
       }
      value = new Date();
      value.setHours(RegExp.$1)
      value.setMinutes(RegExp.$2)
      source.value = timeToString(value)
    }
  });
}

/*
  一方を入力すると、もう一方にも同じデータがコピーされるようにする
  source: コピー元入力要素
  dest: コピー先入力要素
*/
function SetPair(source, dest) {
  AddEventHandler(source, 'onchange', function() {
    dest.value = source.value;
    dest.onchange;
  });
}

/*
  innerTextに代入する、クロスブラウザ対応
  dest: 代入先要素
  text: 代入するテキスト
*/
function SetInnerText(dest, text) {
  if (dest.firstChild) dest.replaceChild(document.createTextNode(text), dest.firstChild);
    else dest.appendChild(document.createTextNode(text));
}

