// DP Javascript suit loader

var DP = {
  Version: '2.0.0',
  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
  },
  require_css: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<link rel="stylesheet" type="text/css" href="'+libraryName+'">');
  },
  REQUIRED_PROTOTYPE: '1.6.0',

  // モジュールの読み込み順
  MODULES: ['checkform', 'googlemaps', 'table', 'datatable', 'dialog', 'edit'],
  // モジュールの依存関係
  LOADS: {
    checkform: {
        'script': [],
        'css':[]
    },
    googlemaps: {
        'script': [],
        'css':[]
    },
    table: {
        'script': [],
        'css':['table']
    },
    datatable: {
        'script': [],
        'css': ['datatable']
    },
    dialog: {  // 要Script.acuro.us
        'script' : ['table'],
        'css': ['dialog']
    },
    edit: {
        'script' : ['datatable', 'dialog'],
        'css':['edit']
    }
  },

  load: function() {
    if((typeof Prototype=='undefined') ||
       (typeof Element == 'undefined') ||
       (typeof Element.Methods=='undefined') ||
       (DP.Util.convertVersionString(Prototype.Version) <
        DP.Util.convertVersionString(DP.REQUIRED_PROTOTYPE))) {
          throw("DP suit requires the Prototype JavaScript framework >= " + DP.REQUIRED_PROTOTYPE);
        }

    var s = $A(document.getElementsByTagName("script")).findAll( function(s) {
      return (s.src && s.src.match(/dp(?:\.debug)?\.js(\?.*)?$/));
    }).last();
    var path = s.src.replace(/dp(?:\.debug)?\.js(\?.*)?$/,'');
    var debug = s.src.match(/dp\.debug\.js/);
    var includes = s.src.match(/\?.*load=([a-z\d,]*)/i);

    var loads = [];
    var loads_css = [];
    if (includes) {
      // module 指定あり
      includes = includes[1].split(/,/);
      for (var i = 0, l = includes.length; i < l; i++) {
        getModules(includes[i], loads, loads_css);
      }
    } else {
      // module 指定なし(全モジュールロード)
      for (var i in DP.LOADS) {
        getModules(i, loads, loads_css);
      }
    }
    DP.MODULES.each(function(s) {
      if (loads.include(s)) {
        DP.require(path+s+(debug ? '.debug' : '')+'.js');
      }
    });
    loads_css.uniq().each(function (s) {
      DP.require_css(path+'css/'+s+'.css');
    });
    // モジュールを再帰取得
    function getModules(mod, scr, css) {
      if (!scr.include(mod) && DP.LOADS[mod]) {
        // すでに含まれていなければ、追加
        scr.push(mod);
        // 依存するものを追加
        for (var i = 0, l = DP.LOADS[mod].script.length; i < l; i++) {
          getModules(DP.LOADS[mod].script[i], scr, css);
        }
        css.combine(DP.LOADS[mod].css);
      }
    }
  }
}

DP.Util = {
  Version: '1.0.0',

  // version文字列を数値にして返す
  convertVersionString: function (versionString){
    var r = versionString.split('.');
    return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
  },

  // documentが表示されているウィンドウ(フレーム)のサイズ
  getWindowDimension: function (doc) {
    if (!doc) {
      doc = document;
    }
    return doc.viewport.getDimensions();
  },

  // document全体のサイズ
  getDocumentDimension: function (doc) {
    if (!doc) {
      doc = document;
    }
    if (doc.body) {
      if (Prototype.Browser.Opera) return $(doc.documentElement).getAllDimensions();
      return $(doc.body).getAllDimensions();
    } else {
      return null;
    }
  },

  // document全体または表示ウィンドウ(フレーム)の大きい方のサイズ
  getFullDimension: function (doc) {
    if (!doc) {
      doc = document;
    }
    var w = DP.Util.getWindowDimension(doc);
    var d = DP.Util.getDocumentDimension(doc);
    return {width: Math.max(w.width, d.width), height: Math.max(w.height, d.height)};
  },

  // Replace2:replaceJSONでiframe経由で送信されたデータの正規化
  // 引数：受信したデータが納められているframe(window) element
  // 戻り値：evalされていないJSONデータ、またはbodyのinnerHTML
  fromReplaceJSON: function(win) {
    // Opera では動かない
    if (! (win.contentWindow && win.contentWindow.document.URL.match(/^http/))) {
      throw 'document not ready';
    }
    var d = win.contentDocument || win.contentWindow.document || win.document;
    var e = d.getElementById('json');
    if (e) {
      // unescape(Replace2:replaceJson()の内容を同期させること)
      var s = e.innerHTML;
      s = s.replace(/^.*?<\!\-\-(.*)\-\->.*$/, "$1");
      s = s.replace(/\\([<>])/g, "$1");
      s = s.replace(/\\\\/g, "\\");
      return s;
    } else if (d && d.body) {
      return d.body.innerText || d.body.textContent;
    } else {
      return '';
    }
  },

  // 簡易メールアドレスチェック
  isMailaddr: function(addr) {
    return addr.match(/^[a-z0-9_\-\+\.]+\@([a-z0-9_\-]+\.)+[a-z0-9_\-]+$/i);
  },

  // マルチバイト英字、一部の記号を ASCII に
  // regularizeChar(str, {japanese_symbol: false})
  regularizeChar: (function() {
    var conv_char_alpha_number = function(ch) { return String.fromCharCode(ch.charCodeAt() - 0xFEE0); }; // [0-9A-Za-z]
    var tr_alpha_number = function(s) { return s.replace(/[\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A]/g, conv_char_alpha_number); };
    var tr_symbol = function(s) { return s.replace(/[\u2010-\u2015\u2212\uFF0D]/g, '-').replace(/\uFF08/g, '(')
        .replace(/\uFF09/g, ')').replace(/\u3000/g, ' '); }; // minus, hyphen, space, parenthes
    var tr_japanese_symbol = function(s) { return s.replace(/\u30FC/g, '-'); }; // 長音記号
    return function(str, opt) {
      var alpha_number = true;
      var symbol = true;
      var japanese_symbol = true;
      if (typeof opt == 'object') {
        if ('alpha_number' in opt) {
          alpha_number = !!opt.alpha_number;
        }
        if ('symbol' in opt) {
          symbol = !!opt.symbol;
        }
        if ('japanese_symbol' in opt) {
          japanese_symbol = !!opt.japanese_symbol;
        }
      }
      var ret = str;
      if (alpha_number) { ret = tr_alpha_number(ret); }
        if (symbol) { ret = tr_symbol(ret); }
          if (japanese_symbol) { ret = tr_japanese_symbol(ret); }
            return ret;
    };
  })(),

  // ブラウザ上に表示されるスクロールバーの幅(pixel)をチェックして返す
  // チェックできなかったときは 0 を返す
  getScrollbarSize: function () {
    var body = document.body
    if (body && body.hasChildNodes()) {
      var d = new Element('div', {style: 'overflow: scroll; width: 100px; height: 100px; padding: 0; margin: 0; border: 0 none;'});
      body.appendChild(d);
      var ret = d.offsetWidth - d.clientWidth + 1;
      body.removeChild(d);
      return ret;
    } else {
      return 0;
    }
  },

  // マウスホイールイベントの拡張 - prototype.js の Event を拡張する
  // 1. 'mousewheel' タイプが使用可能になる
  // 2. Event.wheel(event) または event.wheel が使用可能になる
  enableMouseWheelEvent: function () {
    Event.__observe__ = Event.observe;
    Event.__stopObserving__ = Event.stopObserving;
    Event.__fire__ = Event.fire;
    Event.observe = function (element, eventName, handler) {
      if (Prototype.Browser.Gecko && eventName == 'mousewheel') {
        eventName = 'DOMMouseScroll';
      }
      Event.__observe__(element, eventName, handler);
    };
    Event.stopObserving = function (element, eventName, handler) {
      if (Prototype.Browser.Gecko && eventName == 'mousewheel') {
        eventName = 'DOMMouseScroll';
      }
      return Event.__stopObserving__(element, eventName, handler);
    };
    Event.fire = function (element, eventName, handler) {
      if (Prototype.Browser.Gecko && eventName == 'mousewheel') {
        eventName = 'DOMMouseScroll';
      }
      return Event.__fire__(element, eventName, handler);
    };

    Element.addMethods({
      fire:          Event.fire,
      observe:       Event.observe,
      stopObserving: Event.stopObserving
    });
    Object.extend(document, {
      fire:          Element.Methods.fire.methodize(),
      observe:       Element.Methods.observe.methodize(),
      stopObserving: Element.Methods.stopObserving.methodize()
    });

    Event.Methods.wheel = function (event){
      var delta = 0;
      if (!event) {
        event = window.event;
      }
      if (event.wheelDelta) {
        delta = -event.wheelDelta/120;
      } else if (event.detail) {
        delta = event.detail/3;
      }
      return Math.round(delta); //Safari Round
    };

    Object.extend(Event, Event.Methods);

  },

  dummy: 0  // terminater
};


// Array 拡張
Object.extend(Array.prototype, {
  // 配列に配列を結合したものを返す(もとの配列は変化しない)
  append: function (ary) {
    var dst = this;
    if (Object.isArray(ary)) {
      for (var i = 0, l = ary.length; i < l; i++) {
        dst.push(ary[i]);
      }
      return dst;
    } else {
      return this.concat(ary);
    }
  },
  // thisの末尾に配列を結合する(thisを変更する) - 結合後の配列の長さを返す
  combine: function (ary) {
    if (Object.isArray(ary)) {
      for (var i = 0, l = ary.length; i < l; i++) {
        this.push(ary[i]);
      }
      return this.length;
    } else {
      return this.push(ary);
    }
  }
});

// Element
Element.addMethods({
  // 全ての子ノードを削除する
  removeAllChildren: function (element) {
    while (element.hasChildNodes()) {
      element.removeChild(element.firstChild);
    }
  },
  // 計算済styleを返す
  getComputedStyle: function (element, pusedo) {
    if (window.getComputedStyle) {
      return getComputedStyle(element, pusedo);
    } else if (element.currentStyle) {
      return element.currentStyle;
    } else {
      return null;
    }
  },
  // 拡張Dimensionを返す(IEの値はいい加減な場合があるので使用には注意すること)
  getAllDimensions: function (element) {
    element = $(element);
    var style = element.getComputedStyle();
    if (style) {
      var ret = {};
        $w('marginLeft marginRight marginTop marginBottom paddingLeft paddingRight paddingTop paddingBottom').each(function (k) {
          ret[k] = parseInt(style[k]);
          if (isNaN(ret[k])) ret[k] = 0;
        });
        $w('borderLeft borderRight borderTop borderBottom').each(function (k) {
          ret[k] = parseInt(style[k+'Width']);
          if (isNaN(ret[k])) ret[k] = 0;
        });

      ret.paddingWidth = ret.paddingLeft + ret.paddingRight;
      ret.paddingHeight = ret.paddingTop + ret.paddingBottom;
      ret.marginWidth = ret.marginLeft + ret.marginRight;
      ret.marginHeight = ret.marginTop + ret.marginBottom;
      ret.borderWidth = ret.borderLeft + ret.borderRight;
      ret.borderHeight = ret.borderTop + ret.borderBottom;
      ret.height = element.offsetHeight;
      ret.width = element.offsetWidth;
      ret.widthAll = ret.width + ret.marginWidth;
      ret.heightAll = ret.height + ret.marginHeight;
      ret.height -= ret.borderHeight;
      ret.width -= ret.borderWidth;
      return ret;
    } else {
      return null;
    }
  }
});




////////////////////////////
// 依存ライブラリの読み込み
////////////////////////////
DP.load();
