/public/js/list.js
JavaScript | 435 lines | 367 code | 41 blank | 27 comment | 72 complexity | c6b632d340dd27fb08c1b3c88dc76269 MD5 | raw file
- var listId = "";
- var syncTimer;
- var syncAction = "getAll";
- var syncStatus = 0;
- var syncTimeout = 10;
- var block = false;
- var categoryList;
- var itemList;
- /*
- * Functions to update localStorage object.
- */
- function populateList(json,id) { // Takes a list object, and merges into the localStorage object.
- if(typeof id === "undefined") { id = listId; }
- var list = getList(id);
- list.name = json.name;
- list.description = json.description;
- list.showCat = json.showCat;
- list.showQty = json.showQty;
- list.lastupdate = getTime();
- $.each(json.items,function(index, item){
- updateItem(item,list.items);
- });
- setList(list);
- }
- function updateItem(item,target) { // Adds or syncs an item to the localStorage object.
- // Find the target
- var index = findIndex(item.id,target);
- if (index === false) {
- // Add the new item to the array
- target.push(item);
- } else {
- var t = target[index];
- var types = ["cat","so","value","qty","done"];
- for (i=0;i<types.length;i++) { // Check each element and update if newer.
- var type = types[i];
- if (typeof item[type] !== "undefined") {
- if (typeof t[type] === "undefined") {
- t[type] = item[type];
- } else if (item[type].time > t[type].time) {
- t[type] = item[type];
- }
- }
- }
- }
- }
- function updRow(item,id,type) { // Update row in localStorage object from the app. Operates on only one field at the time.
- var list = getList();
- var index = findIndex(id,list.items);
- var refresh = false;
- list.items[index].updated = getTime();
- switch(type) {
- case "cat":
- list.items[index].cat.value = item.trim();
- list.items[index].cat.time = getTime();
- refresh = true;
- break;
- case "value":
- item = item.trim();
- if (item.length > 0) { // Has text in value field
- list.items[index].value.value = item;
- list.items[index].value.time = getTime();
- } else { // Empty field, delete item instead.
- list.items[index].done.value = 2;
- list.items[index].done.time = getTime();
- refresh = true;
- }
- break;
- case "value":
- list.items[index].value.value = Number(item);
- list.items[index].value.time = getTime();
- break;
- case "done":
- list.items[index].done.value = (list.items[index].done.value == 1)?0:1;
- list.items[index].done.time = getTime();
- if (list.items[index].done.value == 1) {
- $("#"+id).addClass("done");
- } else {
- $("#"+id).removeClass("done");
- }
- refresh = true;
- break;
- }
- $("#sync").removeClass();
- $("#sync").addClass("sync_old");
- syncStatus = 1;
- block = false;
- setList(list);
- if (refresh) buildList();
- }
- function addItem(value) { // Add a new row to the object
- if (typeof value === "undefined") {
- value = $("#new_value").val().trim()
- }
- var cat = $("#new_cat").val().trim();
- $("#new_value").val("");
- $("#new_cat").val("");
- var list = getList();
- if (value != "") {
- if (!rescurrectItem(list,value,$("#new_cat").val())) {
- // Create the new item.
- var item = new Object();
- item.id = createGuid();
- item.cat = new Object();
- if (cat != "") {
- item.cat.value = cat;
- $("#new_cat").attr("placeholder", cat);
- } else if ($("#new_cat").attr("placeholder") != "Category") {
- item.cat.value = $("#new_cat").attr("placeholder");
- } else {
- item.cat.value = "";
- }
- item.cat.time = getTime();
- item.value = new Object();
- item.value.value = value;
- item.value.time = getTime();
- item.qty = new Object();
- item.qty.value = value;
- item.qty.time = getTime();
- item.done = new Object();
- item.done.value = 0;
- item.done.time = getTime();
- item.so = new Object();
- item.so.value = 0;
- item.so.time = getTime();
- // Push the item onto the list.
- list.items.push(item);
- }
- $("#sync").removeClass();
- $("#sync").addClass("sync_old");
- syncStatus = 1;
- }
- setList(list);
- saveOrder();
- syncJSON('updList');
- // Redraw the list
- buildList();
- }
- function rescurrectItem(list,value,cat) {
- var match = false;
- $.each(list.items,function (index,item) {
- if (item.done.value > 1 && item.value.value == value) { // Match deleted item
- item.done.value = 0;
- item.done.time = getTime();
- item.so.value = 0;
- item.so.time = getTime();
- if (cat != "" && item.cat.value != cat) {
- item.cat.value = cat;
- item.cat.time = getTime();
- }
- match = true;
- return false;
- }
- });
- return match;
- }
- /*
- Functions to draw the list on the doc.
- */
- function buildList() { // Update name and empty the list
- var list = getList();
- var inSync = true;
- $("#listname").html(list.name);
- // Only if not blocked
- if (block == false) {
- $("#listbody").html("");
- var catTmp = "";
- $(list.items).sort(dynamicSortMultiple("cat","done","so")).each(function(index,element) {
- addCategoryList(element.cat.value);
- addItemList(element.value.value);
- if (element.done.value <= 1) {
- if (list.lastsync < element.updated) {
- inSync = false;
- }
- if (catTmp != element.cat.value) {
- catTmp = element.cat.value;
- $("#listbody").append('<tr id="catRow_'+catTmp+'"><th colspan="3">'+catTmp+'</th></tr>');
- }
- addRow(index,element);
- }
- });
- $('#new_cat').autocomplete("option", { source: categoryList });
- $('#new_value').autocomplete("option", { source: itemList });
- }
- if (!inSync) {
- $("#sync").removeClass();
- $("#sync").addClass("sync_old");
- syncStatus = 1;
- }
- }
- function addRow (index,element) { // Draw a row
- var cl = "";
- if (element.done.value > 0) {
- cl = ' class="done"';
- }
- $("#listbody").append('<tr id="'+ element.id +'"'+cl+'>' +
- '<td class="checkbox" onclick="updRow(1,\''+ element.id +'\',\'done\')" id="check_'+ element.id +'"></td>' +
- '<td colspan="2"><input type="hidden" id="cat_'+ element.id +'" value="' + element.cat.value + '" /><input type="text" onkeyup="blockDraw(\''+ element.id +'\');" onchange="updRow(this.value,\''+ element.id +'\',\'value\')" name="value_'+ element.id +'" value="' + HTMLEncode(element.value.value) + '" tabindex="'+(20000+element.so.value)+'"/></td>' +
- '<td><img src="img/move.png" alt="Move" class="handle"/></td>' +
- "</tr>");
- }
- function buildIndex (items) { // Draw index page
- $(".lists").html("");
- var lists = $(readLists()).sort(dynamicSortMultiple("name"));
- $.each(lists,function(id,list) {
- var html = '<li><a href="#list/'+list.id+'" onclick="openList(\''+list.id+'\')">'+list.name;
- if (items != false) {
- html += ' ('+showItemCount(list.items)+')';
- }
- html += '</a></li>';
- $(".lists").append(html);
- });
- }
- function showItemCount(items) {
- var total = 0;
- var pending = 0;
- $.each(items,function (index,item) {
- if (item.done.value < 2) total++;
- if (item.done.value == 0) pending++;
- });
- return pending+" / "+total;
- }
- function openList (id) { // Set the list, draw and show it.
- $("#settingsLink").attr("href",rpath+"settings/list-"+id);
- listId = id; // Set the list id
- categoryList = []; // Empty the datalist
- itemList = []; // Empty the datalist
- $("#listid").val(id); // Set id in form as well, in case it is used.
- buildIndex(false); // Draw the index.
- buildList(); // Draw the list.
- syncAction = "updList";
- syncJSON('updList'); // Call a list sync
- // Finally show the list
- $("#index").addClass("shaded");
- $("#list").show();
- }
- function closeList (sync) { // Close the list view, and return to index.
- $("#settingsLink").attr("href",rpath+"settings");
- if (sync !== false) {
- syncJSON('updList'); // Call a list sync before closing.
- }
- listId = ""; // Unset the list id
- $('#categories').html(""); // Empty the datalist
- $("#listid").val(""); // Unset form id.
- $(".lists").html(""); // Empty the HTML, just in case.
- buildIndex(); // Draw the index.
- syncAction = "getAll";
- syncJSON('getAll'); // Call an index sync
- // Finally show the list
- $("#list").hide();
- $("#index").removeClass("shaded");
- }
- function addCategoryList(cat) { // Add category to array if not already there.
- var exists = false;
- for (i=0;i<categoryList.length;i++) {
- if (categoryList[i] == cat) exists = true;
- }
- if (!exists)
- categoryList.push(cat);
- }
- function addItemList(item) { // Add item to list if not already there.
- var exists = false;
- for (i=0;i<itemList.length;i++) {
- if (itemList[i] == item) exists = true;
- }
- if (!exists)
- itemList.push(item);
- }
- function delChecked () {
- var list = getList();
- $.each(list.items,function (index,item) {
- if (item.done.value == 1) {
- item.done.value = 2;
- item.done.time = getTime();
- }
- });
- setList(list);
- buildList();
- }
- /*
- * Block drawing of the list.
- * This is so that half edited rows will not be lost.
- * This could be made to block only a specific row, but requires that the drawing be redone.
- */
- function blockDraw(id) {
- block = id;
- }
- // Save item order on reordering.
- function saveOrder(ui) {
- var list = getList();
- var so = 0;
- var cat = "";
- $("#listbody tr").each(function(){
- var id = $(this).attr("id");
- if (id.substr(0,6) == "catRow") {
- cat = id.substr(7);
- } else {
- $.each(list.items,function(){
- if (this.id == id) {
- so = so + 10;
- this.so.value = so;
- this.so.time = getTime();
- if (this.cat.value != cat) {
- this.cat.value = cat;
- this.cat.time = getTime();
- }
- return true;
- }
- });
- }
- });
- setList(list);
- $("#sync").removeClass();
- $("#sync").addClass("sync_old");
- syncStatus = 1;
- block = false;
- buildList();
- }
- /*
- * Sync data to server.
- */
- function syncJSON(action) {
- if(typeof action === "undefined") { action = syncAction; }
- if (navigator.onLine !== false){
- var json = "{}";
- switch (action) {
- case "updList":
- var list = getList();
- list.lastsent = getTime();
- json = JSON.stringify(list);
- setList(list);
- break;
- }
- var token = getCookie("userToken");
- $("#sync").removeClass();
- $("#sync").addClass("sync_on");
- syncStatus = 2;
- syncTimer = setTimeout(function(){ syncFail() },syncTimeout * 1000);
- $.ajax({
- type: "POST",
- url: jsonURL,
- data: {token: token, action: action, json: json},
- success: parseData,
- dataType: "json"
- });
- }
- }
- // AJAX return handler
- function parseData(data) {
- $("#sync").removeClass();
- $("#sync").addClass("sync");
- syncStatus = 0;
- clearTimeout(syncTimer);
- switch (data.status) {
- case 0:
- setCookie("userToken",data.token);
- switch (data.action) {
- case "update":
- populateList(data.data,data.id);
- buildList();
- break;
- case "index":
- $.each(data.data,function (id,list) {
- populateList(list,list.id);
- });
- // Clean up deleted lists
- $.each(readLists(),function (index,list){
- if (list !== null && findIndex(list.id,data.data) === false) { // If the list is not in the returned data, nuke it.
- deleteList(list.id);
- }
- })
- buildIndex();
- break;
- }
- break;
- case 1:
- //window.location.assign("/login");
- break;
- case 18: // List does not exist
- closeList(false);
- break;
- default:
- syncFail();
- alert("Unhandled Error #"+data.status+": "+data.errmsg);
- break;
- }
- }
- // Sync timed out or failed.
- function syncFail () {
- if (syncStatus == 2) {
- $("#sync").removeClass();
- $("#sync").addClass("sync_error");
- syncStatus = 3
- }
- }