TodoMVC with Web and jQuery

This page walks through the TodoMVC variant written with Web and jQuery. It shows the same model as TodoMVC with Silk, on the same page. Its view has the shape of TodoMVC with Web. One class binds and renders, and one widget shows a todo. Web builds, and jQuery does the rest. This page shows only what differs from the Web variant. It builds on TodoMVC with jQuery for jQuery’s own words.

Taking Web-JQuery in

The package imports 'amber/jquery/Web-JQuery' beside 'amber/web/Web'. Web-JQuery comes with @ambers/contrib-jquery 0.8.2, and brings Wrappers-JQuery along. It puts jQuery under Web, as the Web page says. A brush answers asJQuery. TagBrush fromJQuery: makes a brush on a jQuery, and HTMLCanvas onJQuery: a canvas that renders into one. A widget, a block and a string answer appendToJQuery:, which renders them into a jQuery.

The page

web-jquery.html is silk.html with its own title, its own bundle, and its own class to start, WebJQueryTodoApp. Its parts carry the hidden attribute as there.

The view

The view is the package TodoMVC-Web-JQuery, with two classes, WebJQueryTodoApp and WebJQueryTodoItem. It keeps the todos under todos-amber-web-jquery. WebJQueryTodoApp has three slots. todoList is the TodoList. app is a jQuery on the .todoapp section, and listElement one on the ul. start attaches it to '.todoapp' asJQuery. The bindings are those of the jQuery variant, find:, on:do:, val and prop:, and followRoute binds hashchange on window asJQuery.

Rendering

render renders the same five things as the Web variant. The list is emptied with jQuery, and each todo renders itself into it:

renderList
	listElement empty.
	todoList shownTodos do: [ :each | (WebJQueryTodoItem on: each in: self) appendToJQuery: listElement ]

appendToJQuery: sent to a widget makes a canvas on the jQuery and renders the widget on it. The counter is a block rendered the same way:

renderCount
	| count |
	count := app find: '.todo-count'.
	count empty.
	[ :html |
		html strong: todoList activeCount.
		html with: ' ', todoList activeCountLabel ] appendToJQuery: count

The three other things are jQuery’s, as in the jQuery variant. prop:value: sets hidden and checked, and each: with toggleClass:value: marks the links.

One todo

WebJQueryTodoItem is a Widget, with the four slots of WebTodoItem. Its renderOn: is that of WebTodoItem, line for line. The tag messages build the item, class: and the checked attribute set its state, and the on...: messages bind it. The widget keeps the brushes listItem and edit.

Editing

The editing goes through jQuery. asJQuery on a brush answers a jQuery on its element:

startEditing
	listItem asJQuery addClass: 'editing'.
	edit asJQuery val: todo title.
	self bindEdit.
	edit asJQuery trigger: 'focus'

addClass: adds one class and keeps the others. bindEdit binds Enter, Escape and blur on edit asJQuery, as JQueryTodoItem >> bindEdit does, and takes the blur handler off with off:with:. The Web variant has no word for that, and keeps a guard instead. This one does not need it.

What each point costs

The table of TodoMVC with Silk, for this variant:

The specification says Where it is What it takes
Hide main and footer with no todos renderVisibility two prop:value:
Focus the input on load web-jquery.html autofocus, from the template
Enter adds, trimmed, empty ignored bindNewTodo, TodoList >> add: one on:do:; the model trims
Mark all as complete bindToggleAll, renderToggleAll one on:do:, one prop:value:
Mark all cleared after Clear completed renderToggleAll, TodoList >> allAreCompleted nothing; the model answers false for no todos
Toggle, class completed WebJQueryTodoItem >> renderOn:, WebJQueryTodoApp >> toggle: one onChange:, one class:, one attribute
Destroy button on hover WebJQueryTodoItem >> renderOn:, WebJQueryTodoApp >> remove: one onClick:; the stylesheet shows the button
Double-click edits WebJQueryTodoItem >> renderOn:, startEditing one onDblClick:, one method
Enter or blur saves, Escape cancels, empty destroys WebJQueryTodoItem >> bindEdit, WebJQueryTodoApp >> retitle:to:, TodoList >> retitle:to: two on:do:; the model removes the todo
The counter, item or items renderCount, TodoList >> activeCountLabel one block rendered; the model words it
Clear completed, hidden when none bindClearCompleted, renderVisibility one on:do:, one prop:value:
Persistence under todos-amber-web-jquery start, TodoStore one key; the model saves
Routing, class selected, kept on reload followRoute, routeTo:, renderFilters one on:do: on the window, one fromRoute: per link

Each thing the Web variant reaches the DOM for has a jQuery word here. Finding an element inside another is find:. Reading a value or a property is val and prop:, and setting one is prop:value:. One class among others is addClass:, a handler taken back is off:with:, and the window is window asJQuery. Nothing reaches past the two. The cost is two APIs on one element. The item builds with brushes and edits with jQueries, and asJQuery is the step between them, four times.

The tests of the view

WebJQueryTodoAppTest, in TodoMVC-Web-JQuery-Tests, answers attach:to: with a WebJQueryTodoApp attached to anElement asJQuery. The 25 tests of TodoAppTest are the same as for the other variants.

Running it

Open http://localhost:4000/web-jquery.html, and try it as TodoMVC with Silk says. The todos are in localStorage under todos-amber-web-jquery. The test runner of Helios runs the 25 tests of WebJQueryTodoAppTest on the page.