}
},
watch: {
- files: ['<%= jshint.files %>'],
+ files: ['<%= jshint.files %>', '<%= concat.css.src %>'],
tasks: ['default']
},
bower_concat: {
dist: {
src: ['src/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
+ },
+ css: {
+ src: ['src/**/*.css'],
+ dest: 'dist/<%= pkg.name %>.css'
}
},
copy: {
--- /dev/null
+.text {
+ font-size: 20pt;
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+.bullets > .todo {
+ margin-left: 30px;
+}
+
+.todo.completed > .text {
+ text-decoration: line-through;
+ color: grey;
+}
+
+.todo.collapsed .todo {
+ display: none;
+}
return {
completed: false,
collapsed: false,
- text: "",
+ text: "Should never be visible",
bullets: [],
- parent: 0,
+ parent: null,
};
},
toggleComplete: function() {
},
getChildren: function(collection) {
return _.map(this.get("bullets"), function(id) {
- return collection.models[id];
+ return collection.get(id);
}, this);
},
getParent: function(collection) {
- return collection.models[this.parent];
+ return collection.get(this.get("parent"));
},
isTopLevel: function(collection) {
- return this.parent === collection.rootId;
+ return this.get("parent") === collection.rootId;
},
- isParentLoaded: function(collection) {
- return isTopLevel(collection) ? true : !!this.getParent(collection);
+ isParentLoaded: function(collection, collectionView) {
+ return this.isTopLevel(collection) ? true : (this.getParent(collection) && collectionView.getView(this.getParent(collection)));
},
});
options = _.defaults({}, options, flowyDocDefaults);
this.id = options.id;
this.default = options.default;
+ this.rootId = options.rootId;
},
model: TodoModel,
localStorage: new Backbone.LocalStorage("todos-backbone"),
options.error = function(_, resp, __) {
if (resp ==="Record Not Found" && collection.default) {
var method = options.reset ? 'reset' : 'set';
- collection[method](resp, options);
- collection.set(collection.default);
+ collection[method](collection.default);
}
if (error) error(collection, resp, options);
};
var TodoView = Backbone.View.extend({
tagName: 'div',
+ className: 'todo',
events: {
- "click": "toggleComplete",
+ "click > .text": "toggleComplete",
},
initialize: function() {
this.listenTo(this.model, "change", this.render);
this.listenTo(this.model, 'destroy', this.remove);
},
- toggleComplete: function() {
+ toggleComplete: function(e) {
this.model.toggleComplete();
+ e.stopPropagation();
},
template: "<div class=\"text\">{{text}}</div><div class=\"bullets\"></div>",
+ addChild: function(el, position) {
+ if(typeof position === 'undefined') {
+ console.log("TodoView:addChild called without a position");
+ }
+ this.$el.find("> .bullets").append(el);
+ return this;
+ },
render: function() {
- //this.$el.html(this.template(this.model.attributes));
- this.$el.html(Mustache.to_html(this.template, this.model.toJSON()));
+ var oldChildren = this.$el.find("> .bullets > *");
+ this.$el.html(Mustache.to_html(this.template, this.model.toJSON())); // Should hopefully be model.attributes
this.$el.toggleClass('completed', this.model.get('completed'));
this.$el.toggleClass('collapsed', this.model.get('collapsed'));
+ this.$el.find("> .bullets").append(oldChildren);
return this;
},
});
this.listenTo(todos, 'add', this.addOne);
this.listenTo(todos, 'reset', this.addAll);
this.list = options.list;
+ this.views = {}; // A list of views for each element in the collection
this.list.fetch();
},
render: function() {
this.renderTodo(todo);
},
renderTodo: function(todo) {
- if (todo.view) {
+ if (this.getView(todo)) {
console.log("View rendered more than once for todo #" + todo.id);
return;
}
var view = new TodoView({model: todo});
- todo.view = view;
+ this.setView(todo, view);
if (todo.isTopLevel(this.list)) {
this.$("#todo-list").append(view.render().el);
- } else if (todo.isParentLoaded(this.list)) {
- todo.getParent(this.list).view.el.append(view.render().el);
+ } else if (todo.isParentLoaded(this.list, this)) {
+ var parent = todo.getParent(this.list);
+ var parentView = this.getView(parent);
+ parentView.addChild(view.render().el);
}
// Find unrendered descendents and render them, too.
_.each(todo.getChildren(this.list), function(child) {
- if (child && !child.view) {
+ if (child && !this.getView(child)) {
this.renderTodo(child);
}
}, this);
return this;
},
+ setView: function(model, view) {
+ this.views[model.id] = view;
+ },
+ getView: function(model) {
+ return this.views[model.id];
+ },
addAll: function() {
this.list.each(this.addOne, this);
},
<head>
<script src="_bower.js"></script>
<script src="flowy.js"></script>
+<link rel="stylesheet" type="text/css" href="flowy.css">
</head>
<body>
<div id="todo-app">
--- /dev/null
+.text {
+ font-size: 20pt;
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+.bullets > .todo {
+ margin-left: 30px;
+}
+
+.todo.completed > .text {
+ text-decoration: line-through;
+ color: grey;
+}
+
+.todo.collapsed .todo {
+ display: none;
+}
<head>
<script src="_bower.js"></script>
<script src="flowy.js"></script>
+<link rel="stylesheet" type="text/css" href="flowy.css">
</head>
<body>
<div id="todo-app">
return {
completed: false,
collapsed: false,
- text: "",
+ text: "Should never be visible",
bullets: [],
- parent: 0,
+ parent: null,
};
},
toggleComplete: function() {
},
getChildren: function(collection) {
return _.map(this.get("bullets"), function(id) {
- return collection.models[id];
+ return collection.get(id);
}, this);
},
getParent: function(collection) {
- return collection.models[this.parent];
+ return collection.get(this.get("parent"));
},
isTopLevel: function(collection) {
- return this.parent === collection.rootId;
+ return this.get("parent") === collection.rootId;
},
- isParentLoaded: function(collection) {
- return isTopLevel(collection) ? true : !!this.getParent(collection);
+ isParentLoaded: function(collection, collectionView) {
+ return this.isTopLevel(collection) ? true : (this.getParent(collection) && collectionView.getView(this.getParent(collection)));
},
});
options = _.defaults({}, options, flowyDocDefaults);
this.id = options.id;
this.default = options.default;
+ this.rootId = options.rootId;
},
model: TodoModel,
localStorage: new Backbone.LocalStorage("todos-backbone"),
options.error = function(_, resp, __) {
if (resp ==="Record Not Found" && collection.default) {
var method = options.reset ? 'reset' : 'set';
- collection[method](resp, options);
- collection.set(collection.default);
+ collection[method](collection.default);
}
if (error) error(collection, resp, options);
};
var TodoView = Backbone.View.extend({
tagName: 'div',
+ className: 'todo',
events: {
- "click": "toggleComplete",
+ "click > .text": "toggleComplete",
},
initialize: function() {
this.listenTo(this.model, "change", this.render);
this.listenTo(this.model, 'destroy', this.remove);
},
- toggleComplete: function() {
+ toggleComplete: function(e) {
this.model.toggleComplete();
+ e.stopPropagation();
},
template: "<div class=\"text\">{{text}}</div><div class=\"bullets\"></div>",
+ addChild: function(el, position) {
+ if(typeof position === 'undefined') {
+ console.log("TodoView:addChild called without a position");
+ }
+ this.$el.find("> .bullets").append(el);
+ return this;
+ },
render: function() {
- //this.$el.html(this.template(this.model.attributes));
- this.$el.html(Mustache.to_html(this.template, this.model.toJSON()));
+ var oldChildren = this.$el.find("> .bullets > *");
+ this.$el.html(Mustache.to_html(this.template, this.model.toJSON())); // Should hopefully be model.attributes
this.$el.toggleClass('completed', this.model.get('completed'));
this.$el.toggleClass('collapsed', this.model.get('collapsed'));
+ this.$el.find("> .bullets").append(oldChildren);
return this;
},
});
this.listenTo(todos, 'add', this.addOne);
this.listenTo(todos, 'reset', this.addAll);
this.list = options.list;
+ this.views = {}; // A list of views for each element in the collection
this.list.fetch();
},
render: function() {
this.renderTodo(todo);
},
renderTodo: function(todo) {
- if (todo.view) {
+ if (this.getView(todo)) {
console.log("View rendered more than once for todo #" + todo.id);
return;
}
var view = new TodoView({model: todo});
- todo.view = view;
+ this.setView(todo, view);
if (todo.isTopLevel(this.list)) {
this.$("#todo-list").append(view.render().el);
- } else if (todo.isParentLoaded(this.list)) {
- todo.getParent(this.list).view.el.append(view.render().el);
+ } else if (todo.isParentLoaded(this.list, this)) {
+ var parent = todo.getParent(this.list);
+ var parentView = this.getView(parent);
+ parentView.addChild(view.render().el);
}
// Find unrendered descendents and render them, too.
_.each(todo.getChildren(this.list), function(child) {
- if (child && !child.view) {
+ if (child && !this.getView(child)) {
this.renderTodo(child);
}
}, this);
return this;
},
+ setView: function(model, view) {
+ this.views[model.id] = view;
+ },
+ getView: function(model) {
+ return this.views[model.id];
+ },
addAll: function() {
this.list.each(this.addOne, this);
},