217 lines
6.1 KiB
JavaScript
Executable file
217 lines
6.1 KiB
JavaScript
Executable file
(function () {
|
|
"use strict";
|
|
|
|
var ENTER_KEY = 13;
|
|
var newTodoDom = document.getElementById("new-todo");
|
|
var syncDom = document.getElementById("sync-wrapper");
|
|
|
|
var db = new PouchDB("todos");
|
|
var remoteCouch = "http://admin:123456@127.0.0.1:5984/todos";
|
|
var cookie;
|
|
|
|
db.info().then(function (info) {
|
|
db.changes({ since: info.update_seq, live: true }).on("change", function (change) {
|
|
showTodos();
|
|
});
|
|
});
|
|
|
|
// We have to create a new todo document and enter it in the database
|
|
function addTodo(text) {
|
|
var todo = {
|
|
title: text,
|
|
completed: false,
|
|
};
|
|
db.post(todo).then(function (response) {
|
|
console.log("Successfully posted a todo!");
|
|
});
|
|
}
|
|
|
|
// Show the current list of todos by reading them from the database
|
|
function showTodos() {
|
|
db.allDocs({ include_docs: true, conflicts: true })
|
|
.then(function (doc) {
|
|
console.log(doc);
|
|
redrawTodosUI(doc.rows);
|
|
})
|
|
.catch(function (err) {
|
|
console.log(err);
|
|
});
|
|
}
|
|
|
|
// Remove all conflicting revisions from the database
|
|
function resolveConflict(todo, rev) {
|
|
console.log(todo, rev)
|
|
todo._conflicts.forEach((r) => {
|
|
if (r !== rev) {
|
|
db.remove(todo._id, r);
|
|
}
|
|
});
|
|
if (todo._rev !== rev) {
|
|
db.remove(todo._id, todo._rev);
|
|
}
|
|
}
|
|
|
|
function checkboxChanged(todo, event) {
|
|
todo.completed = event.target.checked;
|
|
db.put(todo);
|
|
}
|
|
|
|
// User pressed the delete button for a todo, delete it
|
|
function deleteButtonPressed(todo) {
|
|
db.remove(todo);
|
|
}
|
|
|
|
// The input box when editing a todo has blurred, we should save
|
|
// the new title or delete the todo if the title is empty
|
|
function todoBlurred(todo, event) {
|
|
var trimmedText = event.target.value.trim();
|
|
if (!trimmedText) {
|
|
db.remove(todo);
|
|
} else {
|
|
todo.title = trimmedText;
|
|
db.put(todo);
|
|
}
|
|
}
|
|
|
|
// Initialise a sync with the remote server
|
|
function sync() {
|
|
// syncDom.setAttribute("data-sync-state", "syncing");
|
|
var remote = new PouchDB(remoteCouch, { headers: { Cookie: cookie } });
|
|
var pushRep = db.replicate
|
|
.to(remote, {
|
|
continuous: true,
|
|
})
|
|
.on("active", syncStarted)
|
|
.on("error", syncError)
|
|
.on("paused", syncComplete)
|
|
.on("complete", syncComplete);
|
|
var pullRep = db.replicate
|
|
.from(remote, {
|
|
continuous: true,
|
|
})
|
|
.on("active", syncStarted)
|
|
.on("error", syncError)
|
|
.on("paused", syncComplete)
|
|
.on("complete", syncComplete);
|
|
}
|
|
|
|
// EDITING STARTS HERE (you dont need to edit anything below this line)
|
|
|
|
// There was some form or error syncing
|
|
function syncStarted() {
|
|
syncDom.setAttribute("data-sync-state", "syncing");
|
|
}
|
|
function syncComplete() {
|
|
syncDom.setAttribute("data-sync-state", "complete");
|
|
}
|
|
function syncError() {
|
|
syncDom.setAttribute("data-sync-state", "error");
|
|
}
|
|
|
|
// User has double clicked a todo, display an input so they can edit the title
|
|
function todoDblClicked(todo) {
|
|
var div = document.getElementById("li_" + todo._id);
|
|
var inputEditTodo = document.getElementById("input_" + todo._id);
|
|
div.className = "editing";
|
|
inputEditTodo.focus();
|
|
}
|
|
|
|
// If they press enter while editing an entry, blur it to trigger save
|
|
// (or delete)
|
|
function todoKeyPressed(todo, event) {
|
|
if (event.keyCode === ENTER_KEY) {
|
|
var inputEditTodo = document.getElementById("input_" + todo._id);
|
|
inputEditTodo.blur();
|
|
}
|
|
}
|
|
|
|
// Given an object representing a todo, this will create a list item
|
|
// to display it.
|
|
function createTodoListItem(todo) {
|
|
var checkbox = document.createElement("input");
|
|
checkbox.className = "toggle";
|
|
checkbox.type = "checkbox";
|
|
checkbox.addEventListener("change", checkboxChanged.bind(this, todo));
|
|
|
|
var label = document.createElement("label");
|
|
label.appendChild(document.createTextNode(todo.title));
|
|
label.addEventListener("dblclick", todoDblClicked.bind(this, todo));
|
|
|
|
var deleteLink = document.createElement("button");
|
|
deleteLink.className = "destroy";
|
|
deleteLink.addEventListener("click", deleteButtonPressed.bind(this, todo));
|
|
|
|
var divDisplay = document.createElement("div");
|
|
divDisplay.className = "view";
|
|
divDisplay.appendChild(checkbox);
|
|
divDisplay.appendChild(label);
|
|
divDisplay.appendChild(deleteLink);
|
|
|
|
var inputEditTodo = document.createElement("input");
|
|
inputEditTodo.id = "input_" + todo._id;
|
|
inputEditTodo.className = "edit";
|
|
inputEditTodo.value = todo.title;
|
|
inputEditTodo.addEventListener("keypress", todoKeyPressed.bind(this, todo));
|
|
inputEditTodo.addEventListener("blur", todoBlurred.bind(this, todo));
|
|
|
|
var li = document.createElement("li");
|
|
li.id = "li_" + todo._id;
|
|
li.appendChild(divDisplay);
|
|
li.appendChild(inputEditTodo);
|
|
|
|
if (todo._conflicts) {
|
|
var conflictsP = document.createElement("p");
|
|
conflictsP.textContent = "conflicts with: ";
|
|
|
|
var ca = document.createElement("a");
|
|
ca.textContent = "(Keep this revision)";
|
|
ca.onclick = () => resolveConflict(todo, todo._rev);
|
|
conflictsP.appendChild(ca);
|
|
|
|
todo._conflicts.forEach((rev) => {
|
|
db.get(todo._id, { rev }).then(function (t) {
|
|
var ca = document.createElement("a");
|
|
ca.textContent = t.title;
|
|
ca.onclick = () => resolveConflict(todo, rev);
|
|
|
|
conflictsP.appendChild(ca);
|
|
});
|
|
});
|
|
|
|
li.appendChild(conflictsP);
|
|
}
|
|
|
|
if (todo.completed) {
|
|
li.className += "complete";
|
|
checkbox.checked = true;
|
|
}
|
|
|
|
return li;
|
|
}
|
|
|
|
function redrawTodosUI(todos) {
|
|
var ul = document.getElementById("todo-list");
|
|
ul.innerHTML = "";
|
|
todos.forEach(function (todo) {
|
|
ul.appendChild(createTodoListItem(todo.doc));
|
|
});
|
|
}
|
|
|
|
function newTodoKeyPressHandler(event) {
|
|
if (event.keyCode === ENTER_KEY) {
|
|
addTodo(newTodoDom.value);
|
|
newTodoDom.value = "";
|
|
}
|
|
}
|
|
|
|
function addEventListeners() {
|
|
newTodoDom.addEventListener("keypress", newTodoKeyPressHandler, false);
|
|
}
|
|
|
|
addEventListeners();
|
|
showTodos();
|
|
|
|
if (remoteCouch) {
|
|
sync();
|
|
}
|
|
})();
|