Files
pecklist/wwwroot/js/app.main.js
2018-06-28 23:08:13 +00:00

400 lines
11 KiB
JavaScript

/*
* app.main.js
* License key generator
*/
/*jslint browser : true, continue : true,
devel : true, indent : 2, maxerr : 50,
newcap : true, nomen : true, plusplus : true,
regexp : true, sloppy : true, vars : false,
white : true
*/
/*global $, app */
app.main = (function () {
'use strict';
//---------------- BEGIN MODULE SCOPE VARIABLES --------------
var
stateMap = {},
configModule, initModule,
ENTER_KEY = 13, ESCAPE_KEY = 27,
render,
onSync, onNextList, onClearDone,
onInsert, onShowContextMenu, onShowListContextMenu, onNewPriority, onDoneChanged,
onNewText, onNewListName, onDeleteList;
//----------------- END MODULE SCOPE VARIABLES ---------------
//------------------- BEGIN UTILITY METHODS ------------------
///////////////////////////
// RENDER - DRAW THE LIST
//
render = function () {
var smallScreen = app.utilB.getMediaSize() == "app-small-mode";
var $l = $('#peck-list');
var $title = $('#peck-title');
var $listContextDiv = $('#list-context-div');
var $newItem =
$listContextDiv.empty();
$l.empty();
$title.text('');
var rawList = app.api.getActiveList();
if (rawList == null) {
$title.text('?? NO LIST ??');
$l.append('<li>NO LIST</li>');
return;
}
var deletedList = rawList.deleted;
var listDisplayName = rawList.name;
if (deletedList) {
listDisplayName = "[" + rawList.name + "] - DELETE NEXT SYNC ";
$('#new-item').hide();
$title.addClass('text-danger');
} else {
$title.removeClass('text-danger');
}
$title.text(listDisplayName);
// Sort by `user` in ascending order and by `age` in descending order.
var l = _.orderBy(rawList.items, ['priority', 'text'], ['desc', 'asc']);
//draw the list
//{"id":"FmcIT283XkSFxvoyBGCmw","completed":false,"text":"Paper towel","v":3706,"priority":2}
var len = l.length, i = 0;
for (i; i < len; i++) {
var o = l[i];
if (o.priority > -1) {
var itemTextSpanClass = '';
if (!o.text) {
o.text = "## EMPTY ITEM ###";
}
//3 = old highlight (orangey red) and 2 is default dark green, 1 is black and 0 is faded gray
switch (o.priority) {
case 3:
itemTextSpanClass = 'text-danger';
break;
case 2:
itemTextSpanClass = 'text-primary';
break;
case 1:
itemTextSpanClass = 'text-dark';
break;
default:
itemTextSpanClass = 'text-secondary';
}
if (deletedList) {
itemTextSpanClass = 'text-warning';
}
if (smallScreen && o.text.length > 30) {
itemTextSpanClass += ' pl-long-item';
} else {
itemTextSpanClass += ' pl-short-item';
}
var listItem;
if (o.completed || deletedList) {
listItem = '<li data-id="' + o.id + '" class="list-group-item text-right pl-done">' +
'<span id="b' + i + '" class="w-100 ' + itemTextSpanClass + '" >' + o.text + '</span>' +
'</li>'
} else {
listItem = '<li data-id="' + o.id + '" class="list-group-item">' +
'<span id="b' + i + '" class="w-100 font-weight-bold ' + itemTextSpanClass + '" >' + o.text + '</span>' +
'</li>'
}
$l.append(listItem);
if (!deletedList) {
$('#b' + i).bind('click', o, onShowContextMenu);
}
}
}
}
//-------------------- END UTILITY METHODS -------------------
//------------------- BEGIN EVENT HANDLERS -------------------
//////////////////////////////////////////////////
//
onSync = function () {
$.gevent.publish('app-clear-error');
app.api.doSync(function (res) {
if (res.error) {
$.gevent.publish('app-show-error', res.msg);
} else {
render();
//alert("Stub: onSync success ");
return false;
}
});
};
//////////////////////////////////////////////////
// ADVANCE TO NEXT LIST
//
onNextList = function (e) {
app.api.goToNextList();
render();
};
//////////////////////////////////////////////////
// Clear completed items
//
onClearDone = function (e) {
var l = app.api.getActiveList();
if (l == null) {
return;
}
var len = l.items.length, i = 0;
for (i; i < len; i++) {
if (l.items[i].completed) {
l.items[i].priority = -1;
}
}
app.api.replaceActiveList(l);
render();
};
//////////////////////////////////////////////////
//
onInsert = function (e) {
e.preventDefault();
var $input = $(e.target);
var val = $input.val().trim();
if (e.which !== ENTER_KEY || !val) {
return;
}
//{id: "3GtklnXES0Ox7QrOJpEFRQ", completed: false, text: "No need for lock feature if it's not used", v: 49, priority: 2}
var newRecord = {
id: "NEW_" + _.now(),
completed: false,
text: val,
v: 0,
priority: 1
};
app.api.insertRecordInStore(newRecord);
$input.val('');
render();
return false; //prevent default
};
//////////////////////////////////////////////////
// Show context menu
//
onShowContextMenu = function (e) {
e.preventDefault();
$('.pl-mnu').remove();
var li = $('li[data-id="' + e.data.id + '"]');
li.append(Handlebars.templates['app.main.context']({}));
var edTxt = $('#edtxt');
var btnToggleDone = $("#btn-toggle-done");
edTxt.val(e.data.text);
edTxt.keyup(e.data, onNewText);
btnToggleDone.focus();
if (e.data.completed) {
btnToggleDone.addClass("mdi-checkbox-blank-outline");
} else {
btnToggleDone.addClass("mdi-checkbox-marked");
}
btnToggleDone.click(e.data, onDoneChanged);
$('.ct-btn-priority').click(e.data, onNewPriority);
return false;
};
//////////////////////////////////////////////////
// Show LIST context menu
//
onShowListContextMenu = function (e) {
//rename or delete
e.preventDefault();
var listContextDiv = $('#list-context-div');
//is it already displayed?
if (listContextDiv.children().length > 0) {
//div has tags in it, so clear it and return, it's a dismissal
listContextDiv.empty();
return false;
}
listContextDiv.append(Handlebars.templates['app.main.list-context']({}));
var edTxt = $('#edtxt');
var btnDeleteList = $("#btn-delete-list");
var rawList = app.api.getActiveList();
var deletedList = rawList.deleted;
var $title = $('#peck-title');
if (deletedList) {
btnDeleteList.removeClass('btn-danger').addClass('btn-success');
btnDeleteList.text('UNDELETE LIST');
edTxt.hide();
} else {
edTxt.val($title.text());
edTxt.keyup(onNewListName);
edTxt.focus();
}
btnDeleteList.click(onDeleteList);
return false;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
//CONTEXT FUNCTIONS HERE
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////
// CHANGE PRIORITY
//
onNewPriority = function (e) {
//List item id: e.data
//priority value: e.target.value
var rec = app.api.getRecordFromStore(e.data.id);
rec.priority = _.toNumber(e.target.value);
app.api.replaceRecordInStore(e.data.id, rec);
render();
return false;
};
//////////////////////////////////////////////////
// CHANGE TEXT
//
onNewText = function (e) {
var newText = e.target.value.trim();
if (e.which !== ENTER_KEY || !newText) {
return;
}
var rec = app.api.getRecordFromStore(e.data.id);
rec.text = newText;
app.api.replaceRecordInStore(e.data.id, rec);
render();
return false;
};
//////////////////////////////////////////////////
// CHANGE COMPLETED
//
onDoneChanged = function (e) {
//List item id: e.data
//priority value: e.target.value
var rec = app.api.getRecordFromStore(e.data.id);
rec.completed = !rec.completed;
app.api.replaceRecordInStore(e.data.id, rec);
render();
return false;
};
//////////////////////////////////////////////////
// CHANGE TEXT
//
onNewListName = function (e) {
var newText = e.target.value.trim();
if (e.which !== ENTER_KEY || !newText) {
return;
}
app.api.renameActiveList(newText);
render();
return false;
};
//////////////////////////////////////////////////
// CHANGE TEXT
//
onDeleteList = function (e) {
e.preventDefault();
app.api.toggleDeleteActiveList();
render();
return false;
};
//-------------------- END EVENT HANDLERS --------------------
//------------------- BEGIN PUBLIC METHODS -------------------
//CONFIGMODULE
//
configModule = function (context) {
stateMap.context = context.context;
if (stateMap.context.params.id) {
stateMap.id = stateMap.context.params.id;
}
};
//INITMODULE
//
initModule = function ($container) {
if (typeof $container === 'undefined') {
$container = $('#app-shell-main-content');
}
$container.html(Handlebars.templates['app.main']({}));
//Context menu
app.nav.contextClear();
////app.nav.setContextTitle("License");
//make context menu
//Context menu
app.nav.contextClear();
app.nav.contextAddButton('btn-sync', 'Sync', 'sync', onSync);
app.nav.contextAddButton('btn-clear-done', 'Clear done', 'nuke', onClearDone);
app.nav.contextAddButton('btn-next', 'List', 'skip-next', onNextList);
//bind event handlers
$('#new-item').keyup(onInsert);
$('#btn-test').click(onNewPriority);
$('#peck-title').bind('click', onShowListContextMenu);
//display the cached data
render();
};
// return public methods
return {
configModule: configModule,
initModule: initModule
};
//------------------- END PUBLIC METHODS ---------------------
}());