Skip to content

Instantly share code, notes, and snippets.

@andrzejkrzywda
Created March 2, 2013 11:22
Show Gist options
  • Save andrzejkrzywda/5070577 to your computer and use it in GitHub Desktop.
Save andrzejkrzywda/5070577 to your computer and use it in GitHub Desktop.
Hexagonaljs TodoMVC example
class WebTodoApp
constructor: ->
useCase = new CompleteTasksUseCase()
window.useCase = useCase
gui = new WebGui()
localStorage = new LocalStorage("todo_app")
glue = new WebGlue(useCase, gui, localStorage)
useCase.showFiltered()
new WebTodoApp()
class WebGlue
constructor: (@useCase, @gui, @storage)->
AutoBind(@gui, @useCase)
After(@gui, 'enterKeyPressed', (content) => @useCase.addNewTask(new Task(content)))
After(@useCase, 'addNewTask', => @gui.showTasks(@useCase.filteredTasks()))
Before(@useCase, 'showFiltered', => @useCase.setInitialTasks(@storage.getTasks()))
After(@useCase, 'showFiltered', => @gui.showTasks(@useCase.filteredTasks()))
AfterAll(@useCase,
[
'addNewTask',
'updateTaskContent',
'deleteTask',
'completeAllTasks',
'toggleTaskCompletion'
],
=> @storage.set("tasks", @useCase.todoTasks))
After(@useCase, 'deleteTask', @gui.deleteTask)
After(@useCase, 'completeTask', @gui.completeTask)
After(@useCase, 'uncompleteTask', @gui.uncompleteTask)
After(@useCase, 'editTaskContent', @gui.editTaskContent)
After(@gui, 'taskContentDoubleClicked', @useCase.editTaskContent)
After(@useCase, 'updateTaskContent', @gui.updateTaskContent)
After(@gui, 'enterKeyPressedWhenEditing', @useCase.updateTaskContent)
AfterAll(@useCase,
[
'addNewTask',
'deleteTask',
'completeAllTasks',
'toggleTaskCompletion',
'showFiltered',
],
=> @gui.showStats(@useCase.remainingTasks().length, @useCase.completedTasks().length))
After(@gui, 'allTasksClicked', => @useCase.selectFilter("all"))
After(@gui, 'completedTasksClicked', => @useCase.selectFilter("completed"))
After(@gui, 'remainingTasksClicked', => @useCase.selectFilter("active"))
AfterAll(@gui,
[
'allTasksClicked',
'completedTasksClicked',
'remainingTasksClicked'
],
=> @useCase.showFiltered())
After(@useCase, 'showFiltered', => @gui.showTasks(@useCase.filteredTasks()))
After(@useCase, 'showFiltered', => @gui.selectFilter(@useCase.filter))
After(@gui, 'clearCompletedClicked', => @useCase.clearCompleted())
After(@useCase, 'clearCompleted', (deletedTasks) => @gui.clearCompleted(deletedTasks))
LogAll(@useCase)
LogAll(@gui)
class WebGui
constructor: ->
$("#new-todo").keypress((event) => @keyPressed(event))
$("#toggle-all").click( => @completeAllTasksClicked())
$("#all-tasks").click => @allTasksClicked()
$("#active-tasks").click => @remainingTasksClicked()
$("#completed-tasks").click => @completedTasksClicked()
@taskElements = []
createElementFor: (task, templateId) =>
source = $(templateId).html()
template = Handlebars.compile(source)
data = {content: task.content, completed: task.completed}
html = template(data)
element = $(html)
addNewTask: (task) =>
element = @createElementFor(task, "#todo-template")
element.task = task
@taskElements.push(element)
$("#todo-list").append(element)
element.find(".destroy").click( => @deleteTaskClicked(task))
element.find(".toggle").click( => @toggleTaskCompletionClicked(task))
element.dblclick( => @taskContentDoubleClicked(task))
findTaskElement: (task) => @taskElements.find((taskElement) -> taskElement.task == task)
taskContentDoubleClicked: (task) =>
deleteTaskClicked: (task) =>
deleteTask: (task) => @findTaskElement(task).remove()
editTaskContent: (task) =>
element = @findTaskElement(task)
element.addClass("editing").find("input.edit").show().select().focus()
element.find("input.edit").keypress((event) => @editingKeyPressed(event, element))
editingKeyPressed: (event, element) =>
ENTER_KEY_CODE = 13
if event.keyCode == ENTER_KEY_CODE
@enterKeyPressedWhenEditing(element.task, element.find("input.edit").val())
enterKeyPressedWhenEditing: (task, newContent) =>
updateTaskContent: (task, content) =>
element = @findTaskElement(task)
element.removeClass("editing").find("input.edit").hide()
element.find("label").html(content)
completeTask: (task) =>
element = @findTaskElement(task)
element.addClass("completed")
element.find("input.toggle").attr("checked", "checked")
uncompleteTask: (task) =>
element = @findTaskElement(task)
element.removeClass("completed")
element.find("input .toggle").attr("checked", "")
showTasks: (tasks) =>
$("#todo-list").html("")
for task in tasks
@addNewTask(task)
completeAllTasksClicked: =>
toggleTaskCompletionClicked: (task) =>
keyPressed: (event) =>
ENTER_KEY_CODE = 13
if event.keyCode == ENTER_KEY_CODE
@enterKeyPressed(@newTodoContent())
@clearNewTodoTextBox()
clearNewTodoTextBox: =>
$("#new-todo").val("")
newTodoContent: =>
$("#new-todo").val()
enterKeyPressed: (content) =>
showStats: (remaining, completed) =>
source = $("#stats-template").html()
template = Handlebars.compile(source)
moreThanOne = remaining > 1
data = {remaining: remaining, moreThanOne: moreThanOne, completed: completed}
html = template(data)
$("#todo-count, #clear-completed").remove()
$("#footer").append(html)
$("#clear-completed").click => @clearCompletedClicked()
allTasksClicked: =>
completedTasksClicked: =>
remainingTasksClicked: =>
clearCompletedClicked: =>
clearCompleted: (tasks)=>
console.log("gui.clearCompleted")
tasks.each (task) -> @deleteTask(task)
selectFilter: (name) =>
$("#filters a").removeClass("selected")
$("##{name}-tasks").addClass("selected")
class CompleteTasksUseCase
constructor: ->
@todoTasks = []
@filter = "all"
completedTasks: => @todoTasks.filter (task) -> task.completed
remainingTasks: => @todoTasks.filter (task) -> not task.completed
filteredTasks: =>
switch @filter
when "all" then @todoTasks
when "active" then @remainingTasks()
when "completed" then @completedTasks()
setInitialTasks: (tasks) =>
@todoTasks = tasks
selectFilter: (@filter) =>
showFiltered: =>
addNewTask: (task) =>
@todoTasks.push(task)
editTaskContent: (task) =>
updateTaskContent: (task, content) =>
task.content = content
deleteTask: (task) =>
@todoTasks.remove(task)
completeAllTasks: =>
@todoTasks.map((task) => @completeTask(task))
toggleTaskCompletion: (task) =>
if task.completed
@uncompleteTask(task)
else
@completeTask(task)
completeTask: (task) =>
task.complete()
uncompleteTask: (task) =>
task.uncomplete()
clearCompleted: =>
@completedTasks().each (task) => @deleteTask(task)
class Task
constructor: (@content, @completed=false) ->
complete: =>
@completed = true
uncomplete: =>
@completed = false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment