how can I improve the following code mainly regarding the router, when to initialize the and fetch the collection and how I can filter the models?=
Thank you
jQuery ->
class window.Movie extends Backbone.Model
idAttribute: '_id'
defaults:
cast: 'not available'
genres: 'not available'
original_title: 'not available'
overview: 'not available'
poster_path: 'not available'
release_date: 'not available'
runtime: 'not available'
vote_average: 'not available'
toggleWatched: ->
@save
_watched: !@get '_watched'
class window.DecoratedMovie
constructor: (@movie) ->
@data = {}
@deferred = @fetchDataFromTMDb()
toJSON: ->
json = _.clone @movie.attributes
if @data
$.extend json, @data
else
json
fetchDataFromTMDb: ->
that = @
_tmdb_id = @movie.get '_tmdb_id'
if _tmdb_id
urls = [
"http://api.themoviedb.org/3/configuration?api_key=api_key"
"http://api.themoviedb.org/3/movie/#{_tmdb_id}?api_key=api_key"
"http://api.themoviedb.org/3/movie/#{_tmdb_id}/casts?api_key=api_key"
]
deferreds = $.map urls, (url) ->
$.get url, (data) ->
$.extend that.data, data
$.when.apply $, deferreds
else
deferred = new $.Deferred
deferred.resolve()
adjustData: ->
@data.cast = @processArray @data.cast[0..9]
@data.genres = @processArray @data.genres
@data.release_date = @processDate @data.release_date
processArray: (array) ->
rv = []
_.each array, (item) ->
rv.push item.name
rv.join ", "
processDate: (date) ->
options =
year: 'numeric'
month: 'long'
day: 'numeric'
[year, month, day] = date.split '-'
rv = new Date year, month, day
rv.toLocaleDateString 'en-US', options
class window.Movies extends Backbone.Collection
model: Movie
url: '/api/movies'
sortAttribute: '_id'
sortDirection: 1
comparator: (a, b) ->
a = a.get @sortAttribute
b = b.get @sortAttribute
if a is b
return
if @sortDirection is 1
if a > b then 1 else -1
else
if a < b then 1 else -1
sortByAttribute: (attr) ->
@sortAttribute = attr
@sort()
class window.MovieView extends Backbone.View
tagName: 'tr'
events:
'click .remove': 'clear'
'click .watched': 'toggleWatched'
initialize: ->
that = @
@listenTo @model, 'change', @render
@listenTo @model, 'destroy', @remove
@template = _.template ($ '#movie-view-template').html()
render: ->
($ @el).html(@template @model.toJSON())
@
# TODO: confirmation
clear: ->
@model.destroy()
toggleWatched: ->
@model.toggleWatched()
class window.MoviesView extends Backbone.View
tagName: 'div'
className: 'row'
events:
'click .sortable': 'sort'
'keypress .submit': 'submit'
initialize: ->
@listenTo @collection, 'change', @render
@listenTo @collection, 'reset', @render
@listenTo @collection, 'sort', @render
# @listenTo @collection, 'filter', @filter
@template = _.template ($ '#movies-view-template').html()
render: ->
($ @el).html(@template {})
$tbody = @$ 'tbody'
@collection.each (movie) ->
movieView = new MovieView
model: movie
$tbody.append movieView.render().el
@
# TODO: validation
submit: (e) ->
$input = @$ '.submit'
if e.which isnt 13
return
rawDescription = $input.val().trim()
[all, _title, _year] = @parseRawDescription rawDescription
@fetchTMDbId _year, _title
$input.val ''
parseRawDescription: (rawDescription) ->
pattern = ///
([^$]+) # _title
(\d{4}) # _year
///
result = rawDescription.match pattern
r.trim().replace /,/g, '' for r in result
fetchTMDbId: (_year, _title) ->
that = @
url = "http://api.themoviedb.org/3/search/movie?api_key=api_key&query=#{_title}&include_adult=false&year=#{_year}"
$.get url, (data) ->
that.createMovie data.results[0]?.id, _year, _title
createMovie: (_tmdb_id, _year, _title) ->
movie =
_tmdb_id: _tmdb_id
_year: _year
_title: _title
options =
sort: false
@collection.create movie, options
sort: (e) ->
$el = $ e.currentTarget
attr = $el.data 'val'
if attr is @collection.sortAttribute
@collection.sortDirection *= -1
else
@collection.sortDirection = 1
@collection.sortByAttribute attr
# filter: ->
# collection = @collection.fetch()
# if @filterType is 'all'
# @collection.reset collection.moels
# if @filterType is 'watched'
# console.log collection
# filtered = collection.where
# _watched: true
# @collection.reset filtered
class window.MovieSingleView extends Backbone.View
tagName: 'div'
className: 'row'
initialize: ->
@template = _.template ($ '#movie-single-view-template').html()
render: ->
that = @
@model.deferred.done ->
if that.model.movie.get '_tmdb_id'
that.model.adjustData()
($ that.el).html(that.template that.model.toJSON())
@
class window.Router extends Backbone.Router
routes:
'': 'index'
'filter/:type': 'index'
'movies/:id': 'movieSingleView'
initialize: ->
@collection = new Movies()
@deferred = @collection.fetch
reset: true
index: (type) ->
moviesView = new MoviesView
collection: @collection
if type is 'watched'
watched = @collection.where
_watched: true
moviesView.collection.reset watched
if type is 'all'
@collection.fetch
reset: true
# moviesView.filterType = type
# @collection.trigger 'filter'
($ '#container')
.empty()
.append moviesView.render().el
movieSingleView: (id) ->
that = @
# wait until collection is loaded before rendering
@deferred.done ->
movie = that.collection.get id
decoratedMovie = new DecoratedMovie movie
movieSingleView = new MovieSingleView
model: decoratedMovie
($ '#container')
.empty()
.append movieSingleView.render().el
$ ->
window.router = new Router()
Backbone.history.start
pushstate: true