MJL.event.add(window, "load", function() {
    MJL.enable.tab("tabs");
    MJL.enable.styleSwitcher("styleSwitcher");
    MJL.enable.heightEqualizer("form-list-02");
    MJL.enable.heightEqualizer("form-list-03");
    MJL.enable.heightEqualizer("form-list-04");
    MJL.enable.heightEqualizer("list-col2", {groupBy : 2});
    MJL.enable.heightEqualizer("list-col3", {groupBy : 3});
    MJL.enable.rollover("roll", {disable:"unroll"});
    MJL.enable.flash("flash", {version: 9});
    MJL.enable.window("popup", {top:100, width:700, height:570});


    // ------------------------------------------------------------------------
    // 画像とテキスト (based on jQuery)
    // ------------------------------------------------------------------------
    // 画像とテキストの並列処理を行う関数を返す高階関数
    function getImgParallelStyler(side) {
        // 実行関数
        return function() {
            var obj = $(this);
            var imgBlock = $("div.image:first-child", obj);
            var imgWidth = $("p.image img", imgBlock).width(); // 画像幅
            imgBlock.css("width", imgWidth+30+"px"); // 画像幅を強制
            // 別カラムの margin を調整
            $("div.column", obj).css("margin-"+side,
                                     imgBlock[0].offsetWidth+"px");
        };
    }
    // 実行
    $(".image-parallel.image-L").each(getImgParallelStyler("left"));
    $(".image-parallel.image-R").each(getImgParallelStyler("right"));
}, false);


// ----------------------------------------------------------------------------
// jQuery
// ----------------------------------------------------------------------------
$(function() {
    // ------------------------------------------------------------------------
    // スタイルスイッチャ挿入
    // ------------------------------------------------------------------------
    $('#font-control dd').prepend(
        '<ul class="styleSwitcher roll"><li><a href="#font-s"><img src="/shared/images/str-header/btn-font-01.gif" alt="小" /></a></li><li><a href="#font-m"><img src="/shared/images/str-header/btn-font-02.gif" alt="中" /></a></li><li><a href="#font-l"><img src="/shared/images/str-header/btn-font-03.gif" alt="大" /></a></li></ul>'
    );


    // ------------------------------------------------------------------------
    // 印刷ダイアログ表示ボタン挿入
    // ------------------------------------------------------------------------
    ("print" in window) && $([ // window.print() 実装 UA のみ利用
        // {
        //     target    : '対象要素 CSS セレクタ',
        //     container : 'ボタンを格納する target 子要素のマークアップ',
        //     src       : 'ボタン画像のパス'
        // }, ...
        {
            target    : '.control-print-01',
            container : '<p class="btn-print roll"></p>',
            src       : '/shared/images/btn-print-01.gif'
        },
        {
            target    : '.control-print-02',
            container : '<p class="btn-print roll"></p>',
            src       : '/shared/images/btn-print-02.gif'
        },
        {
            target    : '.control-print-03',
            container : '<li class="btn-print"></li>',
            src       : '/shared/images/btn-print-02.gif'
        }
    ]).each(function(n, item) {
        $(item.target).append(
            $(item.container).append(
                $('<input type="image" src='+item.src+' alt="このページを印刷" />').click(function() {
                    window.print();
                    return false;
                })
            )
        );
    });


    // ------------------------------------------------------------------------
    // プレースホルダ実装
    // ------------------------------------------------------------------------
    $('.form-placeholder').each(function() {
        var root  = $(this),                      // 包含ブロック
            lab   = $('label', root),             // label 要素
            input = $('#'+lab.attr('for'), root); // label に関連づいた input
        // アクティブにしてから
        root.addClass('form-placeholder-active');
        // 位置取得
        var rpos = root.offset(),  // 包含ブロック
            ipos = input.offset(); // input
        // label 要素 設定
        lab.css({
            // input 左上を原点として位置あわせ
            top  : Math.abs(ipos.top - rpos.top),
            left : Math.abs(ipos.left - rpos.left),
            // input の padding を与えて最適位置にする
            paddingTop  : input.css('paddingTop'),
            paddingLeft : input.css('paddingLeft'),
            // 背景変更時に備えて 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();
        });
    });


    // ------------------------------------------------------------------------
    // Google Analytics トラッキングコード
    // ------------------------------------------------------------------------
    if ('pageTracker' in window) {
        // アンカー
        $('a.analysis-01').click(function() {
            var href = $(this).attr('href');
            href && window.pageTracker._trackPageview(href);
        });

        // 詳細検索フォーム (トップページ専用)
        $('form.form-analysis-top').each(function() {
            var form = $(this);           // 対象 form 要素
            var cond = /[ \t\n\f\r]+/g;   // 空白文字列 正規表現 (HTML5 仕様)
            var path = location.pathname; // GA 第1引数に与えるパス
            // empty 要素 class 属性値
            var emptyId = 'FORM-ANALYSIS-ID-'+(new Date()).getTime()+'-empty';
            // empty 要素 マークアップ (\u00A0 <=> &nbsp;)
            var empty = '<span class="'+emptyId+'">\u00A0</span>';

            // タブ内 form 関連要素のテキスト化開始
            form.submit(function() {
                var act = ''; // 項目名 (GA 第2引数)
                var lab = ''; // 項目値 (GA 第3引数)
                // テキスト化実行
                form.find('.tabPanel.active').each(function() {
                    var tabPanel = $(this); // アクティブ タブパネル要素
                    var target   = null;    // lab 取得対象要素
                    // 項目名は hx 要素
                    act = $.trim($(':header', tabPanel).text());
                    // タブパネル別 target 取得・部分テキスト化処理
                    $('.form-analysis-include', tabPanel).filter('ul').each(function() {
                        // 馬情報
                        target = $(this).clone(true);
                        var labs = $('label', target);
                        // チェックボックス処理
                        $(':checkbox', target).each(function() {
                            var checkbox = $(this);
                            // 不要 label 要素削除
                            if (!checkbox.is(':checked')) {
                                labs.filter(
                                    '[for="'+checkbox.attr('id')+'"]'
                                ).remove();
                            }
                            // コントロールは常に削除
                            checkbox.remove();
                        });
                    }).end().filter('p').each(function() {
                        // レース
                        var root    = $(this);
                        var origins = root.find('select');
                        target = root.clone(true);
                        // select 要素処理
                        $('select', target).each(function(n) {
                            var select = $(this);
                            var origin = origins.eq(n);
                            // テキスト化
                            select.replaceWith(
                                $.trim(origin.val()) ? $.trim(
                                    origin.find('option:selected').text()
                                ) : empty
                            );
                        });
                        // empty 要素処理
                        var empties = $('.'+emptyId, target);
                        if (origins.length <= empties.length) {
                            target.empty();   // 全て empty 要素なら全削除
                        } else {
                            empties.remove(); // empty 要素内 &nbsp; 出現防止
                        }
                    });
                    // 全範囲のテキスト化
                    if (target) {
                        lab = $.trim(target.text().replace(cond, ' '));
                    }
                });
                // Google Analytics に伝達
                act && lab && pageTracker._trackEvent(path, act, lab);
            });
        });

        // 詳細検索フォーム
        $('form.form-analysis').each(function() {
            var form = $(this);           // 対象 form 要素
            var cond = /[ \t\n\f\r]+/g;   // 空白文字列 正規表現 (HTML5 仕様)
            var path = location.pathname; // GA 第1引数に与えるパス
            // 部分テキスト化済要素 class 属性値
            var wrapId = 'FORM-ANALYSIS-ID-'+(new Date()).getTime();
            // empty 要素 class 属性値
            var emptyId = wrapId+'-empty';
            // 部分テキスト化済要素 マークアップ
            var wrap = '<span class="'+wrapId+'"></span>';
            // empty 要素 マークアップ (\u00A0 <=> &nbsp;)
            var empty = '<span class="'+emptyId+'">\u00A0</span>';

            // td 要素内 form 関連要素のテキスト化開始
            form.submit(function() {
                // オリジナル form 要素内の th 要素群
                var oths = $('th', form);
                // オリジナルの form 要素に影響を与えないためのクローン
                var clone = form.clone(true);
                // th 要素群
                var ths = $('th', clone);
                // 操作対象 label 要素群
                var labs = $('td label', clone);

                // BUG jQuery 1.3.2: クローンが DOM ツリーに追加されていないと
                //                   Sizzle による要素検索時に Sf3 で L2118 の
                //                   aRange.selectNode(a); がエラーになる
                clone.hide().appendTo(document.body); // レンダリングはしない

                // BUG: clone() では select 要素のセレクト状態が引き継がれない
                (function() {
                    var selects = $('select', clone);
                    $('select', form).each(function(n) {
                        // オリジナルから状態を強制移植して回避
                        selects.eq(n).val($(this).val());
                    });
                })();

                // 1行に2つ以上の th 要素がある場合、強制行分割を実施
                // 後の除外・テキスト化処理のアルゴリズムを簡易にする
                $('tr', clone).each(function() {
                    // 検索中の行
                    var tr = $(this);
                    // もう1組の th-td ペア (非汎用的)
                    var th     = $('th:eq(1)', this);      // th 要素のみ
                    var target = $($.makeArray(th).concat( // th-td 要素ペア
                        $.makeArray(th.nextAll())
                    ));
                    // もう1組の th-td ペアを直後の行に強制分割
                    if (0 < target.length) {
                        tr.after(target.wrapAll('<tr></tr>').parent());
                    }
                });

                // 注釈文言 動的変更 (レース検索 ONLY) 部分を非表示時に
                // 削除対象要素とする
                (function() {
                    // クローンは DOM ツリーに追加していないので :hidden 判定
                    // できない
                    // オリジナル form 要素で判定し、クローン内で対応する要素
                    // を変更
                    var selector = '.form-changeword-term'; // 対象 CSS セレクタ
                    var cw       = $(selector, clone);      // クローン内対象要素
                    $(selector, form).each(function(n) {
                        $(this).is(':hidden') && cw.eq(n).remove();
                    });
                })();

                // 部分テキスト化実行後のデータ取得
                ths.map(function(n) {
                    // 意図的に隠されている場合は無視
                    if (oths.eq(n).is(':hidden')) { return ''; }
                    // 各 table 関連要素集合
                    var th = $(this);
                    var tr = th.parent();
                    var td = tr.find('td');
                    // 関連して処理する追加行数
                    var rows = parseInt(th.attr('rowspan'), 10) || 0;
                    // rowspan があれば td 要素を追加取得
                    if (1 < rows) {
                        // merge 利用不可により次の方法で代替:
                        //   1. jQuery オブジェクト → Array
                        //   2. 得られた Array を concat
                        //   3. concat した Array を $() に食わせて
                        //      jQuery オブジェクト化
                        td = $($.makeArray(td).concat($.makeArray(
                            // rowspan 分の tr > td 要素
                            tr.nextAll(':lt('+(rows-1)+')').find('td:first-child')
                        )));
                    }
                    // 部分テキスト化
                    td.find(':image, :submit, :reset, :button').remove(
                        // 削除対象要素の除外処理
                        // empty 要素化はしない
                    ).end().find('.form-analysis-exclude, .list-notice-01, p').each(function() {
                        // 対象外要素の empty 要素化
                        var exclude = $(this);
                        // 関連 label 要素も empty 要素化
                        labs.filter(
                            '[for="'+exclude.attr('id')+'"]'
                        ).replaceWith(empty);
                        // 対象外要素を empty 要素化
                        exclude.replaceWith(empty);
                    }).end().find('select').each(function() {
                        // select 要素処理
                        var select = $(this);
                        // テキスト化
                        select.replaceWith(
                            $.trim(select.val()) ? $(wrap).text(
                                $.trim(select.find('option:selected').text())
                            ) : empty
                        );
                    }).end().find(':text').each(function() {
                        // ユーザ入力テキスト処理
                        var text = $(this);
                        var val  = $.trim(text.val());
                        // テキスト化
                        text.replaceWith(
                            val ? $(wrap).text(val) : empty
                        );
                    }).end().find(':radio, :checkbox').each(function() {
                        // チェックボックス・ラジオボタン処理
                        var box = $(this);
                        var lab = labs.filter('[for="'+box.attr('id')+'"]');
                        // テキスト化
                        if (box.is(':checked')) {
                            lab.wrapAll(wrap);
                        } else {
                            lab.replaceWith(empty);
                        }
                        // コントロールは常に削除
                        box.remove();
                    });
                    // 対象 td 要素群 全体をテキスト化
                    var tdStr = $.trim($.makeArray(td.map(function() {
                        this.normalize(); // 念のため
                        var obj     = $(this);
                        var wraps   = obj.find('.'+wrapId);  // 部分テキスト群
                        var empties = obj.find('.'+emptyId); // empty 要素群
                        var ret     = '';
                        // テキスト取得対象ならテキスト化
                        //   通常 (= 部分テキスト群 有)
                        //     form 関連要素がテキスト化されている
                        //   特殊 (= empty 要素 無)
                        //     最初からテキストのみ存在
                        //     例：会員用ページ内 各種詳細検索フォーム
                        if (0 < wraps.length || empties.length < 1) {
                            empties.remove(); // empty 要素内 &nbsp; 出現防止
                            ret = obj.text();
                        }
                        return ret;
                    })).join('').replace(cond, ' ')); // 空白文字は最適化
                    // 拾うべき内容があれば保存
                    return tdStr ? {
                        act : th.text(), // 項目名 (GA 第2引数)
                        lab : tdStr      // 項目値 (GA 第3引数)
                    } : null; // 何もない場合
                // Google Analytics に伝達
                }).each(function(n, item) {
                    item && pageTracker._trackEvent(path, item.act, item.lab);
                });
                // BUG jQuery 1.3.2: 対応で DOM ツリーに追加したクローンを削除
                clone.remove();
            });
        });
    }


    // ------------------------------------------------------------------------
    // 注釈文言 動的変更
    // ------------------------------------------------------------------------
    $('.form-changeword').each(function() {
        var root = $(this),
            form = root.parents('form'),
            json = '/shared/js/form-changeword.json';
        // label - 文言対応のある JSON ファイルをロード
        $.getJSON(json, function(data) {
            // 親要素の class 属性値から適切な文言一覧を取得
            var texts; // label - 文言対応
            for (var selector in data) {
                if (0 < root.parents(selector).length) {
                    texts = data[selector];
                    break; // 一意に絞る
                }
            }
            if (!texts) { return; } // 見つからなければ何もしない
            // 各種要素
            var notice  = $('<ul class="list-notice-01"></ul>'), // 挿入対象
                targets = $('input:radio', root),                // 対象
                before;                                          // 前回表示
            // 文言生成
            targets.each(function() {
                var target = $(this),
                    key    = $('label', target.parent()).text(), // label 文言
                    item;                                        // 文言キャッシュ
                // ラベルがある場合のみ有効
                key && target.change(function() {
                    // 初回時 文言生成
                    if (!item) {
                        item = $('<li><span>※</span>'+texts[key]+'</li>').hide();
                        notice.append(item);
                    }
                    // チェックされたら文言を表示
                    //   before は item を直接代入することで、言語仕様レベルの
                    //   オブジェクト比較を可能にしている
                    if (target.is(':checked') && before !== item) {
                        before && before.hide();
                        item.show();
                        before = item;
                    }
                });
            });
            // リセット対応
            form.bind('reset', function() {
                targets.filter(function() {
                    return this.defaultChecked;
                }).attr('checked', true).trigger('change');
            });
            root.after(notice); // 表示
            targets.filter(':checked').trigger('change'); // ロード時初期化
        });
    });


    // ------------------------------------------------------------------------
    // 注釈文言 動的変更 (レース検索 ONLY)
    // ------------------------------------------------------------------------
    $('.form-race').each(function() {
        var form    = $(this).parents('form'),                 // form 要素
            targets = $('.form-changeword input:radio', this), // 対象要素
            term    = $('.form-changeword-term', this),        // 元要素
            // 元要素を表示させるラベル
            cond    = /フリーワード/,
            // 文言
            notice  = $('<ul class="list-notice-01 reset-mb-00"><li><span>※</span>本日より過去1年分のデータを集計します</li></ul>').hide();
        // 挙動
        targets.each(function() {
            var target = $(this),
                key    = $('label', target.parent()).text(); // label 文言
            // ラベルがある場合のみ有効
            key && target.change(function() {
                if (target.is(':checked')) {
                    if (cond.test(key)) { // 元要素を表示
                        term.show();
                        notice.hide();
                    } else {              // 文言を表示
                        term.hide();
                        notice.show();
                    }
                }
            });
        });
        // リセット対応
        form.bind('reset', function() {
            targets.filter(function() {
                return this.defaultChecked;
            }).attr('checked', true).trigger('change');
        });
        term.after(notice); // 表示
        targets.filter(':checked').trigger('change'); // ロード時初期化
    });


    // ------------------------------------------------------------------------
    // テーブル行表示 動的変更
    // ------------------------------------------------------------------------
    $('.form-switch').each(function() {
        var form = $(this),
            json = '/shared/js/form-switch.json';
        // label - 表示対象対応のある JSON ファイルをロード
        $.getJSON(json, function(data) {
            var inter; // label - 表示対象対応
            for (var selector in data) {
                if (form.is(selector)) {
                    inter = data[selector];
                    break; // 一意に絞る
                }
            }
            if (!inter) { return; } // 見つからなければ何もしない

            var targets = $(inter.targets, form), // イベント対象
                hides   = $(inter.hides, form),   // 非表示対象
                lines   = $('tr', form),          // 再描画対象行
                ths     = $('th', form),          // 行数基準要素
                before;                           // 前回表示
            // 奇数/偶数行 (odd/even) 色分け再描画
            function drawSegmentLine() {
                // 描画キャンセル
                lines.removeClass('segment');
                // 行数基準要素のカウントで偶数行を決定
                // jQuery の :odd/:even は0ベースなので :odd
                ths.filter(':visible:odd').each(function() {
                    var obj    = $(this),
                        parent = obj.parent(),
                        rows   = parseInt(obj.attr('rowspan'), 10) || 1;
                    // 親要素は常に偶数行なので描画
                    parent.addClass('segment');
                    // rowspan 数だけ同一色で描画
                    for (var r = 1; r < rows; r++) {
                        parent.next().addClass('segment');
                    }
                });
            }
            // 設定
            targets.each(function() {
                var target = $(this),
                    lab    = $('label', target.parent()).text(); // label 文言
                // ラベルがある場合のみ有効
                if (lab && lab in inter.shows) {
                    var shows = $(inter.shows[lab], form); // 表示対象
                    target.change(function() {
                        // 表示/非表示 切替
                        if (target.is(':checked') && before !== lab) {
                            // 一旦全て非表示 → 表示
                            hides.hide();
                            shows.show();
                            drawSegmentLine();
                            before = lab;
                        }
                    });
                }
            }).filter(':checked').trigger('change'); // ロード時初期化
            // リセット対応
            form.bind('reset', function() {
                targets.filter(function() {
                    return this.defaultChecked;
                }).attr('checked', true).trigger('change');
            });
        });
    });


    // ------------------------------------------------------------------------
    // フォーム validation
    // ------------------------------------------------------------------------
    $('.form-validate').each(function() {
        var form = $(this),
            json = '/shared/js/form-validate.json';

        // ランキング検索 専用指定
        if (form.is('.form-ranking')) {
            // 「テーブル行表示 動的変更」に依存するため
            // 全 Ajax リクエストが終了した後で実行
            $(document).ajaxStop(function() {
                // ランキング種類
                var rankings = $('.form-change-ranking input:radio', form);
                // 区分
                var division = $('.form-validate-division', form);
                // 対象要素
                var targets = $('input:radio', division);
                // 競争種別
                var types = $('.form-change-type', form);
                // 競争種別 (コース)
                var cources = $('#form-coursetype-composite, #form-coursetype-lawn, #form-coursetype-dirt', form);
                // 競争種別 (レース)
                var races = $('.form-validate-racetype input:radio', form);
                // デフォルト競争種別 (コース)
                var defCource = cources.filter(function() { return this.defaultChecked; });
                // デフォルト競争種別 (レース)
                var defRace = races.filter(function() { return this.defaultChecked; });
                // 総合 (コース)
                var comp = cources.filter(function() {
                    return '総合' === $(this).siblings('label').text();
                });
                // 平地 (レース)
                var plain = races.filter(function() {
                    return '平地' === $(this).siblings('label').text();
                });
                // 「区分」変更チェック
                targets.each(function() {
                    var target = $(this),
                        lab    = target.siblings('label').text(); // label 文言
                    target.change(function() {
                        if (target.is(':checked')) {
                            // 「地方」は常に
                            //   * 競争種別 (コース): 総合
                            //   * 競争種別 (レース): 平地
                            if ('地方' === lab) {
                                comp.attr('checked', true);
                                plain.attr('checked', true);
                                cources.attr('disabled', true);
                                races.attr('disabled', true);
                            // 前状態が「地方」なら既定状態に戻す
                            // plain の disabled で判定 (true なら前状態が「地方」)
                            } else if (plain.attr('disabled')) {
                                defCource.attr('checked', true);
                                defRace.attr('checked', true);
                                cources.attr('disabled', false);
                                races.attr('disabled', false);
                            }
                        }
                    });
                }).filter(':checked').trigger('change'); // ロード時初期化
                // 「ランキング」項目の変更に追従
                // 「テーブル行表示 動的変更」に依存
                rankings.bind('change', function() {
                    if (division.is(':hidden') && types.is(':visible')) {
                        // 「区分」非表示なら disable 解除
                        cources.attr('disabled', false);
                        races.attr('disabled', false);
                    } else {
                        // 「区分」変更チェックを実行させる
                        targets.filter(':checked').trigger('change');
                    }
                });
                // リセット対応
                form.bind('reset', function() {
                    targets.filter(function() {
                        return this.defaultChecked;
                    }).attr('checked', true).trigger('change');
                });
            });
            return; // あとは無視
        }

        // 対象要素 - 操作対象要素 イベント設定
        function setSwitch(forSelector, toSelector) {
            var fors     = $(forSelector, form), // 対象要素
                tos      = $(toSelector, form),  // 操作対象要素
                tosArea  = tos.filter(           // 操作対象 (val() 対象)
                    ':text, :password, :file, select, textarea'
                ),
                tosInput = tos.filter(           // 操作対象 (attr() 対象)
                    ':checkbox, :radio'
                );
            fors.each(function() {
                var target = $(this),              // 対象要素
                    isArea = target.is(            // val() 対象是非
                        ':text, :password, :file, select, textarea'
                    ),
                    isRadio = target.is(':radio'); // ラジオボタン是非
                // ラジオボタンなら同一 name 属性値の要素を対象として再収集
                if (isRadio) {
                    var name = target.attr('name');
                    if (name) {
                        target = $('input:radio[name="'+name+'"]', form);
                    }
                }
                // 設定
                target.bind('change reset', function(event) {
                    var obj     = $(this),
                        isReset = ('reset' === event.type),
                        // disabled 属性値
                        //   val() 対象:   val() 値の有無で判定
                        //   ラジオボタン: forSelector の checked 値で判定
                        //   その他:       checked 値で判定
                        disabled = isArea ? (0 < fors.filter(function() {
                                      return !!$.trim($(this).val());
                                  }).length)
                                : isRadio ? obj.is(':checked') && obj.is(forSelector)
                                : (0 < fors.filter(':checked').length);
                    // 無効化時に操作対象要素の状態をリセット
                    if (isReset || disabled) {
                        tosArea.val('');
                        tosInput.attr('checked', false);
                    }
                    // 無効化設定
                    tos.attr('disabled', isReset ? false : disabled);
                    // reset 時は reset イベントを bubble-up させない
                    //   -> form 要素が bubble-up した reset イベントを拾って
                    //      無限ループになるため
                    return !isReset; // false で preventDefault/stopPropagation
                });
            }).trigger('change'); // ロード時初期化
            // リセット対応
            form.bind('reset', function() {
                fors.trigger('reset');
            });
        }
        // 操作対象要素 CSS セレクタ - 対象要素 CSS セレクタ対応のある
        // JSON ファイルをロード
        $.getJSON(json, function(data) {
            // 基底要素 CSS セレクタから適切なセレクタ対応を取得
            for (var selector in data) {
                if (form.is(selector)) {
                    var types = data[selector];
                    for (var forSelector in types) { // イベント設定
                        setSwitch(forSelector, types[forSelector]);
                    }
                    break; // 一意に絞る
                }
            }
        });
    });


    // ------------------------------------------------------------------------
    // スライダ
    // ------------------------------------------------------------------------
    jQuery.ui && $('.form-slider-01').each(function() {
        var root         = $(this),
            form         = root.parents('form'),
            from         = $('.form-slider-from', root),
            to           = $('.form-slider-to', root),
            wrapper      = $('<div class="form-slider-wrapper"></div>'),
            slider       = $('<div class="form-slider-widget"></div>'),
            input2slider = $('<input type="image" src="/shared/images/contents-form/btn-slider-01-01.gif" alt="スライダに反映" class="reset-ml-20" />');
        // スライダ動作時 イベントリスナ
        function setValue(event, ui) {
            // 各入力フォームへ値を設定
            // ∞なら上限なしとみなす
            from.val(ui.values[0]);
            to.val(isFinite(ui.values[1]) ? ui.values[1] : '');
        }
        // スライダ設定
        slider.slider({
            range  : true,
            min    : 0,      // 0円
            max    : 100000, // 10億円
            step   : 1000,   // 1000万円
            values : [
                parseInt(from.val(), 10) || 0,
                parseInt(to.val(), 10)   || 0,
            ],
            slide  : setValue,
            change : setValue
        });
        // 「スライダに反映」ボタン追加
        $('.list-notice-01', root).before(input2slider.click(function() {
            var fromVal = parseInt(from.val(), 10),
                toVal   = parseInt(to.val(), 10);
            // 不正時正規化 (NaN ないし 0 未満)
            if (isNaN(fromVal) || fromVal < 0) { // fromVal 不正
                fromVal = 0;
            }
            if (isNaN(toVal)) {     // 未入力と認識したら上限なし
                toVal = Number.POSITIVE_INFINITY;
            } else if (toVal < 0) { // toVal 不正
                toVal = 0;
            }
            // 下限と上限の逆転防止
            if (toVal < fromVal) {
                // 下限と上限を swap して対応
                var tmp = fromVal;
                fromVal = toVal;
                toVal   = tmp;
            }
            // スライダに反映
            slider.slider(
                'values', 0, fromVal
            );
            slider.slider(
                'values', 1, 0 <= toVal ? toVal : Number.POSITIVE_INFINITY
            );
            return false;
        }).trigger('click')); // ロード時初期化
        // リセット対応
        form.bind('reset', function() {
            from.val(0);
            to.val('');
            input2slider.trigger('click');
        });
        // 表示
        root.prepend(wrapper.append(slider));
    });


    // ------------------------------------------------------------------------
    // 画像プレビュー
    // ------------------------------------------------------------------------
    jQuery.ui && (function() {
        // プレビュー構成要素
        var dialog = $('<div class="dialog-preview-01"></div>'),
            img    = $('<img alt="" />'),
            close  = $('<input type="image" src="/shared/images/btn-close-01.gif" alt="閉じる" />');
        // 組立
        dialog.append($('<p class="preview"></p>').append(img))
              .append($('<p class="close"></p>').append(close));
        // jQuery UI dialog 生成
        dialog.dialog({
            autoOpen  : false,
            width     : 'auto',
            height    : 'auto',
            modal     : true,
            resizable : false,
            stack     : false,
            open      : function() { // fadeIn を利用
                // open 前に show しているため一旦 hide
                root.hide();
                // BUG IE6: フォーム関連要素が z-index を無視する
                if ($.browser.msie && $.browser.version <= 6) {
                    // オーバレイ用要素は open 時に都度生成されるため都度取得が
                    // 必要 (キャッシュ不可)
                    var overlay = $('div.ui-widget-overlay');
                    // hide → iframe 挿入 → show しないとレンダリング失敗
                    overlay.hide();
                    // dialog の bgiframe オプションだと modal:true であっても
                    // 強制的に root 要素で bgiframe が実行されるため独自処理
                    // root 要素に bgiframe をかけると各種アニメーションが
                    // 無効化される
                    overlay.bgiframe();
                    overlay.show();
                    // 疑似的に別プロセス化しないとうまくアニメーションしない
                    setTimeout(function() {
                        root.fadeIn('slow');
                    }, 0);
                } else {
                    root.fadeIn('slow');
                }
            },
            close : function() {     // fadeOut を利用
                // close 前に hide しているため一旦 show
                root.show();
                root.fadeOut('slow');
            }
        });
        // dialog の基底要素
        var root = dialog.parent(); // dialog() 実行後でないと実体がない
        // titlebar は不要
        $('.ui-dialog-titlebar', root).remove();
        // 独自 close ボタン
        close.click(function() {
            dialog.dialog('close');
            return false;
        });
        // 表示
        $('.preview-01').click(function() {
            var href = $(this).attr('href');
            if (href) {
                if (href === img.attr('src')) { // 前回表示画像と同一
                    dialog.dialog('open');
                } else {                        // 前回表示画像と違う
                    img.attr('src', href).load(function() {
                        // UA 側に画像キャッシュがない場合
                        // 画像のロード完了まで待たないとダイアログ位置が不正
                        dialog.dialog('open');
                    });
                }
            }
            return false;
        });
    })();


    // ------------------------------------------------------------------------
    // BUG Trident: Fix
    // ------------------------------------------------------------------------
    if($.browser.msie) {
        // blur しないと change イベントが発生しない
        $('input:radio, input:checkbox').click(function() {
            this.blur();
            this.focus();
        });
    }
});


// ----------------------------------------------------------------------------
// MJL Extensions
// ----------------------------------------------------------------------------
(function(window, document) {
    // アクティブ状態 class 属性値
    var active = "active";

    // isSameNode: 同一ノード是非
    MJL.isSameNode = document.isSameNode ? function(n1, n2) { // W3C DOM
        // WebKit: window.isSameNode 未定義
        return (window !== n1 && window !== n2) ? n1.isSameNode(n2) : (n1 === n2);
    } : function(n1, n2) {                                    // Trident
        return n1 === n2;
    };

    // イベント発送 (= fire)
    MJL.event.dispatch = document.createEvent ? (function() {
        // BUG Sf2: "HTMLEvents" でないと "DOM Exception 9" 例外発生
        // BUG Op: "Event" 未サポート
        var eventType = (MJL.ua.webkit && MJL.ua.version < 3) ? "HTMLEvents"
                                                              : "Event";
        return function(node, type, bubbles) {
            var event = document.createEvent(eventType);
            event.initEvent(type, bubbles, true);
            return node.dispatchEvent(event);
        };
    })() : document.createEventObject ? function(node, type, bubbles) {
        var event = document.createEventObject();
        event.cancelBubble = !bubbles;
        return node.fireEvent("on"+type, event);
    } : null;


    // ------------------------------------------------------------------------
    // Tab
    // ------------------------------------------------------------------------
    // アクティブタブ＆コンテンツ切替
    MJL.Tab.prototype.active = (function() {
        var tmp = MJL.Tab.prototype.active;
        return function(id) {
            var aid = this._getActiveId();
            tmp.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);
            }
        };
    })();


    // ------------------------------------------------------------------------
    // style.Switcher
    // ------------------------------------------------------------------------
    // 生成
    MJL.style.Switcher.prototype.create = function(/* arguments */) {
        this.setOptions.apply(this, arguments);
        this._setTargets();
        this._setEvent();
        // 同時に set を実行
        // this._getCookie 内の set は削除
        this.set(this._getCookie());
    };

    // スタイルを title に設定
    MJL.style.Switcher.prototype.set = function(title) {
        // デフォルトスタイルシートの有無を考慮
        var before = this._getNowTitle(), // 現在の title
            after  = title || before,     // 設定する title
            id     = this._title2id(after),
            aid    = isNaN(this._activeId) ? id : this._activeId;
        // Rollover アクティベート対応
        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;
        // BUG IE6: このタイミングで描画しないと、他の画像がロードされない
        //          場合がある
        title && MJL.style.switchAlt(title);
        this._setCookie(after); // 必ず after を設定
    };

    // スタイルタイトルから id を逆算
    MJL.style.Switcher.prototype._title2id = function(title) {
        var targets  = this.targets,
            ntargets = targets.length;
        for (var t = 0; t < ntargets; t++) { // 線形探索するしかない
            if (title === targets[t].title) {
                return t;
            }
        }
        return 0; // なければ先頭
    };

    // 現在アクティブなスタイルのタイトルを取得
    MJL.style.Switcher.prototype._getNowTitle = function() {
        var sheets  = document.styleSheets,
            nsheets = sheets.length;
        for (var s = 0; s < nsheets; s++) {
            if (sheets[s].title && !sheets[s].disabled) {
                return sheets[s].title;
            }
        }
        return "";
    };

    // Cookie 値を取得
    MJL.style.Switcher.prototype._getCookie = function() {
        // set は実行せず、値を return するように変更
        return this._cookie.get(this._COOKIE_STATUS.key);
    };


    // ------------------------------------------------------------------------
    // Rollover
    // ------------------------------------------------------------------------
    // 生成
    MJL.Rollover.prototype.create = (function() {
        var tmp = MJL.Rollover.prototype.create;
        return function(/* arguments */) {
            tmp.apply(this, arguments);
            var targets  = this.targets,
                ntargets = targets.length;
            // 1回 on/off して強制アクティベート
            for (var t = 0; t < ntargets; t++) {
                MJL.event.dispatch(targets[t].element, "mouseover");
                MJL.event.dispatch(targets[t].element, "mouseout");
            }
        };
    })();

    // 対象要素とイベントリスナのコレクションを生成
    // this.targets の各アイテムに親要素 parent の項目を追加
    MJL.Rollover.prototype._setTargets = function() {
        var parents  = MJL.getElementsByClassName(document, this.enable),
            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),
                    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(),
                getters = this._TYPES[name].getters,
                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,
            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 obj = this,
                    sw  = ("on" === type) ? true : false,
                    off = target.element.getAttribute("src"),
                    on  = off.replace(
                        this.options.switchers.on.cond,
                        this.options.switchers.on.replace
                    );
                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"),
                    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);
                    }
                };
            };
        }
        // button 要素の場合を追加
        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")
                }
            },
            button : {
                isTarget : function(elem) {
                    var imgs = elem.getElementsByTagName("img");
                    return (0 < imgs.length);
                },
                // button 要素の子孫要素からイベントがバブリングしない
                getters : MJL.ua.trident ? {
                    // Trident: バブリングするため設定厳禁
                    //          dispatch がループしてスタックオーバーフロー
                    focus : getDescendantEventGetter("on"),
                    blur  : getDescendantEventGetter("off")
                } : {
                    mouseover : getDescendantEventGetter("on"),
                    mouseout  : getDescendantEventGetter("off"),
                    focus     : getDescendantEventGetter("on"),
                    blur      : getDescendantEventGetter("off")
                }
            },
            a : {
                isTarget : function(elem) {
                    var imgs = elem.getElementsByTagName("img");
                    return (0 < imgs.length);
                },
                getters : {
                    focus : getDescendantEventGetter("on"),
                    blur  : getDescendantEventGetter("off")
                }
            }
        };
    })();
})(window, document);

