declare module Backbone { export class Model { constructor ( attr ? , opts ? ) ; get ( name ) ; set ( name , val ) ; set ( obj ) ; save ( attr ? , opts ? ) ; destroy ( ) ; bind ( ev , f , ctx ? ) ; toJSON ( ) ; } export class Collection < T > { constructor ( models ? , opts ? ) ; bind ( ev , f , ctx ? ) ; length : number ; create ( attrs , opts ? ) ; each ( f ) ; fetch ( opts ? ) ; last ( ) ; last ( n ) ; filter ( f ) ; without ( ... values ) ; } export class View { constructor ( options ? ) ; $ ( selector ) ; el : HTMLElement ; $el : JQuery ; model : Model ; remove ( ) ; delegateEvents : any ; make ( tagName , attrs ? , opts ? ) ; setElement ( element , delegate ? ) ; setElement ( element , delegate ? ) ; tagName : string ; events : any ; static extend : any ; } } interface JQuery { fadeIn ( ) : JQuery ; fadeOut ( ) : JQuery ; focus ( ) : JQuery ; html ( ) : string ; html ( val ) : JQuery ; show ( ) : JQuery ; addClass ( className ) : JQuery ; removeClass ( className ) : JQuery ; append ( el ) : JQuery ; val ( ) : string ; val ( value ) : JQuery ; attr ( attrName ) : string ; } declare var $ ; declare var _ ; declare var Store ; class Todo extends Backbone . Model { defaults ( ) { return { content : "empty todo..." , done : false } ; } initialize ( ) { if ( ! this . get ( "content" ) ) { this . set ( { "content" : this . defaults ( ) . content } ) ; } } toggle ( ) { this . save ( { done : ! this . get ( "done" ) } ) ; } clear ( ) { this . destroy ( ) ; } } class TodoList extends Backbone . Collection < Todo > { model = Todo ; localStorage = new Store ( "todos-backbone" ) ; done ( ) { return this . filter ( todo => todo . get ( 'done' ) ) ; } remaining ( ) { return this . without . apply ( this , this . done ( ) ) ; } nextOrder ( ) { if ( ! this . length ) return 1 ; return this . last ( ) . get ( 'order' ) + 1 ; } comparator ( todo ) { return todo . get ( 'order' ) ; } } var Todos = new TodoList ( ) ; class TodoView extends Backbone . View { template : ( data : any ) => string ; model : Todo ; input : JQuery ; constructor ( options ? ) { super ( options ) ; this . tagName = "li" ; this . events = { "click .check" : "toggleDone" , "dblclick label.todo-content" : "edit" , "click span.todo-destroy" : "clear" , "keypress .todo-input" : "updateOnEnter" , "blur .todo-input" : "close" } ; this . template = _ . template ( $ ( '#item-template' ) . html ( ) ) ; _ . bindAll ( this , 'render' , 'close' , 'remove' ) ; this . model . bind ( 'change' , this . render ) ; this . model . bind ( 'destroy' , this . remove ) ; } render ( ) { this . $el . html ( this . template ( this . model . toJSON ( ) ) ) ; this . input = this . $ ( '.todo-input' ) ; return this ; } toggleDone ( ) { this . model . toggle ( ) ; } edit ( ) { this . $el . addClass ( "editing" ) ; this . input . focus ( ) ; } close ( ) { this . model . save ( { content : this . input . val ( ) } ) ; this . $el . removeClass ( "editing" ) ; } updateOnEnter ( e ) { if ( e . keyCode == 13 ) close ( ) ; } clear ( ) { this . model . clear ( ) ; } } class AppView extends Backbone . View { events = { "keypress #new-todo" : "createOnEnter" , "keyup #new-todo" : "showTooltip" , "click .todo-clear a" : "clearCompleted" , "click .mark-all-done" : "toggleAllComplete" } ; input : JQuery ; allCheckbox : HTMLInputElement ; statsTemplate : ( params : any ) => string ; constructor ( ) { super ( ) ; this . setElement ( $ ( "#todoapp" ) , true ) ; _ . bindAll ( this , 'addOne' , 'addAll' , 'render' , 'toggleAllComplete' ) ; this . input = this . $ ( "#new-todo" ) ; this . allCheckbox = this . $ ( ".mark-all-done" ) [ 0 ] ; this . statsTemplate = _ . template ( $ ( '#stats-template' ) . html ( ) ) ; Todos . bind ( 'add' , this . addOne ) ; Todos . bind ( 'reset' , this . addAll ) ; Todos . bind ( 'all' , this . render ) ; Todos . fetch ( ) ; } render ( ) { var done = Todos . done ( ) . length ; var remaining = Todos . remaining ( ) . length ; this . $ ( '#todo-stats' ) . html ( this . statsTemplate ( { total : Todos . length , done : done , remaining : remaining } ) ) ; this . allCheckbox . checked = ! remaining ; } addOne ( todo ) { var view = new TodoView ( { model : todo } ) ; this . $ ( "#todo-list" ) . append ( view . render ( ) . el ) ; } addAll ( ) { Todos . each ( this . addOne ) ; } newAttributes ( ) { return { content : this . input . val ( ) , order : Todos . nextOrder ( ) , done : false } ; } createOnEnter ( e ) { if ( e . keyCode != 13 ) return ; Todos . create ( this . newAttributes ( ) ) ; this . input . val ( '' ) ; } clearCompleted ( ) { _ . each ( Todos . done ( ) , todo => todo . clear ( ) ) ; return false ; } tooltipTimeout : number = null ; showTooltip ( e ) { var tooltip = $ ( ".ui-tooltip-top" ) ; var val = this . input . val ( ) ; tooltip . fadeOut ( ) ; if ( this . tooltipTimeout ) clearTimeout ( this . tooltipTimeout ) ; if ( val == '' || val == this . input . attr ( 'placeholder' ) ) return ; this . tooltipTimeout = _ . delay ( ( ) => tooltip . show ( ) . fadeIn ( ) , 1000 ) ; } toggleAllComplete ( ) { var done = this . allCheckbox . checked ; Todos . each ( todo => todo . save ( { 'done' : done } ) ) ; } } $ ( ( ) => { new AppView ( ) ; } ) ;