2013年10月28日月曜日

jQueryで要素の置換 select要素(セレクトボックス)←→textタイプのinput要素(テキストボックス)

jQueryで要素の置換は、replaceAllやreplaceWithを使う。

replaceWithを使う例として、div要素の置換は、よく見かけるけど、select要素の置換はあまり見かけなかったので、メモっとく。


「radioタイプのinput要素(ラジオボタン)を変更した場合に、他のselect要素を選択できなくさせたい」って時に、disabledにするとグレーアウトされて、見た目の変更ができなくて困った。

で考えたのが、readonlyで行こうと。(submitされるけどね)
readonlyなら、フォントの色の変更とかができて自由だし。

でも、select要素には、readonlyがない。

ということで、select要素をtextタイプのinput要素(テキストボックス)に置換して、readonlyにすることで、落ち着いた。


jQueryならシンプルで簡単にできると思ったら、functionの実行時に、DOM操作が即時反映されないことが仇になり、結構苦戦。

素のJavaScriptでやってしまったら負けだと思って、追求したら、なんとかできた。

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Example</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript">
    var example = {
        /**
         * idをキーにtextタイプのinput要素に置換したselect要素を保持する連想配列.
         */
        clonedSelects: {}
        ,
        /**
         * select要素をtextタイプのinput要素に置換する.
         * @param id select要素のid
         * @param value 固定のvalueを指定する(未指定の場合、現在選択中のvalueが設定される)
         */
        replaceToText:
            function (id, value) {
                // id内の.(ドット)はエスケープ
                var elem = $('#' + id.replace(/\./g, '\\.'));
                // select要素でない場合、処理終了
                if (elem[0].nodeName != 'SELECT') {
                    return;
                }
                
                example.clonedSelects[id] = elem.clone(true);
                
                // 固定のvalueを設定
                if (typeof value !== 'undefined') elem.val(value);
                
                // select要素のvalue値をhiddenで持つ
                var elemHidden = $('<input type="hidden"/>');
                // replaceWithを行うまではidが重複するため、別のidにする
                elemHidden.attr('id', id + 'Hidden');
                elemHidden.attr('name', elem.attr('name'));
                elemHidden.val(elem.val());
                elem.after(elemHidden);
                
                // select要素をtextタイプのinput要素に置換
                elem.replaceWith(function (elem, id) {
                    var elemText = $('<input type="text"/>').attr({readonly: 'readonly', tabindex: '-1'});
                    elemText.val(elem.children(':selected').text());
                    elemText.attr('style', elem.attr('style'));
                    
                    // textタイプのinput要素にするため、id,nameを変更
                    elemText.attr('id', id + 'Text');
                    elemText.attr('name', elem.attr('name') + 'Text');
                    return elemText;
                }(elem, id));
                
                // replaceWithを行った後、select要素のidをhiddenへ設定
                elemHidden.attr('id', id);
            }
        ,
        /**
         * textタイプのinput要素をselect要素に戻す.
         * "戻す"と記載しているのは、select要素を保持しているのが前提のため。
         * @param id 戻すselect要素のid
         * @param value 固定のvalueを指定する(未指定の場合、現在選択中のvalueが設定される)
         */
        replaceToSelect:
            function (id, value) {
                // select要素を保持する連想配列に存在しない場合、処理終了
                if (typeof example.clonedSelects[id] === 'undefined') {
                    return;
                }
                
                // id内の.(ドット)はエスケープ
                var elemHidden = $('#' + id.replace(/\./g, '\\.'));
                // replaceWithを行うとidが重複するため、事前に別のidにする
                elemHidden.attr('id', id + 'Hidden');
                
                // 固定のvalueを設定
                if (typeof value !== 'undefined') elemHidden.val(value);
                
                // id内の.(ドット)はエスケープ
                var elem = $('#' + id.replace(/\./g, '\\.') + 'Text');
                elem.replaceWith(function (id, value) {
                    var elemSelect = example.clonedSelects[id];
                    
                    // select要素に戻すため、idも戻す
                    elemSelect.attr('id', id);
                    
                    elemSelect.val(value);
                    
                    return elemSelect;
                }(id, elemHidden.val()));
                
                // select要素に戻したため、保持していたselect要素を削除
                delete example.clonedSelects[id];
                
                // select要素に戻すため、hiddenを削除
                elemHidden.remove();
            }
    }
    </script>
</head>
<body>

<input type="radio" name="radioexample" onclick="example.replaceToSelect('example');" checked="checked" />select要素へ置換
<input type="radio" name="radioexample" onclick="example.replaceToText('example')" />textタイプのinput要素へ置換

<br />

<select id="example" name="example">
    <option>サンプル1</option>
    <option>サンプル2</option>
    <option>サンプル3</option>
</select>

</body>
</html>

(注)select要素の置換なので、textタイプのinput要素を初期表示としたい場合、onloadでtextタイプのinput要素とすること。

(注)id内のドットのエスケープは、Strutsなどを使用していない限り、なくてもOK。


JavaScriptライブラリを比較するときに、役に立った本。
jQuery、Prototype、Dojo、YUI、script.aculo.usを比較してる。
今は、jQuery優勢かな。

2013年10月20日日曜日

湘南台文化センター こども館 世界のおもちゃ!KAPLA

雨の日でも、めいっぱい遊べるのが、湘南台文化センター こども館。

プラネタリウム(宇宙劇場)とパソコン触れる展示ホール(3F 円環ギャラリー)もあるけど、今日は、幼児から大人まで楽しめる、おもちゃいっぱいの展示ホール(B1F 展示ギャラリー)を紹介。

地下一階で、まず目に入るのが、恐竜の卵と滑り台!

恐竜の卵 ハロウィーン
滑り台

でっかい昆虫!

蜂の下は、トンネルだよ

セミの抜け殻

最強のオニヤンマ

虫じゃないけど、、きのことどんぐり

また虫じゃないけど、、ヤモリ乗れるよ!

こっそりといるクモ

楽器!
いろんな楽器があり、幼児でも扱えるものも多く、大人もいろんな音色に癒されるコーナー。

太鼓 太鼓 太鼓 太鼓 太鼓…

2才児もはまる、こする系楽器

これもこする系楽器

あと、世界のおもちゃ!

ペルーかどこかの磁石の釣り

今日、はまったのは、KAPLA。
例えるなら、全部同じ形の積木。形は細いカマボコ板。

KAPLA!

ちょっと使い方教えたら、4才児と6才児で結構立派なもの作ってて、感激。

線路とお家

自分で使って感じたのは、ただのカマボコ板だけど、一つ一つ同じ大きさと重さになってるみたいで、重ねたときの安定感が半端ない。さすが、おフランス。

もう一つのおすすめは、ZOOB。
これは例えるのが、難しい。いわゆるブロック系のおもちゃだけど、人間の関節の動きを元に設計されてるので、くっつけてから動かすことができる。
ブロック系のおもちゃは、形を作って、その形のまま遊ぶってのが一般的な中、動かせるってのは、めっちゃ新鮮。

今日はやってないので、展示されている見本
次回はZOOBやろっかな。

2013年10月19日土曜日

こども自然公園(大池公園) どんぐりいっぱい

こども自然公園は、とっても大きい自然いっぱいの公園。
といっても、遊具も結構立派なのがあり、自然だけじゃない。

あるのはというと、
  • (これが別名「大池公園」の由来)
  • (長袖、長ズボンで!)
  • 小川 (何もしたことない…見るだけ?)
  • 梅林 (ふわふわの道)
  • 桜の木の丘 (今は治療中で枝がない)
  • プチ動物園 (無料!ハムスターとかがいる)
  • 遊具小 (1、2才向けのこじんまりしたとこ)
  • 遊具大 (2才から小学生まで楽しめる立派なとこ)
  • バーベキュー場 (小さな山にある)

行くと、何で遊ぶか迷う。でも幼児は、走り回ってるだけで楽しいみたいで、散歩道だけでもいいよう。

今日は、秋なので、いろんなどんぐりをいっぱい拾い、遊具で盛り上がった。

ローラー滑り台は、大人も楽しめるけど、ケツが痛いので、ケツマット必須。こどもより、おとなの方が必要かも。でも静電気の痛みだけは、逃れられない…

駐車場は1時間300円。臨時もあるけど、暑いときは満車になることあるから、バーベキューの人は早めに行った方がいいよ。

これが大池
どんぐりいっぱい
森は足元が笹だらけ
柿、食べれるの?
秋を感じる、見渡す限りのすすき
黄,緑,赤,青、4つのブロックに分かれてる
黄から青へ難しくなってく


ローラー滑り台
トンネルになってるのがイカすでしょ

2013年10月6日日曜日

海老名運動公園 冒険広場 ボルダリング

海老名運動公園は、体育館やプールもあり、大きい公園だけど、今回は、冒険広場を紹介。

車で公園に入ると、駐車場が高架下で、スペースを有効利用してる感じもいいし、何より日陰で車の中があっつくならないのが、グッド。

冒険広場は、こじんまりとしてるけど、いろんな遊具があって、 幼児から小学生まで、見渡せる場所で飽きずに遊んでくれる。

意図したことかわかんないけど、ロープやボルダリングのホールド(手や足を掛ける突起)がたくさんあり、握力つきそう。

遊具の下は全面砂場で、登ってて途中で落っこちても、ちょっとした衝撃吸収材になってるよ。

日陰がグッドな駐車場
大小、滑り台がいっぱい
ボルダリングのホールドがいっぱい
ターザンロープ(綱に捕まってシャーっての)と綱のピラミッド