Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

partially setup client interaction #9

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
27 changes: 27 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "express-todo-app",
"version": "1.0.0",
"description": "**Objective:** Use Express to make a RESTful API for a to do list. Build a client for your app that uses AJAX and Handlebars templating to `CREATE`, `READ`, `UPDATE`, and `DELETE` todos.",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mrockway/express-todo-app.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/mrockway/express-todo-app/issues"
},
"homepage": "https://github.com/mrockway/express-todo-app#readme",
"dependencies": {
"body-parser": "^1.14.1",
"express": "^4.13.3",
"hbs": "^4.0.0",
"mongo": "^0.1.0",
"mongoose": "^4.2.5"
}
}
92 changes: 92 additions & 0 deletions public/scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
console.log("10-4 little buddy");

//set up variable for data
// handlebars template and source

var source = $('#task-template').html();
var template = Handlebars.compile(source);

var allTasks = [];

$('.todoEdit').hide();

//refresh book list on page
var render = function() {
$('.todoList').empty();
var todoHtml = template({data : allTasks});
$('.todoList').append(todoHtml);
};

//get request, put books on the page
$.get('http://localhost:3000/api/todos/', function(data) {
todoResults = template({data : data});
allTasks = data;
$('.todoList').append(todoResults);
return todoResults;
});

//create new todo task
$('.todoForm').on('submit',function(event) {
event.preventDefault();
var newTask = $(this).serialize();
$.post('http://localhost:3000/api/todos/',newTask, function(data) {
console.log(data);
allTasks.push(data);
render();
});
});

//drop down edit form
$('.edit').on('click','.edit', function(event){
$('.todoEdit').show();
});

//update todo list
$('.todoList').on('submit', '.todoEdit', function(event){
event.preventDefault();
var editTask = $(this).serialize();
console.log(editTask);
var taskId = $(this).closest('.task').attr('data-id');
console.log(taskId);
var taskUpdate = allTasks.filter(function(task) {
return allTasks._id == taskId;
})[0];
$.ajax({
type: 'PUT',
url: 'http://localhost:3000/api/todos/'+taskId,
data: editTask,
success: function(data){
allTasks.splice(allTasks.indexOf(taskUpdate), 1, data);
render();
}
});
});

//delete todo list items
$('.todoList').on('click', '.delete', function(event){
event.preventDefault();
var taskId = $(this).closest('.task').attr('data-id');
console.log(taskId);
var taskRemove = allTasks.filter(function(task) {
return allTasks._id == taskId;
})[0];
$.ajax({
type: 'DELETE',
url: 'http://localhost:3000/api/todos/'+taskId,
success: function(data){
allTasks.splice(allTasks.indexOf(taskRemove), 1);
render();
}
});
});











8 changes: 8 additions & 0 deletions public/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
body {
background-color: #337AB7;
}

.todoHeader {
color: #AAA7A7;
font-size: 50px;
}
101 changes: 101 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//require node packages
var express = require('express');
var bodyParser = require('body-parser');
var hbs = require('hbs');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/tododb');

//set variable for express function
var app = express();

//set up bodyParser to extract info from URL
app.use(bodyParser.urlencoded({extended: true}));

//set up public folder for css and js
app.use(express.static('public'));

//set up view engine for hbs if server side render
app.set('view engine', 'hbs');

//seed data for to-do list
var todos = [{_id: 1,
task: "homework",
description: "finish today's homework"},
{_id: 2,
task: "beer",
description: "drink a beer"},
{_id: 3,
task: "dinner",
description: "make dinner"}
];

//route for the index page, prior to setting up index.hbs
app.get('/', function(req,res) {
res.render('index');
});

//get route for requesting all the todos
app.get('/api/todos', function(req,res) {
res.json(todos);
});

//get route for requesting a single todo
app.get('/api/todos/:id', function(req,res) {
//set variable to convert id from URL into integer
var todoId = parseInt(req.params.id);
//set variable to look for todoID within the todos array
var todoDisplay = todos.filter(function(todo) {
return todo._id === todoId;
})[0];
res.json(todoDisplay);
});

//post new todo route
app.post('/api/todos', function(req,res) {
//set variable to save new todo data
var newTodo = req.body;
//check if any id's have been created and assign one
if (todos.length > 0) {
newTodo._id = todos[todos.length -1]._id +1;
} else {
newTodo._id = 1;
}
//push new todo into array
todos.push(newTodo);
//send back confirmation of todo add
return res.json(newTodo);
});

//update existing todo route
app.put('/api/todos/:id', function(req,res) {
//set variable to save todo ID
var todoId = parseInt(req.params.id);
var todoUpdate = todos.filter(function(todo) {
return todo._id === todoId;
})[0];
//update task from info that gets sent over
todoUpdate.task = req.body.task;
//update description from info being sent over
todoUpdate.description = req.body.description;
//send confirmation to user of update
res.json(todoUpdate);
});

//delete existing todo route
app.delete('/api/todos/:id', function(req,res){
var todoId = parseInt(req.params.id);
var todoDelete = todos.filter(function(todo) {
return todo._id === todoId;
})[0];
//variable to keep index of todo to be deleted
var todoIndex = todos.indexOf(todoDelete);
//remove todo from array
todos.splice(todoIndex,1);
//send confirmation to user of deletion
return res.json(todoDelete);
});

//telling server to listen to port 3000
app.listen(3000, function() {
console.log("Ready");
});
52 changes: 52 additions & 0 deletions views/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ToDo List</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- custom css -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center todoHeader">to-do list</h1>
<hr>
<h2>add to your list:</h2>
<form class="todoForm input-group">
<input class="form-control" type="text" placeholder="Task" name="task">
<input class="form-control" type="text" placeholder="Description" name="description">
<input class="form-control" type="submit">
</form>
</div> <!-- end of to-do header -->
</div> <!-- end of header row -->
<!-- begining of handlebars -->
<div class="todoList row">
<script id="task-template" type="text/x-handlebars-template">
\{{#each data}}
<div class="col-md-8 col-md-offset-2 task" data-id=\{{_id}}>
<h3 class="task">Task: \{{task}}</h3>
<h3 class="description">Description \{{description}}</h3>
<button class="edit">Edit</button>
<form class="todoEdit input-group">
<input class="form-control" type="text" placeholder="EditTask" name="task">
<input class="form-control" type="text" placeholder="Edit Description" name="description">
<input class="form-control" type="submit">
</form>
<button class="delete">Remove</button>
</div>
\{{/each}}
</script>
</div>
</div> <!-- end of container row -->

<!-- handlebars js -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.3/handlebars.min.js"></script>
<!-- jquery -->
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<!-- custom js -->
<script type="text/javascript" src="scripts.js"></script>
</body>
</html>