To learn some more about backbone.js and jquery mobile I decided to build a little language trainer. I'm currently studying German and have lots of trouble learning the genders of all the words.

After a number of iterations I finally got the hang of seperating the model and view code out and linking them all with events.

The basic premise of the app is to show you a word and you have to click either der, die or _das and it will either tell you you are wrong and let you try again or if you are right hit the server and ask for a new word and then present it to you.

~

I originally wrote this with just jquery mobile ui and let the server do all the rendering but on my HTC Desire the latency was intollerable for such an app and I decided to do most of it in javascript.

The code for the application is below

$('#mainPage').live('pagecreate',function(event){

  // Source of words. Generates JSON data of
  // the form
  //
  // { word: "Mann", article: "der" }
  var Word = Backbone.Model.extend({

    initialize: function() {
      this.fetch();
      this.set({message: ''});
    }

    ,url: '/words/new.json'

    ,setAnswer: function (article){
      txt = article + " " + this.get('word');
      if (article == this.get('article')){
        this.set({message: txt + " is correct"});
        this.fetch();
      }else{
        this.set({message: txt + " is incorrect"});
      }
    }

  });

  var WordView = Backbone.View.extend({

    word: new Word()

    , initialize: function() {
      this.bindModel();
    }

    // ---------------------
    // Model Event Handling
    // ---------------------

    , bindModel: function(){
      _.bindAll(this, "renderMessage", "renderWord");
      this.word.bind('change:message', this.renderMessage);
      this.word.bind('change:word', this.renderWord);

    }

    , renderWord: function(){
        $("#word h1").html(this.word.get('word'));
    }

    , renderMessage: function(){
        $("#messages").html(this.word.get('message'));
    }


    // ------------------
    // UI Event Handling
    // ------------------

    , events: {  "click .der" : "handleDer" ,
                 "click .die" : "handleDie" ,
                 "click .das" : "handleDas" ,
              }

    , handleDer: function(data) {
      this.word.setAnswer('der');
    }
    , handleDie: function(data) {
      this.word.setAnswer('die');
    }
    , handleDas: function(data) {
      this.word.setAnswer('das');
    }

  });

  // Attach the view to an element
  var view = new WordView({el: $("#derdiedas")});

})    

the view is generated by the following haml layout

!!! 5
%html
  %head
    %title Oh My Der Die Das
    = javascript_include_tag :defaults
    %link{:href => "http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css", :rel => "stylesheet"}/
    %script{:src => "http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"}
    %script{:src =>"http://documentcloud.github.com/underscore/underscore-min.js"}
    %script{:src =>"http://documentcloud.github.com/backbone/backbone-min.js"}
    = javascript_include_tag 'words'
    = csrf_meta_tag
  %body
    %div{:id => "mainPage", "data-role" => "page"}

      = content_tag :div, "", :id => "messages", :class => "ui-body ui-body-e"

      = yield

and view

%div{:id=>"word", :data => {:role => "header", :backbtn=>"false" }}
  %h1=@word[:word]

%div{ :data => {:role => "content" }}
  %ul{:id=>"derdiedas",  :data => { :role=> "listview" }}
    %li
      %a.der(data-role="button" rel="external") der
    %li
      %a.die(data-role="button" rel="external") die
    %li
      %a.das(data-role="button" rel="external") das

and I have a controller at /words/new.json that generates data like

  // { word: "Mann", article: "der" }

There is currently a working app at ohmyderdiedas. It is obviously best viewed on a modern smart phone though it does work in a desktop browser.