MJL.event.add(window, "load", function(event) {
    MJL.enable.window("popup", {
        width: 620,
        height: 580
    });
    MJL.enable.rollover("roll", {disable:"unroll"});
    MJL.enable.flash("flash");
    MJL.enable.styleSwitcher("styleSwitcher");
    MJL.enable.tab("tabs");
    MJL.enable.heightEqualizer("lyt-2col-01", {
        groupBy: 2,
        collect: function(parent){
            return MJL.getElementsByClassName(parent, "column");
        }
    });
    MJL.enable.heightEqualizer("lyt-3col-01", {
        groupBy: 3,
        collect: function(parent){
            return MJL.getElementsByClassName(parent, "column");
        }
    });
    MJL.enable.heightEqualizer("nav-contents-02", {groupBy: 4});
    MJL.enable.heightEqualizer("nav-contents-04", {groupBy: 2});
    MJL.enable.heightEqualizer("form-departure", {
        groupBy: 2,
        collect: function(parent){
            return MJL.getElementsByClassName(parent, "column");
        }
    });

    // ツアー検索
    var pBaitai = document.getElementById("search-tour-p_baitai");
    if (pBaitai) {
        if (pBaitai.value === "990") {
            pBaitai.value = "";
        }
        MJL.event.add(document.getElementById("search-tour"), "submit", function() {
            if (!pBaitai.value) {
                pBaitai.value = "990";
            }
        }, true);
    }
}, false);


// ----------------------------------------------------------------------------
// jQuery
// ----------------------------------------------------------------------------
"jQuery" in window && $(function() {
    // ------------------------------------------------------------------------
    // Bug Trident: ラジオボタンとチェックボックスでは blur しないと
    //              change イベントが発生しない
    // ------------------------------------------------------------------------
    $.browser.msie && $('input:radio, input:checkbox').click(function() {
        this.blur();
        this.focus();
        $(this).trigger('change');
    });


    // ------------------------------------------------------------------------
    // 強制 wrapping
    // ------------------------------------------------------------------------
    $('.tabContainer .tabs .box-index-01').each(function() {
        var targets   = $('.lyt-2col-01 > div', this), // 対象要素集合
            lastIndex = targets.length - 1,            // 最終要素の index
            isOdd     = (0 === lastIndex % 2);         // 対象要素数の奇数是非
                                                       //   是: true, 非: false
        targets.each(function(n) {
            // n の範囲: 0 <= n <= lastIndex
            var target =
                // 2つの要素を選択可能 (先頭要素を除く)
                (0 < n && 1 === n % 2) ? targets.slice(n-1, n+1) :
                // 対象要素数が奇数の場合における処理
                // 余剰の要素を1つだけラッピング
                //   例: 0 === lastIndex -> 0番目の要素のみラッピング
                //   例: 2 === lastIndex -> 2番目の要素のみラッピング
                (isOdd && n === lastIndex) ? targets.eq(n) :
                // その他: 対象を確定しない
                null;
            // 対象が確定できた場合のみラッピング
            target && target.wrapAll('<div class="wrap"></div>');
        });
    });


    // ------------------------------------------------------------------------
    // プレースホルダ実装
    // ------------------------------------------------------------------------
    $('#AccelaBizSearchASPForm .placeholder').each(function() {
        var root  = $(this),                      // 包含ブロック
            lab   = $('label', root),             // label 要素
            input = $('#'+lab.attr('for'), root); // label に関連づいた要素
        // アクティブにしてから
        root.addClass('run');
        // 位置取得
        var rpos = root.offset(),  // 包含ブロック
            ipos = input.offset(); // input
        // label 要素 設定
        lab.css({
            // input 左上を原点として位置あわせ
            // input の padding と border も加算して最適位置にする
            top  : Math.abs(
                  ipos.top - rpos.top
                + (parseInt(input.css('borderTopWidth'), 10) || 0)
                + (parseInt(input.css('paddingTop'), 10) || 0)
            ),
            left : Math.abs(
                  ipos.left - rpos.left
                + (parseInt(input.css('borderLeftWidth'), 10) || 0)
                + (parseInt(input.css('paddingLeft'), 10) || 0)
            ),
            // line-height もあわせないとうまく位置が揃わない
            lineHeight : input.css('lineHeight'),
            // 背景変更時に備えて input の前景色にあわせる
            color : input.css('color')
        }).click(function() {
            lab.hide();
            // label の文言を範囲選択した場合にフォーカスしない問題に対応
            input.trigger('focus');
        });
        // input 要素 設定
        input.focus(function() {
            // label 消去
            lab.hide();
        }).blur(function() {
            // 内容がなければ label を出す
            !$.trim(input.val()) && lab.show();
        });

        // ロード時に内容があれば label を隠す (例: ヒストリ遷移)
        $.trim(input.val()) && lab.hide();
    });


    // ------------------------------------------------------------------------
    // 詳細検索
    // ------------------------------------------------------------------------
    (function() {
        // 対象 CSS セレクタ一覧
        var targets = {
            'kaigai' : {
                form     : '#kaigai-detail-search',   // 基準 form 要素
                reset    : '.btn-reset',              // リセットボタン
                mapText  : '#kaigai-chosen-district', // 表示テキスト
                dst      : '#kaigai-district',        // 方面 (p_dest)
                dstSub   : '#kaigai-dst-sub',         // 方面 複数値指定用 (p_dest)
                country  : '#kaigai-country',         // 国名 (p_country)
                city     : '#kaigai-city',            // 都市 (p_city)
                dpt      : '#kaigai-departure',       // 出発地 (p_hatsu)
                dptM     : '#kaigai-departure-m',     // 出発日 月 (p_month)
                dptD     : '#kaigai-departure-d',     // 出発日 日 (p_dd)
                dptFix   : '#kaigai-fixed',           // 出発決定ツアー限定 (p_saiko)
                dptWeekN : '#kaigai-day-none',        // 出発日 曜日 未指定
                dptWeeks : [                          // 出発日 曜日 (p_day)
                    '#kaigai-day-sun',
                    '#kaigai-day-mon',
                    '#kaigai-day-tue',
                    '#kaigai-day-wed',
                    '#kaigai-day-thu',
                    '#kaigai-day-fri',
                    '#kaigai-day-sat'
                ].join(','),
                daysMin   : [                         // 最小旅行日数 (p_kikan_fr)
                    'select#kaigai-days-min',
                    '#kaigai-days-min input'
                ].join(','),
                daysMax   : '#kaigai-days-max',       // 最大旅行日数 (p_kikan_to)
                budgetMin : [                         // 最低予算 (p_price_min)
                    'select#kaigai-budget-min',
                    '#kaigai-budget-min input'
                ].join(','),
                budgetMax : '#kaigai-budget-max'      // 最大予算 (p_price_max)
            },
            'kokunai' : {
                form     : '#kokunai-detail-search',    // 基準 form 要素
                reset    : '.btn-reset',                // リセットボタン
                mapText  : '#kokunai-chosen-departure', // 表示テキスト
                dst      : '#kokunai-district',         // 方面 (p_dest)
                dstSub   : '#kokunai-dst-sub',          // 方面 複数値指定用 (p_dest)
                dpt      : '#kokunai-departure',        // 出発地 (p_hatsu)
                dptSub   : '#kokunai-dpt-sub',          // サブ出発地 (p_hatsu_sub)
                dptM     : '#kokunai-departure-m',      // 出発日 月 (p_month)
                dptD     : '#kokunai-departure-d',      // 出発日 日 (p_dd)
                dptFix   : '#kokunai-fixed',            // 出発決定ツアー限定 (p_saiko)
                dptWeekN : '#kokunai-day-none',         // 出発日 曜日 未指定
                dptWeeks : [                            // 出発日 曜日 (p_day)
                    '#kokunai-day-sun',
                    '#kokunai-day-mon',
                    '#kokunai-day-tue',
                    '#kokunai-day-wed',
                    '#kokunai-day-thu',
                    '#kokunai-day-fri',
                    '#kokunai-day-sat'
                ].join(','),
                daysMin   : [                           // 最小旅行日数 (p_kikan_fr)
                    'select#kokunai-days-min',
                    '#kokunai-days-min input'
                ].join(','),
                daysMax   : '#kokunai-days-max',        // 最大旅行日数 (p_kikan_to)
                budgetMin : [                           // 最低予算 (p_price_min)
                    'select#kokunai-budget-min',
                    '#kokunai-budget-min input'
                ].join(','),
                budgetMax : '#kokunai-budget-max'       // 最大予算 (p_price_max)
            },
            'bus' : {
                form     : '#bus-detail-search',  // 基準 form 要素
                reset    : '.btn-reset',          // リセットボタン
                dpt      : '#bus-departure',      // 出発地 (p_hatsu)
                dptSub   : '#bus-dpt-sub',        // サブ出発地 (p_hatsu_sub)
                meeting  : '#bus-meeting',        // 集合場所 (p_bunrui2)
                dptM     : '#bus-departure-m',    // 出発日 月 (p_month)
                dptD     : '#bus-departure-d',    // 出発日 日 (p_dd)
                dptFix   : '#bus-fixed',          // 出発決定ツアー限定 (p_saiko)
                daysMin  : '#bus-days-min input', // 最小旅行日数 (p_kikan_fr)
                daysMax  : '#bus-days-max',       // 最大旅行日数 (p_kikan_to)
                dptWeekN : '#bus-day-none',       // 出発日 曜日 未指定
                dptWeeks : [                      // 出発日 曜日 (p_day)
                    '#bus-day-sun',
                    '#bus-day-mon',
                    '#bus-day-tue',
                    '#bus-day-wed',
                    '#bus-day-thu',
                    '#bus-day-fri',
                    '#bus-day-sat'
                ].join(','),
                daysMin  : '#bus-days-min input', // 最小旅行日数 (p_kikan_fr)
                daysMax  : '#bus-days-max',       // 最大旅行日数 (p_kikan_to)
                budgetMin : [                     // 最低予算 (p_price_min)
                    'select#bus-budget-min',
                    '#bus-budget-min input'
                ].join(','),
                budgetMax : '#bus-budget-max'     // 最大予算 (p_price_max)
            }
        };
        // JSON ファイル一覧
        var jsons = {
            abroad  : '/shared/script/abroad.json',
            dpt     : '/shared/script/hatsu_sub.json',
            meeting : '/shared/script/meeting_place.json',
            select  : '/shared/script/select.json'
        };
        // JSON データキャッシュ
        var jsonDatas = {
            abroad  : null,
            dpt     : null,
            meeting : null,
            select  : null
        };
        // document オブジェクト jQuery ラッピング
        var DOC = $(document);
        // 一時利用 空配列
        var EMPTY = [];

        $.each(targets, function(TYPE, selectors) {
            // 基準 form 要素
            var form = $(selectors.form);
            if (form.length < 1) { return; }
            delete selectors.form;  // objs に含ませないよう削除
            // リセットボタン
            var reset = $(selectors.reset);
            delete selectors.reset; // objs に含ませないよう削除
            // 対象要素
            var objs = $.extend({}, selectors);
            $.each(objs, function(n, selector) {
                objs[n] = form.find(selector); // 先行投資
            });


            // ----------------------------------------------------------------
            // 送信前処理
            // ----------------------------------------------------------------
            form.bind('submit', function() {
                // 海外旅行の方面・国名・都市は、いずれか1パラメタのみ指定可能
                // 註: 指定しても問題なさそうだが、開発初期段階でダメと言われた
                //   方面             -> 方面
                //   方面＆国名       -> 国名
                //   方面＆国名＆都市 -> 都市
                if (objs.country && objs.country.val()) {
                    if (objs.dst) {
                        // マップの場合はチェックを外す
                        objs.dst.is('select') ? objs.dst.val('')
                                              : objs.dst.find('input:checked').attr('checked', false);
                    }
                    objs.dstSub && objs.dstSub.val('');
                }
                if (objs.city && objs.city.val()) {
                    objs.country && objs.country.val('');
                }

                // 方面の空値は許されない (サブ値は空値になりうる)
                if (objs.dstSub && !objs.dstSub.val()) {
                    objs.dstSub.remove();
                }
            });


            // ----------------------------------------------------------------
            // 方面・出発地 自動選択
            // ----------------------------------------------------------------
            $(objs.dst || objs.dpt || EMPTY).filter('select').each(function() {
                // 対象 select 要素
                var select = $(this);
                // 必ず全ての非同期通信が完了した後で実行
                // select 要素に change イベントが設定されていない状態が
                // ありうる為
                DOC.ajaxStop(function() {
                    // 自動選択 開始
                    var data = jsonDatas.select[TYPE], // 選択条件
                        key  = (                       // 対象の種類
                            // 検索フォーム種類毎に異なる条件を使用
                            (new RegExp(data.cond)).exec(
                                location.pathname || '' // URL から判定
                            ) || EMPTY
                        )[1] || '';
                    if (key && key in data.data) {
                        // 対象 option 要素の種類 - CSS セレクタ対応を使用
                        $('option', select).filter(data.data[key]).each(function() {
                            // val() は利用不可
                            // 複数 option 要素の value 属性値が
                            // 同一の場合がある
                            this.selected = true;
                            // 他の非同期通信により change イベントが設定された
                            // 後に実行
                            select.trigger('change');
                        });
                    }
                });
                // 選択条件データを取得
                jsonDatas.select || $.getJSON(jsons.select, function(data) {
                    jsonDatas.select = data;
                });
                jsonDatas.select = jsonDatas.select || true;
            });


            // ----------------------------------------------------------------
            // 出発日 月 自動追加
            // ----------------------------------------------------------------
            objs.dptM && objs.dptM.each(function() {
                var dptM     = $(this);
                // 箇月数 (半年/1年を select 要素の class 属性値で切替可能)
                var noptions = dptM.is('.departure-m-half') ? 6 : 12;
                var options  = new Array(noptions); // option 要素集合
                var date     = new Date();
                // 日は使わないので1日に固定
                // 例: 5/31 + 1月 → 6/31 は存在しないので 7/1 になってしまう
                date.setDate(1);
                for (var o = 0; o < noptions; o++) {
                    var month = date.getMonth()+1; // 0..11
                    options[o] = '<option value="'
                               + date.getFullYear()
                               + '/'
                               + (month < 10 ? '0' : '') // 01..09 にする
                               + month
                               + '/01">'                 // 日は1日に固定
                               + month
                               + '</option>';
                    // 次の月を算出
                    date.setMonth(month); // 11+1 → 1 (翌年1月)
                }
                dptM.append(options.join(''));
            });


            // ----------------------------------------------------------------
            // 方面 マップ
            // ----------------------------------------------------------------
            if (objs.dst && objs.mapText) {
                objs.dst.bind('change reset', function(event) {
                    var target = $(event.target),     // 対象 input 要素
                        items  = objs.dst.children(), // アクティベート対象要素
                        text   = '';                  // 表示テキスト

                    // アクティブな要素があれば非アクティブにする
                    items.filter('.active').removeClass('active').find('img').each(function() {
                        // jQuery trigger メソッドは独自実装なのでうまくいかない
                        // MJL 側で対応
                        MJL.event.dispatch(this, "mouseout", false);
                    });

                    // reset 時はアクティベートさせない
                    if ('reset' !== event.type) {
                        // アクティベート
                        text = target.parent().addClass('active').find('img').each(function() {
                            MJL.event.dispatch(this, "mouseover", false);
                        }).attr('alt'); // 表示テキストを取得
                    }

                    // 表示テキストを反映
                    // reset 時・不正値なら既定値 &nbsp; を表示
                    objs.mapText.text(text || '\u00A0');
                });

                // BUG Trident: label 要素子孫要素の img 要素の click が
                //              label 要素のデフォルト挙動に影響しない
                $.browser.msie && objs.dst.find('label').click(function() {
                    // 明示的に click() メソッドを実行すると
                    // デフォルト挙動を強制的に発生させることが可能
                    this.click();
                });
            }


            // ----------------------------------------------------------------
            // 出発決定ツアー限定 排他制御
            // ----------------------------------------------------------------
            objs.dptFix && (function() {
                // アルゴリズム
                function switchDptFix(event) {
                    // enable: 月日両方に値が必須
                    if ('reset' !== event.type &&
                        objs.dptM.val()        &&
                        objs.dptD.val()) {
                        objs.dptFix.attr('disabled', false)
                                   .parent().removeClass('disabled');
                    // disable: 「指定なし」ないし reset 時
                    } else {
                        objs.dptFix.attr('disabled', true)
                                   .attr('checked', false)
                                   .parent().addClass('disabled');
                    }
                }
                // 設定
                objs.dptM.bind('change reset', switchDptFix).trigger('change');
                objs.dptD.bind('change reset', switchDptFix).trigger('change');
            })();


            // ----------------------------------------------------------------
            // 出発日・曜日 排他制御
            // ----------------------------------------------------------------
            // 「出発日 日」
            //   「選択なし」選択: 何もしない
            //   他項目を選択:     「出発日 曜日 未指定」チェック ON
            objs.dptD && objs.dptWeekN && objs.dptD.bind('change reset', function() {
                objs.dptD.val() && objs.dptWeekN.attr('checked', true)
                                                .trigger('change');
            }).trigger('change');

            // 「出発日 曜日 未指定」
            //   チェック ON:  「出発日 曜日」無効・チェック OFF
            //   チェック OFF: 「出発日 曜日」有効
            objs.dptWeekN && objs.dptWeeks && objs.dptWeekN.bind('change reset', function() {
                var disabled = objs.dptWeekN.is(':checked');
                objs.dptWeeks.attr('disabled', disabled);
                disabled && objs.dptWeeks.attr('checked', false);
                objs.dptWeeks.trigger('change');
            }).trigger('change');

            // 「出発日 曜日」
            //   チェック ON  (1項目でも): 「出発日 日」無効・デフォルト値選択
            //   チェック OFF (全項目):    「出発日 日」有効
            objs.dptWeeks && objs.dptD && objs.dptWeeks.bind('change reset', function() {
                var disabled = (0 < objs.dptWeeks.filter(':checked').length);
                objs.dptD.attr('disabled', disabled);
                disabled && objs.dptD.val('').trigger('change');
            }).trigger('change');


            // ----------------------------------------------------------------
            // 各サブ値 同時設定
            // ----------------------------------------------------------------
            $.each([
                [objs.dst,       objs.dstSub],
                [objs.daysMin,   objs.daysMax],
                [objs.budgetMin, objs.budgetMax]
            ], function() {
                var mains = this[0],                 // 設定用コントロール群
                    subs  = this[1],                 // サブ値群
                    cond  = /-[\dA-Z]+-([\dA-Z]+)$/; // サブ値判定・抽出条件
                // 片方でも存在しなければ何もしない
                if (!mains || !subs) { return; }
                // 全サブ値に対し実行
                subs.each(function() {
                    var sub   = $(this), // サブ値
                        cache = {};      // id - 値対応のキャッシュ
                    // 設定用コントロールの id から最大値を算出・設定
                    mains.each(function() {
                        var main   = $(this), // 設定用コントロール
                            target = main.is('select') ? main.find('option') : main;
                        target.each(function() {
                            var id  = $(this).attr('id'),
                                val = (cond.exec(id) || [])[1] || '';
                            if (id) {
                                // 例: id="foo-bar-100-200"
                                //     100: value 属性値
                                //     200: サブ値
                                // 例: id="foo-bar-ABC-DEF"
                                //     "ABC": value 属性値
                                //     "DEF": サブ値
                                var num = parseInt(val, 10);
                                cache[id] = isNaN(num) ? val :
                                            0 < num    ? num : '';
                            }
                        });
                    }).bind('change', function() {
                        var main   = $(this),
                            target = main.is('select') ? main.find('option:selected')
                                                       : main.filter(':checked'),
                            id     = target.attr('id');
                        id && id in cache && sub.val(cache[id]);
                    });
                }).bind('reset', function() {
                    subs.val('');
                });
            });


            // ----------------------------------------------------------------
            // 対応要素追加：方面 → 国名 → 都市名
            // ----------------------------------------------------------------
            (objs.dst && objs.country && objs.city) && (function() {
                // 既定 option 要素
                var countryDef = objs.country.children(), // 国名
                    cityDef    = objs.city.children();    // 都市名

                // 変換規則に即した option 要素を取得
                var getOptElems = (function() {
                    // 生成済 option 要素キャッシュ
                    var cache = {area : {}, country : {}, city : {}};
                    // option 要素一時保存用 select 要素
                    var tmp = $('<select></select>');
                    // id:     抽出キー
                    // def:    既定要素 (= 先頭要素)
                    // before: 変換前のキー種類
                    // after:  変換するキーの種類
                    return function(id, def, before, after) {
                        // 空文字列なら既定要素のみ返却
                        if ('' === id) { return def; }
                        // 未キャッシュなら生成
                        if (!cache[after][id]) {
                            var ids  = id.split('-'),
                                nids = ids.length;
                            // 初期化
                            tmp.empty().append(def);
                            // option 要素追加
                            for (var i = 0; i < nids; i++) {
                                var vals  = jsonDatas.abroad[before][ids[i]].values,
                                    nvals = vals ? vals.length : 0;
                                for (var v = 0; v < nvals; v++) {
                                    tmp.append(
                                          '<option value="'+vals[v]+'">'
                                        + jsonDatas.abroad[after][vals[v]].name
                                        + '</option>'
                                    );
                                }
                            }
                            cache[after][id] = tmp.children();
                        }
                        return cache[after][id];
                    };
                })();

                DOC.ajaxComplete(function(event, xhr, opt) {
                    if (jsons.abroad === opt.url) {
                        // 方面 変更時
                        objs.dst.bind('change reset', (function() {
                            var before = '',            // 前回実行時の値
                                cond   = /^[^\n]*dst-/; // id 属性値 変換条件
                            return function() {
                                // 値の取得対象
                                var target = objs.dst.find('option:selected, input:checked');
                                // id 属性値から得た value 属性値
                                var id = (target.attr('id') || '').replace(cond, '');
                                // value 属性値
                                var val = target.val() || '';
                                // 現状値
                                //   特殊パターン「方面 = 国名」なら id が該当
                                var now = (!val || val === id) ? val : id;
                                // 前回実行時と同一でなければ option 要素を入替
                                if (before !== now) {
                                    before = now;
                                    objs.country.empty().append(
                                        getOptElems(now, countryDef, 'area', 'country')
                                    );
                                }
                                // BUG IE6: select 要素に option 要素を挿入後
                                //          少し待たないと selected 指定で未定義
                                //          のエラーが出る場合がある
                                setTimeout(function() {
                                    // 国名 セレクト
                                    objs.country.val(
                                        // 特殊パターン「方面 = 国名」なら
                                        // country の value 属性値を id として
                                        // 国名を選択
                                        (val === id) ? '' : id
                                    ).trigger('change');
                                }, 1);
                            };
                        })());

                        // 国名 変更時
                        objs.country.bind('change reset', (function() {
                            var before = '';
                            return function(event) {
                                var val = ('reset' === event.type) ? '' : $(this).val();
                                // 前回実行時と同一でなければ実行
                                // '' === val でも実行
                                if (before !== val) {
                                    before = val;
                                    objs.city.empty().append(
                                        getOptElems(val, cityDef, 'country', 'city')
                                    );
                                }
                                // 各種セレクト処理
                                // 常に先頭要素をセレクト
                                objs.city.val('');
                            };
                        })());
                    }
                });

                // データ取得
                jsonDatas.abroad || $.getJSON(jsons.abroad, function(data) {
                    jsonDatas.abroad = data;
                });
                jsonDatas.abroad = jsonDatas.abroad || true;
            })();


            // ----------------------------------------------------------------
            // 出発地 - サブ出発値 同時設定
            // ----------------------------------------------------------------
            (objs.dpt && objs.dptSub) && (function() {
                // 設定
                DOC.ajaxComplete(function(event, xhr, opt) {
                    // 対象 JSON ファイル読込時のみ有効
                    if (jsons.dpt === opt.url) {
                        objs.dpt.bind('change', function() {
                            var data   = jsonDatas.dpt,
                                option = $('option:selected', this),
                                name   = ((
                                    // title 属性値がなければテキストノード流用
                                    option.attr('title') || option.text()
                                ).split(' '))[0]; // 複数値の場合は先頭値のみ
                            // サブ出発地設定
                            objs.dptSub.val(
                                name && name in data ? data[name] : ''
                            );
                        });
                    }
                });
                // リセット
                objs.dptSub.bind('reset', function() {
                    objs.dptSub.val('');
                });
                // データ取得
                jsonDatas.dpt || $.getJSON(jsons.dpt, function(data) {
                    jsonDatas.dpt = data;
                });
                jsonDatas.dpt = jsonDatas.dpt || true;
            })();


            // ----------------------------------------------------------------
            // 出発地 に基づく 集合場所 の追加
            // ----------------------------------------------------------------
            (objs.dpt && objs.meeting) && (function() {
                var def   = objs.meeting.children(), // 既定 option 要素群
                    tmp   = $('<select></select>'),  // キャッシュ時疑似親要素
                    cache = {};                      // option 要素群キャッシュ
                // 設定
                DOC.ajaxComplete(function(event, xhr, opt) {
                    // 対象 JSON ファイル読込時のみ有効
                    if (jsons.meeting === opt.url) {
                        objs.dpt.bind('change', function() {
                            var option   = $('option:selected', this),
                                fullName = option.attr('title') || option.text();
                            // 未キャッシュ時: option 要素生成
                            if (fullName && !(fullName in cache)) {
                                var names   = fullName.split(' '),
                                    nnames  = names.length,
                                    options = [];
                                for (var n = 0; n < nnames; n++) {
                                    var name   = names[n],
                                        places = jsonDatas.meeting[name];
                                    // 登録されている都道府県 - 集合場所対応を使用
                                    if (name && places) {
                                        var nplaces = places.length;
                                        for (var p = 0; p < nplaces; p++) {
                                            options.push('<option value="'+places[p].value+'">'+places[p].name+'</option>');
                                        }
                                    }
                                }
                                cache[fullName] = tmp.append(options.join(''))
                                                     .children();
                            }
                            // option 要素を入替・先頭要素セレクト
                            objs.meeting.empty().append(def).append(
                                fullName ? cache[fullName] : ''
                            ).val('');
                        });
                    }
                });
                // リセット
                objs.meeting.bind('reset', function() {
                    objs.meeting.empty().append(def);
                });
                // データ取得
                jsonDatas.meeting || $.getJSON(jsons.meeting, function(data) {
                    jsonDatas.meeting = data;
                });
                jsonDatas.meeting = jsonDatas.meeting || true;
            })();


            // ----------------------------------------------------------------
            // リセット
            // ----------------------------------------------------------------
            function resetAll() {
                // form 要素をリセット
                form.each(function() {
                    this.reset();
                });
                // reset 独自イベントを発行
                $.each(objs, function() {
                    // スクリプト側で処理した諸々を後始末
                    this.trigger('reset');
                });
                return false;
            }
            reset.click(resetAll); // reset ボタン
            resetAll();
        });
    })();
});


// ----------------------------------------------------------------------------
// MJL Extensions
// ----------------------------------------------------------------------------
(function(window, document) {
    // アクティブタブ class 属性値
    var active = "active";
    // isZoomed 用ズーム基準要素取得
    var getZoomObj = function() {
        return document.getElementById("str-contents") || document.body;
    };

    // isSameNode: 同一ノードの是非を取得
    MJL.isSameNode = document.isSameNode ? function(n1, n2) {
        return n1.isSameNode(n2); // W3C DOM
    } : function(n1, n2) {
        return (n1 == n2);        // Trident etc.
    };

    // --------------------------------
    // event
    // --------------------------------
    // 発送 (= fire)
    MJL.event.dispatch = document.createEvent ? (function() {   // W3C DOM
        // DOM Events レベル
        // BUG Fx2: DOM3 は未サポート部分が多い為使わない
        var level = (MJL.ua.gecko && MJL.ua.version < 3) ? "DOM2" : "DOM3";
        // event オブジェクト初期化
        var initEvent = function(event, init, type, options) {
            event[init].apply(event, [type].concat(options));
        };

        // Sf2 専用設定
        if (MJL.ua.webkit && MJL.ua.version < 3) {
            // BUG Sf2: DOM2 しかサポートしていない
            // BUG Sf2: document.createEvent に未サポートの種類を与えると
            //          "DOM Exception 9" 例外発生
            level = "DOM2";
            // BUG Sf2: 初期化メソッドは initEvent しかサポートしていない
            // BUG Sf2: initEvent.apply が未定義
            initEvent = function(event, init, type, options) {
                // options[2] 以降は全て無視
                event.initEvent(type, options[0], options[1]);
            };
        }

        return function(node, type, bubbles) {
            // イベント種類別 初期化情報
            var data = this._TYPES[level][
                type in this._TYPES[level] ? type : "DEFAULT"
            ];
            // event オブジェクト
            var event = document.createEvent(data.type);
            // 初期化メソッドに与える引数の設定
            var options = ("function" === typeof data.def) ? data.def(node)
                                                           : data.def;
            if ("boolean" === typeof bubbles) {
                options[0] = bubbles;
            }
            // 初期化
            initEvent(event, data.init, type, options);
            return node.dispatchEvent(event);
        };
    })() : document.fireEvent ? function(node, type, bubbles) { // Trident
        var event = document.createEventObject();
        event.cancelBubble = !bubbles;
        return node.fireEvent("on"+type, event);
    } : null;

    // DOM Events デフォルト設定一覧
    // {
    //     DOM Events レベル : {
    //         イベント名 : {
    //             type : カテゴリ,
    //             init : 初期化メソッド名,
    //             // 通常
    //             def  : [パラメタデフォルト値, ...]
    //             // relatedTarget 必要時
    //             def : function(relatedTarget) {
    //                 return [パラメタデフォルト値, ...];
    //             }
    //         }, ...
    //     }, ...
    // }
    MJL.event._TYPES = {
        DOM2 : (function() {
            // カテゴリ
            var UI_EVENT    = "UIEvents",
                MOUSE_EVENT = "MouseEvents",
                HTML_EVENT  = "HTMLEvents",
            // 初期化メソッド名
                INIT_UI_EVENT    = "initUIEvent",
                INIT_MOUSE_EVENT = "initMouseEvent",
                INIT_HTML_EVENT  = "initEvent";
            return {
                // 未定義時のデフォルト
                "DEFAULT"     : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  true]},
                // 定義済イベント種類 (仕様の一部のみ)
                "click"       : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 1, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mousedown"   : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 1, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mouseup"     : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 1, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mouseover"   : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : function(relatedTarget) { return [true,  true,  window, 0, 0, 0, 0, 0, false, false, false, false, 0, relatedTarget]; }},
                "mousemove"   : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 0, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mouseout"    : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : function(relatedTarget) { return [true,  true,  window, 0, 0, 0, 0, 0, false, false, false, false, 0, relatedTarget]; }},
                "load"        : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [false, false]},
                "unload"      : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [false, false]},
                "abort"       : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  false]},
                "error"       : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  false]},
                "select"      : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  false]},
                "change"      : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  false]},
                "focus"       : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [false, false]},
                "blur"        : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [false, false]},
                "resize"      : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  false, window, 1]},
                "scroll"      : {type : HTML_EVENT,  init : INIT_HTML_EVENT,  def : [true,  false, window, 1]}
            };
        })(),
        DOM3 : (function() {
            // カテゴリ
            var UI_EVENT    = "UIEvent",
                TEXT_EVENT  = "TextEvent",
                MOUSE_EVENT = "MouseEvent",
                EVENT       = "Event",
            // 初期化メソッド名
                INIT_UI_EVENT    = "initUIEvent",
                INIT_TEXT_EVENT  = "initTextEvent",
                INIT_MOUSE_EVENT = "initMouseEvent",
                INIT_EVENT       = "initEvent";
            return {
                // 未定義時のデフォルト
                "DEFAULT"     : {type : EVENT,       init : INIT_EVENT,       def : [true,  true]},
                // 定義済イベント種類 (仕様の一部のみ)
                "focus"       : {type : UI_EVENT,    init : INIT_UI_EVENT,    def : [false, false, window, 1]},
                "blur"        : {type : UI_EVENT,    init : INIT_UI_EVENT,    def : [false, false, window, 1]},
                "click"       : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 1, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "dblclick"    : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 2, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mousedown"   : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 1, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mouseup"     : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 1, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mouseover"   : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : function(relatedTarget) { return [true,  true,  window, 0, 0, 0, 0, 0, false, false, false, false, 0, relatedTarget]; }},
                "mousemove"   : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : [true,  true,  window, 0, 0, 0, 0, 0, false, false, false, false, 0, null]},
                "mouseout"    : {type : MOUSE_EVENT, init : INIT_MOUSE_EVENT, def : function(relatedTarget) { return [true,  true,  window, 0, 0, 0, 0, 0, false, false, false, false, 0, relatedTarget]; }},
                "load"        : {type : EVENT,       init : INIT_EVENT,       def : [false, false]},
                "unload"      : {type : EVENT,       init : INIT_EVENT,       def : [false, false]},
                "abort"       : {type : EVENT,       init : INIT_EVENT,       def : [true,  false]},
                "error"       : {type : EVENT,       init : INIT_EVENT,       def : [true,  false]},
                "select"      : {type : EVENT,       init : INIT_EVENT,       def : [true,  false]},
                "change"      : {type : EVENT,       init : INIT_EVENT,       def : [true,  false]},
                "resize"      : {type : UI_EVENT,    init : INIT_UI_EVENT,    def : [true,  false, window, 1]},
                "scroll"      : {type : UI_EVENT,    init : INIT_UI_EVENT,    def : [true,  false, window, 1]}
            };
        })()
    };

    // --------------------------------
    // HeightEqualizer
    // --------------------------------
    // BUG IE7: Tab との組み合わせでリサイズが発生しない問題の修正
    if (MJL.ua.trident && 7 === MJL.ua.version) {
        MJL.HeightEqualizer.prototype.__setAutoResize =
            MJL.HeightEqualizer.prototype._setAutoResize;
        MJL.HeightEqualizer.prototype._setAutoResize = function() {
            this.__setAutoResize();
            var obj = this;
            // this.parent の resize で無理矢理リサイズ
            MJL.event.add(this.parent, "resize", function() {
                obj.set();
            }, false);
        };
    }

    // --------------------------------
    // Tab
    // --------------------------------
    // アクティブタブ＆コンテンツ切替
    MJL.Tab.prototype._active = MJL.Tab.prototype.active;
    MJL.Tab.prototype.active = function(id) {
        var aid = this._getActiveId();
        this._active.apply(this, arguments);
        if (!this._isValidId(id)) { id = aid; }
        // Rollover アクティベート対応
        MJL.event.dispatch(this.items[id].event, "focus", false);
        if (id !== aid) {
            MJL.event.dispatch(this.items[aid].event, "blur", false);
        }
        // resize イベント発送
        if (MJL.ua.trident && 7 <= MJL.ua.version) { // IE7 以降
            // MJL 2.0.7 で追加した無限ループ回避 hack に抵触
            // resize イベントの dispatch が無効になってしまう
            // window.fireEvent が無いためコールスタックで代用
            MJL.event._runStack("resize");
        } else {                                     // IE6, その他
            // HeightEqualizer 自動リサイズ強制作動
            MJL.event.dispatch(this.items[id].panel, "resize", true);
        }
    };

    // --------------------------------
    // style
    // --------------------------------
    // body 要素以外の (style.Switcher による) テキストサイズ変化に対応
    MJL.style.isZoomed = (function() {
        // font-size の Computed Style + ViewPort サイズを利用
        // BUG Opera: ズーム時に Computed Style 値が再計算されない
        if (MJL.ua.opera) {
            var innserSize = 0;    // ViewPort サイズ
            var fontSize   = 0;    // font-size の Computed Style
            var obj        = null; // 計測対象
            // ViewPort サイズがなぜか増減することを併用
            // 但し、何らかの DOM スタイル操作で ViewPort のスクロールバーが
            // 縦横同時に出現した場合、ズームされなくとも true を返す
            // font-size の Computed Style はスタイルスイッチ & 直接変更
            MJL.event.add(window, "load", function() {
                obj       = getZoomObj();
                innerSize = MJL.vp.getInnerSize();
                fontSize  = MJL.style.getComputed(obj, "fontSize");
            }, false);
            return function() {
                var nowInnerSize = MJL.vp.getInnerSize();
                var nowFontSize  = MJL.style.getComputed(obj, "fontSize");
                if (innerSize.width  === nowInnerSize.width  &&
                    innerSize.height === nowInnerSize.height &&
                    fontSize         === nowFontSize) { return false; }
                innerSize = nowInnerSize;
                fontSize  = nowFontSize;
                return true;
            };
        // font-size の Computed Style を利用
        } else {
            var size = 0;    // font-size の Computed Style
            var obj  = null; // 計測対象
            MJL.event.add(window, "load", function() {
                obj  = getZoomObj();
                size = MJL.style.getComputed(obj, "fontSize");
            }, false);
            return function() {
                var nowsize = MJL.style.getComputed(obj, "fontSize");
                if (size === nowsize) { return false; }
                size = nowsize;
                return true;
            }
        }
    })();

    // --------------------------------
    // style.Switcher
    // --------------------------------
    // 生成
    MJL.style.Switcher.prototype._create = MJL.style.Switcher.prototype.create;
    MJL.style.Switcher.prototype.create = function() {
        this._create.apply(this, arguments);
        this.set(); // 同時に set を実行するようにしただけ
    };

    // スタイルを title に設定
    MJL.style.Switcher.prototype._set = MJL.style.Switcher.prototype.set;
    MJL.style.Switcher.prototype.set = function(title) {
        this._set.apply(this, arguments);
        // デフォルトスタイルシートの有無を考慮
        if (!title) {
            title = this._getNowStyleTitle();
        }
        var id  = this._title2id(title);
        var aid = isNaN(this._activeId) ? id : this._activeId;
        // Rollover アクティベート対応
        // this._activeId: アクティブなスイッチの ID
        MJL.addClassName(this.targets[id].node, active);
        MJL.event.dispatch(this.targets[id].node, "focus", false);
        if (id !== aid) {
            MJL.removeClassName(this.targets[aid].node, active);
            MJL.event.dispatch(this.targets[aid].node, "blur", false);
        }
        this._activeId = id;
    };

    // スタイルタイトルから id を逆算
    MJL.style.Switcher.prototype._title2id = function(title) {
        var targets = this.targets;
        var ntargets = targets.length;
        for (var t = 0; t < ntargets; t++) { // 線形探索するしかない
            if (title === targets[t].title) {
                return t;
            }
        }
        return 0;
    };

    // 現在アクティブなスタイルのタイトルを取得
    MJL.style.Switcher.prototype._getNowStyleTitle = function() {
        var sheets = document.styleSheets;
        var nsheets = sheets.length;
        for (var s = 0; s < nsheets; s++) {
            if (sheets[s].title && !sheets[s].disabled) {
                return sheets[s].title;
            }
        }
        return "";
    };


    // --------------------------------
    // Rollover
    // --------------------------------
    // 対象要素とイベントリスナのコレクションを生成
    // this.targets の各アイテムに親要素 parent の項目を追加
    MJL.Rollover.prototype._setTargets = function() {
        var parents  = MJL.getElementsByClassName(document, this.enable);
        var nparents = parents.length;
        for (var p = 0; p < nparents; p++) {
            // 取得した要素自身が対象要素の場合もありうる -> 追加
            this._setTargetsSub(parents[p], parents[p])
            // 取得した要素の子孫要素に対し検索をかける
            for (var n in this._TYPES) {
                var childs = parents[p].getElementsByTagName(n);
                var nchilds = childs.length;
                for (var c = 0; c < nchilds; c++) {
                    this._setTargetsSub(parents[p], childs[c]);
                }
            }
        }
    };

    // 実際に this.targets へ値を設定 (_setTargets 補助)
    MJL.Rollover.prototype._setTargetsSub = function(parent, target) {
        if (this._isTarget(target)) {
            var name = target.nodeName.toLowerCase();
            var getters = this._TYPES[name].getters;
            var item = {
                element : target,
                parent  : parent,
                events  : {}
            };
            for (var v in getters) {
                // call しないと this が違ったままなので注意
                item.events[v] = getters[v].call(this, item);
            }
            this.targets.push(item);
        }
    };

    // 手動アクティブの是非
    // this.targets アイテム仕様に対応
    MJL.Rollover.prototype._isActive = function(target) {
        var element = target.element;
        var parent  = target.parent
        do {
            if (MJL.hasClassName(element, active)) {
                return true;
            }
        } while (
            !MJL.isSameNode(element, parent) && (element = element.parentNode)
        );
        return false;
    };

    // 対象にする要素の種類-条件対応
    // this.targets アイテム仕様に対応
    MJL.Rollover.prototype._TYPES = (function() {
        function getEventGetter(type) {
            return function(target) {
                var off = target.element.getAttribute("src");
                var on  = off.replace(
                    this.options.switchers.on.cond,
                    this.options.switchers.on.replace
                );
                var obj = this;
                var sw  = ("on" === type) ? true : false;
                this._addCache(on);
                return function(event) {
                    target.element.setAttribute(
                        "src",
                        (obj._isActive(target) || sw) ? on : off
                    );
                };
            };
        }
        // イベント種類変換条件
        var event2event = {"focus" : "mouseover", "blur" : "mouseout"};
        function getDescendantEventGetter(type) {
            // this.targets への push が行われる時に実行される
            return function(target) {
                var imgs = target.element.getElementsByTagName("img");
                var nimgs = imgs.length;
                return function(event) {
                    var type = event2event[event.type] || event.type;
                    for (var i = 0; i < nimgs; i++) {
                        // dispatch 方式に変更
                        MJL.event.dispatch(imgs[i], type, false);
                    }
                };
            };
        }
        // 以降はオリジナルから変更なし
        return {
            img : {
                isTarget : function() { return true; },
                getters : {
                    mouseover : getEventGetter("on"),
                    mouseout  : getEventGetter("off")
                }
            },
            input : {
                isTarget : function(elem) {
                    return ("image" === elem.getAttribute("type"));
                },
                getters : {
                    mouseover : getEventGetter("on"),
                    mouseout  : getEventGetter("off"),
                    focus     : getEventGetter("on"),
                    blur      : getEventGetter("off")
                }
            },
            a : {
                isTarget : function(elem) {
                    var imgs = elem.getElementsByTagName("img");
                    return (0 < imgs.length);
                },
                getters : {
                    focus : getDescendantEventGetter("on"),
                    blur  : getDescendantEventGetter("off")
                }
            }
        };
    })();
})(window, document);
