knockoutと既存UIライブラリの連携

    この記事は、knockout.js Advent Calendar 2015の６日目の記事です。 先に５日目に目を通すことを推奨しています。
    knockout , knockout-es5 , knockout.punches環境を想定しています。

実はknockoutは、jQueryのプラグイン等の既存のUIライブラリとの相性も良いです。
たとえば、Twitterの[Bootstrapのjavascript部分](http://getbootstrap.com/javascript/)関連との連携があげられます。
ほぼほぼ静的なサイトであれば、Bootstrapの``Via data attributes``だけでも十分な場合も多々ありますが、
[knockstrap](http://faulknercs.github.io/Knockstrap/)等の連携ライブラリもあるのでこれらを利用するのも１つの手です。

>ただし、knockout-es5での利用を想定していないライブラリが大半なので、knockout-es5環境で2way-bindingにする際には、ko.getObservable(mode,'property-name')でobservableを渡すか、ライブラリ側の拡張が必要になる場合があります。（参考: [Knockout ES5 に対応したカスタムバインディングを書く作法](http://qiita.com/sukobuto/items/ba8c1c6b6ce2ee508e1c) )

個人的には、UIライブラリのモデル操作部分についてはjavascript部分は無理に使う必要はないとも考えています。
この手のUIライブラリは、単純にHTML要素のclassに"active"などのクラスを付替えたりしているだけで、見た目等についてはCSSで制御されていることが大半なので、それら(classの付替え)の処理はknockoutに任せてしまうのも手です。

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

具体的に、同じく UIライブラリの一種である、[semantic ui](http://semantic-ui.com/)を例として挙げてみます。　
今回は[このチェックボックス](http://semantic-ui.com/modules/checkbox.html)を使ってみます。

見た目の切替等制御をknockoutに任せる方法
=====================================

まず、semantic uiが提供しているscriptを使わずに、knockout側でclassを付替える[**サンプル**](http://jsfiddle.net/MKGaru/zkssvz3n/)をやってみます。

semantic ui のラジオボタンは、checked classの有無で見た目を切り替えているようなので、

```js:javascript
function VM(){
	this.often='2';
    this.wishNewsletter = false;
	ko.track(this);
}

ko.punches.enableAll();
ko.applyBindings(new VM());
```

```html:html
<div class="ui form">
  <div class="grouped fields">
    <label>How often do you use checkboxes?</label>
    <div class="field">
      <div class="ui radio checkbox {{often=='1'?'checked':''}}">
        <input type="radio" id="often-1" class="hidden" name="often" value="1" data-bind="checked:often">
        <label for="often-1">Once a week</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox {{often=='2'?'checked':''}}">
        <input type="radio" id="often-2" class="hidden" name="often" value="2" data-bind="checked:often">
        <label for="often-2">2-3 times a week</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox {{often=='3'?'checked':''}}">
        <input type="radio" id="often-3" class="hidden" name="often" value="3" data-bind="checked:often">
        <label for="often-3">Once a day</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox {{often=='4'?'checked':''}}">
        <input type="radio" id="often-4" class="hidden" name="often" value="4" data-bind="checked:often">
        <label for="often-4">Twice a day</label>
      </div>
    </div>
  </div>
</div>
```
このようにして、oftenの現在値によってchecked classの有無を切り替えることで期待通りの動きをしています。

`ニュースレター通知`のトグル部分はより単純で、

```html:html
<div class="ui toggle checkbox">
  <input type="checkbox" data-bind="checked:wishNewsletter">
  <label>Subscribe to weekly newsletter</label>
</div>
```
だけでも動いているみたいです。

----------------------------------------------------------------------------------------
CustomBindingを用いて連携する方法
================================
もう１つの方法として、semantic uiが用意しているscriptを忠実に利用する方法で連携してみたいと思います。([**サンプル**](http://jsfiddle.net/MKGaru/pmbtysps/))

```js:javascript
function VM(){
	this.often='2';
    this.wishNewsletter = false;
	ko.track(this);
}

ko.punches.enableAll();

ko.bindingHandlers['checkbox'] ={
	init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.unwrap(valueAccessor())||{};
		if(!options.onChange){
            options.onChange = function(){
                $(this).triggerHandler('click');
            };
        }
        $(element)['checkbox'](options);
	}
};

ko.applyBindings(new VM());

```
```html:html
<div class="ui form">
  <div class="grouped fields">
    <label>How often do you use checkboxes?</label>
    <div class="field">
      <div class="ui radio checkbox" data-bind="checkbox:{}">
        <input type="radio" name="often" value="1" data-bind="checked:often">
        <label>Once a week</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox" data-bind="checkbox:{}">
        <input type="radio" name="often" value="2" data-bind="checked:often">
        <label>2-3 times a week</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox" data-bind="checkbox:{}">
        <input type="radio" name="often" value="3" data-bind="checked:often">
        <label>Once a day</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox" data-bind="checkbox:{}">
        <input type="radio" name="often" value="4" data-bind="checked:often">
        <label>Twice a day</label>
      </div>
    </div>
  </div>
</div>
        
<div class="ui toggle checkbox" data-bind="checkbox:{}">
  <input type="checkbox" data-bind="checked:wishNewsletter">
  <label>Subscribe to weekly newsletter</label>
</div>
```
この方法は、`checkbox`というcustom bindingを定義して、[semantic ui のscript](http://semantic-ui.com/modules/checkbox.html#/usage)と連携するというアプローチです。
checkbox:`{}`には、[これらの設定（オプション）](http://semantic-ui.com/modules/checkbox.html#/settings)のイベントハンドラを設定できます。