(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(); } })();