Backbone.LinkedCollection

This is a coffee-script version. Smarter Backbone Collection object utilising Web Linking (RFC5988). This demo uses Github API.

by davidhong

HTML

<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script src="https://github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<script src="https://github.com/hongymagic/Backbone.LinkedCollection/raw/master/lib/RFC5988-parser.js"></script>
<script src="https://github.com/hongymagic/Backbone.LinkedCollection/raw/master/src/Backbone.LinkedCollection.js"></script>
<div class="container">
    <h1>Public Gists</h1>
    <ul id="gists"></ul>
    <nav role="pager">
        <a href="#next" rel="next">Load more</a>
    </nav>
</div>

<script id="template-gist" type="html/template">
    <li data-id="{{id}}">
        <a href="{{html_url}}">
            {{#if description}}
                {{description}}
            {{else}}
            <span class="noname">Untitled</span>
            {{/if}}
        </a> 
        <small>by <a href="{{user.url}}">{{user.login}}</a></small>
    </li>
</script>

CSS

html, body { font: 16px/140% Palatino, Georgia, 'Times New Roman', serif; }
body, ul { margin: 0; padding: 0; }

a { color: #222; }
a, a:hover, a:active, a:focus, a:visited { text-decoration: none; }

h1 { margin: 10px 0; font-weight: 300; }
small { font-size: 80%; }
small, .noname { color: #bbb; }

ul { margin: 25px 0; border-top: 1px solid #000; border-bottom: 1px solid #000; padding: 25px 0; list-style: none; }
li { padding: 4px 0 4px 20px; width: 100%; box-sizing: border-box; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; background: transparent url(https://a248.e.akamai.net/assets.github.com/images/gist/gist/paste.png) no-repeat left 4px; line-height: 16px; }

.container { margin: 0 auto; padding: 10px; width: 90%; box-sizing: border-box; }
[role=pager] a { display: block; text-align: center; }

CoffeeScript

Demo = 
  Models: {}
  Collections: {}
  Views: {}
  Utility: {}

class Demo.Models.Gist extends Backbone.Model
  urlRoot: 'https://api.github.com/gists'

class Demo.Collections.Gists extends Backbone.LinkedCollection
  url: 'https://api.github.com/gists/public'
  model: Demo.Models.Gist

class Demo.Views.TemplateView extends Backbone.View
  template: (id) ->
    html = $(id or @tid).html() or ''
    Handlebars.compile html
    
  compile: (id, model) ->
    tmpl = @template ('#' + (id or @tid))
    tmpl model

class Demo.Views.Gist extends Demo.Views.TemplateView
  tid: 'template-gist'
  
  render: ->
    html = @compile @tid, @model.toJSON()
    @$el.html html
    @

class Demo.Views.GistList extends Demo.Views.TemplateView
  initialize: (options = {}) ->
    @model.on 'reset', @addAll, @
    @model.on 'add',   @add, @
    _.extend @, options

  addAll: (list) ->
    @$el.empty()
    list.each (model) => @add model
    list

  add: (gist) ->
    view = new Demo.Views.Gist({ model: gist })
    @$el.append view.render().el
    view

class Demo.Views.Main extends Demo.Views.TemplateView
  events:
    'click [role=pager] a[rel]': 'jump'

  initialize: ->
    @model.get('gists').fetch()

  render: ->
    @gists = new Demo.Views.GistList({ el: $('#gists').get(0), model: @model.get 'gists' })
    @
    
  jump: (event) ->
    event.preventDefault()
        
    target = $ event.target
    rel = target.attr 'rel'
    gists = @model.get 'gists'
    fn = gists[rel]
    
    fn.call(gists, { add: true }) if _.isFunction fn
    @

$ () ->
  model = new Backbone.Model({ gists: new Demo.Collections.Gists() })
  main = new Demo.Views.Main({ el: $('div.container').get(0), model: model })
  main.render()