mirror of
https://github.com/wassname/HackFlowy.git
synced 2026-06-27 16:00:04 +08:00
Fixed indenting, up and down arrows, basic sorting
This commit is contained in:
@@ -29,6 +29,11 @@ localforageBackbone
|
||||
return Backbone.sync.apply(this, arguments);
|
||||
},
|
||||
|
||||
/** sort by priority then created date **/
|
||||
comporator: function(child){
|
||||
return [child.get('priority'),child.get('createdAt')];
|
||||
},
|
||||
|
||||
url: '/tasks'
|
||||
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ function() {
|
||||
UP_ARROW: 38,
|
||||
DOWN_ARROW: 40,
|
||||
TAB: 9,
|
||||
CNTRL: 17,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ define(
|
||||
Marionette
|
||||
) {
|
||||
|
||||
// The tree's root: a simple collection view that renders
|
||||
// a recursive tree structure for each item in the collection
|
||||
// renders recursive tree structure for each item in collection
|
||||
var ListView = Backbone.Marionette.CollectionView.extend({
|
||||
|
||||
el: $("#main .children"),
|
||||
@@ -33,9 +32,7 @@ define(
|
||||
initialize: function () {
|
||||
var self = this;
|
||||
|
||||
Tasks = new List();
|
||||
|
||||
// this.listenTo(this.collection, 'add', this.renderTask);
|
||||
this.collection = Tasks = new List();
|
||||
|
||||
/** Load demo data **/
|
||||
function loadDemoData() {
|
||||
@@ -50,7 +47,6 @@ define(
|
||||
if (children.length === 0)
|
||||
loadDemoData();
|
||||
else {
|
||||
this.collection = {models:Tasks.filter({'parentId':0})};
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
@@ -60,7 +56,8 @@ define(
|
||||
error: function () {
|
||||
|
||||
// switch to localforage database if server isn't present and fetch again
|
||||
window.hackflowyOffline=true;
|
||||
// from there
|
||||
window.hackflowyOffline = true;
|
||||
$('#header').append('<div class="alert-box secondary round">Running in offline mode, data may be lost </div>');
|
||||
Tasks.fetch({
|
||||
success: success,
|
||||
@@ -74,63 +71,8 @@ define(
|
||||
|
||||
// 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();
|
||||
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
|
||||
// });
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return child.get('parentId') === 0;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
define(
|
||||
['jquery',
|
||||
'backbone',
|
||||
@@ -55,7 +53,7 @@ define(
|
||||
this.listenTo(this.model, 'destroy', this.remove);
|
||||
|
||||
// updates from server
|
||||
if (!window.hackflowyOffline){
|
||||
if (!window.hackflowyOffline) {
|
||||
this.socket = io.connect();
|
||||
this.socket.on('task', function (data) {
|
||||
if (task.model.id == data.id) {
|
||||
@@ -64,16 +62,23 @@ define(
|
||||
'isCompleted': data.isCompleted
|
||||
});
|
||||
} else {
|
||||
console.error("task.model.id != data.id",task.model.id , data.id);
|
||||
console.error("task.model.id != data.id", task.model.id, data.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// Only show direct children
|
||||
// override marionette filter to filter displayed children
|
||||
filter: function (child, index, collection) {
|
||||
return child.get('parentId') === this.model.get('id');
|
||||
return child.get('parentId') === this.model.get('id');
|
||||
},
|
||||
|
||||
/** Get the parent view or root view **/
|
||||
getParentView: function(){
|
||||
var parentId = this.model.get('parentId');
|
||||
if (parentId>0) return Tasks.get(parentId).view;
|
||||
else return listView;
|
||||
},
|
||||
|
||||
edit: function () {
|
||||
@@ -84,32 +89,58 @@ define(
|
||||
handleKey: function (e) {
|
||||
if (e.keyCode === constants.ENTER_KEY)
|
||||
this.addNote(e.currentTarget);
|
||||
if (e.keyCode == constants.DOWN_ARROW)
|
||||
this.$el.next('li').find('input').focus();
|
||||
else if (e.keyCode == constants.UP_ARROW)
|
||||
this.$el.prev('li').find('input').focus();
|
||||
|
||||
// shift and tab
|
||||
if (e.shiftKey && e.keyCode == constants.TAB) {
|
||||
else if (e.ctrlKey && e.keyCode == constants.DOWN_ARROW){
|
||||
e.preventDefault();
|
||||
var newParentId = this.$el.parents('ul:first').find('input:first').data('parent-id');
|
||||
if (newParentId === null) newParentId = 0;
|
||||
this.model.set('parentId', newParentId);
|
||||
this.model.save();
|
||||
Tasks.get(newParentId).view.render()
|
||||
this.model.save({priority: this.model.get('priority')-1});
|
||||
this.getParentView().collection.sortBy();
|
||||
this.getParentView().resortView();
|
||||
this.model.view.ui.input.focus();
|
||||
} else if (e.ctrlKey && e.keyCode == constants.UP_ARROW){
|
||||
e.preventDefault();
|
||||
this.model.save({priority: this.model.get('priority')+1});
|
||||
this.getParentView().collection.sortBy();
|
||||
this.getParentView().resortView();
|
||||
this.model.view.ui.input.focus();
|
||||
} else if (e.keyCode == constants.DOWN_ARROW){
|
||||
var all = listView.$el.find('ul:visible');
|
||||
var next = $(all[all.index(this.$el)+1]);
|
||||
if (next)
|
||||
next.find('input:first').focus();
|
||||
} else if (e.keyCode == constants.UP_ARROW){
|
||||
var all = listView.$el.find('ul:visible');
|
||||
var prev = $(all[all.index(this.$el)-1]);
|
||||
if (prev)
|
||||
prev.find('input:first').focus();
|
||||
}
|
||||
// indent one less, by changing parent
|
||||
else if (e.shiftKey && e.keyCode == constants.TAB) {
|
||||
e.preventDefault();
|
||||
var parent = this.$el.parents('ul:first');
|
||||
var grandparentId = parent.find('input:first').data('parent-id') || 0;
|
||||
if (this.model.get('parentId') !== grandparentId) {
|
||||
this.model.save({parentId: grandparentId});
|
||||
this.getParentView().render();
|
||||
this.model.view.ui.input.focus();
|
||||
} else {
|
||||
console.warn("Can't untab any further");
|
||||
}
|
||||
}
|
||||
// indent one more, by changing parent
|
||||
else if (e.keyCode == constants.TAB) {
|
||||
e.preventDefault();
|
||||
var newParentId = this.$el.prev('ul').find('input:first').data('id');
|
||||
this.model.set('parentId', newParentId);
|
||||
this.model.save();
|
||||
this.model.view.remove();
|
||||
Tasks.get(newParentId).view.render();
|
||||
this.model.view.ui.input.focus();
|
||||
var prevSibling = this.$el.prev('ul');
|
||||
if (prevSibling.length > 0) {
|
||||
var siblingId = prevSibling.find('input:first').data('id');
|
||||
this.model.save({parentId: siblingId});
|
||||
this.model.view.remove();
|
||||
this.getParentView().render();
|
||||
this.model.view.ui.input.focus();
|
||||
} else {
|
||||
console.warn("Can't tab any further");
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.hackflowyOffline){
|
||||
if (!window.hackflowyOffline) {
|
||||
this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
@@ -126,9 +157,12 @@ define(
|
||||
var value = this.$('.edit:first').val().trim();
|
||||
if (value === '')
|
||||
// remove empty items
|
||||
// TODO let us tab and untab empty ones
|
||||
this.model.destroy();
|
||||
else
|
||||
this.model.save({content: value});
|
||||
this.model.save({
|
||||
content: value
|
||||
});
|
||||
this.$el.removeClass('editing');
|
||||
},
|
||||
|
||||
@@ -162,6 +196,7 @@ define(
|
||||
|
||||
/** Add a new blank note **/
|
||||
addNote: function () {
|
||||
// TODO add it after the current one
|
||||
var currentId = this.ui.input.data('id') || 0;
|
||||
parentId = this.ui.input.data('parent-id');
|
||||
|
||||
@@ -173,7 +208,7 @@ define(
|
||||
},
|
||||
|
||||
/** Fold children of the clicked element */
|
||||
foldChildren: function(){
|
||||
foldChildren: function () {
|
||||
this.$el.find('ul').toggle();
|
||||
this.$el.find('li').toggleClass('folded');
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user