mirror of
https://github.com/wassname/HackFlowy.git
synced 2026-06-27 16:00:04 +08:00
Merge pull request #30 from wassname/master
Updates, bugfix, static demo
This commit is contained in:
@@ -16,6 +16,7 @@ results
|
||||
|
||||
npm-debug.log
|
||||
node_modules
|
||||
bower_components
|
||||
|
||||
*.sqlite
|
||||
*.env
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://gitter.im/abhshkdz/HackFlowy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
An open-source [Workflowy](http://workflowy.com) clone.
|
||||
An open-source [Workflowy](http://workflowy.com) clone. [Static demo available here](http://abhshkdz.github.io/HackFlowy/).
|
||||
|
||||

|
||||
|
||||
@@ -10,6 +10,8 @@ An open-source [Workflowy](http://workflowy.com) clone.
|
||||
|
||||
* Edit `config/development.json` and `config/database.json` to your needs
|
||||
* `npm install`
|
||||
* `npm install bower`
|
||||
* `bower install`
|
||||
* `node server.js`
|
||||
|
||||
## Heroku deploy
|
||||
@@ -28,13 +30,20 @@ Or proceed manually as follow:
|
||||
## Controls
|
||||
|
||||
* <kbd>UP</kbd> & <kbd>DOWN</kbd>: navigate through tasks
|
||||
* <kbd>CNTRL+UP</kbd> & <kbd>CNTRL+DOWN</kbd>: shuffle tasks
|
||||
* <kbd>TAB</kbd>: right-indent
|
||||
* <kbd>SHIFT</kbd> + <kbd>TAB</kbd>: left-indent
|
||||
* <kbd>BACKSPACE</kbd>: Remove an empty task
|
||||
* <kbd>ENTER</kbd>: New task
|
||||
* Click on a bullet point to fold it
|
||||
* Hover on a bullet point and click complete to complete it
|
||||
|
||||
## Technologies used
|
||||
|
||||
* Node + Socket.io
|
||||
* Backbone
|
||||
* Backbone.marionette
|
||||
* Backbone.localforage
|
||||
* Foundation
|
||||
|
||||
## To-do
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "hackflowy",
|
||||
"description": "A simple WorkFlowy clone",
|
||||
"main": "public/javascripts/app.js",
|
||||
"version": "0.0.3",
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"socket.io-client": "~1.4.5",
|
||||
"text": "requirejs-text#~2.0.14",
|
||||
"jquery": "~2.2.0",
|
||||
"backbone": "~1.2.3",
|
||||
"requirejs": "~2.1.22",
|
||||
"modernizr": "http://modernizr.com/download/?-inlinesvg-svg-svgclippaths-touch-shiv-mq-cssclasses-teststyles-prefixes-ie8compat-load.zip",
|
||||
"localforage": "~1.3.3",
|
||||
"localforage-backbone": "~0.6.2",
|
||||
"normalize-css": "normalize.css#~3.0.3",
|
||||
"backbone.marionette": "~2.4.4",
|
||||
"underscore": "~1.8.3",
|
||||
"foundation-sites": "~6.1.2",
|
||||
"foundation-icon-fonts": "*"
|
||||
},
|
||||
"resolutions": {
|
||||
"jquery": "^1.8.0 || ^2.0.0"
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -3,12 +3,14 @@ var Sequelize = require('sequelize');
|
||||
module.exports = {
|
||||
instance: function(orm) {
|
||||
task = orm.define('Tasks', {
|
||||
id : {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
|
||||
id : {type: Sequelize.UUID, primaryKey: true, defaultValue: Sequelize.UUIDV4,},
|
||||
content : {type: Sequelize.TEXT, allowNull: false},
|
||||
parent : Sequelize.INTEGER,
|
||||
isCompleted: Sequelize.BOOLEAN,
|
||||
createdAt : Sequelize.DATE,
|
||||
updatedAt : Sequelize.DATE
|
||||
parentId : {type: Sequelize.UUID, defaultValue: '00000000-0000-0000-0000-000000000000'},
|
||||
isCompleted: {type: Sequelize.BOOLEAN, defaultValue: false},
|
||||
priority : {type: Sequelize.INTEGER, defaultValue: 0},
|
||||
isFolded : {type: Sequelize.BOOLEAN, defaultValue: false},
|
||||
createdAt : {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
||||
updatedAt : {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
|
||||
});
|
||||
|
||||
orm.sync();
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
var config = require('config'),
|
||||
orm = require('../../orm').configure(config.get('database')),
|
||||
Tasks = require('../../db/models/task').instance(orm);
|
||||
Tasks = require('../../db/models/task').instance(orm),
|
||||
demoData = require('../../public/javascripts/data/demo.json');
|
||||
|
||||
Tasks.destroy().success(function() {
|
||||
Tasks.bulkCreate([
|
||||
{content: 'Welcome to HackFlowy!', isCompleted: false},
|
||||
{content: 'An open-source WorkFlowy clone', isCompleted: false},
|
||||
{content: 'Built using Backbone + Socket.IO', isCompleted: false},
|
||||
{content: 'I pulled this together in a few hours to learn Backbone', isCompleted: false},
|
||||
{content: 'Feel free to try it out and hack on it', isCompleted: false},
|
||||
{content: 'Good Luck!', isCompleted: false}
|
||||
]);
|
||||
Tasks.destroy({where: {}}).then(function() {
|
||||
Tasks.bulkCreate(demoData);
|
||||
});
|
||||
|
||||
orm.sync();
|
||||
|
||||
+16
-10
@@ -1,25 +1,31 @@
|
||||
{
|
||||
"name": "hackflowy",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.3",
|
||||
"license": "MIT",
|
||||
"description": "A simple WorkFlowy clone",
|
||||
"dependencies": {
|
||||
"express": "~3.1.0",
|
||||
"path": "~0.4.9",
|
||||
"body-parser": "^1.14.2",
|
||||
"config": "~1.19.0",
|
||||
"errorhandler": "^1.4.3",
|
||||
"express": "^4",
|
||||
"lodash": "^4.0.1",
|
||||
"method-override": "^2.3.5",
|
||||
"path": "~0.12.7",
|
||||
"pg": "~3.4.1",
|
||||
"sequelize": "~1.7.9",
|
||||
"socket.io": "~1.0.6",
|
||||
"config": "~1.0.2"
|
||||
"sequelize": "~3.17.3",
|
||||
"sequelize-cli": "^2.3.1",
|
||||
"socket.io": "~1.4.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sqlite3": "~2.1.0"
|
||||
"sqlite3": "~3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "0.10.x",
|
||||
"npm": "3.3.5"
|
||||
"node": "5.4.x",
|
||||
"npm": "3.3.11"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"db:migrate": "./node_modules/sequelize/bin/sequelize -m --config config/database.json",
|
||||
"db:migrate": "./node_modules/.bin/sequelize -m --config config/database.json",
|
||||
"db:seed": "node db/seed/initial_tasks.js",
|
||||
"postinstall": "npm run db:migrate && npm run db:seed"
|
||||
},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
+62
-23
@@ -1,39 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||
<!--[if gt IE 8]><!-->
|
||||
<html class="no-js" lang="en">
|
||||
<!--<![endif]-->
|
||||
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>HackFlowy</title>
|
||||
<link rel="icon" type="image/x-icon" href="images/favicon.png" />
|
||||
<link rel="stylesheet" href="stylesheets/normalize.css" />
|
||||
<link rel="stylesheet" href="bower_components/normalize-css/normalize.css" />
|
||||
<link rel="stylesheet" href="bower_components/foundation-sites/dist/foundation.css" />
|
||||
<link rel="stylesheet" href="bower_components/foundation-icon-fonts/foundation-icons.css" />
|
||||
<link rel="stylesheet" href="stylesheets/app.css" />
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="row">
|
||||
<div class="large-12 columns">
|
||||
<section id="hackflowy">
|
||||
<header id="header"></header>
|
||||
<div class="large-12 columns">
|
||||
<section id="hackflowy">
|
||||
<header id="header">
|
||||
<div id="header-alerts"></div>
|
||||
<div id="task-breadcrumbs"></div>
|
||||
|
||||
<section id="main">
|
||||
</header>
|
||||
|
||||
<div id="name">
|
||||
<h2></h2>
|
||||
</div>
|
||||
<ul class="children">
|
||||
</ul>
|
||||
</section>
|
||||
<section id="main">
|
||||
|
||||
<footer id="footer">
|
||||
Make Lists. Not War. <3 Open Source.
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
<div id="name">
|
||||
<h2></h2>
|
||||
</div>
|
||||
<ul class="children">
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
||||
<footer id="footer">
|
||||
<div class="large-10 columns" >
|
||||
<span id="footer-qoute">Make love. Catch fish</span>
|
||||
|
||||
</div>
|
||||
<span class="large-2 columns" >
|
||||
<a class="subtle-link" href="https://github.com/abhshkdz/HackFlowy">
|
||||
<i class="fi-heart"></i> open source
|
||||
</a>
|
||||
</span>
|
||||
<script>
|
||||
// into the footer, a random qoute about lists which was originally about love
|
||||
var qoutes = [
|
||||
"Lists cannot be sold only given.",
|
||||
"Make lists. Free lists.",
|
||||
"Make lists, catch fish.",
|
||||
"Dance like there's nobody watching, list like you'll never be hurt.",
|
||||
"We accept the list we think we deserve.",
|
||||
"A friend is someone who knows all about you and still lists you.",
|
||||
"Better to be hated for what you are than to be listed for what you are not.",
|
||||
"List all, trust a few, do wrong to none - Shakespeare.",
|
||||
"I list you and that's the beginning and end of everything - F. Scott Fitzgerald.",
|
||||
"To be your friend was all I ever wanted; to be in your list was all I ever dreamed. - V. Lombardo.",
|
||||
"To the list, you may be one item, but to one item you are the list - Bill Wilson.",
|
||||
"I list you as one lists certain dark things, secretly, between the shadow and the soul - P. Neruda.",
|
||||
"It was list at first sight, at last sight, at ever and ever sight. - Vladimir Nabokov",
|
||||
"When a list is not madness it is not a list. - P. Calderón de la Barca."
|
||||
]
|
||||
var newQoute = qoutes[Math.floor(Math.random() * qoutes.length)];
|
||||
document.getElementById("footer-qoute").textContent = newQoute;
|
||||
</script>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script data-main="javascripts/app" src="bower_components/requirejs/require.js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
|
||||
<script data-main="javascripts/app" src="javascripts/vendor/require.js" ></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+25
-23
@@ -1,30 +1,32 @@
|
||||
require.config({
|
||||
|
||||
//load lib files required
|
||||
paths: {
|
||||
jquery: "vendor/jquery.min",
|
||||
lodash:"vendor/lodash.min",
|
||||
backbone: "vendor/backbone",
|
||||
modernizr:"vendor/custom.modernizr",
|
||||
socket:"vendor/socket.io.min",
|
||||
text:"vendor/text"
|
||||
},
|
||||
|
||||
shim: {
|
||||
backbone: {
|
||||
deps: ["lodash", "jquery"],
|
||||
exports: "Backbone"
|
||||
}
|
||||
},
|
||||
|
||||
waitSeconds: 5
|
||||
//load lib files required
|
||||
paths: {
|
||||
jquery: '../bower_components/jquery/dist/jquery',
|
||||
underscore: "../bower_components/underscore/underscore",
|
||||
backbone: '../bower_components/backbone/backbone',
|
||||
localforage: '../bower_components/localforage/dist/localforage',
|
||||
localforagebackbone: '../bower_components/localforage-backbone/dist/localforage.backbone',
|
||||
modernizr: "../bower_components/modernizr/custom.modernizr",
|
||||
socket: "../bower_components/socket.io-client/socket.io",
|
||||
text: '../bower_components/text/text',
|
||||
marionette: '../bower_components/backbone.marionette/lib/backbone.marionette'
|
||||
},
|
||||
shim: {
|
||||
backbone: {
|
||||
deps: ["underscore", "jquery"],
|
||||
exports: "Backbone"
|
||||
}
|
||||
},
|
||||
|
||||
waitSeconds: 5
|
||||
|
||||
});
|
||||
|
||||
//start the app
|
||||
require([
|
||||
'views/page'
|
||||
],
|
||||
function( App ) {
|
||||
new App();
|
||||
});
|
||||
'views/page'
|
||||
],
|
||||
function (App) {
|
||||
pageView = new App();
|
||||
});
|
||||
|
||||
@@ -1,21 +1,106 @@
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'models/task'
|
||||
'models/task',
|
||||
'localforage',
|
||||
'localforagebackbone'
|
||||
],
|
||||
|
||||
function(
|
||||
Backbone,
|
||||
Task
|
||||
Task,
|
||||
localforage,
|
||||
localforageBackbone
|
||||
) {
|
||||
|
||||
var List = Backbone.Collection.extend({
|
||||
var List = Backbone.Collection.extend({
|
||||
|
||||
model: Task,
|
||||
url: '/tasks'
|
||||
|
||||
});
|
||||
model: Task,
|
||||
offlineSync: Backbone.localforage.sync("tasks"),
|
||||
|
||||
|
||||
/** Override backbone parse **/
|
||||
// parse: function(models){
|
||||
// if (this._isModel(models))
|
||||
// return models;
|
||||
// var parsedModels =[];
|
||||
// for (var i = 0; i < models.length; i++) {
|
||||
// if (this._isModel(models[i]))
|
||||
// parsedModels.push(models[i]);
|
||||
// else
|
||||
// parsedModels.push(new this.model(models[i]));
|
||||
// }
|
||||
// return parsedModels;
|
||||
//
|
||||
// },
|
||||
|
||||
initialize: function(){
|
||||
// update order on add, remove.
|
||||
// Ref: http://stackoverflow.com/a/11665085/221742
|
||||
this.on('add remove sort', this.updateModelPriority);
|
||||
},
|
||||
|
||||
/**
|
||||
* Move a model in the list up. Only a sort event is emitted
|
||||
* @param {Backbone.Model} model - Model to be moved
|
||||
*/
|
||||
moveUp: function(model) { // I see move up as the -1
|
||||
var index = this.indexOf(model);
|
||||
if (index > 0) {
|
||||
this.remove(model, {silent: true});
|
||||
this.add(model, {at: index-1, silent: true});
|
||||
}
|
||||
this.trigger('sort', this, {});
|
||||
},
|
||||
|
||||
/**
|
||||
* Move a model in the list up. Only a sort event is emitted
|
||||
* @param {Backbone.Model} model - Model to be moved
|
||||
*/
|
||||
moveDown: function(model) { // I see move up as the -1
|
||||
var index = this.indexOf(model);
|
||||
if (index < this.models.length) {
|
||||
this.remove(model, {silent: true});
|
||||
this.add(model, {at: index+1, silent: true});
|
||||
}
|
||||
this.trigger('sort', this, {});
|
||||
},
|
||||
|
||||
/** Updated priority of each member of list **/
|
||||
updateModelPriority: function() {
|
||||
this.each(function(model, index) {
|
||||
if (model && model.get('priority')!==index)
|
||||
model.save({'priority': index});
|
||||
|
||||
}, this);
|
||||
},
|
||||
|
||||
/** switches sync between server and local databases **/
|
||||
sync: function(){
|
||||
//var self = this;
|
||||
_localforageNamespace = this.offlineSync._localforageNamespace;
|
||||
_localeForageKeyFn=this.offlineSync._localeForageKeyFn;
|
||||
localforageKey = this.offlineSync._localeForageKeyFn;
|
||||
if (window.hackflowyOffline)
|
||||
return this.offlineSync.apply(this, arguments);
|
||||
else
|
||||
return Backbone.sync.apply(this, arguments);
|
||||
},
|
||||
|
||||
/** sort by priority then created date **/
|
||||
comparator: function(child){
|
||||
return [child.get('priority')];
|
||||
},
|
||||
|
||||
url: '/tasks'
|
||||
|
||||
});
|
||||
|
||||
// a couple of vars backbone.localforage needs in the sync function
|
||||
List.prototype.sync.localforage = List.prototype.offlineSync._localeForageKeyFn;
|
||||
List.prototype.sync._localeForageKeyFn = List.prototype.offlineSync._localeForageKeyFn;
|
||||
List.prototype.sync._localforageNamespace = List.prototype.offlineSync._localforageNamespace;
|
||||
|
||||
return List;
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
[{
|
||||
"id": "fba0d0d9-d540-03c2-ecd5-cb5c391484ef",
|
||||
"content": "Welcome to HackFlowy!",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 1,
|
||||
"createdAt": "2016-01-29T05:44:30.858Z",
|
||||
"updatedAt": "2016-01-29T05:44:30.858Z"
|
||||
}, {
|
||||
"id": "886689fd-8ca1-75ed-8086-fe05904ff039",
|
||||
"content": "An open-source WorkFlowy clone",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 2,
|
||||
"createdAt": "2016-01-29T05:44:30.858Z",
|
||||
"updatedAt": "2016-01-29T05:44:30.858Z"
|
||||
}, {
|
||||
"id": "bbc8e79d-5e51-83b8-2639-812471972e04",
|
||||
"content": "Built using Backbone + Socket.IO",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 3,
|
||||
"createdAt": "2016-01-29T05:44:30.858Z",
|
||||
"updatedAt": "2016-01-29T05:44:30.858Z"
|
||||
}, {
|
||||
"id": "602f03a8-bfdd-5193-f0bb-b4d0f5fa165c",
|
||||
"content": "Pulled this together in a few hours to learn Backbone",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 4,
|
||||
"createdAt": "2016-01-29T05:44:30.858Z",
|
||||
"updatedAt": "2016-01-29T05:44:30.858Z"
|
||||
}, {
|
||||
"id": "1e663464-4c22-bd0a-85a7-3a287ac2f02e",
|
||||
"content": "Feel free to try it out and hack on it",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 5,
|
||||
"createdAt": "2016-01-29T05:44:30.858Z",
|
||||
"updatedAt": "2016-01-29T05:44:30.858Z"
|
||||
}, {
|
||||
"id": "d25704a8-fe09-ab2a-7c54-58c5e8113e88",
|
||||
"content": "Good Luck!",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 6,
|
||||
"createdAt": "2016-01-29T05:44:30.858Z",
|
||||
"updatedAt": "2016-01-29T05:44:30.858Z"
|
||||
}, {
|
||||
"id": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"content": "P.S",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 7,
|
||||
"isFolded": true,
|
||||
"createdAt": "2016-01-29T05:44:40.978Z",
|
||||
"updatedAt": "2016-01-29T05:44:40.978Z"
|
||||
}, {
|
||||
"id": "70a84964-658d-fbf9-4552-e8f243138f6e",
|
||||
"content": "It makes sense if you don't think about it; I haven't",
|
||||
"parentId": "00000000-0000-0000-0000-000000000000",
|
||||
"isCompleted": false,
|
||||
"priority": 8,
|
||||
"createdAt": "2016-01-29T05:44:58.737Z",
|
||||
"updatedAt": "2016-01-29T05:45:50.939Z"
|
||||
}, {
|
||||
"id": 89,
|
||||
"content": "Make love not war",
|
||||
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"isCompleted": false,
|
||||
"priority": 1,
|
||||
"createdAt": "2016-01-29T05:45:03.048Z",
|
||||
"updatedAt": "2016-01-29T05:45:57.481Z"
|
||||
}, {
|
||||
"id": 91,
|
||||
"content": "Love can be brought not sold",
|
||||
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"isCompleted": false,
|
||||
"priority": 2,
|
||||
"createdAt": "2016-01-29T05:45:32.331Z",
|
||||
"updatedAt": "2016-01-29T05:46:10.478Z"
|
||||
}, {
|
||||
"id": 93,
|
||||
"content": "How do I love thee? Let me count the ways - Shakespeare",
|
||||
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"isCompleted": false,
|
||||
"priority": 3,
|
||||
"createdAt": "2016-01-29T05:46:25.119Z",
|
||||
"updatedAt": "2016-01-29T05:48:00.604Z"
|
||||
}, {
|
||||
"id": 95,
|
||||
"content": "Therefore: love can be listed and lists can be loved",
|
||||
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"isCompleted": false,
|
||||
"priority": 4,
|
||||
"createdAt": "2016-01-29T05:46:38.998Z",
|
||||
"updatedAt": "2016-01-29T05:48:22.937Z"
|
||||
}, {
|
||||
"content": "Conclusion: lists and love should be free",
|
||||
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"isCompleted": false,
|
||||
"priority": 5,
|
||||
"createdAt": "2016-01-29T05:47:26.684Z",
|
||||
"updatedAt": "2016-01-29T05:48:29.796Z"
|
||||
}, {
|
||||
"content": "But how can our lists be real if our love isnt? - Jaden Smith",
|
||||
"parentId": "b61c6f7d-07d0-3fa3-4c30-6e2159280f18",
|
||||
"isCompleted": false,
|
||||
"priority": 6,
|
||||
"createdAt": "2016-01-29T05:47:46.930Z",
|
||||
"updatedAt": "2016-01-29T05:47:46.930Z"
|
||||
}]
|
||||
@@ -1,34 +1,65 @@
|
||||
define(
|
||||
['backbone'
|
||||
],
|
||||
|
||||
function(
|
||||
Backbone
|
||||
['backbone',
|
||||
'localforage',
|
||||
'localforagebackbone',
|
||||
'util/constants',
|
||||
],function (
|
||||
Backbone,
|
||||
localforage,
|
||||
localforageBackbone,
|
||||
constants
|
||||
) {
|
||||
|
||||
var TaskModel = Backbone.Model.extend({
|
||||
|
||||
defaults: {
|
||||
parent: 0,
|
||||
content: '',
|
||||
isCompleted: 0
|
||||
},
|
||||
var TaskModel = Backbone.Model.extend({
|
||||
|
||||
toggelCompletedStatus:function(isCompleted){
|
||||
var prev_isCompleted = isCompleted,
|
||||
self = this;
|
||||
this.save({'isCompleted':isCompleted},
|
||||
{
|
||||
success:function(){},
|
||||
error:function(){
|
||||
//REVERT BACK ON ERROR
|
||||
self.set({'isCompleted':prev_isCompleted});
|
||||
}
|
||||
})
|
||||
}
|
||||
offlineSync: Backbone.localforage.sync('TaskModel'),
|
||||
|
||||
});
|
||||
/** switches sync between server and local databases **/
|
||||
sync: function () {
|
||||
|
||||
return TaskModel;
|
||||
if (window.hackflowyOffline)
|
||||
return this.offlineSync.apply(this, arguments);
|
||||
else
|
||||
return Backbone.sync.apply(this, arguments);
|
||||
},
|
||||
|
||||
defaults: {
|
||||
parentId: constants.ROOT_PARENT_ID,
|
||||
content: '',
|
||||
isCompleted: false,
|
||||
isFolded: false,
|
||||
priority: 0,
|
||||
id: undefined,
|
||||
},
|
||||
|
||||
toggelCompletedStatus: function (isCompleted) {
|
||||
var prev_isCompleted = isCompleted,
|
||||
self = this;
|
||||
this.save({
|
||||
'isCompleted': isCompleted
|
||||
}, {
|
||||
success: function () {},
|
||||
error: function () {
|
||||
//REVERT BACK ON ERROR
|
||||
self.set({
|
||||
'isCompleted': prev_isCompleted
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
focusOnView: function(){
|
||||
if (this.view && this.view.$el)
|
||||
return this.view.$('input:first').focus();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// a couple of vars backbone.localforage needs in the sync function
|
||||
TaskModel.prototype.sync.localforage = TaskModel.prototype.offlineSync._localeForageKeyFn;
|
||||
TaskModel.prototype.sync._localeForageKeyFn = TaskModel.prototype.offlineSync._localeForageKeyFn;
|
||||
TaskModel.prototype.sync._localforageNamespace = TaskModel.prototype.offlineSync._localforageNamespace;
|
||||
|
||||
return TaskModel;
|
||||
|
||||
});
|
||||
|
||||
@@ -2,13 +2,19 @@ define(
|
||||
[],
|
||||
|
||||
function() {
|
||||
|
||||
var constants = {
|
||||
|
||||
ENTER_KEY :13
|
||||
var constants = {
|
||||
ROOT_PARENT_ID: '00000000-0000-0000-0000-000000000000',
|
||||
|
||||
ENTER_KEY :13,
|
||||
UP_ARROW: 38,
|
||||
DOWN_ARROW: 40,
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
CNTRL: 17,
|
||||
|
||||
};
|
||||
|
||||
return constants;
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
-1571
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
-5
File diff suppressed because one or more lines are too long
-39
@@ -1,39 +0,0 @@
|
||||
/*!
|
||||
Lo-Dash 0.8.2 lodash.com/license
|
||||
Underscore.js 1.4.2 underscorejs.org/LICENSE
|
||||
*/
|
||||
;(function(e,t){function s(e){if(e&&e.__wrapped__)return e;if(!(this instanceof s))return new s(e);this.__wrapped__=e}function o(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||H),s=i?{}:e;if(i)for(n=t-1;++n<r;){var o=e[n]+"";(Z.call(s,o)?s[o]:s[o]=[]).push(e[n])}return function(e){if(i){var n=e+"";return Z.call(s,n)&&-1<T(s[n],e)}return-1<T(s,e,t)}}function u(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function a(e,t,n){function r(){var u=arguments
|
||||
,a=s?this:t;return i||(e=t[o]),n.length&&(u=u.length?n.concat(nt.call(u)):n),this instanceof r?(p.prototype=e.prototype,a=new p,(u=e.apply(a,u))&&Ht[typeof u]?u:a):e.apply(a,u)}var i=m(e),s=!n,o=e;return s&&(n=t),r}function f(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:A}function l(){for(var e={e:"",g:Et,i:"",j:Mt,m:Tt,n:kt,o:J,p:"",q:n,r:_t,c:{d:""},l:{d:""}},t,i=-1;t=arguments[++i];)for(var s in t){var o=t[s];/d|h/.test(s)?("string"==typeof
|
||||
o&&(o={b:o,k:o}),e.c[s]=o.b,e.l[s]=o.k):e[s]=o}t=e.a;if("d"!=(e.f=/^[^,]+/.exec(t)[0])||!e.c.h)e.c=r;i="",e.r&&(i+="'use strict';"),i+="var i,A,j="+e.f+",t="+(e.i||e.f)+";if(!"+e.f+")return t;"+e.p+";",e.c&&(i+="var k=j.length;i=-1;",e.l&&(i+="if(k===+k){"),e.n&&(i+="if(y.call(j)==w){j=j.split('')}"),i+=e.c.d+";while(++i<k){A=j[i];"+e.c.h+"}",e.l&&(i+="}"));if(e.l){e.c?i+="else {":e.m&&(i+="var k=j.length;i=-1;if(k&&O(j)){while(++i<k){A=j[i+=''];"+e.l.h+"}}else {"),e.g||(i+="var u=typeof j=='function'&&q.call(j,'prototype');"
|
||||
);if(e.j&&e.q)i+="var n=-1,o=Y[typeof j]?l(j):[],k=o.length;"+e.l.d+";while(++n<k){i=o[n];",e.g||(i+="if(!(u&&i=='prototype')){"),i+="A=j[i];"+e.l.h+"",e.g||(i+="}");else{i+=e.l.d+";for(i in j){";if(!e.g||e.q)i+="if(",e.g||(i+="!(u&&i=='prototype')"),!e.g&&e.q&&(i+="&&"),e.q&&(i+="h.call(j,i)"),i+="){";i+="A=j[i];"+e.l.h+";";if(!e.g||e.q)i+="}"}i+="}";if(e.g){i+="var g=j.constructor;";for(s=0;7>s;s++)i+="i='"+e.o[s]+"';if(","constructor"==e.o[s]&&(i+="!(g&&g.prototype===j)&&"),i+="h.call(j,i)){A=j[i];"+
|
||||
e.l.h+"}"}if(e.c||e.m)i+="}"}return i+=e.e+";return t",Function("D,E,F,I,e,f,J,h,M,O,Q,S,T,X,Y,l,q,v,w,y,z","var G=function("+t+"){"+i+"};return G")(Dt,_,L,u,Q,f,en,Z,T,v,$t,m,Jt,mt,Ht,ut,tt,nt,yt,rt)}function c(e){return"\\"+Bt[e]}function h(e){return Qt[e]}function p(){}function d(e){return Gt[e]}function v(e){return rt.call(e)==ct}function m(e){return"function"==typeof e}function g(e){var t=i;if(!e||"object"!=typeof e||v(e))return t;var n=e.constructor;return(!Lt||"function"==typeof e.toString||"string"!=typeof
|
||||
(e+""))&&(!m(n)||n instanceof n)?xt?(en(e,function(e,n,r){return t=!Z.call(r,n),i}),t===i):(en(e,function(e,n){t=n}),t===i||Z.call(e,t)):t}function y(e,t,n,s,o){if(e==r)return e;n&&(t=i);if(n=Ht[typeof e]){var u=rt.call(e);if(!Pt[u]||Nt&&v(e))return e;var a=u==ht,n=a||(u==mt?Jt(e):n)}if(!n||!t)return n?a?nt.call(e):Zt({},e):e;n=e.constructor;switch(u){case pt:case dt:return new n(+e);case vt:case yt:return new n(e);case gt:return n(e.source,U.exec(e))}s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[
|
||||
u]==e)return o[u];var f=a?n(e.length):{};return s.push(e),o.push(f),(a?mn:tn)(e,function(e,n){f[n]=y(e,t,r,s,o)}),f}function b(e,t,s,o){if(e==r||t==r)return e===t;if(e===t)return 0!==e||1/e==1/t;if(Ht[typeof e]||Ht[typeof t])e=e.__wrapped__||e,t=t.__wrapped__||t;var u=rt.call(e);if(u!=rt.call(t))return i;switch(u){case pt:case dt:return+e==+t;case vt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case gt:case yt:return e==t+""}var a=Dt[u];if(Nt&&!a&&(a=v(e))&&!v(t)||!a&&(u!=mt||Lt&&("function"!=typeof e.
|
||||
toString&&"string"==typeof (e+"")||"function"!=typeof t.toString&&"string"==typeof (t+""))))return i;s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var u=-1,f=n,l=0;s.push(e),o.push(t);if(a){l=e.length;if(f=l==t.length)for(;l--&&(f=b(e[l],t[l],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!m(a)||!(a instanceof a&&m(f)&&f instanceof f)))return i;for(var c in e)if(Z.call(e,c)&&(l++,!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;for(c in t)if(Z.call(t,c)&&!(l--))return i;if(
|
||||
Et)for(;7>++u;)if(c=J[u],Z.call(e,c)&&(!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;return n}function w(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function E(e,t,n,r){var s=e,o=e?e.length:0,u=3>arguments.length;if(o!==+o)var a=sn(e),o=a.length;else kt&&rt.call(e)==yt&&(s=e.split(""));return mn(e,function(e,f,l){f=a?a[--o]:--o,n=u?(u=i,s[f]):t.call(r,n,s[f],f,l)}),n}function S(e,t,n){
|
||||
if(e)return t==r||n?e[0]:nt.call(e,0,t)}function x(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];$t(s)?et.apply(i,t?s:x(s)):i.push(s)}return i}function T(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?at(0,i+n):n||0)-1;else if(n)return r=C(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function N(e,t,n){return e?nt.call(e,t==r||n?1:t):[]}function C(e,t,n,r){var i=0,s=e?e.length:i;if(n){n=f(n,r);for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+
|
||||
s>>>1,e[r]<t?i=r+1:s=r;return i}function k(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n=f(n,r);++s<o;)if(r=n(e[s],s,e),t?!s||a[a.length-1]!==r:0>T(a,r))a.push(r),u.push(e[s]);return u}function L(e,t){return Ot||it&&2<arguments.length?it.call.apply(it,arguments):a(e,t,nt.call(arguments,2))}function A(e){return e}function O(e){mn(nn(e),function(t){var r=s[t]=e[t];s.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&et.apply(e,arguments)
|
||||
,e=r.apply(s,e),this.__chain__&&(e=new s(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,M="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),_=Array.prototype,D=Object.prototype,P=0,H=30,B=e._,j=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,F=/&(?:amp|lt|gt|quot|#x27);/g,I=/\b__p\+='';/g,q=/\b(__p\+=)''\+/g,R=/(__e\(.*?\)|\b__t\))\+'';/g,U=/\w*$/,z=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,W=RegExp("^"+(D.valueOf+""
|
||||
).replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/($^)/,V=/[&<>"']/g,$=/['\n\r\t\u2028\u2029\\]/g,J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),K=Math.ceil,Q=_.concat,G=Math.floor,Y=W.test(Y=Object.getPrototypeOf)&&Y,Z=D.hasOwnProperty,et=_.push,tt=D.propertyIsEnumerable,nt=_.slice,rt=D.toString,it=W.test(it=nt.bind)&&it,st=W.test(st=Array.isArray)&&st,ot=e.isFinite,ut=W.test(ut=Object.keys)&&ut
|
||||
,at=Math.max,ft=Math.min,lt=Math.random,ct="[object Arguments]",ht="[object Array]",pt="[object Boolean]",dt="[object Date]",vt="[object Number]",mt="[object Object]",gt="[object RegExp]",yt="[object String]",bt=e.clearTimeout,wt=e.setTimeout,Et,St,xt,Tt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments)Tt=!r;Et=4>(n+"").length,xt="x"!=n[0],St=(n.splice.call(t,0,1),t[0])})(1);var Nt=!v(arguments),Ct="x"!=nt.call("x"
|
||||
)[0],kt="xx"!="x"[0]+Object("x")[0];try{var Lt=("[object Object]",rt.call(e.document||0)==mt)}catch(At){}var Ot=it&&/\n|Opera/.test(it+rt.call(e.opera)),Mt=ut&&/^.+$|true/.test(ut+!!e.attachEvent),_t=!Ot,Dt={};Dt[pt]=Dt[dt]=Dt["[object Function]"]=Dt[vt]=Dt[mt]=Dt[gt]=i,Dt[ct]=Dt[ht]=Dt[yt]=n;var Pt={};Pt[ct]=Pt["[object Function]"]=i,Pt[ht]=Pt[pt]=Pt[dt]=Pt[vt]=Pt[mt]=Pt[gt]=Pt[yt]=n;var Ht={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Bt={"\\":"\\","'":"'","\n":"n"
|
||||
,"\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var jt={a:"d,c,x",p:"c=f(c,x)",h:"if(c(A,i,d)===false)return t"},Ft={i:"{}",p:"c=f(c,x)",h:"var p=c(A,i,d);(h.call(t,p)?t[p]++:t[p]=1)"},It={i:"true",h:"if(!c(A,i,d))return!t"},qt={q:i,r:i,a:"m",p:"for(var a=1,b=arguments.length;a<b;a++){if(j=arguments[a]){",h:"t[i]=A",e:"}}"},Rt={i:"[]",h:"c(A,i,d)&&t.push(A)"},Ut={p:"c=f(c,x)"}
|
||||
,zt={h:{k:jt.h}},Wt={i:"d||[]",d:{b:"t=Array(k)",k:"t="+(Mt?"Array(k)":"[]")},h:{b:"t[i]=c(A,i,d)",k:"t"+(Mt?"[n]=":".push")+"(c(A,i,d))"}},Xt={q:i,a:"m,c,x",i:"{}",p:"var R=typeof c=='function';if(R)c=f(c,x);else var s=e.apply(E,arguments)",h:"if(R?!c(A,i,m):M(s,i)<0)t[i]=A"},Vt=l({a:"m",i:"{}",h:"t[A]=i"});Nt&&(v=function(e){return e?Z.call(e,"callee"):i});var $t=st||function(e){return rt.call(e)==ht};m(/x/)&&(m=function(e){return"[object Function]"==rt.call(e)});var Jt=Y?function(e){if(!e||"object"!=typeof
|
||||
e)return i;var t=e.valueOf,n="function"==typeof t&&(n=Y(t))&&Y(n);return n?e==n||Y(e)==n&&!v(e):g(e)}:g,Kt=l({a:"m",i:"[]",h:"t.push(i)"}),Qt={"&":"&","<":"<",">":">",'"':""","'":"'"},Gt=Vt(Qt),Yt=l(qt,{h:"if(t[i]==null)"+qt.h}),Zt=l(qt),en=l(jt,Ut,zt,{q:i}),tn=l(jt,Ut,zt),nn=l({q:i,a:"m",i:"[]",h:"S(A)&&t.push(i)",e:"t.sort()"}),rn=l({a:"A",i:"true",p:"var H=y.call(A),k=A.length;if(D[H]"+(Nt?"||O(A)":"")+"||(H==X&&k===+k&&S(A.splice)))return!k",h:{k:"return false"}}),sn=ut?function(
|
||||
e){var t=typeof e;return"function"==t&&tt.call(e,"prototype")?Kt(e):e&&Ht[t]?ut(e):[]}:Kt,on=l(qt,{a:"m,dd,N",p:"var P,C=arguments,a=0;if(N==I){var b=2,ee=C[3],ff=C[4]}else var b=C.length,ee=[],ff=[];while(++a<b){if(j=C[a]){",h:"if((dd=A)&&((P=Q(dd))||T(dd))){var K=false,gg=ee.length;while(gg--)if(K=ee[gg]==dd)break;if(K){t[i]=ff[gg]}else {ee.push(dd);ff.push(A=(A=t[i],P)?(Q(A)?A:[]):(T(A)?A:{}));t[i]=G(A,dd,I,ee,ff)}}else if(dd!=null)t[i]=dd"}),un=l(Xt),an=l({a:"m",i:"[]",h:"t"+(Mt?"[n]=":".push"
|
||||
)+"([i,A])"}),fn=l(Xt,{p:"if(typeof c!='function'){var i=0,s=e.apply(E,arguments),k=s.length;while(++i<k){var p=s[i];if(p in m)t[p]=m[p]}}else {c=f(c,x)",h:"if(c(A,i,m))t[i]=A",e:"}"}),ln=l({a:"m",i:"[]",h:"t.push(A)"}),cn=l({a:"d,hh",i:"false",n:i,d:{b:"if(y.call(d)==w)return d.indexOf(hh)>-1"},h:"if(A===hh)return true"}),hn=l(jt,Ft),pn=l(jt,It),dn=l(jt,Rt),vn=l(jt,Ut,{i:"z",h:"if(c(A,i,d))return A"}),mn=l(jt,Ut),gn=l(jt,Ft,{h:"var p=c(A,i,d);(h.call(t,p)?t[p]:t[p]=[]).push(A)"}),yn=l(Wt,{a:"d,U"
|
||||
,p:"var C=v.call(arguments,2),R=typeof U=='function'",h:{b:"t[i]=(R?U:A[U]).apply(A,C)",k:"t"+(Mt?"[n]=":".push")+"((R?U:A[U]).apply(A,C))"}}),bn=l(jt,Wt),wn=l(Wt,{a:"d,bb",h:{b:"t[i]=A[bb]",k:"t"+(Mt?"[n]=":".push")+"(A[bb])"}}),En=l({a:"d,c,B,x",i:"B",p:"var V=arguments.length<3;c=f(c,x)",d:{b:"if(V)t=j[++i]"},h:{b:"t=c(t,A,i,d)",k:"t=V?(V=false,A):c(t,A,i,d)"}}),Sn=l(jt,Rt,{h:"!"+Rt.h}),xn=l(jt,It,{i:"false",h:It.h.replace("!","")}),Tn=l(jt,Ft,Wt,{h:{b:"t[i]={a:c(A,i,d),b:i,c:A}",k:"t"+(Mt?"[n]="
|
||||
:".push")+"({a:c(A,i,d),b:i,c:A})"},e:"t.sort(I);k=t.length;while(k--)t[k]=t[k].c"}),Nn=l(Rt,{a:"d,aa",p:"var s=[];J(aa,function(A,p){s.push(p)});var cc=s.length",h:"for(var Z=true,r=0;r<cc;r++){var p=s[r];if(!(Z=A[p]===aa[p]))break}Z&&t.push(A)"}),Cn=l({q:i,r:i,a:"m",p:"var L=arguments,i=0,k=L.length;if(k>1){while(++i<k)t[L[i]]=F(t[L[i]],t);return t}",h:"if(S(A))t[i]=F(A,t)"});s.VERSION="0.8.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=L,s.bindAll=
|
||||
Cn,s.chain=function(e){return e=new s(e),e.__chain__=n,e},s.clone=y,s.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},s.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=cn,s.countBy=hn,s.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,bt(a),a=wt(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=
|
||||
Yt,s.defer=function(e){var n=nt.call(arguments,1);return wt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=nt.call(arguments,2);return wt(function(){return e.apply(t,r)},n)},s.difference=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=Q.apply(_,arguments),i=o(i,r);++n<r;){var s=e[n];i(s)||t.push(s)}return t},s.escape=function(e){return e==r?"":(e+"").replace(V,h)},s.every=pn,s.extend=Zt,s.filter=dn,s.find=vn,s.first=S,s.flatten=x,s.forEach=mn,s.forIn=en,s.forOwn=tn,
|
||||
s.functions=nn,s.groupBy=gn,s.has=function(e,t){return e?Z.call(e,t):i},s.identity=A,s.indexOf=T,s.initial=function(e,t,n){return e?nt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=arguments.length,n=[],r=-1,i=e?e.length:0,s=[];e:for(;++r<i;){var u=e[r];if(0>T(s,u)){for(var a=1;a<t;a++)if(!(n[a]||(n[a]=o(arguments[a])))(u))continue e;s.push(u)}}return s},s.invert=Vt,s.invoke=yn,s.isArguments=v,s.isArray=$t,s.isBoolean=function(e){return e===n||e===i||rt.call(e)==pt},s.isDate=function(
|
||||
e){return rt.call(e)==dt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=rn,s.isEqual=b,s.isFinite=function(e){return ot(e)&&rt.call(e)==vt},s.isFunction=m,s.isNaN=function(e){return rt.call(e)==vt&&e!=+e},s.isNull=function(e){return e===r},s.isNumber=function(e){return rt.call(e)==vt},s.isObject=function(e){return e?Ht[typeof e]:i},s.isPlainObject=Jt,s.isRegExp=function(e){return rt.call(e)==gt},s.isString=function(e){return rt.call(e)==yt},s.isUndefined=function(e){return e===t},s
|
||||
.keys=sn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:nt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?at(0,r+n):ft(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.lateBind=function(e,t){return a(t,e,nt.call(arguments,2))},s.map=bn,s.max=w,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return Z.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=on,s.min=function(e,t,n){var r=
|
||||
Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},s.mixin=O,s.noConflict=function(){return e._=B,this},s.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},s.omit=un,s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},s.pairs=an,s.partial=function(e){return a(e,nt.call(arguments,1))},s.pick=fn,s.pluck=
|
||||
wn,s.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+G(lt()*((+t||0)-e+1))},s.range=function(e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=at(0,K((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=En,s.reduceRight=E,s.reject=Sn,s.rest=N,s.result=function(e,t){var n=e?e[t]:r;return m(n)?e[t]():n},s.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return mn(e,function(e){var r=G(lt()*(++t+1));n[t]=n[r],n[r]=e}),n},s.size=function(e){var t=e?e.length:0;return t===+
|
||||
t?t:sn(e).length},s.some=xn,s.sortBy=Tn,s.sortedIndex=C,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){e||(e=""),n||(n={});var r,i,o=0,u=s.templateSettings,a="__p += '",f=n.variable||u.variable,l=f;e.replace(RegExp((n.escape||u.escape||X).source+"|"+(n.interpolate||u.interpolate||X).source+"|"+(n.evaluate||u.evaluate||X).source+"|$","g"),function(t,n,i,s,u){a+=e.slice(o,u).replace($,c),a+=n?"'+__e("+n+")+'":s?"';"+s+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=s||j.test(
|
||||
n||i)),o=u+t.length}),a+="';",l||(f="obj",r?a="with("+f+"){"+a+"}":(n=RegExp("(\\(\\s*)"+f+"\\."+f+"\\b","g"),a=a.replace(z,"$&"+f+".").replace(n,"$1__d"))),a=(r?a.replace(I,""):a).replace(q,"$1").replace(R,"$1;"),a="function("+f+"){"+(l?"":f+"||("+f+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(l?"":",__d="+f+"."+f+"||"+f)+";")+a+"return __p}";try{i=Function("_","return "+a)(s)}catch(h){throw h.source=a,h}return t?i(t):(i.source=
|
||||
a,i)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(bt(u),a=r,s=e.apply(o,i)):u||(u=wt(n,f)),s}},s.times=function(e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},s.toArray=function(e){if(!e)return[];var t=e.length;return t===+t?(Ct?rt.call(e)==yt:"string"==typeof e)?e.split(""):nt.call(e):ln(e)},s.unescape=function(e){return e==r?"":(e+"").replace(F,d)},s.union=
|
||||
function(){for(var e=-1,t=Q.apply(_,arguments),n=t.length,r=[];++e<n;){var i=t[e];0>T(r,i)&&r.push(i)}return r},s.uniq=k,s.uniqueId=function(e){var t=P++;return e?e+t:t},s.values=ln,s.where=Nn,s.without=function(e){for(var t=-1,n=e?e.length:0,r=o(arguments,1,20),i=[];++t<n;){var s=e[t];r(s)||i.push(s)}return i},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&et.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){for(var t=-1,n=e?w(wn(arguments,"length")):0,r=Array(n);++
|
||||
t<n;)r[t]=wn(arguments,t);return r},s.all=pn,s.any=xn,s.collect=bn,s.detect=vn,s.drop=N,s.each=mn,s.foldl=En,s.foldr=E,s.head=S,s.include=cn,s.inject=En,s.methods=nn,s.select=dn,s.tail=N,s.take=S,s.unique=k,O(s),s.prototype.chain=function(){return this.__chain__=n,this},s.prototype.value=function(){return this.__wrapped__},mn("pop push reverse shift sort splice unshift".split(" "),function(e){var t=_[e];s.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),St&&e.length===0&&delete
|
||||
e[0],this.__chain__&&(e=new s(e),e.__chain__=n),e}}),mn(["concat","join","slice"],function(e){var t=_[e];s.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new s(e),e.__chain__=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):M?"object"==typeof module&&module&&module.exports==M?(module.exports=s)._=s:M._=s:e._=s})(this);
|
||||
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
RequireJS 2.1.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
Available via the MIT or new BSD license.
|
||||
see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
var requirejs,require,define;
|
||||
(function(Z){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function y(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function l(b,c){return s(b,c)&&b[c]}function F(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function Q(b,c,d,h){c&&F(c,function(c,j){if(d||!s(b,j))h&&"string"!==typeof c?(b[j]||(b[j]={}),Q(b[j],
|
||||
c,d,h)):b[j]=c});return b}function u(b,c){return function(){return c.apply(b,arguments)}}function aa(b){throw b;}function ba(b){if(!b)return b;var c=Z;y(b.split("."),function(b){c=c[b]});return c}function A(b,c,d,h){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=h;d&&(c.originalError=d);return c}function ha(b){function c(a,f,b){var e,m,c,g,d,h,j,i=f&&f.split("/");e=i;var n=k.map,p=n&&n["*"];if(a&&"."===a.charAt(0))if(f){e=l(k.pkgs,f)?i=[f]:i.slice(0,i.length-
|
||||
1);f=a=e.concat(a.split("/"));for(e=0;f[e];e+=1)if(m=f[e],"."===m)f.splice(e,1),e-=1;else if(".."===m)if(1===e&&(".."===f[2]||".."===f[0]))break;else 0<e&&(f.splice(e-1,2),e-=2);e=l(k.pkgs,f=a[0]);a=a.join("/");e&&a===f+"/"+e.main&&(a=f)}else 0===a.indexOf("./")&&(a=a.substring(2));if(b&&n&&(i||p)){f=a.split("/");for(e=f.length;0<e;e-=1){c=f.slice(0,e).join("/");if(i)for(m=i.length;0<m;m-=1)if(b=l(n,i.slice(0,m).join("/")))if(b=l(b,c)){g=b;d=e;break}if(g)break;!h&&(p&&l(p,c))&&(h=l(p,c),j=e)}!g&&
|
||||
h&&(g=h,d=j);g&&(f.splice(0,d,g),a=f.join("/"))}return a}function d(a){z&&y(document.getElementsByTagName("script"),function(f){if(f.getAttribute("data-requiremodule")===a&&f.getAttribute("data-requirecontext")===i.contextName)return f.parentNode.removeChild(f),!0})}function h(a){var f=l(k.paths,a);if(f&&I(f)&&1<f.length)return d(a),f.shift(),i.require.undef(a),i.require([a]),!0}function $(a){var f,b=a?a.indexOf("!"):-1;-1<b&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function n(a,
|
||||
f,b,e){var m,B,g=null,d=f?f.name:null,h=a,j=!0,k="";a||(j=!1,a="_@r"+(L+=1));a=$(a);g=a[0];a=a[1];g&&(g=c(g,d,e),B=l(r,g));a&&(g?k=B&&B.normalize?B.normalize(a,function(a){return c(a,d,e)}):c(a,d,e):(k=c(a,d,e),a=$(k),g=a[0],k=a[1],b=!0,m=i.nameToUrl(k)));b=g&&!B&&!b?"_unnormalized"+(M+=1):"";return{prefix:g,name:k,parentMap:f,unnormalized:!!b,url:m,originalName:h,isDefine:j,id:(g?g+"!"+k:k)+b}}function q(a){var f=a.id,b=l(p,f);b||(b=p[f]=new i.Module(a));return b}function t(a,f,b){var e=a.id,m=l(p,
|
||||
e);if(s(r,e)&&(!m||m.defineEmitComplete))"defined"===f&&b(r[e]);else if(m=q(a),m.error&&"error"===f)b(m.error);else m.on(f,b)}function v(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(y(b,function(f){if(f=l(p,f))f.error=a,f.events.error&&(e=!0,f.emit("error",a))}),!e)j.onError(a)}function w(){R.length&&(ia.apply(G,[G.length-1,0].concat(R)),R=[])}function x(a){delete p[a];delete T[a]}function E(a,f,b){var e=a.map.id;a.error?a.emit("error",a.error):(f[e]=!0,y(a.depMaps,function(e,c){var g=e.id,
|
||||
d=l(p,g);d&&(!a.depMatched[c]&&!b[g])&&(l(f,g)?(a.defineDep(c,r[g]),a.check()):E(d,f,b))}),b[e]=!0)}function C(){var a,f,b,e,m=(b=1E3*k.waitSeconds)&&i.startTime+b<(new Date).getTime(),c=[],g=[],j=!1,l=!0;if(!U){U=!0;F(T,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||g.push(b),!b.error))if(!b.inited&&m)h(f)?j=e=!0:(c.push(f),d(f));else if(!b.inited&&(b.fetched&&a.isDefine)&&(j=!0,!a.prefix))return l=!1});if(m&&c.length)return b=A("timeout","Load timeout for modules: "+c,null,c),b.contextName=
|
||||
i.contextName,v(b);l&&y(g,function(a){E(a,{},{})});if((!m||e)&&j)if((z||da)&&!V)V=setTimeout(function(){V=0;C()},50);U=!1}}function D(a){s(r,a[0])||q(n(a[0],null,!0)).init(a[1],a[2])}function J(a){var a=a.currentTarget||a.srcElement,b=i.onScriptLoad;a.detachEvent&&!W?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=i.onScriptError;(!a.detachEvent||W)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function K(){var a;for(w();G.length;){a=
|
||||
G.shift();if(null===a[0])return v(A("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));D(a)}}var U,X,i,N,V,k={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},shim:{},config:{}},p={},T={},Y={},G=[],r={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=r[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){var b=
|
||||
l(k.pkgs,a.map.id);return(b?l(k.config,a.map.id+"/"+b.main):l(k.config,a.map.id))||{}},exports:r[a.map.id]}}};X=function(a){this.events=l(Y,a.id)||{};this.map=a;this.shim=l(k.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};X.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=u(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;
|
||||
this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],u(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=
|
||||
this.map.url;S[a]||(S[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,m=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(H(m)){if(this.events.error&&this.map.isDefine||j.onError!==aa)try{e=i.execCb(c,m,b,e)}catch(d){a=d}else e=i.execCb(c,m,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==
|
||||
this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",v(this.error=a)}else e=m;this.exports=e;if(this.map.isDefine&&!this.ignore&&(r[c]=e,j.onResourceLoad))j.onResourceLoad(i,this.map,this.depMaps);x(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=
|
||||
!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=n(a.prefix);this.depMaps.push(d);t(d,"defined",u(this,function(e){var m,d;d=this.map.name;var g=this.map.parentMap?this.map.parentMap.name:null,h=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,g,!0)})||""),e=n(a.prefix+"!"+d,this.map.parentMap),t(e,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),
|
||||
d=l(p,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else m=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),m.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];F(p,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&x(a.map.id)});v(a)}),m.fromText=u(this,function(e,c){var d=a.name,g=n(d),B=O;c&&(e=c);B&&(O=!1);q(g);s(k.config,b)&&(k.config[d]=k.config[b]);try{j.exec(e)}catch(ca){return v(A("fromtexteval",
|
||||
"fromText eval for "+b+" failed: "+ca,ca,[b]))}B&&(O=!0);this.depMaps.push(g);i.completeLoad(d);h([d],m)}),e.load(a.name,h,m,k)}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){T[this.map.id]=this;this.enabling=this.enabled=!0;y(this.depMaps,u(this,function(a,b){var c,e;if("string"===typeof a){a=n(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=l(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;t(a,"defined",u(this,function(a){this.defineDep(b,
|
||||
a);this.check()}));this.errback&&t(a,"error",u(this,this.errback))}c=a.id;e=p[c];!s(N,c)&&(e&&!e.enabled)&&i.enable(a,this)}));F(this.pluginMaps,u(this,function(a){var b=l(p,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){y(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:k,contextName:b,registry:p,defined:r,urlFetched:S,defQueue:G,Module:X,makeModuleMap:n,
|
||||
nextTick:j.nextTick,onError:v,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};F(a,function(a,b){e[b]?"map"===b?(k.map||(k.map={}),Q(k[b],a,!0,!0)):Q(k[b],a,!0):k[b]=a});a.shim&&(F(a.shim,function(a,b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);c[b]=a}),k.shim=c);a.packages&&(y(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,
|
||||
location:a.location||a.name,main:(a.main||"main").replace(ja,"").replace(ea,"")}}),k.pkgs=b);F(p,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=n(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Z,arguments));return b||a.exports&&ba(a.exports)}},makeRequire:function(a,f){function d(e,c,h){var g,k;f.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return v(A("requireargs",
|
||||
"Invalid require call"),h);if(a&&s(N,e))return N[e](p[a.id]);if(j.get)return j.get(i,e,a,d);g=n(e,a,!1,!0);g=g.id;return!s(r,g)?v(A("notloaded",'Module name "'+g+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):r[g]}K();i.nextTick(function(){K();k=q(n(null,a));k.skipMap=f.skipMap;k.init(e,c,h,{enabled:!0});C()});return d}f=f||{};Q(d,{isBrowser:z,toUrl:function(b){var d,f=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==f&&(!("."===g||".."===g)||1<f))d=b.substring(f,b.length),b=
|
||||
b.substring(0,f);return i.nameToUrl(c(b,a&&a.id,!0),d,!0)},defined:function(b){return s(r,n(b,a,!1,!0).id)},specified:function(b){b=n(b,a,!1,!0).id;return s(r,b)||s(p,b)}});a||(d.undef=function(b){w();var c=n(b,a,!0),f=l(p,b);delete r[b];delete S[c.url];delete Y[b];f&&(f.events.defined&&(Y[b]=f.events),x(b))});return d},enable:function(a){l(p,a.id)&&q(a).enable()},completeLoad:function(a){var b,c,e=l(k.shim,a)||{},d=e.exports;for(w();G.length;){c=G.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===
|
||||
a&&(b=!0);D(c)}c=l(p,a);if(!b&&!s(r,a)&&c&&!c.inited){if(k.enforceDefine&&(!d||!ba(d)))return h(a)?void 0:v(A("nodefine","No define call for "+a,null,[a]));D([a,e.deps||[],e.exportsFn])}C()},nameToUrl:function(a,b,c){var e,d,h,g,i,n;if(j.jsExtRegExp.test(a))g=a+(b||"");else{e=k.paths;d=k.pkgs;g=a.split("/");for(i=g.length;0<i;i-=1)if(n=g.slice(0,i).join("/"),h=l(d,n),n=l(e,n)){I(n)&&(n=n[0]);g.splice(0,i,n);break}else if(h){a=a===h.name?h.location+"/"+h.main:h.location;g.splice(0,i,a);break}g=g.join("/");
|
||||
g+=b||(/\?/.test(g)||c?"":".js");g=("/"===g.charAt(0)||g.match(/^[\w\+\.\-]+:/)?"":k.baseUrl)+g}return k.urlArgs?g+((-1===g.indexOf("?")?"?":"&")+k.urlArgs):g},load:function(a,b){j.load(i,a,b)},execCb:function(a,b,c,e){return b.apply(e,c)},onScriptLoad:function(a){if("load"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=J(a),i.completeLoad(a.id)},onScriptError:function(a){var b=J(a);if(!h(b.id))return v(A("scripterror","Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();
|
||||
return i}var j,w,x,C,J,D,P,K,q,fa,la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,ea=/\.js$/,ja=/^\.\//;w=Object.prototype;var L=w.toString,ga=w.hasOwnProperty,ia=Array.prototype.splice,z=!!("undefined"!==typeof window&&navigator&&window.document),da=!z&&"undefined"!==typeof importScripts,ka=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,W="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),E={},t={},R=[],O=
|
||||
!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(H(requirejs))return;t=requirejs;requirejs=void 0}"undefined"!==typeof require&&!H(require)&&(t=require,require=void 0);j=requirejs=function(b,c,d,h){var q,n="_";!I(b)&&"string"!==typeof b&&(q=b,I(c)?(b=c,c=d,d=h):b=[]);q&&q.context&&(n=q.context);(h=l(E,n))||(h=E[n]=j.s.newContext(n));q&&h.configure(q);return h.require(b,c,d)};j.config=function(b){return j(b)};j.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,
|
||||
4)}:function(b){b()};require||(require=j);j.version="2.1.8";j.jsExtRegExp=/^\/|:|\?|\.js$/;j.isBrowser=z;w=j.s={contexts:E,newContext:ha};j({});y(["toUrl","undef","defined","specified"],function(b){j[b]=function(){var c=E._;return c.require[b].apply(c,arguments)}});if(z&&(x=w.head=document.getElementsByTagName("head")[0],C=document.getElementsByTagName("base")[0]))x=w.head=C.parentNode;j.onError=aa;j.createNode=function(b){var c=b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):
|
||||
document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};j.load=function(b,c,d){var h=b&&b.config||{};if(z)return h=j.createNode(h,c,d),h.setAttribute("data-requirecontext",b.contextName),h.setAttribute("data-requiremodule",c),h.attachEvent&&!(h.attachEvent.toString&&0>h.attachEvent.toString().indexOf("[native code"))&&!W?(O=!0,h.attachEvent("onreadystatechange",b.onScriptLoad)):(h.addEventListener("load",b.onScriptLoad,!1),h.addEventListener("error",
|
||||
b.onScriptError,!1)),h.src=d,K=h,C?x.insertBefore(h,C):x.appendChild(h),K=null,h;if(da)try{importScripts(d),b.completeLoad(c)}catch(l){b.onError(A("importscripts","importScripts failed for "+c+" at "+d,l,[c]))}};z&&M(document.getElementsByTagName("script"),function(b){x||(x=b.parentNode);if(J=b.getAttribute("data-main"))return q=J,t.baseUrl||(D=q.split("/"),q=D.pop(),fa=D.length?D.join("/")+"/":"./",t.baseUrl=fa),q=q.replace(ea,""),j.jsExtRegExp.test(q)&&(q=J),t.deps=t.deps?t.deps.concat(q):[q],!0});
|
||||
define=function(b,c,d){var h,j;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=null);!c&&H(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(h=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),h=P;h&&(b||(b=h.getAttribute("data-requiremodule")),j=E[h.getAttribute("data-requirecontext")])}(j?j.defQueue:
|
||||
R).push([b,c,d])};define.amd={jQuery:!0};j.exec=function(b){return eval(b)};j(t)}})(this);
|
||||
-2
File diff suppressed because one or more lines are too long
Vendored
-308
@@ -1,308 +0,0 @@
|
||||
/**
|
||||
* @license RequireJS text 2.0.3 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/requirejs/text for details
|
||||
*/
|
||||
/*jslint regexp: true */
|
||||
/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
|
||||
define: false, window: false, process: false, Packages: false,
|
||||
java: false, location: false */
|
||||
|
||||
define(['module'], function (module) {
|
||||
'use strict';
|
||||
|
||||
var text, fs,
|
||||
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
|
||||
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
|
||||
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
|
||||
hasLocation = typeof location !== 'undefined' && location.href,
|
||||
defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
|
||||
defaultHostName = hasLocation && location.hostname,
|
||||
defaultPort = hasLocation && (location.port || undefined),
|
||||
buildMap = [],
|
||||
masterConfig = (module.config && module.config()) || {};
|
||||
|
||||
text = {
|
||||
version: '2.0.3',
|
||||
|
||||
strip: function (content) {
|
||||
//Strips <?xml ...?> declarations so that external SVG and XML
|
||||
//documents can be added to a document without worry. Also, if the string
|
||||
//is an HTML document, only the part inside the body tag is returned.
|
||||
if (content) {
|
||||
content = content.replace(xmlRegExp, "");
|
||||
var matches = content.match(bodyRegExp);
|
||||
if (matches) {
|
||||
content = matches[1];
|
||||
}
|
||||
} else {
|
||||
content = "";
|
||||
}
|
||||
return content;
|
||||
},
|
||||
|
||||
jsEscape: function (content) {
|
||||
return content.replace(/(['\\])/g, '\\$1')
|
||||
.replace(/[\f]/g, "\\f")
|
||||
.replace(/[\b]/g, "\\b")
|
||||
.replace(/[\n]/g, "\\n")
|
||||
.replace(/[\t]/g, "\\t")
|
||||
.replace(/[\r]/g, "\\r")
|
||||
.replace(/[\u2028]/g, "\\u2028")
|
||||
.replace(/[\u2029]/g, "\\u2029");
|
||||
},
|
||||
|
||||
createXhr: masterConfig.createXhr || function () {
|
||||
//Would love to dump the ActiveX crap in here. Need IE 6 to die first.
|
||||
var xhr, i, progId;
|
||||
if (typeof XMLHttpRequest !== "undefined") {
|
||||
return new XMLHttpRequest();
|
||||
} else if (typeof ActiveXObject !== "undefined") {
|
||||
for (i = 0; i < 3; i += 1) {
|
||||
progId = progIds[i];
|
||||
try {
|
||||
xhr = new ActiveXObject(progId);
|
||||
} catch (e) {}
|
||||
|
||||
if (xhr) {
|
||||
progIds = [progId]; // so faster next time
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xhr;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses a resource name into its component parts. Resource names
|
||||
* look like: module/name.ext!strip, where the !strip part is
|
||||
* optional.
|
||||
* @param {String} name the resource name
|
||||
* @returns {Object} with properties "moduleName", "ext" and "strip"
|
||||
* where strip is a boolean.
|
||||
*/
|
||||
parseName: function (name) {
|
||||
var strip = false, index = name.indexOf("."),
|
||||
modName = name.substring(0, index),
|
||||
ext = name.substring(index + 1, name.length);
|
||||
|
||||
index = ext.indexOf("!");
|
||||
if (index !== -1) {
|
||||
//Pull off the strip arg.
|
||||
strip = ext.substring(index + 1, ext.length);
|
||||
strip = strip === "strip";
|
||||
ext = ext.substring(0, index);
|
||||
}
|
||||
|
||||
return {
|
||||
moduleName: modName,
|
||||
ext: ext,
|
||||
strip: strip
|
||||
};
|
||||
},
|
||||
|
||||
xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
|
||||
|
||||
/**
|
||||
* Is an URL on another domain. Only works for browser use, returns
|
||||
* false in non-browser environments. Only used to know if an
|
||||
* optimized .js version of a text resource should be loaded
|
||||
* instead.
|
||||
* @param {String} url
|
||||
* @returns Boolean
|
||||
*/
|
||||
useXhr: function (url, protocol, hostname, port) {
|
||||
var uProtocol, uHostName, uPort,
|
||||
match = text.xdRegExp.exec(url);
|
||||
if (!match) {
|
||||
return true;
|
||||
}
|
||||
uProtocol = match[2];
|
||||
uHostName = match[3];
|
||||
|
||||
uHostName = uHostName.split(':');
|
||||
uPort = uHostName[1];
|
||||
uHostName = uHostName[0];
|
||||
|
||||
return (!uProtocol || uProtocol === protocol) &&
|
||||
(!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
|
||||
((!uPort && !uHostName) || uPort === port);
|
||||
},
|
||||
|
||||
finishLoad: function (name, strip, content, onLoad) {
|
||||
content = strip ? text.strip(content) : content;
|
||||
if (masterConfig.isBuild) {
|
||||
buildMap[name] = content;
|
||||
}
|
||||
onLoad(content);
|
||||
},
|
||||
|
||||
load: function (name, req, onLoad, config) {
|
||||
//Name has format: some.module.filext!strip
|
||||
//The strip part is optional.
|
||||
//if strip is present, then that means only get the string contents
|
||||
//inside a body tag in an HTML string. For XML/SVG content it means
|
||||
//removing the <?xml ...?> declarations so the content can be inserted
|
||||
//into the current doc without problems.
|
||||
|
||||
// Do not bother with the work if a build and text will
|
||||
// not be inlined.
|
||||
if (config.isBuild && !config.inlineText) {
|
||||
onLoad();
|
||||
return;
|
||||
}
|
||||
|
||||
masterConfig.isBuild = config.isBuild;
|
||||
|
||||
var parsed = text.parseName(name),
|
||||
nonStripName = parsed.moduleName + '.' + parsed.ext,
|
||||
url = req.toUrl(nonStripName),
|
||||
useXhr = (masterConfig.useXhr) ||
|
||||
text.useXhr;
|
||||
|
||||
//Load the text. Use XHR if possible and in a browser.
|
||||
if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
|
||||
text.get(url, function (content) {
|
||||
text.finishLoad(name, parsed.strip, content, onLoad);
|
||||
}, function (err) {
|
||||
if (onLoad.error) {
|
||||
onLoad.error(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//Need to fetch the resource across domains. Assume
|
||||
//the resource has been optimized into a JS module. Fetch
|
||||
//by the module name + extension, but do not include the
|
||||
//!strip part to avoid file system issues.
|
||||
req([nonStripName], function (content) {
|
||||
text.finishLoad(parsed.moduleName + '.' + parsed.ext,
|
||||
parsed.strip, content, onLoad);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
write: function (pluginName, moduleName, write, config) {
|
||||
if (buildMap.hasOwnProperty(moduleName)) {
|
||||
var content = text.jsEscape(buildMap[moduleName]);
|
||||
write.asModule(pluginName + "!" + moduleName,
|
||||
"define(function () { return '" +
|
||||
content +
|
||||
"';});\n");
|
||||
}
|
||||
},
|
||||
|
||||
writeFile: function (pluginName, moduleName, req, write, config) {
|
||||
var parsed = text.parseName(moduleName),
|
||||
nonStripName = parsed.moduleName + '.' + parsed.ext,
|
||||
//Use a '.js' file name so that it indicates it is a
|
||||
//script that can be loaded across domains.
|
||||
fileName = req.toUrl(parsed.moduleName + '.' +
|
||||
parsed.ext) + '.js';
|
||||
|
||||
//Leverage own load() method to load plugin value, but only
|
||||
//write out values that do not have the strip argument,
|
||||
//to avoid any potential issues with ! in file names.
|
||||
text.load(nonStripName, req, function (value) {
|
||||
//Use own write() method to construct full module value.
|
||||
//But need to create shell that translates writeFile's
|
||||
//write() to the right interface.
|
||||
var textWrite = function (contents) {
|
||||
return write(fileName, contents);
|
||||
};
|
||||
textWrite.asModule = function (moduleName, contents) {
|
||||
return write.asModule(moduleName, fileName, contents);
|
||||
};
|
||||
|
||||
text.write(pluginName, nonStripName, textWrite, config);
|
||||
}, config);
|
||||
}
|
||||
};
|
||||
|
||||
if (masterConfig.env === 'node' || (!masterConfig.env &&
|
||||
typeof process !== "undefined" &&
|
||||
process.versions &&
|
||||
!!process.versions.node)) {
|
||||
//Using special require.nodeRequire, something added by r.js.
|
||||
fs = require.nodeRequire('fs');
|
||||
|
||||
text.get = function (url, callback) {
|
||||
var file = fs.readFileSync(url, 'utf8');
|
||||
//Remove BOM (Byte Mark Order) from utf8 files if it is there.
|
||||
if (file.indexOf('\uFEFF') === 0) {
|
||||
file = file.substring(1);
|
||||
}
|
||||
callback(file);
|
||||
};
|
||||
} else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
|
||||
text.createXhr())) {
|
||||
text.get = function (url, callback, errback) {
|
||||
var xhr = text.createXhr();
|
||||
xhr.open('GET', url, true);
|
||||
|
||||
//Allow overrides specified in config
|
||||
if (masterConfig.onXhr) {
|
||||
masterConfig.onXhr(xhr, url);
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function (evt) {
|
||||
var status, err;
|
||||
//Do not explicitly handle errors, those should be
|
||||
//visible via console output in the browser.
|
||||
if (xhr.readyState === 4) {
|
||||
status = xhr.status;
|
||||
if (status > 399 && status < 600) {
|
||||
//An http 4xx or 5xx error. Signal an error.
|
||||
err = new Error(url + ' HTTP status: ' + status);
|
||||
err.xhr = xhr;
|
||||
errback(err);
|
||||
} else {
|
||||
callback(xhr.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
};
|
||||
} else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
|
||||
typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
|
||||
//Why Java, why is this so awkward?
|
||||
text.get = function (url, callback) {
|
||||
var stringBuffer, line,
|
||||
encoding = "utf-8",
|
||||
file = new java.io.File(url),
|
||||
lineSeparator = java.lang.System.getProperty("line.separator"),
|
||||
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
|
||||
content = '';
|
||||
try {
|
||||
stringBuffer = new java.lang.StringBuffer();
|
||||
line = input.readLine();
|
||||
|
||||
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
||||
// http://www.unicode.org/faq/utf_bom.html
|
||||
|
||||
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
|
||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
|
||||
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
||||
// Eat the BOM, since we've already found the encoding on this file,
|
||||
// and we plan to concatenating this buffer with others; the BOM should
|
||||
// only appear at the top of a file.
|
||||
line = line.substring(1);
|
||||
}
|
||||
|
||||
stringBuffer.append(line);
|
||||
|
||||
while ((line = input.readLine()) !== null) {
|
||||
stringBuffer.append(lineSeparator);
|
||||
stringBuffer.append(line);
|
||||
}
|
||||
//Make sure we return a JavaScript string and not a Java string.
|
||||
content = String(stringBuffer.toString()); //String
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
callback(content);
|
||||
};
|
||||
}
|
||||
|
||||
return text;
|
||||
});
|
||||
-1246
File diff suppressed because it is too large
Load Diff
Vendored
-1884
File diff suppressed because it is too large
Load Diff
@@ -1,50 +1,50 @@
|
||||
define(
|
||||
['jquery',
|
||||
'backbone',
|
||||
'collections/list',
|
||||
'views/task'
|
||||
],
|
||||
['jquery',
|
||||
'backbone',
|
||||
'collections/list',
|
||||
'views/task',
|
||||
'text!../../templates/task.html',
|
||||
'marionette'
|
||||
],
|
||||
|
||||
function(
|
||||
$,
|
||||
Backbone,
|
||||
List,
|
||||
TaskView
|
||||
) {
|
||||
function (
|
||||
$,
|
||||
Backbone,
|
||||
List,
|
||||
TaskView,
|
||||
listTemplate,
|
||||
Marionette
|
||||
) {
|
||||
|
||||
var ListView = Backbone.View.extend({
|
||||
// renders recursive tree structure for each item in collection
|
||||
var ListView = Backbone.Marionette.CollectionView.extend({
|
||||
|
||||
el: $("#main .children"),
|
||||
el: $("#main .children"),
|
||||
childView: TaskView,
|
||||
viewComparator: List.prototype.comporator,
|
||||
template: _.template(listTemplate),
|
||||
|
||||
events: {
|
||||
'click #add': 'addTask'
|
||||
},
|
||||
events: {
|
||||
'click #add': 'addTask',
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
Tasks = this.collection = new List();
|
||||
this.collection.fetch();
|
||||
this.listenTo(this.collection, 'add', this.renderTask);
|
||||
},
|
||||
initialize: function () {
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.collection.each(function(task) {
|
||||
this.renderTask(task);
|
||||
}, this);
|
||||
},
|
||||
/** This is the root view in the tree **/
|
||||
getParentView: function () {
|
||||
return this;
|
||||
},
|
||||
|
||||
renderTask: function(task) {
|
||||
var taskView = new TaskView({
|
||||
model: task
|
||||
});
|
||||
var a = taskView.render();
|
||||
if (a.model.get('parent')!=0)
|
||||
a.$el.insertAfter($('*[data-id="'+a.model.get('parent')+'"]').parents('li:first'));
|
||||
else
|
||||
this.$el.append(a.el);
|
||||
}
|
||||
/** Update parentId when added to collection **/
|
||||
onAddChild: function(childView){
|
||||
var rootId = pageView.getRootId();
|
||||
if (childView.model.get('parentId')!=rootId && childView.model==rootId)
|
||||
childView.model.save({parentId: rootId});
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
return ListView;
|
||||
return ListView;
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,40 +1,136 @@
|
||||
define(
|
||||
['jquery',
|
||||
'backbone',
|
||||
'marionette',
|
||||
'views/list',
|
||||
'models/task'
|
||||
'text!data/demo.json',
|
||||
'models/task',
|
||||
'collections/list',
|
||||
'util/constants',
|
||||
],
|
||||
|
||||
function(
|
||||
$,
|
||||
Backbone,
|
||||
Marionette,
|
||||
ListView,
|
||||
Task
|
||||
demoData,
|
||||
Task,
|
||||
List,
|
||||
constants
|
||||
) {
|
||||
|
||||
var PageView = Backbone.View.extend({
|
||||
var PageView = Marionette.View.extend({
|
||||
|
||||
el: $("#main"),
|
||||
el: $("#hackflowy"),
|
||||
|
||||
events: {
|
||||
'keypress #newTask': 'createNewTask',
|
||||
'blur #newTask': 'createNewTask'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.listView = new ListView();
|
||||
this.input = $('#newTask');
|
||||
|
||||
// this wholeCollection holds all items
|
||||
this.collection = new List();
|
||||
|
||||
|
||||
function success(children, data, promise) {
|
||||
// load demo data if the server returns nothing
|
||||
var directChildren = children.filter(this.filterDirectChildren,this);
|
||||
if (directChildren.length === 0){
|
||||
for (var i = 0; i < demoData.length; i++) {
|
||||
var task = this.collection.add(demoData[i]);
|
||||
task.save();
|
||||
}
|
||||
}
|
||||
this.listView.collection.add(children.filter(this.filterDirectChildren,this));
|
||||
this.listView.render();
|
||||
this.updateBreadCrumbs();
|
||||
}
|
||||
|
||||
this.collection.fetch({
|
||||
success: success,
|
||||
error: function () {
|
||||
// switch to localforage database if server isn't present and fetch again
|
||||
// from there
|
||||
window.hackflowyOffline = true;
|
||||
this.$('#header-alerts').append('<div class="alert-box secondary round">Running in offline mode, data may be lost </div>');
|
||||
this.collection.fetch({
|
||||
success: success,
|
||||
context: this
|
||||
});
|
||||
},
|
||||
context: this
|
||||
});
|
||||
|
||||
var rootItems = new List(this.collection.filter(this.filterDirectChildren,this));
|
||||
this.listView = new ListView({collection: rootItems});
|
||||
|
||||
|
||||
// change root item when the url hash changes
|
||||
// HACK should ideally use http://stackoverflow.com/a/19114496/221742
|
||||
$(window).on("hashchange", this.changeRootId.bind(this));
|
||||
|
||||
// stop browser going back a page when jamming backspace
|
||||
$(window).on('keydown',function(e){if(e.keyIdentifier=='U+0008'||e.keyIdentifier=='Backspace'){if(e.target==document.body){e.preventDefault();}}});
|
||||
|
||||
|
||||
},
|
||||
|
||||
/** remove non backbone listener on delete **/
|
||||
onDestroy: function() {
|
||||
$(window).off("haschange",this.changeRootId);
|
||||
$(window).off('keydown',function(e){if(e.keyIdentifier=='U+0008'||e.keyIdentifier=='Backspace'){if(e.target==document.body){e.preventDefault();}}});
|
||||
},
|
||||
|
||||
/** Get root id for the displayed list from the url hash or 0 **/
|
||||
getRootId: function(){
|
||||
var hash = window.location.hash.slice(1);
|
||||
if (hash && pageView.collection.get(hash))
|
||||
return hash;
|
||||
else if (hash)
|
||||
window.location.hash='';
|
||||
return constants.ROOT_PARENT_ID;
|
||||
},
|
||||
|
||||
/** Called when window location hash changes **/
|
||||
changeRootId: function(){
|
||||
// change the listview children
|
||||
this.listView.collection.remove(this.collection.models);
|
||||
this.listView.collection.add(this.collection.filter(this.filterDirectChildren,this));
|
||||
this.updateBreadCrumbs();
|
||||
},
|
||||
|
||||
// Only show direct children
|
||||
filterDirectChildren: function (child, index, collection) {
|
||||
var rootId = this.getRootId();
|
||||
if (rootId === constants.ROOT_PARENT_ID)
|
||||
return child.get('parentId') === rootId;
|
||||
else
|
||||
return child.get('id') == rootId;
|
||||
},
|
||||
|
||||
updateBreadCrumbs: function(){
|
||||
var rootId = this.getRootId();
|
||||
this.$('#task-breadcrumbs').empty();
|
||||
if (rootId!==constants.ROOT_PARENT_ID){
|
||||
var current = this.collection.get(rootId);
|
||||
var breadCrumbs = '';//_.template('<a href="#<%= id %>"><%= content %></a>')(current.attributes);
|
||||
var depth=0;
|
||||
while (current && current.get('parentId') && depth<100){
|
||||
depth++;
|
||||
current = this.collection.get(current.get('parentId'));
|
||||
if (current)
|
||||
breadCrumbs=_.template('<a href="#<%= id %>"><%= content %></a> > ')(current.attributes)+breadCrumbs;
|
||||
}
|
||||
if (depth>=100) console.error('Max depth exceeded while making breadCrumbs');
|
||||
breadCrumbs='<a href="#">Home</a> > '+breadCrumbs;
|
||||
this.$('#task-breadcrumbs').append(breadCrumbs);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
createNewTask: function(e) {
|
||||
if (e.keyCode != 13) return;
|
||||
if (!this.input.val().trim()) return;
|
||||
this.listView.collection.add(new Task({content: this.input.val().trim() }));
|
||||
this.input.val('');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return PageView;
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
+269
-133
@@ -1,154 +1,290 @@
|
||||
define(
|
||||
['jquery',
|
||||
'backbone',
|
||||
'socket',
|
||||
'util/constants',
|
||||
'text!../../templates/task.html'
|
||||
],
|
||||
['jquery',
|
||||
'backbone',
|
||||
'socket',
|
||||
'collections/list',
|
||||
'util/constants',
|
||||
'text!../../templates/task.html',
|
||||
'marionette'
|
||||
],
|
||||
|
||||
function(
|
||||
$,
|
||||
Backbone,
|
||||
socket,
|
||||
constants,
|
||||
taskTemplate
|
||||
) {
|
||||
function (
|
||||
$,
|
||||
Backbone,
|
||||
io,
|
||||
List,
|
||||
constants,
|
||||
taskTemplate,
|
||||
Marionette
|
||||
) {
|
||||
// The recursive tree view. Ref:http://jsfiddle.net/wassname/zf61mLvh/2/
|
||||
var TaskView = Backbone.Marionette.CompositeView.extend({
|
||||
|
||||
var TaskView = Backbone.View.extend({
|
||||
template: _.template(taskTemplate),
|
||||
tagName: 'ul',
|
||||
className: "task-view",
|
||||
viewComparator: List.prototype.comporator,
|
||||
childView: TaskView,
|
||||
childViewContainer: '.children',
|
||||
childViewOptions: {
|
||||
reorderOnSort: true
|
||||
},
|
||||
|
||||
tagName: 'li',
|
||||
template: taskTemplate,
|
||||
ui: {
|
||||
input: '.task input:first',
|
||||
options: '.task .options:first',
|
||||
// ui elements are bound before child render
|
||||
// so the below child hashes are only available because
|
||||
// render:collection triggers this.bindUIElements
|
||||
children: '.children>ul',
|
||||
descendants: '.children ul',
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .task': 'edit',
|
||||
'blur .edit': 'close',
|
||||
'keyup .edit': 'handleKeyup',
|
||||
'keypress .edit': 'update',
|
||||
'mouseover .link':'showOptions',
|
||||
'mouseout .link':'hideOptions',
|
||||
'click .complete':'markComplete',
|
||||
'click .uncomplete':'unmarkComlete',
|
||||
'click .note':'addNote'
|
||||
},
|
||||
events: {
|
||||
'click .task:first': 'edit',
|
||||
'blur .edit:first': 'close',
|
||||
'keyup .edit:first': 'handleKeyUp',
|
||||
'keydown .edit:first': 'handleKeyDown',
|
||||
'keypress .edit:first': 'handleKeyPress',
|
||||
'mouseover .link:first': 'showOptions',
|
||||
'mouseout .link:first': 'hideOptions',
|
||||
'click .complete:first': 'markComplete',
|
||||
'click .uncomplete:first': 'unmarkComlete',
|
||||
'click .note:first': 'addNote',
|
||||
'click .fold-button:first': 'foldChildren',
|
||||
'click .fold:first': 'foldChildren',
|
||||
// TODO make this destroy children too
|
||||
'click .destroy:first': 'destroy',
|
||||
// custom events
|
||||
'focus': 'this.model.focusOnView',
|
||||
|
||||
initialize: function() {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.listenTo(this.model, 'destroy', this.remove);
|
||||
this.socket = io.connect();
|
||||
var task = this;
|
||||
this.socket.on('task', function(data){
|
||||
if (task.model.id == data.id) {
|
||||
task.model.set({'content':data.content, 'isCompleted':data.isCompleted});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var tmpl = _.template(this.template);
|
||||
var task = this;
|
||||
this.$el.html(tmpl({model:this.model.toJSON()}));
|
||||
if (this.model.get('parentId')!=0) {
|
||||
this.$el.addClass('shift1');
|
||||
var className = $('*[data-id="'+this.model.get('parentId')+'"]').parents('li:first').attr('class');
|
||||
if (className!=undefined && className!=0 && className.substring(0,5) == 'shift') {
|
||||
this.$el.removeClass();
|
||||
this.$el.addClass('shift' + (parseInt(className.charAt(5))+1));
|
||||
}
|
||||
}
|
||||
this.$input = this.$('.edit:first');
|
||||
collectionEvents: {
|
||||
},
|
||||
|
||||
return this;
|
||||
},
|
||||
childEvents: {},
|
||||
|
||||
edit: function() {
|
||||
this.$el.addClass('editing');
|
||||
this.$input.focus();
|
||||
},
|
||||
initialize: function (options) {
|
||||
var task = this;
|
||||
|
||||
handleKeyup: function(e) {
|
||||
if (e.keyCode == 40)
|
||||
this.$el.next('li').find('input').focus();
|
||||
else if (e.keyCode == 38)
|
||||
this.$el.prev('li').find('input').focus();
|
||||
// backlink
|
||||
this.model.view = this;
|
||||
|
||||
if (e.shiftKey && e.keyCode == 9) {
|
||||
var model = this.$el.next('li').find('input').data('id');
|
||||
model = Tasks.get(model);
|
||||
var old_parent = model.get('parentId');
|
||||
old_parent = Tasks.get(old_parent);
|
||||
var new_parent = old_parent.get('parentId');
|
||||
if (new_parent == null) new_parent = 0;
|
||||
model.set('parentId',new_parent);
|
||||
model.save({content: model.get('content'), parentId: model.get('parentId')});
|
||||
}
|
||||
else if (e.keyCode == 9) {
|
||||
var parent = this.$el.prev('li').prev('li').find('input').data('id');
|
||||
var current = this.$el.prev('li').find('input').data('id');
|
||||
var model = Tasks.get(current);
|
||||
model.set('parentId',parent);
|
||||
model.save({content: model.get('content'), parentId: model.get('parentId')});
|
||||
}
|
||||
this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
content: this.$input.val().trim(),
|
||||
isCompleted:this.model.toJSON().isCompleted
|
||||
});
|
||||
},
|
||||
// get only direct children from all tasks in pageView.collection
|
||||
var children = pageView.collection.filter(
|
||||
function (child, index, collection) {
|
||||
return child.get('parentId') === this.model.id;
|
||||
}, this);
|
||||
this.collection = new List(children);
|
||||
|
||||
update: function(e) {
|
||||
if ( e.which === constants.ENTER_KEY ) {
|
||||
Tasks.add({content:'', parentId: this.model.get('parentId')});
|
||||
this.$input.blur();
|
||||
this.$el.next('li').find('input').focus();
|
||||
}
|
||||
},
|
||||
// there is probobly a better way to do this
|
||||
if (this.isEmpty()){
|
||||
this.$el.addClass('empty');
|
||||
}
|
||||
|
||||
close: function() {
|
||||
var value = this.$input.val().trim();
|
||||
if (value === '') {
|
||||
this.model.destroy();
|
||||
}
|
||||
else {
|
||||
this.model.save({content: value, parentId: this.model.attributes.parentId});
|
||||
}
|
||||
this.$el.removeClass('editing');
|
||||
},
|
||||
// events
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.listenTo(this.model, 'destroy', this.remove);
|
||||
// refresh ui hashes after children are rendered
|
||||
this.listenTo(this, 'render:collection', this.bindUIElements);
|
||||
// custom event
|
||||
this.listenTo(this, 'focus', this.model.focusOnView);
|
||||
|
||||
showOptions:function(){
|
||||
this.$el.find('.options').show();
|
||||
},
|
||||
// updates from server
|
||||
if (!window.hackflowyOffline) {
|
||||
this.socket = io.connect();
|
||||
this.socket.on('task', function (data) {
|
||||
if (task.model.id == data.id) {
|
||||
task.model.set({
|
||||
'content': data.content,
|
||||
'isCompleted': data.isCompleted
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
hideOptions:function(){
|
||||
this.$el.find('.options').hide();
|
||||
},
|
||||
},
|
||||
|
||||
markComplete:function(){
|
||||
this.model.toggelCompletedStatus(true);
|
||||
this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
content:this.model.toJSON().content,
|
||||
isCompleted: this.model.toJSON().isCompleted
|
||||
});
|
||||
},
|
||||
// override marionette filter to filter displayed children
|
||||
// filterDirectChildren: function (child, index, collection) {
|
||||
// return child.get('parentId') === this.model.get('id');
|
||||
// },
|
||||
|
||||
unmarkComlete:function(){
|
||||
this.model.toggelCompletedStatus(false);
|
||||
this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
content:this.model.toJSON().content,
|
||||
isCompleted: this.model.toJSON().isCompleted
|
||||
});
|
||||
},
|
||||
edit: function () {
|
||||
this.$el.addClass('editing');
|
||||
this.$('.edit:first').focus();
|
||||
},
|
||||
|
||||
addNote:function(){
|
||||
this.$el.find('.divNote').show();
|
||||
}
|
||||
/** Get the parent view or root view **/
|
||||
getParentView: function () {
|
||||
var parent = pageView.collection.get(this.model.get('parentId'));
|
||||
if (parent) return parent.view;
|
||||
else return pageView.listView;
|
||||
},
|
||||
|
||||
});
|
||||
/** Update parentId when added to collection **/
|
||||
onAddChild: function(childView){
|
||||
if (childView.model.get('parentId')!==this.model.id)
|
||||
childView.model.save({parentId: this.model.id});
|
||||
},
|
||||
|
||||
return TaskView;
|
||||
/** Focus on the next visible element down despite list level **/
|
||||
focusOnPrev: function () {
|
||||
var all = pageView.listView.$el.find('ul:visible');
|
||||
var prev = $(all[all.index(this.$el) - 1]);
|
||||
if (prev.length){
|
||||
prev.find('input:first').focus();
|
||||
}
|
||||
return prev;
|
||||
},
|
||||
|
||||
});
|
||||
focusOnNext: function () {
|
||||
var all = pageView.listView.$el.find('ul:visible');
|
||||
var next = $(all[all.index(this.$el) + 1]);
|
||||
if (next)
|
||||
next.find('input:first').focus();
|
||||
return next;
|
||||
},
|
||||
|
||||
handleKeyUp: function(e){
|
||||
},
|
||||
|
||||
handleKeyPress: function(e){
|
||||
},
|
||||
|
||||
handleKeyDown: function (e) {
|
||||
if (e.keyCode == constants.BACKSPACE) {
|
||||
// remove if backspace pressed on empty/soon-to-be-empty item
|
||||
if (this.ui.input.val().length < 2 && this.$('.children>ul').length===0) {
|
||||
e.preventDefault();
|
||||
prev = this.focusOnPrev();
|
||||
this.model.destroy();
|
||||
this.destroy();
|
||||
// set the cursor to the end of the previous input
|
||||
prev.find('input:first').focus();
|
||||
var input = prev.find('input:first')[0];
|
||||
input.selectionStart = input.selectionEnd = input.value.length;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (e.keyCode === constants.ENTER_KEY)
|
||||
this.addNote(e.currentTarget);
|
||||
else if (e.ctrlKey && e.keyCode == constants.DOWN_ARROW) {
|
||||
// move down list by swapping priority with next sibling
|
||||
e.preventDefault();
|
||||
this.getParentView().collection.moveDown(this.model);
|
||||
this.model.focusOnView();
|
||||
} else if (e.ctrlKey && e.keyCode == constants.UP_ARROW) {
|
||||
// move up the list
|
||||
e.preventDefault();
|
||||
this.getParentView().collection.moveUp(this.model);
|
||||
this.model.focusOnView();
|
||||
} else if (e.keyCode == constants.DOWN_ARROW) {
|
||||
this.focusOnNext();
|
||||
} else if (e.keyCode == constants.UP_ARROW) {
|
||||
this.focusOnPrev();
|
||||
} else if (e.shiftKey && e.keyCode == constants.TAB) {
|
||||
// indent one less, by changing parent
|
||||
e.preventDefault();
|
||||
var parentId = this.$el.parents('ul:first').find('input:first').data('id');
|
||||
if (parentId===0){
|
||||
|
||||
} else if (parentId){
|
||||
parentModel = pageView.collection.get(parentId);
|
||||
this.getParentView().collection.remove(this.model);
|
||||
var index = parentModel.view.getParentView().collection.indexOf(parentModel);
|
||||
if (index<0) index=this.getParentView().collection.length-1;
|
||||
parentModel.view.getParentView().collection.add(this.model, {at:index+1});
|
||||
this.model.focusOnView();
|
||||
} else {
|
||||
console.warn("Can't untab any further");
|
||||
}
|
||||
} else if (e.keyCode == constants.TAB) {
|
||||
// indent one more, by changing parent
|
||||
e.preventDefault();
|
||||
var prevSibling = this.$el.prev('ul');
|
||||
if (prevSibling.length) {
|
||||
var prevSibId = prevSibling.find('input:first').data('id');
|
||||
var prevSibView =pageView.collection.get(prevSibId).view;
|
||||
this.getParentView().collection.remove(this.model);
|
||||
prevSibView.collection.add(this.model);
|
||||
this.model.focusOnView();
|
||||
} else {
|
||||
console.warn("Can't tab any further");
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.hackflowyOffline) {
|
||||
this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
content: this.$('.edit:first').val().trim(),
|
||||
isCompleted: this.model.toJSON().isCompleted
|
||||
});
|
||||
} else {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
/** Finish editing an item **/
|
||||
close: function () {
|
||||
var value = this.$('.edit:first').val().trim();
|
||||
if (this.model.get('content')!=value)
|
||||
this.model.save({content: value});
|
||||
this.$el.removeClass('editing');
|
||||
},
|
||||
|
||||
showOptions: function () {
|
||||
this.ui.options.show();
|
||||
},
|
||||
|
||||
hideOptions: function () {
|
||||
this.ui.options.hide();
|
||||
},
|
||||
|
||||
markComplete: function () {
|
||||
this.model.toggelCompletedStatus(true);
|
||||
if (!window.hackflowyOffline) this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
content: this.model.toJSON().content,
|
||||
isCompleted: this.model.toJSON().isCompleted
|
||||
});
|
||||
},
|
||||
|
||||
unmarkComlete: function () {
|
||||
this.model.toggelCompletedStatus(false);
|
||||
if (!window.hackflowyOffline) this.socket.emit('task', {
|
||||
id: this.model.id,
|
||||
parentId: this.model.parentId,
|
||||
content: this.model.toJSON().content,
|
||||
isCompleted: this.model.toJSON().isCompleted
|
||||
});
|
||||
},
|
||||
|
||||
/** Add a new blank note below this **/
|
||||
addNote: function () {
|
||||
// var currentId = this.ui.input.data('id') || 0;
|
||||
parentId = this.ui.input.data('parent-id');
|
||||
var index= this.getParentView().collection.indexOf(this.model);
|
||||
var task = pageView.collection.add({parentId: this.model.get('parentId')});
|
||||
task.save();
|
||||
if (index>=0)
|
||||
this.getParentView().collection.add(task, {at:index+1});
|
||||
else
|
||||
this.getParentView().collection.add(task);
|
||||
this.$('input:first').blur();
|
||||
task.focusOnView();
|
||||
},
|
||||
|
||||
/** Fold children of the clicked element */
|
||||
foldChildren: function () {
|
||||
var folded = this.$el.find('li:first').hasClass('folded');
|
||||
this.model.save({isFolded: !folded});
|
||||
},
|
||||
});
|
||||
|
||||
return TaskView;
|
||||
|
||||
});
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>HackFlowy</title>
|
||||
|
||||
<link rel="stylesheet" href="stylesheets/normalize.css" />
|
||||
|
||||
<link rel="stylesheet" href="stylesheets/app.css" />
|
||||
|
||||
|
||||
<script src="javascripts/vendor/custom.modernizr.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="row">
|
||||
<div class="large-12 columns">
|
||||
<section id="hackflowy">
|
||||
<header id="header">
|
||||
|
||||
</header>
|
||||
<section id="main">
|
||||
<div id="name">
|
||||
<h2>test</h2>
|
||||
</div>
|
||||
<div class="children">
|
||||
<div class="task">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Task 1</div>
|
||||
</div>
|
||||
<div class="task with-children open">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Task 2</div>
|
||||
<div class="children">
|
||||
<div class="task with-children open">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Child 1 Task 2</div>
|
||||
<div class="children">
|
||||
<div class="task">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Subchild 1 Child 1 Task 2</div>
|
||||
</div>
|
||||
<div class="task with-children open">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Subchild 2 Child 1 Task 2</div>
|
||||
<div class="children">
|
||||
<div class="task">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Subsubchild 1 Subchild 2 Child 1 Task 2 asbdkjas dkjas bdajsbd kajsdb jasbd kajsb dajskbd akjsb dkjab</div>
|
||||
</div>
|
||||
<div class="task">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Subsubchild 2 Subchild 2 Child 1 Task 2</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Child 1 Task 3</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task">
|
||||
<div class="link">•</div>
|
||||
<div class="content">Task 3</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<footer id="footer">
|
||||
Make Lists. Catch Fish. <3 Open Source.
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/template" id="item-template">
|
||||
|
||||
</script>
|
||||
<script>
|
||||
document.write('<script src=' +
|
||||
('__proto__' in {} ? 'javascripts/vendor/zepto' : 'javascripts/vendor/jquery') +
|
||||
'.js><\/script>')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -53,12 +53,12 @@ body {
|
||||
background-color: $lightgrey;
|
||||
#hackflowy {
|
||||
background-color: white;
|
||||
height: 1000px;
|
||||
min-height: 1000px;
|
||||
margin: 75px 100px;
|
||||
box-shadow: 0px 0px 10px 5px #ccc;
|
||||
padding: 60px 60px;
|
||||
#main {
|
||||
height: 880px;
|
||||
min-height: 880px;
|
||||
border-top: 1px solid #eee;
|
||||
border-bottom: 1px solid #eee;
|
||||
#name {
|
||||
@@ -162,6 +162,9 @@ body {
|
||||
li.shift9 {
|
||||
margin-left: 270px;
|
||||
}
|
||||
ul.shift {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
#main > .children {
|
||||
|
||||
+123
-62
@@ -5543,14 +5543,14 @@ body {
|
||||
/* line 54, ../sass/app.scss */
|
||||
body #hackflowy {
|
||||
background-color: white;
|
||||
height: 1000px;
|
||||
min-height: 1000px;
|
||||
margin: 75px 100px;
|
||||
box-shadow: 0px 0px 10px 5px #cccccc;
|
||||
padding: 60px 60px;
|
||||
}
|
||||
/* line 60, ../sass/app.scss */
|
||||
body #hackflowy #main {
|
||||
height: 880px;
|
||||
min-height: 880px;
|
||||
border-top: 1px solid #eeeeee;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
}
|
||||
@@ -5603,12 +5603,20 @@ body #hackflowy #main .children li .task .with-children > .link {
|
||||
body #hackflowy #main .children li .task .open > .link {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/* Show that this item has folded contents */
|
||||
body #hackflowy #main .children li.folded .task .link {
|
||||
z-index: 7;
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
/* line 105, ../sass/app.scss */
|
||||
body #hackflowy #main .children li .task .link:hover {
|
||||
cursor: pointer;
|
||||
z-index: 8;
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
/* line 110, ../sass/app.scss */
|
||||
body #hackflowy #main .children li .task input.edit {
|
||||
box-shadow: none;
|
||||
@@ -5684,53 +5692,58 @@ body #hackflowy #footer {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
body #hackflowy #main .children ul.task-view {
|
||||
margin-bottom: 0px;
|
||||
margin-left: 0px;
|
||||
|
||||
}
|
||||
.options-div{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.options{
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
color: rgb(51, 51, 51);
|
||||
cursor: auto;
|
||||
display: none;
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
height: 0px;
|
||||
line-height: 16px;
|
||||
width: 675px;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
color: rgb(51, 51, 51);
|
||||
cursor: auto;
|
||||
display: none;
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
height: 0px;
|
||||
line-height: 16px;
|
||||
width: 675px;
|
||||
}
|
||||
|
||||
.options a {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.options-left {
|
||||
background: #ddd;
|
||||
border: 1px solid #bbb;
|
||||
width: 80px;
|
||||
height: 58px;
|
||||
padding: 10px 0 5px 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Helvetica Neue', Arial, Sans-serif;
|
||||
z-index: 8;
|
||||
margin-top: 8px;
|
||||
margin-left: -29px;
|
||||
background: #ddd;
|
||||
border: 1px solid #bbb;
|
||||
width: 80px;
|
||||
min-height: 58px;
|
||||
padding: 10px 0 5px 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Helvetica Neue', Arial, Sans-serif;
|
||||
z-index: 8;
|
||||
margin-top: 16px;
|
||||
margin-left: -29px;
|
||||
}
|
||||
|
||||
|
||||
.options-left a {
|
||||
color: #555;
|
||||
margin-bottom: 5px;
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
width: auto;
|
||||
color: #555;
|
||||
margin-bottom: 5px;
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.options-left a:hover {
|
||||
@@ -5738,41 +5751,89 @@ width: auto;
|
||||
}
|
||||
|
||||
.options-left > .mouse-tip {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 25px;
|
||||
width: 90px;
|
||||
margin-top: -36px;
|
||||
margin-left: -1%;
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 25px;
|
||||
width: 90px;
|
||||
margin-top: -36px;
|
||||
margin-left: -1%;
|
||||
}
|
||||
|
||||
.options-left > .mouse-tip:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 19%;
|
||||
margin-left: -15px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-bottom: 15px solid #ddd;
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 19%;
|
||||
margin-left: -15px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-bottom: 15px solid #ddd;
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
}
|
||||
|
||||
.mouse-tip:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
margin-left: -15px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-bottom: 15px solid #ddd;
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
margin-left: -15px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-bottom: 15px solid #ddd;
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
}
|
||||
|
||||
.options-left > .fold-button {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
/*height: 25px;*/
|
||||
/*width: 90px;*/
|
||||
margin-top: -45px;
|
||||
margin-left: -3%;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.options-left > .fold-button:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* By default show fold button */
|
||||
.options-left>.fold-button:before {
|
||||
content: "-";
|
||||
}
|
||||
/* no fold button on empty nodes */
|
||||
.empty .options-left:first-child > .fold-button:before {
|
||||
content: '';
|
||||
}
|
||||
/* expand button on folded nodes */
|
||||
.folded .options-left:first-child>.fold-button:before {
|
||||
content: "+";
|
||||
}
|
||||
|
||||
.folded.children {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.task-completed{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.subtle-link {
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
.subtle-link:hover {
|
||||
color: rgb(51, 51, 51);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#task-breadcrumbs {
|
||||
font-size: smaller;
|
||||
}
|
||||
#task-breadcrumbs a {
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
#task-breadcrumbs a:hover {
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
Vendored
-405
@@ -1,405 +0,0 @@
|
||||
/* normalize.css v2.1.0 | MIT License | git.io/normalize */
|
||||
/* ==========================================================================
|
||||
HTML5 display definitions
|
||||
========================================================================== */
|
||||
/**
|
||||
* Correct `block` display not defined in IE 8/9.
|
||||
*/
|
||||
/* line 22, ../sass/normalize.scss */
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct `inline-block` display not defined in IE 8/9.
|
||||
*/
|
||||
/* line 32, ../sass/normalize.scss */
|
||||
audio,
|
||||
canvas,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
/* line 41, ../sass/normalize.scss */
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
/* line 50, ../sass/normalize.scss */
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Base
|
||||
========================================================================== */
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
/* line 64, ../sass/normalize.scss */
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
/* 1 */
|
||||
-webkit-text-size-adjust: 100%;
|
||||
/* 2 */
|
||||
-ms-text-size-adjust: 100%;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
/* line 74, ../sass/normalize.scss */
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Links
|
||||
========================================================================== */
|
||||
/**
|
||||
* Address `outline` inconsistency between Chrome and other browsers.
|
||||
*/
|
||||
/* line 86, ../sass/normalize.scss */
|
||||
a:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
/* line 95, ../sass/normalize.scss */
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Typography
|
||||
========================================================================== */
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
/* line 108, ../sass/normalize.scss */
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9, Safari 5, and Chrome.
|
||||
*/
|
||||
/* line 117, ../sass/normalize.scss */
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
/* line 126, ../sass/normalize.scss */
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari 5 and Chrome.
|
||||
*/
|
||||
/* line 134, ../sass/normalize.scss */
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
/* line 142, ../sass/normalize.scss */
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
/* line 152, ../sass/normalize.scss */
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct font family set oddly in Safari 5 and Chrome.
|
||||
*/
|
||||
/* line 164, ../sass/normalize.scss */
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability of pre-formatted text in all browsers.
|
||||
*/
|
||||
/* line 173, ../sass/normalize.scss */
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set consistent quote types.
|
||||
*/
|
||||
/* line 181, ../sass/normalize.scss */
|
||||
q {
|
||||
quotes: "\201C" "\201D" "\2018" "\2019";
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
/* line 189, ../sass/normalize.scss */
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
/* line 198, ../sass/normalize.scss */
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* line 205, ../sass/normalize.scss */
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* line 209, ../sass/normalize.scss */
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Embedded content
|
||||
========================================================================== */
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9.
|
||||
*/
|
||||
/* line 221, ../sass/normalize.scss */
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow displayed oddly in IE 9.
|
||||
*/
|
||||
/* line 229, ../sass/normalize.scss */
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Figures
|
||||
========================================================================== */
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari 5.
|
||||
*/
|
||||
/* line 241, ../sass/normalize.scss */
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Forms
|
||||
========================================================================== */
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
/* line 253, ../sass/normalize.scss */
|
||||
fieldset {
|
||||
border: 1px solid silver;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
/* line 264, ../sass/normalize.scss */
|
||||
legend {
|
||||
border: 0;
|
||||
/* 1 */
|
||||
padding: 0;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct font family not being inherited in all browsers.
|
||||
* 2. Correct font size not being inherited in all browsers.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
/* line 278, ../sass/normalize.scss */
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
/* 1 */
|
||||
font-size: 100%;
|
||||
/* 2 */
|
||||
margin: 0;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
/* line 290, ../sass/normalize.scss */
|
||||
button,
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
|
||||
* Correct `select` style inheritance in Firefox 4+ and Opera.
|
||||
*/
|
||||
/* line 302, ../sass/normalize.scss */
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
/* line 317, ../sass/normalize.scss */
|
||||
button,
|
||||
html input[type="button"],
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
/* 2 */
|
||||
cursor: pointer;
|
||||
/* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
/* line 327, ../sass/normalize.scss */
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9.
|
||||
* 2. Remove excess padding in IE 8/9.
|
||||
*/
|
||||
/* line 337, ../sass/normalize.scss */
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box;
|
||||
/* 1 */
|
||||
padding: 0;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
/* line 348, ../sass/normalize.scss */
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
/* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari 5 and Chrome
|
||||
* on OS X.
|
||||
*/
|
||||
/* line 361, ../sass/normalize.scss */
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
/* line 370, ../sass/normalize.scss */
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove default vertical scrollbar in IE 8/9.
|
||||
* 2. Improve readability and alignment in all browsers.
|
||||
*/
|
||||
/* line 380, ../sass/normalize.scss */
|
||||
textarea {
|
||||
overflow: auto;
|
||||
/* 1 */
|
||||
vertical-align: top;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables
|
||||
========================================================================== */
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
/* line 393, ../sass/normalize.scss */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<li><%= nodeName %></li>
|
||||
+39
-23
@@ -1,25 +1,41 @@
|
||||
<div class="task-wrappper">
|
||||
<div class="task">
|
||||
<div class="link">•
|
||||
<div class="options">
|
||||
<div class="options-left">
|
||||
<div class="mouse-tip"></div>
|
||||
<% if(model.isCompleted){%>
|
||||
<a class="uncomplete">Uncomplete<hr></a>
|
||||
<%}else {%>
|
||||
<a class="complete">Complete<hr></a>
|
||||
<%}%>
|
||||
<a class="note">
|
||||
<span class="note">Add Note</span>
|
||||
</a>
|
||||
<% if (obj.isFolded){ %>
|
||||
<li class="folded">
|
||||
<% } else { %>
|
||||
<li class="">
|
||||
<% } %>
|
||||
<div class="task-wrappper">
|
||||
<div class="task">
|
||||
<div class="link">•
|
||||
<div class="options">
|
||||
<div class="options-left">
|
||||
<a class="fold-button" title="Expand/collapse children"></a>
|
||||
<a class="mouse-tip" href="#<%= obj.id %>"></a>
|
||||
<% if(isCompleted){ %>
|
||||
<a class="uncomplete">Uncomplete<hr></a>
|
||||
<% }else { %>
|
||||
<a class="complete">Complete<hr></a>
|
||||
<% } %>
|
||||
<a class="fold">Fold<hr></a>
|
||||
<a class="destroy">Delete<hr></a>
|
||||
<a class="note">
|
||||
<span class="note">Add Note</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if(isCompleted) { %>
|
||||
<input value="<%= obj.content %>" data-id="<%= obj.id %>" data-parent-id="<%= parentId %>" data-priority="<%= priority %>" class="edit task-completed">
|
||||
<% }else { %>
|
||||
<input value="<%= obj.content %>" data-id="<%= obj.id %>" data-parent-id="<%= parentId %>" data-priority="<%= priority %>" class="edit">
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if(model.isCompleted){%>
|
||||
<input value="<%= model.content %>" data-id="<%= model.id %>" class="edit task-completed">
|
||||
<%}else {%>
|
||||
<input value="<%= model.content %>" data-id="<%= model.id %>" class="edit">
|
||||
<%}%>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<% if (isFolded){ %>
|
||||
<div class="children folded">
|
||||
<% } else { %>
|
||||
<div class="children">
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
@@ -1,64 +1,101 @@
|
||||
var application_root = __dirname,
|
||||
express = require('express'),
|
||||
app = express(),
|
||||
path = require('path'),
|
||||
config = require('config'),
|
||||
orm = require('./orm').configure(config.get('database')),
|
||||
Tasks = require('./db/models/task').instance(orm),
|
||||
server = require('http').createServer(app),
|
||||
io = require('socket.io').listen(server);
|
||||
express = require('express'),
|
||||
app = express(),
|
||||
path = require('path'),
|
||||
config = require('config'),
|
||||
orm = require('./orm').configure(config.get('database')),
|
||||
Tasks = require('./db/models/task').instance(orm),
|
||||
server = require('http').createServer(app),
|
||||
socket = require('socket.io'),
|
||||
bodyParser = require('body-parser'),
|
||||
methodOverride = require('method-override'),
|
||||
errorhandler = require('errorhandler');
|
||||
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
|
||||
// override with the X-HTTP-Method-Override header in the request
|
||||
app.use(methodOverride('X-HTTP-Method-Override'));
|
||||
|
||||
app.use(express.static(path.join(application_root, 'public')));
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// only use in development
|
||||
app.use(errorHandler({
|
||||
dumpExceptions: true,
|
||||
showStack: true
|
||||
}));
|
||||
}
|
||||
|
||||
app.configure(function() {
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.methodOverride());
|
||||
app.use(app.router);
|
||||
app.use(express.static( path.join( application_root, 'public')));
|
||||
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
|
||||
});
|
||||
|
||||
var port = process.env.PORT || config.get('port');
|
||||
server.listen(port, function() {
|
||||
console.log( 'Express server listening on port %d in %s mode', port, app.settings.env );
|
||||
server.listen(port, function () {
|
||||
console.log('Express server listening on port %d in %s mode', port, app.settings.env);
|
||||
});
|
||||
var io = socket.listen(server);
|
||||
|
||||
app.get('/tasks', function(req,res){
|
||||
Tasks.all().success(function(tasks){
|
||||
res.send(tasks);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/tasks', function(req,res){
|
||||
Tasks.create({
|
||||
content: req.body.content,
|
||||
parent: parseInt(req.body.parent) || 0,
|
||||
isCompleted: false
|
||||
}).success(function(task){
|
||||
res.send(task);
|
||||
});
|
||||
});
|
||||
|
||||
app.put('/tasks/:id', function(req,res){
|
||||
console.log(req.body.isCompleted);
|
||||
Tasks.find(req.params.id).success(function(task){
|
||||
task.content = req.body.content;
|
||||
task.parent = parseInt(req.body.parent) || 0,
|
||||
task.isCompleted = req.body.isCompleted == 1;
|
||||
task.save().success(function(task){
|
||||
res.send(task);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
app.delete('/tasks/:id', function(req,res){
|
||||
Tasks.find(req.params.id).success(function(task){
|
||||
task.destroy().success(function(){
|
||||
res.send('');
|
||||
app.get('/tasks', function (req, res) {
|
||||
Tasks.all().then(function (tasks) {
|
||||
res.send(tasks);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/tasks', function (req, res) {
|
||||
console.log({view: "post('/tasks/:id)", id:req.params.id, body:req.body});
|
||||
Tasks.create({
|
||||
content: req.body.content,
|
||||
parentId: req.body.parentId || '00000000-0000-0000-0000-000000000000',
|
||||
isCompleted: false
|
||||
}).then(function (task) {
|
||||
res.send(task);
|
||||
});
|
||||
});
|
||||
|
||||
app.put('/tasks', function (req, res) {
|
||||
console.log({view: "put('/tasks/:id)", id:req.params.id, body:req.body});
|
||||
Tasks.create({
|
||||
content: req.body.content,
|
||||
parentId: req.body.parentId || '00000000-0000-0000-0000-000000000000',
|
||||
isCompleted: false
|
||||
}).then(function (task) {
|
||||
res.send(task);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/tasks/:id', function (req, res) {
|
||||
console.log({view: "get('/tasks/:id)", id:req.params.id, body:req.body});
|
||||
Tasks.findById(req.params.id).then(function (task) {
|
||||
res.send(task);
|
||||
});
|
||||
});
|
||||
|
||||
app.put('/tasks/:id', function (req, res) {
|
||||
console.log({view: "put('/tasks/:id)", id:req.params.id, body:req.body});
|
||||
Tasks.findById(req.params.id).then(function (task) {
|
||||
task.content = req.body.content;
|
||||
task.priority = req.body.priority;
|
||||
task.parentId = req.body.parentId || '00000000-0000-0000-0000-000000000000';
|
||||
task.isFolded = req.body.isFolded == true;
|
||||
task.isCompleted = req.body.isCompleted == true;
|
||||
task.save().then(function (task) {
|
||||
res.send(task);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.delete('/tasks/:id', function (req, res) {
|
||||
console.log({view: "delete('/tasks/:id)", id:req.params.id, body:req.body});
|
||||
console.log({isCompleted: req.body.isCompleted});
|
||||
Tasks.findById(req.params.id).then(function (task) {
|
||||
task.destroy().then(function () {
|
||||
res.send('');
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
socket.on('task', function (data) {
|
||||
socket.broadcast.emit('task', data);
|
||||
});
|
||||
socket.on('task', function (data) {
|
||||
socket.broadcast.emit('task', data);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user