ANTON072
3/3/2015 - 2:41 PM

knockout.jsでMVVM http://bl.ocks.org/ANTON072/8b86844cb60b30b3a653

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>

  <div>
    <header>
      <h1>Gist検索</h1>
    </header>
    <section>
      ユーザー
      <input type="text" data-bind="value: user">
      <button data-bind="click: search">検索</button>
    </section>
    <section>
      <ol data-bind="foreach: gists">
        <li>
          <a href="#" data-bind="attr: {href: html_url}, text: text" target="_blank"></a>
        </li>
      </ol>
    </section>
  </div>

  
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
  <script type="text/javascript">

  /**
  * ■■■■■■■■ Model ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  */
  var AppModel = (function(){

    function AppModel(){
      // データコレクション
      this.gists = ko.observableArray();
    }

    // メソッド定義
    AppModel.prototype.search = function(user){
      var gistapiurl = "https://api.github.com/users/" +
      user + "/gists?callback=?";
      $.ajax({
        url: gistapiurl,
        context: this,
        dataType: 'jsonp'
      })
      .done(function(res) {
        var data = res.data;
        if (data.message) return;
        // データコレクションに追加
        this.gists(data);
      });
      
    };

    return AppModel;

  }());

  /**
  * ■■■■■■■■ ViewModel ■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  */


  // リスト一件分のViewModel
  var GistViewModel = (function(){

    function GistViewModel(id, description, html_url){
      this.id = ko.observable(id);
      this.description = ko.observable(description);
      this.html_url = ko.observable(html_url);
      this.text = ko.computed(function(){
        return this.id() + ':' + this.description();
      }, this);
    }

    return GistViewModel;

  }());

  // アプリケーション全体のViewModel
  var AppViewModel = (function(model){

    function AppViewModel(model){
      // ユーザー
      this.user = ko.observable();
      // Gistデータコレクション
      this.gists = ko.observableArray();
      // AppModel
      this.model = model;

      // Modelの状態変更購読
      this.model.gists.subscribe(function(gists){
        // Gistデータ用ViewModelコレクションを洗い替え
        var newGists = $.map(gists, function(item, index){
          return new GistViewModel(item.id, item.description, item.html_url);
        });
        this.gists(newGists);
      }, this);

    }

    // メソッド定義
    AppViewModel.prototype.search = function(){
      // 既存の検索結果をクリア
      this.gists.removeAll();

      // 入力されたユーザーを登録
      // Modelの検索処理を実行
      this.model.search(this.user());
    };

    return AppViewModel;

  }());

  /**
  * ■■■■■■■■ run app ■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  */
  $(function(){
    var model = new AppModel();
    var viewModel = new AppViewModel(model);
    ko.applyBindings(viewModel);
  });

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