Commit cb03b745 authored by Sindre Sorhus's avatar Sindre Sorhus

Montage - convert to tabs

parent 69d36872
...@@ -2,19 +2,19 @@ var Montage = require("montage").Montage; ...@@ -2,19 +2,19 @@ var Montage = require("montage").Montage;
exports.Todo = Montage.create(Montage, { exports.Todo = Montage.create(Montage, {
initWithTitle: { initWithTitle: {
value: function(title) { value: function(title) {
this.title = title; this.title = title;
return this; return this;
} }
}, },
title: { title: {
value: null value: null
}, },
completed: { completed: {
value: false value: false
} }
}); });
<!doctype html> <!doctype html>
<html lang=en id=montage-todomvc> <head> <meta charset=utf-8> <html lang=en id=montage-todomvc> <head> <meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"> <meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
<title>Montage • TodoMVC</title> <title>Montage • TodoMVC</title>
<link rel=stylesheet href="../../../assets/base.css"> <link rel=stylesheet href="../../../assets/base.css">
<link rel=stylesheet href="assets/app.css"> <link rel=stylesheet href="assets/app.css">
<script src=bundle-0-d67ccde.js data-montage="packages/montage@4763f06/" data-montage-hash=4763f06 data-application-hash=1156f40></script> <script src=bundle-0-d67ccde.js data-montage="packages/montage@4763f06/" data-montage-hash=4763f06 data-application-hash=1156f40></script>
<script type="text/montage-serialization">{"owner":{"prototype":"montage/ui/loader.reel"}}</script> <script type="text/montage-serialization">{"owner":{"prototype":"montage/ui/loader.reel"}}</script>
</head> </head>
<body></body> <body></body>
</html> </html>
\ No newline at end of file
var Montage = require("montage").Montage, var Montage = require("montage").Montage,
Converter = require("montage/core/converter/converter").Converter; Converter = require("montage/core/converter/converter").Converter;
exports.ItemCountConverter = Montage.create(Converter, { exports.ItemCountConverter = Montage.create(Converter, {
convert: { convert: {
value: function(itemCount) { value: function(itemCount) {
return (1 === itemCount) ? "item" : "items"; return (1 === itemCount) ? "item" : "items";
} }
} }
}); });
<!DOCTYPE html> <!doctype html>
<html> <html lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8">
<title>Main</title> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Template • TodoMVC</title>
<link rel="stylesheet" type="text/css" href="main.css">
<link rel="stylesheet" type="text/css" href="main.css"> <script type="text/montage-serialization">
{
"owner": {
"properties": {
"element": {"#": "mainComponent"},
"newTodoForm": {"#": "newTodoForm"},
"newTodoInput": {"#": "new-todo"}
}
},
<script type="text/montage-serialization"> "todoRepetition": {
{ "prototype": "montage/ui/repetition.reel",
"owner": { "properties": {
"properties": { "element": {"#": "todo-list"}
"element": {"#": "mainComponent"}, },
"newTodoForm": {"#": "newTodoForm"}, "bindings": {
"newTodoInput": {"#": "new-todo"} "contentController": {"<-": "@owner.todoListController"}
} }
}, },
"todoRepetition": { "todoView": {
"prototype": "montage/ui/repetition.reel", "prototype": "ui/todo-view.reel",
"properties": { "properties": {
"element": {"#": "todo-list"} "element": {"#": "todoView"}
}, },
"bindings": { "bindings": {
"contentController": {"<-": "@owner.todoListController"} "todo": {"<-": "@todoRepetition.objectAtCurrentIteration"}
} }
}, },
"todoView": { "main": {
"prototype": "ui/todo-view.reel", "prototype": "montage/ui/dynamic-element.reel",
"properties": { "properties": {
"element": {"#": "todoView"} "element": {"#": "main"}
}, },
"bindings": { "bindings": {
"todo": {"<-": "@todoRepetition.objectAtCurrentIteration"} "classList.visible": {"<-": "@owner.todoListController.organizedObjects.0"}
} }
}, },
"main": { "footer": {
"prototype": "montage/ui/dynamic-element.reel", "prototype": "montage/ui/dynamic-element.reel",
"properties": { "properties": {
"element": {"#": "main"} "element": {"#": "footer"}
}, },
"bindings": { "bindings": {
"classList.visible": {"<-": "@owner.todoListController.organizedObjects.0"} "classList.visible": {"<-": "@owner.todoListController.organizedObjects.0"}
} }
}, },
"footer": { "toggleAllCheckbox": {
"prototype": "montage/ui/dynamic-element.reel", "prototype": "montage/ui/native/input-checkbox.reel",
"properties": { "properties": {
"element": {"#": "footer"} "element": {"#": "toggle-all"}
}, },
"bindings": { "bindings": {
"classList.visible": {"<-": "@owner.todoListController.organizedObjects.0"} "checked": {"<->": "@owner.allCompleted"}
} }
}, },
"toggleAllCheckbox": { "todoCount": {
"prototype": "montage/ui/native/input-checkbox.reel", "prototype": "montage/ui/dynamic-text.reel",
"properties": { "properties": {
"element": {"#": "toggle-all"} "element": {"#": "todo-count"}
}, },
"bindings": { "bindings": {
"checked": {"<->": "@owner.allCompleted"} "value": {"<-": "@owner.todosLeft.count()"}
} }
}, },
"todoCount": { "itemCountConverter": {
"prototype": "montage/ui/dynamic-text.reel", "prototype": "ui/main.reel/item-count-converter"
"properties": { },
"element": {"#": "todo-count"}
},
"bindings": {
"value": {"<-": "@owner.todosLeft.count()"}
}
},
"itemCountConverter": { "todoCountWording": {
"prototype": "ui/main.reel/item-count-converter" "prototype": "montage/ui/dynamic-text.reel",
}, "properties": {
"element": {"#": "todo-count-wording"}
},
"bindings": {
"value": {"<-": "@owner.todosLeft.count()", "converter": {"@": "itemCountConverter"}}
}
},
"todoCountWording": { "completedCount": {
"prototype": "montage/ui/dynamic-text.reel", "prototype": "montage/ui/dynamic-text.reel",
"properties": { "properties": {
"element": {"#": "todo-count-wording"} "element": {"#": "completed-count"}
}, },
"bindings": { "bindings": {
"value": {"<-": "@owner.todosLeft.count()", "converter": {"@": "itemCountConverter"}} "value": {"<-": "@owner.completedTodos.count()"}
} }
}, },
"completedCount": { "clearCompletedContainer": {
"prototype": "montage/ui/dynamic-text.reel", "prototype": "montage/ui/dynamic-element.reel",
"properties": { "properties": {
"element": {"#": "completed-count"} "element": {"#": "clear-completed-container"}
}, },
"bindings": { "bindings": {
"value": {"<-": "@owner.completedTodos.count()"} "classList.visible": {"<-": "@owner.completedTodos.count()"}
} }
}, },
"clearCompletedContainer": { "clearCompletedButton": {
"prototype": "montage/ui/dynamic-element.reel", "prototype": "montage/ui/native/button.reel",
"properties": { "properties": {
"element": {"#": "clear-completed-container"} "element": {"#": "clear-completed"}
}, },
"bindings": { "listeners": [
"classList.visible": {"<-": "@owner.completedTodos.count()"} {
} "type": "action",
}, "listener": {"@": "owner"},
"capture": false
"clearCompletedButton": { }
"prototype": "montage/ui/native/button.reel", ]
"properties": { }
"element": {"#": "clear-completed"} }
}, </script>
"listeners": [
{
"type": "action",
"listener": {"@": "owner"},
"capture": false
}
]
}
}
</script>
</head> </head>
<body> <body>
<div data-montage-id="mainComponent"> <div data-montage-id="mainComponent">
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
<form data-montage-id="newTodoForm"> <form data-montage-id="newTodoForm">
<input data-montage-id="new-todo" id="new-todo" placeholder="What needs to be done?" autofocus> <input data-montage-id="new-todo" id="new-todo" placeholder="What needs to be done?" autofocus>
</form> </form>
</header> </header>
<section data-montage-id="main" id="main"> <section data-montage-id="main" id="main">
<input data-montage-id="toggle-all" id="toggle-all" type="checkbox"> <input data-montage-id="toggle-all" id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul data-montage-id="todo-list" id="todo-list"> <ul data-montage-id="todo-list" id="todo-list">
<li data-montage-id="todoView"></li> <li data-montage-id="todoView"></li>
</ul> </ul>
</section> </section>
<footer data-montage-id="footer" id="footer"> <footer data-montage-id="footer" id="footer">
<span id="todo-count"><strong data-montage-id="todo-count">0</strong> <span data-montage-id="todo-count-wording">items</span> left</span> <span id="todo-count"><strong data-montage-id="todo-count">0</strong> <span data-montage-id="todo-count-wording">items</span> left</span>
<div data-montage-id="clear-completed-container" id="clear-completed-container"> <div data-montage-id="clear-completed-container" id="clear-completed-container">
<button data-montage-id="clear-completed" id="clear-completed">Clear completed (<span data-montage-id="completed-count">0</span>)</button> <button data-montage-id="clear-completed" id="clear-completed">Clear completed (<span data-montage-id="completed-count">0</span>)</button>
</div> </div>
</footer> </footer>
</section> </section>
<footer id="info"> <footer id="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Created with <a href="http://github.com/motorola-mobility/montage">Montage</a> </p> <p>Created with <a href="http://github.com/motorola-mobility/montage">Montage</a> </p>
<p>Source available at <a href="http://github.com/mczepiel/montage-todomvc">Montage-TodoMVC</a> </p> <p>Source available at <a href="http://github.com/mczepiel/montage-todomvc">Montage-TodoMVC</a> </p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
</div> </div>
</body> </body>
</html> </html>
var Montage = require("montage").Montage, var Montage = require("montage").Montage,
Component = require("montage/ui/component").Component, Component = require("montage/ui/component").Component,
ArrayController = require("montage/ui/controller/array-controller").ArrayController, ArrayController = require("montage/ui/controller/array-controller").ArrayController,
Todo = require("core/todo").Todo, Todo = require("core/todo").Todo,
Serializer = require("montage/core/serializer").Serializer, Serializer = require("montage/core/serializer").Serializer,
Deserializer = require("montage/core/deserializer").Deserializer, Deserializer = require("montage/core/deserializer").Deserializer,
LOCAL_STORAGE_KEY = "todos-montage"; LOCAL_STORAGE_KEY = "todos-montage";
exports.Main = Montage.create(Component, { exports.Main = Montage.create(Component, {
newTodoForm: { newTodoForm: {
value: null value: null
}, },
newTodoInput: { newTodoInput: {
value: null value: null
}, },
todoListController: { todoListController: {
serializable: false, serializable: false,
value: null value: null
}, },
didCreate: { didCreate: {
value: function() { value: function() {
this.todoListController = ArrayController.create(); this.todoListController = ArrayController.create();
this.load(); this.load();
} }
}, },
load: { load: {
value: function() { value: function() {
if (localStorage) { if (localStorage) {
var todoSerialization = localStorage.getItem(LOCAL_STORAGE_KEY); var todoSerialization = localStorage.getItem(LOCAL_STORAGE_KEY);
if (todoSerialization) { if (todoSerialization) {
var deserializer = Deserializer.create(), var deserializer = Deserializer.create(),
self = this; self = this;
try { try {
deserializer.initWithStringAndRequire(todoSerialization, require).deserializeObject(function(todos) { deserializer.initWithStringAndRequire(todoSerialization, require).deserializeObject(function(todos) {
self.todoListController.initWithContent(todos); self.todoListController.initWithContent(todos);
}, require); }, require);
} catch(e) { } catch(e) {
console.error("Could not load saved tasks."); console.error("Could not load saved tasks.");
console.debug("Could not deserialize", todoSerialization); console.debug("Could not deserialize", todoSerialization);
console.log(e.stack); console.log(e.stack);
} }
} }
} }
} }
}, },
save: { save: {
value: function() { value: function() {
if (localStorage) { if (localStorage) {
var todos = this.todoListController.content, var todos = this.todoListController.content,
serializer = Serializer.create().initWithRequire(require); serializer = Serializer.create().initWithRequire(require);
localStorage.setItem(LOCAL_STORAGE_KEY, serializer.serializeObject(todos)); localStorage.setItem(LOCAL_STORAGE_KEY, serializer.serializeObject(todos));
} }
} }
}, },
prepareForDraw: { prepareForDraw: {
value: function() { value: function() {
this.newTodoForm.identifier = "newTodoForm"; this.newTodoForm.identifier = "newTodoForm";
this.newTodoForm.addEventListener("submit", this, false); this.newTodoForm.addEventListener("submit", this, false);
this.addEventListener("destroyTodo", this, true); this.addEventListener("destroyTodo", this, true);
window.addEventListener("beforeunload", this, true); window.addEventListener("beforeunload", this, true);
} }
}, },
captureDestroyTodo: { captureDestroyTodo: {
value: function(evt) { value: function(evt) {
this.destroyTodo(evt.detail.todo); this.destroyTodo(evt.detail.todo);
} }
}, },
handleNewTodoFormSubmit: { handleNewTodoFormSubmit: {
value: function(evt) { value: function(evt) {
evt.preventDefault(); evt.preventDefault();
var title = this.newTodoInput.value.trim(); var title = this.newTodoInput.value.trim();
if ("" === title) { if ("" === title) {
return; return;
} }
this.createTodo(title); this.createTodo(title);
this.newTodoInput.value = null; this.newTodoInput.value = null;
} }
}, },
createTodo: { createTodo: {
value: function(title) { value: function(title) {
var todo = Todo.create().initWithTitle(title); var todo = Todo.create().initWithTitle(title);
this.todoListController.addObjects(todo); this.todoListController.addObjects(todo);
return todo; return todo;
} }
}, },
destroyTodo: { destroyTodo: {
value: function(todo) { value: function(todo) {
this.todoListController.removeObjects(todo); this.todoListController.removeObjects(todo);
return todo; return todo;
} }
}, },
allCompleted: { allCompleted: {
dependencies: ["todoListController.organizedObjects.completed"], dependencies: ["todoListController.organizedObjects.completed"],
get: function() { get: function() {
return this.todoListController.organizedObjects.getProperty("completed").all(); return this.todoListController.organizedObjects.getProperty("completed").all();
}, },
set: function(value) { set: function(value) {
this.todoListController.organizedObjects.forEach(function(member) { this.todoListController.organizedObjects.forEach(function(member) {
member.completed = value; member.completed = value;
}); });
} }
}, },
todosLeft: { todosLeft: {
dependencies: ["todoListController.organizedObjects.completed"], dependencies: ["todoListController.organizedObjects.completed"],
get: function() { get: function() {
if (this.todoListController.organizedObjects) { if (this.todoListController.organizedObjects) {
var todos = this.todoListController.organizedObjects; var todos = this.todoListController.organizedObjects;
return todos.filter(function(member) { return todos.filter(function(member) {
return !member.completed; return !member.completed;
}); });
} }
} }
}, },
completedTodos: { completedTodos: {
dependencies: ["todoListController.organizedObjects.completed"], dependencies: ["todoListController.organizedObjects.completed"],
get: function() { get: function() {
if (this.todoListController.organizedObjects) { if (this.todoListController.organizedObjects) {
var todos = this.todoListController.organizedObjects; var todos = this.todoListController.organizedObjects;
return todos.filter(function(member) { return todos.filter(function(member) {
return member.completed; return member.completed;
}); });
} }
} }
}, },
handleClearCompletedButtonAction: { handleClearCompletedButtonAction: {
value: function(evt) { value: function(evt) {
var completedTodos = this.todoListController.organizedObjects.filter(function(todo) { var completedTodos = this.todoListController.organizedObjects.filter(function(todo) {
return todo.completed; return todo.completed;
}); });
if (completedTodos.length > 0) { if (completedTodos.length > 0) {
this.todoListController.removeObjects.apply(this.todoListController, completedTodos); this.todoListController.removeObjects.apply(this.todoListController, completedTodos);
} }
} }
}, },
captureBeforeunload: { captureBeforeunload: {
value: function() { value: function() {
this.save(); this.save();
} }
} }
}); });
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>TodoView</title> <title>TodoView</title>
<script type="text/montage-serialization"> <script type="text/montage-serialization">
{ {
"owner": { "owner": {
"properties": { "properties": {
"element": {"#": "todoView"}, "element": {"#": "todoView"},
"editInput": {"@": "editInput"} "editInput": {"@": "editInput"}
} }
}, },
"todoTitle": { "todoTitle": {
"prototype": "montage/ui/dynamic-text.reel", "prototype": "montage/ui/dynamic-text.reel",
"properties": { "properties": {
"element": {"#": "todoTitle"} "element": {"#": "todoTitle"}
}, },
"bindings": { "bindings": {
"value": {"<-": "@owner.todo.title"} "value": {"<-": "@owner.todo.title"}
} }
}, },
"todoCompletedCheckbox": { "todoCompletedCheckbox": {
"prototype": "montage/ui/native/input-checkbox.reel", "prototype": "montage/ui/native/input-checkbox.reel",
"properties": { "properties": {
"element": {"#": "todoCompletedCheckbox"} "element": {"#": "todoCompletedCheckbox"}
}, },
"bindings": { "bindings": {
"checked": {"<->": "@owner.todo.completed"} "checked": {"<->": "@owner.todo.completed"}
} }
}, },
"destroyButton": { "destroyButton": {
"prototype": "montage/ui/native/button.reel", "prototype": "montage/ui/native/button.reel",
"properties": { "properties": {
"element": {"#": "destroyButton"} "element": {"#": "destroyButton"}
}, },
"listeners": [ "listeners": [
{ {
"type": "action", "type": "action",
"listener": {"@": "owner"}, "listener": {"@": "owner"},
"capture": true "capture": true
} }
] ]
}, },
"editInput": { "editInput": {
"prototype": "montage/ui/native/input-text.reel", "prototype": "montage/ui/native/input-text.reel",
"properties": { "properties": {
"element": {"#": "edit-input"} "element": {"#": "edit-input"}
}, },
"bindings": { "bindings": {
"value": {"<-": "@owner.todo.title"} "value": {"<-": "@owner.todo.title"}
} }
} }
} }
</script> </script>
</head> </head>
<body> <body>
<li data-montage-id="todoView"> <li data-montage-id="todoView">
<div class="view"> <div class="view">
<input data-montage-id="todoCompletedCheckbox" class="toggle" type="checkbox"> <input data-montage-id="todoCompletedCheckbox" class="toggle" type="checkbox">
<label data-montage-id="todoTitle"></label> <label data-montage-id="todoTitle"></label>
<button data-montage-id="destroyButton" class="destroy"></button> <button data-montage-id="destroyButton" class="destroy"></button>
</div> </div>
<form data-montage-id="edit"> <form data-montage-id="edit">
<input data-montage-id="edit-input" class="edit" value="Rule the web"> <input data-montage-id="edit-input" class="edit" value="Rule the web">
</form> </form>
</li> </li>
</body> </body>
</html> </html>
var Montage = require("montage").Montage, var Montage = require("montage").Montage,
Component = require("montage/ui/component").Component; Component = require("montage/ui/component").Component;
exports.TodoView = Montage.create(Component, { exports.TodoView = Montage.create(Component, {
todo: { todo: {
value: null value: null
}, },
editInput: { editInput: {
value: null value: null
}, },
didCreate: { didCreate: {
value: function() { value: function() {
Object.defineBinding(this, "isCompleted", { Object.defineBinding(this, "isCompleted", {
boundObject: this, boundObject: this,
boundObjectPropertyPath: "todo.completed", boundObjectPropertyPath: "todo.completed",
oneway: true oneway: true
}); });
} }
}, },
prepareForDraw: { prepareForDraw: {
value: function() { value: function() {
this.element.addEventListener("dblclick", this, false); this.element.addEventListener("dblclick", this, false);
this.element.addEventListener("blur", this, true); this.element.addEventListener("blur", this, true);
this.element.addEventListener("submit", this, false); this.element.addEventListener("submit", this, false);
} }
}, },
captureDestroyButtonAction: { captureDestroyButtonAction: {
value: function() { value: function() {
this.dispatchDestroy(); this.dispatchDestroy();
} }
}, },
dispatchDestroy: { dispatchDestroy: {
value: function() { value: function() {
this.dispatchEventNamed("destroyTodo", true, true, {todo: this.todo}) this.dispatchEventNamed("destroyTodo", true, true, {todo: this.todo})
} }
}, },
handleDblclick: { handleDblclick: {
value: function(evt) { value: function(evt) {
this.isEditing = true; this.isEditing = true;
} }
}, },
_isEditing: { _isEditing: {
value: false value: false
}, },
isEditing: { isEditing: {
get: function() { get: function() {
return this._isEditing; return this._isEditing;
}, },
set: function(value) { set: function(value) {
if (value === this._isEditing) { if (value === this._isEditing) {
return; return;
} }
this._isEditing = value; this._isEditing = value;
this.needsDraw = true; this.needsDraw = true;
} }
}, },
_isCompleted: { _isCompleted: {
value: false value: false
}, },
isCompleted: { isCompleted: {
get: function() { get: function() {
return this._isCompleted; return this._isCompleted;
}, },
set: function(value) { set: function(value) {
if (value === this._isCompleted) { if (value === this._isCompleted) {
return; return;
} }
this._isCompleted = value; this._isCompleted = value;
this.needsDraw = true; this.needsDraw = true;
} }
}, },
captureBlur: { captureBlur: {
value: function(evt) { value: function(evt) {
if (this.isEditing && this.editInput.element === evt.target) { if (this.isEditing && this.editInput.element === evt.target) {
this._submitTitle(); this._submitTitle();
} }
} }
}, },
handleSubmit: { handleSubmit: {
value: function(evt) { value: function(evt) {
if (this.isEditing) { if (this.isEditing) {
evt.preventDefault(); evt.preventDefault();
this._submitTitle(); this._submitTitle();
} }
} }
}, },
_submitTitle: { _submitTitle: {
value: function() { value: function() {
var title = this.editInput.value.trim(); var title = this.editInput.value.trim();
if ("" === title) { if ("" === title) {
this.dispatchDestroy(); this.dispatchDestroy();
} else { } else {
this.todo.title = title; this.todo.title = title;
} }
this.isEditing = false; this.isEditing = false;
} }
}, },
draw: { draw: {
value: function() { value: function() {
if (this.isEditing) { if (this.isEditing) {
this.element.classList.add("editing"); this.element.classList.add("editing");
this.editInput.element.focus(); this.editInput.element.focus();
} else { } else {
this.element.classList.remove("editing"); this.element.classList.remove("editing");
this.editInput.element.blur(); this.editInput.element.blur();
} }
if (this.isCompleted) { if (this.isCompleted) {
this.element.classList.add("completed"); this.element.classList.add("completed");
} else { } else {
this.element.classList.remove("completed"); this.element.classList.remove("completed");
} }
} }
} }
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment