UNPKG

todomvc

Version:

> Helping you select an MV\* framework

280 lines (240 loc) 10 kB
/** * @author Mike Britton, Cliff Hall * * @class TodoForm * @link https://github.com/PureMVC/puremvc-js-demo-todomvc.git */ puremvc.define({ name: 'todomvc.view.component.TodoForm', constructor: function(event) { // data this.todos = []; this.stats = {}; this.filter = ''; // Fixed DOM elements managed by this view component this.todoApp = document.querySelector( '#todoapp' ); this.main = this.todoApp.querySelector( '#main' ); this.toggleAllCheckbox = this.todoApp.querySelector( '#toggle-all' ); this.newTodoField = this.todoApp.querySelector( '#new-todo' ); this.todoList = this.todoApp.querySelector( '#todo-list' ); this.footer = this.todoApp.querySelector( '#footer' ); this.todoCount = this.todoApp.querySelector( '#todo-count' ); this.clearButton = this.todoApp.querySelector( '#clear-completed' ); this.filters = this.todoApp.querySelector( '#filters' ); this.filterAll = this.filters.querySelector( '#filterAll' ); this.filterActive = this.filters.querySelector( '#filterActive' ); this.filterCompleted = this.filters.querySelector( '#filterCompleted' ); // Event listeners for fixed UI elements this.newTodoField.component = this; todomvc.view.event.AppEvents.addEventListener( this.newTodoField, 'keypress', function( event ) { if ( event.keyCode === this.component.ENTER_KEY && this.value ) { this.component.dispatchAddTodo( event ); } }); this.clearButton.component = this; todomvc.view.event.AppEvents.addEventListener( this.clearButton, 'click', function( event ) { this.component.dispatchClearCompleted( event ); }); this.toggleAllCheckbox.component = this; todomvc.view.event.AppEvents.addEventListener( this.toggleAllCheckbox, 'change', function( event ) { this.component.dispatchToggleCompleteAll( event.target.checked ); }); } }, // INSTANCE MEMBERS { ENTER_KEY: 13, ESC_KEY: 27, addEventListener: function ( type, listener, useCapture ){ todomvc.view.event.AppEvents.addEventListener ( this.todoApp, type, listener, useCapture ); }, createEvent: function( eventName ) { return todomvc.view.event.AppEvents.createEvent( eventName ); }, dispatchEvent: function( event ) { todomvc.view.event.AppEvents.dispatchEvent( this.todoApp, event ); }, abandonEditTodo: function( event ) { var todo, todoId, div, inputEditTodo; inputEditTodo = event.target; todoId = inputEditTodo.getAttribute( 'data-todo-id' ) todo = this.getTodoById( todoId ); inputEditTodo.value = todo.title; inputEditTodo.completed = todo.completed; div = document.getElementById( 'li_' + todoId ); div.className = 'view'; this.newTodoField.focus(); }, dispatchToggleComplete: function( event ) { var todo, toggleItemCompleteEvent; todo = this.getTodoById( event.target.getAttribute( 'data-todo-id' ) ); todo.id = event.target.getAttribute( 'data-todo-id' ); todo.completed = event.target.checked; toggleItemCompleteEvent = this.createEvent( todomvc.view.event.AppEvents.TOGGLE_COMPLETE ); toggleItemCompleteEvent.todo = todo; this.dispatchEvent( toggleItemCompleteEvent ); }, dispatchToggleCompleteAll: function( checked ) { var toggleCompleteAllEvent = this.createEvent( todomvc.view.event.AppEvents.TOGGLE_COMPLETE_ALL ); toggleCompleteAllEvent.doToggleComplete = checked; this.dispatchEvent( toggleCompleteAllEvent ); }, dispatchClearCompleted: function() { var clearCompleteEvent = this.createEvent( todomvc.view.event.AppEvents.CLEAR_COMPLETED ); this.dispatchEvent( clearCompleteEvent ); }, dispatchDelete: function( id ) { var deleteItemEvent = this.createEvent( todomvc.view.event.AppEvents.DELETE_ITEM ); deleteItemEvent.todoId = id; this.dispatchEvent( deleteItemEvent ); }, dispatchAddTodo: function( event ) { var addItemEvent, todo = {}; todo.completed = false; todo.title = this.newTodoField.value.trim(); if ( todo.title === '' ) return; addItemEvent = this.createEvent( todomvc.view.event.AppEvents.ADD_ITEM ); addItemEvent.todo = todo; this.dispatchEvent( addItemEvent ); }, dispatchUpdateTodo: function(event) { var eventType, updateItemEvent, todo = {}; todo.id = event.target.id.slice(6); todo.title = event.target.value.trim(); todo.completed = event.target.completed; eventType = ( todo.title === "" ) ? todomvc.view.event.AppEvents.DELETE_ITEM : todomvc.view.event.AppEvents.UPDATE_ITEM; updateItemEvent = this.createEvent( eventType ); updateItemEvent.todo = todo; updateItemEvent.todoId = todo.id; this.dispatchEvent( updateItemEvent ); }, setFilteredTodoList: function( data ) { var todo, checkbox, label, deleteLink, divDisplay, inputEditTodo, li, i, todoId, div, inputEditTodo; // Update instance data this.todos = data.todos; this.stats = data.stats; this.filter = data.filter; // Hide main section if no todos this.main.style.display = this.stats.totalTodo ? 'block' : 'none'; // Create Todo list this.todoList.innerHTML = ''; this.newTodoField.value = ''; for ( i=0; i < this.todos.length; i++ ) { todo = this.todos[i]; // Create checkbox checkbox = document.createElement( 'input' ); checkbox.className = 'toggle'; checkbox.setAttribute( 'data-todo-id', todo.id ); checkbox.type = 'checkbox'; checkbox.component = this; todomvc.view.event.AppEvents.addEventListener( checkbox, 'change', function( event ) { this.component.dispatchToggleComplete( event ); }); // Create div text label = document.createElement( 'label' ); label.setAttribute( 'data-todo-id', todo.id ); label.appendChild( document.createTextNode( todo.title ) ); // Create delete button deleteLink = document.createElement( 'button' ); deleteLink.className = 'destroy'; deleteLink.setAttribute( 'data-todo-id', todo.id ); deleteLink.component = this; todomvc.view.event.AppEvents.addEventListener( deleteLink, 'click', function( event ) { this.component.dispatchDelete( event.target.getAttribute( 'data-todo-id' ) ); }); // Create divDisplay divDisplay = document.createElement( 'div' ); divDisplay.className = 'view'; divDisplay.setAttribute( 'data-todo-id', todo.id ); divDisplay.appendChild( checkbox ); divDisplay.appendChild( label ); divDisplay.appendChild( deleteLink ); todomvc.view.event.AppEvents.addEventListener( divDisplay, 'dblclick', function() { todoId = this.getAttribute( 'data-todo-id' ); div = document.getElementById( 'li_' + todoId ); inputEditTodo = document.getElementById( 'input_' + todoId ); inputEditTodo.setAttribute( 'data-todo-id', todoId ); div.className = 'editing'; inputEditTodo.focus(); }); // Create todo input inputEditTodo = document.createElement( 'input' ); inputEditTodo.id = 'input_' + todo.id; inputEditTodo.className = 'edit'; inputEditTodo.value = todo.title; inputEditTodo.completed = todo.completed; inputEditTodo.component = this; todomvc.view.event.AppEvents.addEventListener( inputEditTodo, 'keypress', function( event ) { if ( event.keyCode === this.component.ENTER_KEY ) { this.component.dispatchUpdateTodo( event ); } }); todomvc.view.event.AppEvents.addEventListener( inputEditTodo, 'keydown', function( event ) { if ( event.keyCode === this.component.ESC_KEY ) { this.component.abandonEditTodo( event ); } }); todomvc.view.event.AppEvents.addEventListener( inputEditTodo, 'blur', function( event ) { this.component.dispatchUpdateTodo( event ); }); // Create Todo ListItem and add to list li = document.createElement( 'li' ); li.id = 'li_' + todo.id; li.appendChild( divDisplay ); li.appendChild( inputEditTodo ); if ( todo.completed ) { li.className += 'completed'; checkbox.checked = true; } this.todoList.appendChild( li ); } // Update UI this.footer.style.display = this.stats.totalTodo ? 'block' : 'none'; this.updateToggleAllCheckbox(); this.updateClearButton(); this.updateTodoCount(); this.updateFilter(); }, getTodoById: function( id ) { var i; for ( i = 0; i < this.todos.length; i++ ) { if ( this.todos[ i ].id === id ) { return this.todos[i]; } } }, updateFilter: function() { this.filterAll.className = ( this.filter === todomvc.AppConstants.FILTER_ALL ) ? 'selected' : ''; this.filterActive.className = ( this.filter === todomvc.AppConstants.FILTER_ACTIVE ) ? 'selected' : ''; this.filterCompleted.className = ( this.filter === todomvc.AppConstants.FILTER_COMPLETED ) ? 'selected' : ''; }, updateToggleAllCheckbox: function() { var i, checked = ( this.todos.length > 0 ); for ( i = 0; i < this.todos.length; i++ ) { if ( this.todos[ i ].completed === false ) { checked = false; break; } } this.toggleAllCheckbox.checked = checked; }, updateClearButton: function() { this.clearButton.style.display = ( this.stats.todoCompleted === 0 ) ? 'none' : 'block'; this.clearButton.innerHTML = 'Clear completed (' + this.stats.todoCompleted + ')'; }, updateTodoCount: function() { var number = document.createElement( 'strong' ), text = ' ' + (this.stats.todoLeft === 1 ? 'item' : 'items' ) + ' left'; number.innerHTML = this.stats.todoLeft; this.todoCount.innerHTML = null; this.todoCount.appendChild( number ); this.todoCount.appendChild( document.createTextNode( text ) ); } }, // STATIC MEMBERS { NAME: 'TodoForm', } );