Added nested rendering, collapsing nodes, uses marionette

This commit is contained in:
2016-01-30 21:00:33 +08:00
parent cf89df815d
commit c17412477d
10 changed files with 264 additions and 171 deletions
+79 -42
View File
@@ -3,7 +3,9 @@ define(
'backbone',
'collections/list',
'views/task',
'data/demo'
'data/demo',
'text!../../templates/task.html',
'marionette'
],
function (
@@ -11,21 +13,29 @@ define(
Backbone,
List,
TaskView,
demoData
demoData,
listTemplate,
Marionette
) {
var ListView = Backbone.View.extend({
// The tree's root: a simple collection view that renders
// a recursive tree structure for each item in the collection
var ListView = Backbone.Marionette.CollectionView.extend({
el: $("#main .children"),
childView: TaskView,
template: '#list-view-template',
events: {
'click #add': 'addTask'
},
initialize: function () {
Tasks = this.collection = new List();
var self = this;
this.listenTo(this.collection, 'add', this.renderTask);
Tasks = new List();
// this.listenTo(this.collection, 'add', this.renderTask);
/** Load demo data **/
function loadDemoData() {
@@ -35,64 +45,91 @@ define(
}
}
function success(data) {
function success(children, data, promise) {
// load demo data if the server returns nothing
if (data.length === 0)
if (children.length === 0)
loadDemoData();
else {
this.collection = {models:Tasks.filter({'parentId':0})};
this.render();
}
}
this.collection.fetch({
Tasks.fetch({
success: success,
error: function () {
// switch to localforage database if server isn't present and fetch again
window.hackflowyOffline=true;
$('#header').append('<div class="alert-box secondary round">Running in offline mode, data may be lost </div>');
Tasks.fetch({
success: success
success: success,
context: this
});
}
},
context: this
});
},
render: function () {
this.collection.each(function (task) {
this.renderTask(task);
}, this);
},
// Only show direct children
filter: function (child, index, collection) {
return child.get('parentId') === 0;
},
// render: function () {
// var models = Tasks.filter({'parentId':0});
//
// _.each(models, function(model, index) {
// var taskView = new this.childView({
// model: model,
// collection: model.collection
// });
// var a = taskView.render();
// this.$el.append(a.el);
// }, this);
//
// this.triggerMethod('render', this);
// return this;
// },
renderTask: function (task) {
var taskView = new TaskView({
model: task
});
var a = taskView.render();
if (a.model.get('parentId') === 0) {
// inset it at the end of the root list
this.$el.append(a.el);
} else {
// insert after the currently edited sibling (same parent)
// or after the last sibling
var parent = $('*[data-id="' + a.model.get('parentId') + '"]');
var siblings = $('*[data-parent-id="' + a.model.get('parentId') + '"]').parents('li')
if (siblings.length>0){
var editingSibling = siblings.filter('.editing')
var lastSibling = siblings.filter(':last');
if (editingSibling)
a.$el.insertAfter(editingSibling);
else
a.$el.insertAfter(lastSibling);
}
else if (parent.length < 0) {
a.$el.insertAfter(parent.parents('li:first'));
} else {
// TODO deal with loading order
console.error("Parent not rendered yet: ", {
selector: parent.selector,
task: task
});
this.$el.append(a.el);
}
}
this.$el.append(a.el);
//
// if (a.model.get('parentId') === 0) {
// // insert it at the end of the top-level items
// this.$el.append(a.el);
// } else {
//
// // TODO use dom nesting instead of data attributes
// var parent = $('*[data-id="' + a.model.get('parentId') + '"]').parents('li:first');
// var siblings = parent.find('.children:first li');
// var editingSibling = siblings.filter('.editing:first');
//
// if (editingSibling.length > 0){
// // insert it after open sibling
// a.$el.insertAfter(editingSibling);
// }
// else if (parent.length > 0) {
// // insert under parent
// a.$el.appendTo(parent.find('.children:first'));
// } else {
// // we have an orphan :(
// // insert at root for lack of a better option
// this.$el.append(a.el);
//
// // TODO deal with loading order
// console.error("Parent not rendered yet: ", {
// selector: parent.selector,
// task: task
// });
//
// }
// }
}
});