2011-12-29 8 views
2

私はFlashからJavascriptへの一連のインタラクティブな教育用アプリケーションの変換に取り組んでいます。私のチームはBackbone.jsをフレームワークとして使用する予定です。これらのアプリは、基本的に、ユーザーに情報を提示したり、質問やインタラクティブなウィジェットの形で対話を促すシーンの集まりです。JSONを使用してインタラクティブなBackbone.jsアプリケーションをパワーアップする方法

  • アプリが持つ「シーン」やオブジェクトの数など、アプリごとに固有の情報が含まれている一連のJSONファイルは異なるものですユーザに表示されるメッセージおよび/またはウィジェットなど
  • ナビゲーション、メッセージなどを表示する方法を管理するバックボーン(おそらくアンダースコア)テンプレートのセット
  • シーン間の移動を容易にするためのバックボーンビュー/ルータ/モデルの集合アプリ内でユーザーのやりとりを処理する
  • ネイティブJavaScriptで組み込まれたいくつかのインタラクティブウィジェット

もちろん、バックボーンに関しては、私は初心者です。基本的なチュートリアルのいくつかを試してみましたが、Backboneと静的なJSONファイルを統合するのに問題があります。

のは、私は3つのシーンをレイアウトする以下の非常に基本的なJSONファイルが表示されるようにしているとしましょう:

var scenes = [ 
{ 
    "name": "Introduction", 
    "label": "Introduction", 
    "message": "Welcome to this app" 
}, 
{ 
    "name": "Exercise", 
    "label": "Exercise", 
    "message": "If this were a real app, there'd be some sort of exercise here" 
}, 
{ 
    "name": "Conclusion", 
    "label": "Conclusion", 
    "order": "Thank you for completing this app" 
} 
] 

は私が必要なもの、と私は何をしようとしている、バックボーンは、ナビゲーションを生成することですユーザーがこれらのシーン間を移動し、各シーンのメッセージを表示できるウィジェットです。 (これは明らかに、現実世界のアプリの非常に単純化されたバージョンである)

は、ここで私が試したものです:

// simplified object containing stage information 
    var stages = [ 
    { 
     "name": "Introduction", 
     "label": "Introduction", 
     "message": "Welcome to this app" 
    }, 
    { 
     "name": "Exercise", 
     "label": "Exercise", 
     "message": "If this were a real app, there'd be some sort of exercise here" 
    }, 
    { 
     "name": "Conclusion", 
     "label": "Conclusion", 
     "order": "Thank you for completing this app" 
    } 
    ]; 
$(function(){ 



    // create model for each stage 
    StageModel = Backbone.Model.extend({}); 

    // create collection for StageModel 
    StageModelList = Backbone.Collection.extend({ 
    model: StageModel 
    }); 

    var stageModelList = new StageModelList(); 

    // create view for list of stages 
    StageListView = Backbone.View.extend({ 

    el: $("#stageNav"), 

    initialize: function() { 
     // if stages are added later 
     stagemodellist.bind('add',this.createStageList, this); 
    }, 

    events: { 
     'click .stageListItem' : 'selectStage' 
    }, 

    createStageList: function(model) { 
     $("#stageList").append("<li class='stageListItem'>"+model.label+"</li>"); 
    }, 

    selectStage: function() { 
     this.router.navigate("stage/"+this.stage.name,true); 
    } 

    }); 

    // create view for each stages 

    StageView = Backbone.View.extend({ 
    el: $("#stage"), 

    initialize: function(options) { 
     // get stage variable from options 
     this.stage = this.options.stage; 
     // display stage 
     createOnEnter(this.stage); 

    }, 

    createOnEnter: function(stage) { 
     $("#stageLabel").html(stage.label); 
     $("#stageMsg").html(stage.message); 
    } 
    }); 

    // create router 
    AppRouter = Backbone.Router.extend({ 

     initialize: function() { 
      Backbone.history.start(); 
      // create collection 
      new StageModelList(); 
      // create view when router is initialized 
      new StageListView(); 
      // loop through stages and add each to StageModelList 
      for (var s in stages) { 
      StageModelList.add(stages[s]); 
      } 
     }, 

     routes: { 
      "stage/:stage" : "renderStage" 
     }, 

     renderStage: function(stage) { 
      // display StageView for this stage 
      new StageView({stage:stage}); 

     } 

    }); 


    var App = new AppRouter(); 

}); 

とHTML:

<!DOCTYPE html> 
<html> 
<head> 
<script class="jsbin" src="http://code.jquery.com/jquery-1.7.1.min.js"></script> 
<script class="jsbin" src="http://documentcloud.github.com/underscore/underscore-min.js"></script> 
<script class="jsbin" src="http://documentcloud.github.com/backbone/backbone.js"></script> 
<script src="js/ilo4.js"></script> 
<meta charset=utf-8 /> 
<title>JS Bin</title> 
</head> 
<body> 
    <p>My pathetic attempt at a Backbone.js app</p> 
    <div id="stageNav"> 
    <ul id="stageList"> 

    </ul> 
    </div> 
    <div id="stage"> 
    <div id="stageLabel"> 

    </div> 
    <div id="stageMsg"> 

    </div> 
    </div> 
</body> 
</html> 

(あなたも見ることができますjsbinバージョンはhttp://jsbin.com/iwerek/edit#javascript,html,liveです)。

今は残念ながらこれは何もしません。

は私が間違ってここにたくさんのことをやっていることを知っている、と私は周り蹴るよいくつかの質問:

  • 私もルータが必要ですか?
  • コレクションを変数として初期化する必要はありますか?
  • モデルをステージのリストにバインドするより良い方法はありますか?あなたが実際にあまりにも遠くはありませんでした

答えて

5

私はそれが動作するあなたのjsbinをクローン化し、それを修正しました:link

私はあなたの質問に対する私の答えとしてことを提出します。私は、何が起こっているのかをかなり徹底的に説明してきました。

見てみるとうまくいけば助かります。

EDIT:何地獄、私はここにもコードを入れます:

// simplified object containing stage information 
window.stages = [ 
    { 
    "name": "Introduction", 
    "label": "Introduction", 
    "message": "Welcome to this app" 
    }, 
    { 
    "name": "Exercise", 
    "label": "Exercise", 
    "message": "If this were a real app, there'd be some sort of exercise here" 
    }, 
    { 
    "name": "Conclusion", 
    "label": "Conclusion", 
    "message": "Thank you for completing this app" 
    } 
]; 

$(function(){ 

    // StageModel: no need to extend if you're not adding anything. 
    StageModel = Backbone.Model; 

    // StageCollection 
    StageCollection = Backbone.Collection.extend({ 
    model: StageModel 
    }); 

    // create view for list of stages 
    StageCollectionView = Backbone.View.extend({ 

    el: $("#stageNav"), 

    initialize: function() { 
     // if stages are added later 
     this.collection.bind('add', this.createStageListItem, this); 
    }, 

    events: { 
     'click .stageListItem' : 'selectStage' 
    }, 

    // I'm adding the model's cid (generated by backbone) as the 
    // id of the 'li' here. Very non-ideal, as one of the points 
    // of backbone et al. is to keep from embedding and retrieving 
    // data from the DOM like this. 
    // 
    // Perhaps better would be to create a StageListItemView and 
    // render one for each model in the collection, perhaps like: 
    //  
    // createStageListItem: function(model) { 
    //  this.$('#stageList').append(new StageListItemView({model: model}); 
    // } 
    // 
    // where you have a StageListItemView that knows how to render 
    // itself and can handle click events and communicate with the 
    // collectionview via events. 
    // 
    // At any rate, this string-munging will suffice for now. 
    createStageListItem: function(model) { 
     this.$("#stageList").append("<li id=\"" + model.cid + "\" class='stageListItem'>" + model.get('label') + "</li>"); 
    }, 

    // Use backbone's event system, it's pretty awesome. Not to mention 
    // that it helps to decouple the parts of your app. 
    // 
    // And note that you can pass arguments when you trigger an event. 
    // So any event handler for the 'new-stage' event would receive 
    // this model as its first argument. 
    selectStage: function(event) { 
     var cid = $(event.target).attr('id'); 
     this.trigger('new-stage', this.collection.getByCid(cid)); 
    }, 

    // This was a missing puzzle piece. Your StageCollectionView wasn't 
    // being rendered at all. 
    // 
    // Backbone convention is to call this function render, but you could 
    // call it whatever you want, as long as you, well, end up _calling_ it. 
    render: function() { 
     var self = this; 
     this.collection.each(function(model) { 
     self.createStageListItem(model); 
     }); 
     return this; 
    } 

    }); 

    // StageView, 
    StageView = Backbone.View.extend({ 
    el: $("#stage"), 

    // We're going to assume here that we get passed a 
    // newStageEventSource property in the options and 
    // that it will fire a 'new-stage' event when we need 
    // to load a new stage. 
    initialize: function(options) { 
     this.eventSource = options.newStageEventSource; 
     this.eventSource.bind('new-stage', this.loadAndRenderStage, this); 
    }, 

    // A load function to set the StageView's model. 
    load: function(model) { 
     this.model = model; 
     return this; 
    }, 

    render: function() { 
     $("#stageLabel").html(this.model.get('label')); 
     $("#stageMsg").html(this.model.get('message')); 
    }, 

    loadAndRenderStage: function(stage) { 
     this.load(stage); 
     this.render(); 
    } 
    }); 

    // Instatiate a StageCollection from the JSON list of stages. 
    // See Backbone docs for more, but you can pass in a list of 
    // hashes, and the Collection will use its model attribute to 
    // make the models for you 
    var stageCollection = new StageCollection(stages); 

    // View constructors take an options argument. Certain properties 
    // will automatically get attached to the view instance directly, 
    // like 'el', 'id', 'tagName', 'className', 'model', 'collection'. 
    var stageCollectionView = new StageCollectionView({ 
    collection: stageCollection 
    }); 

    // Instantiate the StageView, passing it the stageCollectionView in 
    // the options for it to listen to. 
    var stageView = new StageView({ 
    newStageEventSource: stageCollectionView 
    }); 

    // Last step, we need to call 'render' on the stageCollectionView 
    // to tell it to show itself. 
    stageCollectionView.render(); 

}); 
+0

素晴らしい - 非常に役立ちます!あなたにバッジを直接授与することができたら、私はそうするでしょう。 – tchaymore

+0

だから、私はリストの各項目のための別々のビューを作成するあなたの助言に従おうとしました。 。 。私はアプリを壊した。あなたは私の試みをここで見ることができます:http://jsbin.com/emicaw/3。何かアドバイス?ビューの質問を開くのは楽しいです。 – tchaymore

+0

私は再びあなたをクローンし、古いコメントをすべて削除し、新しいコメントをいくつか追加しました。 http://jsbin.com/oviqif/2/edit。私はあなたがかなり近くにいると思っています。背骨がどのように働いているのか、ちょうどいくつかの隅や隙間があります。私にとってもそうです。ソース(http://documentcloud.github.com/backbone/docs/backbone.html)を読むことをお勧めします。 1:それはかなりです。 2:それはよく書かれている(コードと散文)3:それは話すために、ボンネットの下で何が起こっているかの良い考えを与えるでしょう。 – satchmorun

関連する問題