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