幸せになり隊

幸せってなに?どうやったら幸せになれるの?そんな思いを密かに燃えたぎらせる人たちの試行錯誤の記録。

単語帳のブログパーツを作ってみた

f:id:wbhappy:20150118152141p:plain

英語の記事が増えてきたので単語帳のブログパーツを作ってみました。画像は使わずCSSJavaScriptだけで作っています。

いわゆるカードレイアウトで複数のコンテンツを表示していて、中身のデータやレイアウトを修正すれば他の用途にも使えます。(※Chromeでしか動作確認はしていません)

一度に5つのコンテンツをランダムに表示していて、更新ボタンをクリックすると再度ランダムに5つ選んで表示するようになっています。

ちなみにコンテンツはハードコーディングで用意しています。

 

サンプル

画面右の「単語帳」というパーツになります。

以下ソースコードです。(変にこだわってしまった部分もあり若干肥大化してます・・・)

JavaScript

!function(){
    var active = 0;
    var cardSize = 5;
    // カードのコンテンツリスト
    var cardList = [
        {"term": "Where was I?", "mean": "何話してましたっけ?", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/12/120000"},
        {"term": "Are you serious?", "mean": "本気?", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/14/220000"},
        {"term": "I don't care", "mean": "気にしない、どうでもいい", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/16/213000"},
        {"term": "Awesome", "mean": "すげー。ヤバイ", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/17/220000"},
        {"term": "I'm bored", "mean": "飽きた", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/18/220000"},
        {"term": "Do it yourself", "mean": "自分でやってよ", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/21/210000"},
        {"term": "I'm stuck", "mean": "困ったなぁ", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/22/210000"},
        {"term": "I'm happy to help", "mean": "お役に立てて嬉しいです", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/23/210533"},
        {"term": "Can it wait?", "mean": "後でいい?", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/24/213000"},
        {"term": "I told you", "mean": "言ったじゃん", "url": "http://wbhappy.hatenablog.jp/entry/2014/11/27/213745"}
    ]
    var empty = function(el){
        while (el.firstChild) {
          el.removeChild(el.firstChild);
        }
    }
    var getRandomList = function(array, size){
        var indexArray = [];
        var cardLen = array.length;
        if(cardLen < size){
            return array;
        }
        while(indexArray.length < size){
            var index = ~~(Math.random()*(cardLen))
            if(indexArray.indexOf(index) < 0){
                indexArray.push(index);
            }
        }
        var list = [];
        for(var i=0,len=indexArray.length; i<len; i++){
            var index = indexArray[i];
            list.push(array[index]);
        }
        return list;
    }  
    var updateCard = function(){
        var list = getRandomList(cardList, cardSize);
        var wrap = document.getElementById("wb_card_center").children[0];
        empty(wrap);
        var buf = [];
        for(var i=0, len=list.length; i<len; i++){
            var card = list[i];
            // カードの中身のレイアウト
            var el = [
                "<div class=\\"wb-card\\">",
                    "<div class=\\"wb-card-inner\\">",
                        "<a class=\\"term\\" href=\\"", card.url, "\\">", card.term, "</a>",
                        "<hr><span class=\\"mean\\">",
                        card.mean, "</span>",
                    "</div>",
                "</div>"
            ];
            buf.push(el.join(""))
        }
        wrap.innerHTML = buf.join("");
    }  
    var init = function(){
        updateCard();
        var onclick = function(num){
            active += num;
            if(active < 0){
                active = cardSize-1;
            }else if(active > cardSize-1){
                active = 0;
            }
            var radio = document.getElementById("wb_slide" + (active+1));
            radio.checked = true;
        }  
        var left = document.getElementById("wb_card_left");
        var right = document.getElementById("wb_card_right");
        left.addEventListener("click", function(){
            onclick(-1);
        }, false);
        right.addEventListener("click", function(){
            onclick(1)
        }, false);  
        var reload = document.getElementById("wb_reload");
        reload.addEventListener("click", function(){
            updateCard();
        }, false);
    }  
    window.addEventListener("load", init, false);
}();

html

<div id="wb_card_widget">
    <input type="radio" name="slider" id="wb_slide1" checked/>
    <input type="radio" name="slider" id="wb_slide2" />
    <input type="radio" name="slider" id="wb_slide3" />
    <input type="radio" name="slider" id="wb_slide4" />
    <input type="radio" name="slider" id="wb_slide5" />
    <div id="wb_active">
        <label for="wb_slide1"></label>
        <label for="wb_slide2"></label>
        <label for="wb_slide3"></label>
        <label for="wb_slide4"></label>
        <label for="wb_slide5"></label>
    </div>
    <div id="wb_reload" class="wb-icon" title="更新">
        <div class="reload"></div>
    </div>
    <div id="wb_help"><a href="http://wbhappy.hatenablog.jp/entry/2015/01/18/153853" title="このパーツの作り方" target="_blank">?</a></div>
    <div id="wb_card_center">
        <div class="inner">
            <div class="wb-card">
                <div class="wb-card-inner">JavaScriptを有効にしてください。</div>
            </div>
        </div>
    </div>
    <div id="wb_card_left"><</div>
    <div id="wb_card_right">></div>
</div>

CSS

幅300pxで最適化しています。サイズを変更する場合は「パーツの幅」と「コンテンツの幅」の2箇所を修正。あとはボタンの位置等の細かい微調整が必要かも・・・。
#wb_card_widget {
    border: 1px solid rgb(255, 237, 237);
    position: relative;
    height: 100px;
    width: 300px; /* パーツの幅 */
    border-radius: 6px;
    line-height: 1;
}
#wb_card_center {
    overflow: hidden;
}
#wb_card_left,
#wb_card_right {
    -webkit-transition: all 0.1s;
    -moz-transition: all 0.1s;
    -ms-transition: all 0.1s;
    -o-transition: all 0.1s;
    transition: all 0.1s;  
    display: inline-block;
    line-height: 100px;
    height: 100px;
    width: 16px;
    vertical-align: middle;
    text-align: center;
    cursor: pointer;
    font-size: 16pt;
    font-weight: bold;
    background-color: #FF8181;
    color: white;
    position: absolute;
    top: 0px;
}
#wb_card_left {
    border-radius: 6px 0px 0px 6px;
    left: 0px;
}
#wb_card_right{
    border-radius: 0px 6px 6px 0px;
    right: 0px;
}
#wb_card_left:hover,
#wb_card_right:hover{
    background-color: #FCB7B7;
    color: #E07070;
}
#wb_card_widget .inner {
    width: 500%;
    padding: 5px 22px;
    -webkit-transform: translateZ(0);
    -webkit-transition: all 600ms cubic-bezier(0.770, 0.000, 0.175, 1.000); 
    -moz-transition: all 600ms cubic-bezier(0.770, 0.000, 0.175, 1.000); 
    -ms-transition: all 600ms cubic-bezier(0.770, 0.000, 0.175, 1.000); 
     -o-transition: all 600ms cubic-bezier(0.770, 0.000, 0.175, 1.000); 
        transition: all 600ms cubic-bezier(0.770, 0.000, 0.175, 1.000);  
    -webkit-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000);
    -moz-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000); 
    -ms-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000); 
     -o-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000); 
        transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000);
}
#wb_card_widget input{
    display: none;
}
#wb_active {
    position: absolute;
    bottom: 3px;
    left: 115px;
    text-align: center;
}
#wb_active label {
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
    display: inline-block;
    width: 7px;
    height: 7px;
    background: #bbb;
    cursor: pointer;
    margin-left: 2px;
    margin-right: 2px;
}
#wb_active label:hover {
    background: #ccc;
    border-color: #777;
}
#wb_slide1:checked ~ #wb_card_center .inner { margin-left:0; }
#wb_slide2:checked ~ #wb_card_center .inner { margin-left:-100%; }
#wb_slide3:checked ~ #wb_card_center .inner { margin-left:-200%; }
#wb_slide4:checked ~ #wb_card_center .inner { margin-left:-300%; }
#wb_slide5:checked ~ #wb_card_center .inner { margin-left:-400%; }

#wb_slide1:checked ~ #wb_active label:nth-child(1),
#wb_slide2:checked ~ #wb_active label:nth-child(2),
#wb_slide3:checked ~ #wb_active label:nth-child(3),
#wb_slide4:checked ~ #wb_active label:nth-child(4),
#wb_slide5:checked ~ #wb_active label:nth-child(5) {
    background: #333;
    border-color: #333;
}

#wb_card_widget .wb-card {
    width: 20%;
    float: left;
}
#wb_card_widget .wb-card-inner{
    width: 256px; /* カードのコンテンツの幅 */
    word-wrap: break-word;
}

#wb_card_widget .wb-card hr {
    border: 1px dashed #ccc;
    background: none;
    height: 0px;
}

#wb_card_widget .wb-card .mean {
    font-size: 10pt;
}

#wb_help {
    position: absolute;
    right: 26px;
    bottom: 3px;
}

#wb_help a{
    text-decoration: none;
    font-weight: bold;
    color: #aaa;
}

#wb_help a:hover {
    color: #333;
}

/* #############
   更新ボタン   
############# */
div.wb-icon {
    height: 24px;
    width: 24px;
    position: absolute;
    overflow: hidden;
    display: inline-block;
    right: 30px;
    bottom: 3px;
}
div.wb-icon div.reload {
    width: 6px;
    height: 3px;
    border-style: solid;
    border-width: 0px 2px 2px 2px;
    border-color: #aaa;
    -webkit-border-radius: 0 0 50px 50px;
    -moz-border-radius: 0 0 50px 50px;
    border-radius: 0 0 50px 50px;
    position: absolute;
    top: 18px;
    left: 2px;
    cursor: pointer;
}
div.wb-icon div.reload:before {
    content: '';
    position: absolute;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 3px;
    border-color: transparent transparent transparent #aaa;
    bottom: 4px;
    left: 3px;
    cursor: pointer;
}
div.wb-icon div.reload:after {
    content: '';
    width: 3px;
    height: 3px;
    border-style: solid;
    border-width: 2px 0 0 2px;
    border-color: #aaa;
    -webkit-border-radius: 50px 0 0 0;
    -moz-border-radius: 50px 0 0 0;
    border-radius: 50px 0 0 0;
    position: absolute;
    left: -2px;
    bottom: 3px;
    cursor: pointer;
}
div.wb-icon:hover div.reload,
div.wb-icon:hover div.reload:after {
    border-color: #333;
}
div.wb-icon:hover div.reload:before {
    border-color: transparent transparent transparent #333;
}

 

参考

coliss.com