knockout.jsでAdventCalendarを作ってみた


[![AdventCalendar.png](https://qiita-image-store.s3.amazonaws.com/0/58195/9166b10c-de36-547d-b791-f332ebaa276e.png)](http://jsfiddle.net/MKGaru/uux9twaL/)



------------------------------------------------------------------------------

こういう１個１個の引き出しに、お菓子入ってるのあるよね

[knockout.js Advent Calendar 2015](http://qiita.com/advent-calendar/2015/knockoutjs)もよろしくね！

code
----------------

```html:html
<span>数字をクリックしてね</span>

<h1>Advent Calendar</h1>
<div class="cupboard">
    <div class="backpanel"></div>
    <table>
        <tbody data-bind="template:{foreach: weeks,as:'week'}">
            <tr data-bind="foreach:week">
                <td>
                    <div class="cell">
                        <div class="box {{done?'done':'active'}}">
                            <div class="front"><span data-bind="on.click:done=true">{{date.format('{d}')}}</span></div>
                            <div class="back"></div>
                            <div class="left"></div>
                            <div class="right" data-bind="style:{'background-position':($index()*20)+'% '+($parentContext.$index()*20)+'%'}"></div>
                            <div class="bottom"><span>{{note}}</span></div>
                        </div>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
</div>
```

```js:javascript
function Day(date){
    this.note = '';
    this.done = false;
    this.date = date;
    ko.track(this);
}
function AdventCalendar(){
    var calendar = this;
    calendar.date = new Date();
    calendar.days = Date
        .range("12/1","12/25")
        .every('date')
        .map(function(date){
        	return new Day(date);
    	});
    calendar.weeks = Number
        .range(0,24)
        .every(5)
        .map(function(day){
        	return calendar.days.from(day).first(5)
    	});
    calendar.days
        .filter(function(day){
        	return day.date.isBefore(calendar.date)
    	})
    	.forEach(function(day){
        	day.done = true;
    	});
    
    ko.track(calendar);
}
var calendar = new AdventCalendar();
ko.punches.enableAll();
ko.applyBindings(calendar);
```
```less:less
*{
    user-select:none;
}
h1{
    font-family: 'Fredericka the Great', cursive;
    margin: 0;
    margin-top:1em;
    width: 300px;
    text-align: center;
    color: green;
    text-shadow: 2px 2px gray;
}
.cupboard{
    position:absolute;
    left:10px;
    width: 300px;
    transform-style: preserve-3d;
    perspective: 1500px;
    perspective-origin: 50% 0;
    transform: rotateX(0deg);
    .backpanel{
        position:absolute;
        height:100%;
        width:100%;
        left:0;right:0;
        top:0;bottom:0;
        transform: translateZ(-51px);
        background: #664444;
    }
    .cell{
        
    } 
    th,td{
        border:solid 2px darkslategrey;
    }
}

.box{
    width: 50px;
    height: 50px;
    top: 0px;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    transform-style: preserve-3d;
    transform: translateZ(100px);
    transform-origin: 25px 0px -25px;
    transition: transform ease-out 500ms;
    
    //animation: rotateY 5s linear infinite;
    transform: rotateY(180deg)
    &.active{
        transform: rotateY(0deg)
        //animation: pull-push 5s ease-in infinite;
    }
    &.done{
        animation: pull-push 3s ease-in 1;
        transform: rotateY(-90deg);
    }
    
    .front,
    .back,
    .left,
    .right,
    .bottom{
        width: 50px;
        height: 50px;
        position: absolute;
        top: 0px;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;
        text-align: center;
        line-height: 50px;
        opacity: 0.8;
        border: solid 1px brown;
        background: url(https://yabumi.cc/15142c3178cd66b98092f9a6.png);
        &>span{
            display:block;
        }
    }
    .front{
        transform: translateZ(0px);
        &>span{
            background:rgba(red,0.75);
            cursor:pointer;
            color: white;
            font-size:30px;
            font-family: 'Fredericka the Great', cursive;
            font-weight:bold;
        }
    }
    .back{
        transform: translateZ(-50px);
    }
    .left{
        transform: rotatey(-90deg) translateZ(25px) translateX(-25px);
    }
    .right{
        transform: rotatey(90deg) translateZ(25px) translateX(25px);
        background: url(https://yabumi.cc/1514f980720f6480291db5c1.png);
        background-position: 0% 0%;
        background-size: 300px;
    }
    .bottom{
        width:50px;
        height:50px;
        background: url(https://yabumi.cc/15142c179f53b489f5fb929d.png);
        transform: rotateX(90deg) translateZ(-12.5px) translateY(-25px);
    }
}


@keyframes pull-push {
    0% {transform: translateZ(0px) rotateX(0deg)}
    10% {transform: translateZ(50px) rotateX(0deg)}
    30% {transform: translateZ(75px) translateY(25px) rotateX(-45deg)}
    60% {transform: translateZ(75px) translateY(25px) rotateX(-45deg) rotateY(0deg)}
    80% {transform: translateZ(50px) rotateX(0deg) rotateY(-90deg) }
    100% {transform: translateZ(0px) rotateX(0deg) rotateY(-90deg) }
}

```

[Demo](http://jsfiddle.net/MKGaru/uux9twaL/)
--------------------------------------------