ゴミ溜め@技術系日常系雑文

主にWeb技術やそのほかつまづいたこととか引っかかって調べたこととかをまとめてます。

はてなダイアリーから引っ越しました。)

最低限文化的な階調機能付きスライダー

404 Blog Not Found:DHTML - 最低限文化的なスライダーの実装
http://trackback.blogsys.jp/livedoor/dankogai/51733122
で記述されてたスライダーに、階調機能をつけた。

なんかIE7で動かないような気がするけど気のせいかな。

動作デモはこちら

<!DOCTYPE HTML>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title></title>

        <style>
            .slider   { 
                -webkit-user-select: none;
                -webkit-tap-highlight-color: transparent;
                border:inset 1px; height: 2em;
            }
            .slider > div {
                height:100%;
            }
            #status > dt {
                border-top: 2px solid #909090;
                margin-top: 5px;
            }
        </style>

    </head>
    <body>
        <div style="border:outset 1px; padding:0.5em">
            <dl>
                <dt>Red</dt>
                <dd><div id="rslider" class="slider"><div style="background-color:#f00;">&nbsp;</div></div></dd>

                <dt>Green</dt>
                <dd><div id="gslider" class="slider"><div style="background-color:#0f0;">&nbsp;</div></div></dd>

                <dt>Blue</dt>
                <dd><div id="bslider" class="slider"><div style="background-color:#00f;">&nbsp;</div></div></dd>

                <dt>RGB</dt>
                <dd>
                <div id="rgb" class="slider"></div>
                </dd>
            </dl>
        </div>

        <script>

            // 各種設定。
            var setting = {
                tone : 5,   // スライドの階調:falseまたは任意の正の数
                initial: {
                    red   : "100%",
                    green : "80%",
                    blue  : "20%"
                }
            };

            // 数字をゼロ埋めする。
            // 参考 : http://saboten009.blogspot.com/2009/04/javascript0.html
            function formatNum(keta, num) {
                var src = new String(num);
                var cnt = keta - src.length;
                if (cnt <= 0) return src;
                while (cnt-- > 0) src = "0" + src; return src;
            }

            // IE〜8でxEventListenerが使えない仕様の回避。
            var eventListener = {
                add: (function(w){
                    return w.addEventListener
                        ? function(obj, evt, func, bool) { obj.addEventListener(evt, func, bool) }
                        : w.attachEvent
                        ? function(obj, evt, func, bool) { obj.attachEvent("on"+evt, func) }
                        : function(obj, evt, func, bool) { obj["on"+evt] = func };
                })(window),
                remove: (function(w) {
                    return w.removeEventListener
                        ? function(obj, evt, func, bool) { obj.removeEventListener(evt, func, bool) }
                        : w.detachEvent
                        ? function(obj, evt, func, bool) { obj.detachEvent("on"+evt, func) }
                        : function(obj, evt, func, bool) { delete pbj["on"+evt] };
                })(window)
            };

            // IEでgetBoundingClientRectの値がずれる,widthがない等を修正。
            // 参考 : http://d.hatena.ne.jp/terurou/20080223/1203705170
            var getRect = (function(elem) {
                var rect = elem.getBoundingClientRect();

                var pageBorderLeft = document.body.scrollLeft
                || document.documentElement.scrollLeft;
                var pageBorderTop  = document.body.scrollTop
                || document.documentElement.scrollTop;

                return {
                    left  : rect.left   - pageBorderLeft,
                    top   : rect.top    - pageBorderTop,
                    right : rect.right  - pageBorderLeft,
                    bottom: rect.bottom - pageBorderTop,
                    width : rect.right  - rect.left,
                    height: rect.bottom - rect.top
                }
            });

            (function(d){

                var addSliderEvents = function(me, cb){
                    var move, mdown, mmove, mup, tstart, tmove, tend;
                    move = function(clientX, rect){

                        var width = clientX - rect.left
                            unit_with = rect.width / setting.tone;

                        if     (width<0)          width = "0%";
                        else if(rect.width<width) width = "100%";
                        else {
                            if (!setting.tone && setting.tone==0) {
                                width = width/rect.width*100 +"%";
                            }
                            else {
                                width = ( Math.floor(width/unit_with) * unit_with ) / rect.width * 100 + "%";
                            }
                        }
                        me.firstChild.style.width = width;
                        cb();
                    };
                    mdown = function(ev){
                        eventListener.add(d, 'mousemove', mmove, false);
                        eventListener.add(d, 'mouseup', mup, false);
                        mmove(ev);
                    };
                    mmove = function(ev){
                        move(ev.clientX, getRect(me));
                    };
                    mup = function(ev){
                        eventListener.remove(d, 'mousemove', mmove, false);
                        eventListener.remove(d, 'mousedown', mup, false);
                    };
                    eventListener.add(me, 'mousedown', mdown, false);

                    tstart = function(ev){
                        eventListener.add(d, 'touchmove', tmove, false);
                        eventListener.add(d, 'touchend', tend, false);
                        tmove(ev);
                    }
                    tmove = function(ev){
                        ev.preventDefault();
                        move(ev.touches[0].clientX, me.getBoundingClientRect());
                    };
                    tend = function(ev){
                        eventListener.remove(d, 'touchmove', tmove, false);
                        eventListener.remove(d, 'touchend', tend, false);
                    };
                    eventListener.add(me, 'touchstart', tstart, false);
                };
            
                var changecolor = function() {

                    var rgb = d.getElementById('rgb');
                    var bgcolor = (function(bg) {
                        for(var i=0,rgb=['r','g','b']; i<rgb.length; i++ ) {
                            bg+= Math.round( document.getElementById(rgb[i]+'slider')
                            .firstChild.style.width.replace(/%/,'') / 100 * 255 ) + ',';
                        }
                        return ('rgb('+bg.replace(/,$/,')'));
                    })('');
                    rgb.style.backgroundColor = rgb.innerHTML = bgcolor;
                };
                
                for(var i=0, rgb=['r','g','b']; i < rgb.length; i++ ) {
                    addSliderEvents(d.getElementById(rgb[i] + 'slider'), changecolor);
                }

                // 初期化。
                window.onload = function() {

                    if (setting.initial.red)
                        document.getElementById("rslider").firstChild.style.width = setting.initial.red;
                    if (setting.initial.green)
                        document.getElementById("gslider").firstChild.style.width = setting.initial.green;
                    if (setting.initial.blue)
                        document.getElementById("bslider").firstChild.style.width = setting.initial.blue;

                    changecolor();
                };

            })(document);
        </script>
    </body>
</html>

HTML+jQueryでマルチカラムなプルダウンリスト作った。

AccessとかだとおなじみのマルチカラムなプルダウンリストをHTMLでつくってみた。
選択結果を入力するinput-text要素と、プルダウンリストをtableで作ってあげるとプルダウンリストにしてくれる。
jQuery
動作確認はまだ全然なので、バグはたっぷりかも。

動作デモはこちら

<!DOCTYPE HTML>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" type="text/javascript"></script>
    <style type="text/css">
        <!--
            .__select_wrapper {
                border: 1px solid #dbdfe6;  /* プルダウンリストの枠線 */
                max-height:100px;           /* プルダウンリストの最大長 */
                background: #ffffff;        /* プルダウンリストの背景色 */
                display: none;
                
                overflow-y: scroll;
                position: absolute;
            }
            .__select {
                border-collapse: collapse;
                border-spacing: 0;
            }
            .__select * {
                cursor: default;
                font-size: small;
                margin: 0;
                padding: 1px;
            }
            .__select>tbody .__selected {
                background-color: #0000ff;
                color: #ffffff;
            }
        -->
    </style>
</head>
<body>
    
    <p>top text.top text.top text.top text.top text.top text.top text.top text.top text.top text.top text.top text.</p>
    <label for="_select">都道府県</label>
    <input type="text" id="s1" class="_select" name="s1" />
    <div class="__select_wrapper" id="s1__select_wrapper">
        <table id="s1__select" class="__select">
            <thead><!--リストにヘッダを付けることも可-->
                <tr class="__select_head">
                    <th>code</th>
                    <th>name</th>
                    <th>eng.</th>
                </tr>
            </thead>
            <tbody><!--リスト可するオプションはtbodyで括る-->
                <tr id="s1__select_option_1">
                    <!---->
                    <td class="_value">1</td>
                        <!--inputに適応する項目にはclass="_value"を設定する-->
                    <td>東京都</td>
                    <td>TOKYO</td>
                </tr>
                <tr id="s1__select_option_2">
                    <td class="_value">2</td>
                    <td>山梨県</td>
                    <td>YAMANASHI</td>
                </tr>
                <tr id="s1__select_option_3">
                    <td class="_value">3</td>
                    <td>埼玉県</td>
                    <td>SAITAMA</td>
                </tr>
                <tr id="s1__select_option_4">
                    <td class="_value">4</td>
                    <td>神奈川県</td>
                    <td>KANAGAWA</td>
                </tr>
                <tr id="s1__select_option_5">
                    <td class="_value">5</td>
                    <td>千葉県</td>
                    <td>CHIBA</td>
                </tr>
            </tbody>
        </table>
    </div>

    <label for="_select">性別</label>
    <input type="text" id="s2" class="_select" name="s2" />
    <div class="__select_wrapper" id="s2__select_wrapper">
        <table id="s2__select" class="__select">
            <thead>
                <tr class="__select_head">
                    <th>name</th>
                    <th style="display:none">id</th>
                </tr>
            </thead>
            <tbody>
                <tr id="s2__select_option_1">
                    <td></td>
                    <td class="_value" style="display:none">10</td>
                        <!--class="_value"を設定したtd要素に、
                            style="display:none"を設定することで、
                            非表示項目の値をinputに入れることも可能。-->
                </tr>
                <tr id="s2__select_option_2">
                    <td></td>
                    <td class="_value" style="display:none">20</td>
                </tr>
            </tbody>
        </table>
    </div>

    <p>bottom text. bottom text. bottom text. bottom text. bottom text. bottom text. </p>

    <script type="text/javascript">
        <!--
        var id;

        // プルダウンオプションにhoverしたときに色を変える動作。
        $(".__select>tbody>tr>*").hover( function(){
            $(this).parent().children().addClass("__selected");
        }, function(){
            if($(this).parent().attr("id")!=id+"__select_option_"+$("#"+id).attr("value")) {
                $(this).parent().children().removeClass("__selected");
            }
        });

        // 入力部フォーカス時の動作。
        $("._select").focus(function() {

            id = $(this).attr("id");

            // プルダウンリストの表示位置を調節。
            $("#"+id+"__select_wrapper").css("left",$("#"+id)[0].offsetLeft);
            $("#"+id+"__select_wrapper").css("top",$("#"+id)[0].offsetBottom);

            // プルダウンリストを表示する。
            $("div#"+id+"__select_wrapper").css("display","block");

            //選択中のオプションの色づけ。
            $("table#"+id+"__select *").removeClass("__selected");
            $("table#"+id+"__select>tbody>tr#"+id+"__select_option_"+$("#"+id).attr("value")+" *").addClass("__selected");
        });
        // 入力部のフォーカスが外れたときの動作。
        $("._select").blur (function(){
            // プルダウンリストを閉じる。
            $("div#"+id+"__select_wrapper").css("display","none")
        });

        // プルダウンオプションをクリックしたときの動作。
        $(".__select>tbody>tr>*").mousedown(function(){
            $("#"+id).attr("value",$(this).parent().children("._value").html());
        });

        //-->
    </script>
</body>
</html>