mirror of
https://github.com/maxpozdeev/mytinytodo.git
synced 2026-03-11 08:55:27 +00:00
merge
This commit is contained in:
commit
3b46ebb5b0
12 changed files with 648 additions and 379 deletions
476
src/ajax.js
476
src/ajax.js
|
|
@ -21,15 +21,19 @@ var img = {
|
|||
};
|
||||
var taskCnt = { total:0, past: 0, today:0, soon:0 };
|
||||
var tmp = {};
|
||||
var oBtnMenu = {};
|
||||
var tabLists;
|
||||
var curList = 0;
|
||||
var tagsList = [];
|
||||
|
||||
function loadTasks()
|
||||
{
|
||||
tz = -1 * (new Date()).getTimezoneOffset();
|
||||
setAjaxErrorTrigger();
|
||||
if(filter.search) search = '&s='+encodeURIComponent(filter.search); else search = '';
|
||||
if(filter.tag) tag = '&t='+encodeURIComponent(filter.tag); else tag = '';
|
||||
nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?loadTasks&compl='+filter.compl+'&sort='+sortBy+search+tag+'&tz='+tz+nocache, function(json){
|
||||
var search = filter.search ? '&s='+encodeURIComponent(filter.search) : '';
|
||||
var tag = filter.tag ? '&t='+encodeURIComponent(filter.tag) : '';
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?loadTasks&list='+curList.id+'&compl='+filter.compl+'&sort='+sortBy+search+tag+'&tz='+tz+nocache, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
taskList = new Array();
|
||||
taskOrder = new Array();
|
||||
|
|
@ -56,18 +60,19 @@ function loadTasks()
|
|||
|
||||
function prepareTaskStr(item)
|
||||
{
|
||||
id = parseInt(item.id);
|
||||
prio = parseInt(item.prio);
|
||||
readOnly = (flag.needAuth && flag.canAllRead && !flag.isLogged) ? true : false;
|
||||
var id = parseInt(item.id);
|
||||
var prio = parseInt(item.prio);
|
||||
var readOnly = (flag.needAuth && flag.canAllRead && !flag.isLogged) ? true : false;
|
||||
return '<li id="taskrow_'+id+'" class="'+(item.compl?'task-completed ':'')+item.dueClass+'" onDblClick="editTask('+id+')"><div class="task-actions">'+
|
||||
'<a href="#" onClick="return toggleTaskNote('+id+')"><img src="'+img.note[0]+'" onMouseOver="this.src=img.note[1]" onMouseOut="this.src=img.note[0]" title="'+lang.actionNote+'"></a>'+
|
||||
'<a href="#" onClick="return editTask('+id+')"><img src="'+img.edit[0]+'" onMouseOver="this.src=img.edit[1]" onMouseOut="this.src=img.edit[0]" title="'+lang.actionEdit+'"></a>'+
|
||||
'<a href="#" onClick="return deleteTask('+id+')"><img src="'+img.del[0]+'" onMouseOver="this.src=img.del[1]" onMouseOut="this.src=img.del[0]" title="'+lang.actionDelete+'"></a></div>'+
|
||||
'<div class="task-left"><input type="checkbox" '+(readOnly?'disabled':'')+' onClick="completeTask('+id+',this)" '+(item.compl?'checked':'')+'></div>'+
|
||||
'<div class="task-left"><div class="mtt-toggle '+(item.note==''?'invisible':'')+'" onClick="toggleNote('+id+')"></div>'+
|
||||
'<input type="checkbox" '+(readOnly?'disabled':'')+' onClick="completeTask('+id+',this)" '+(item.compl?'checked':'')+'></div>'+
|
||||
'<div class="task-middle">'+prepareDuedate(item.duedate, item.dueClass, item.dueStr)+
|
||||
'<span class="nobr"><span class="task-through">'+preparePrio(prio,id)+'<span class="task-title">'+prepareHtml(item.title)+'</span>'+
|
||||
prepareTagsStr(item.tags)+'<span class="task-date">'+lang.taskDate(item.date)+'</span></span></span>'+
|
||||
'<div class="task-note-block'+(item.note==''?' hidden':'')+'">'+
|
||||
'<div class="task-note-block hidden">'+
|
||||
'<div id="tasknote'+id+'" class="task-note"><span>'+prepareHtml(item.note)+'</span></div>'+
|
||||
'<div id="tasknotearea'+id+'" class="task-note-area"><textarea id="notetext'+id+'"></textarea>'+
|
||||
'<span class="task-note-actions"><a href="#" onClick="return saveTaskNote('+id+')">'+lang.actionNoteSave+
|
||||
|
|
@ -79,13 +84,13 @@ function prepareTaskStr(item)
|
|||
function prepareHtml(s)
|
||||
{
|
||||
// make URLs clickable
|
||||
s = s.replace(/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/gi, '$1<a href="http://$2" target="_blank">$2</a>$4');
|
||||
var s = s.replace(/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/gi, '$1<a href="http://$2" target="_blank">$2</a>$4');
|
||||
return s.replace(/(^|\s|>)((?:http|https|ftp):\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/ig, '$1<a href="$2" target="_blank">$2</a>$4');
|
||||
}
|
||||
|
||||
function preparePrio(prio,id)
|
||||
{
|
||||
cl = v = '';
|
||||
var cl =''; var v = '';
|
||||
if(prio < 0) { cl = 'prio-neg'; v = '−'+Math.abs(prio); }
|
||||
else if(prio > 0) { cl = 'prio-pos'; v = '+'+prio; }
|
||||
else { cl = 'prio-o'; v = '±0'; }
|
||||
|
|
@ -95,9 +100,9 @@ function preparePrio(prio,id)
|
|||
function prepareTagsStr(tags)
|
||||
{
|
||||
if(!tags || tags == '') return '';
|
||||
a = tags.split(',');
|
||||
var a = tags.split(',');
|
||||
if(!a.length) return '';
|
||||
for(i in a) {
|
||||
for(var i in a) {
|
||||
a[i] = '<a href="#" class="tag" onClick=\'addFilterTag("'+a[i]+'");return false\'>'+a[i]+'</a>';
|
||||
}
|
||||
return '<span class="task-tags">'+a.join(', ')+'</span>';
|
||||
|
|
@ -114,8 +119,8 @@ function submitNewTask(form)
|
|||
if(form.task.value == '') return false;
|
||||
var tz = -1 * (new Date()).getTimezoneOffset();
|
||||
setAjaxErrorTrigger()
|
||||
nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?newTask'+nocache, { title: form.task.value, tz:tz, tag:filter.tag }, function(json){
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?newTask'+nocache, { list:curList.id, title: form.task.value, tz:tz, tag:filter.tag }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
$('#total').text( parseInt($('#total').text()) + parseInt(json.total) );
|
||||
|
|
@ -153,7 +158,7 @@ function flashError(str, details)
|
|||
|
||||
function toggleMsgDetails()
|
||||
{
|
||||
el = $("#msgdetails");
|
||||
var el = $("#msgdetails");
|
||||
if(!el) return;
|
||||
if(el.css('display') == 'none') el.show();
|
||||
else el.hide()
|
||||
|
|
@ -171,7 +176,7 @@ function deleteTask(id)
|
|||
return false;
|
||||
}
|
||||
setAjaxErrorTrigger()
|
||||
nocache = '&rnd='+Math.random();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?deleteTask='+id+nocache, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
|
|
@ -188,7 +193,7 @@ function deleteTask(id)
|
|||
|
||||
function completeTask(id,ch)
|
||||
{
|
||||
compl = 0;
|
||||
var compl = 0;
|
||||
if(ch.checked) compl = 1;
|
||||
setAjaxErrorTrigger();
|
||||
$.getJSON('ajax.php?completeTask='+id+'&compl='+compl+nocache, function(json){
|
||||
|
|
@ -216,13 +221,14 @@ function completeTask(id,ch)
|
|||
|
||||
function toggleTaskNote(id)
|
||||
{
|
||||
aArea = '#tasknotearea'+id;
|
||||
var aArea = '#tasknotearea'+id;
|
||||
if($(aArea).css('display') == 'none')
|
||||
{
|
||||
$('#notetext'+id).val(taskList[id].noteText);
|
||||
$('#taskrow_'+id+'>div>div.task-note-block').removeClass('hidden');
|
||||
$(aArea).css('display', 'block');
|
||||
$('#tasknote'+id).css('display', 'none');
|
||||
if(taskList[id].note != '') $('#taskrow_'+id+' .mtt-toggle').addClass('mtt-toggle-expanded');
|
||||
$('#notetext'+id).focus();
|
||||
} else {
|
||||
cancelTaskNote(id)
|
||||
|
|
@ -243,7 +249,7 @@ function cancelTaskNote(id)
|
|||
function saveTaskNote(id)
|
||||
{
|
||||
setAjaxErrorTrigger()
|
||||
nocache = '&rnd='+Math.random();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?editNote='+id+nocache, {note: $('#notetext'+id).val()}, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
|
|
@ -251,6 +257,8 @@ function saveTaskNote(id)
|
|||
taskList[id].note = item.note;
|
||||
taskList[id].noteText = item.noteText;
|
||||
$('#tasknote'+item.id+'>span').html(prepareHtml(item.note));
|
||||
if(item.note == '') $('#taskrow_'+id+' .mtt-toggle').removeClass('mtt-toggle-expanded').addClass('invisible');
|
||||
else $('#taskrow_'+id+' .mtt-toggle').addClass('mtt-toggle-expanded').removeClass('invisible');
|
||||
cancelTaskNote(item.id);
|
||||
}, 'json');
|
||||
return false;
|
||||
|
|
@ -265,12 +273,12 @@ function editTask(id)
|
|||
document.edittask.id.value = item.id;
|
||||
document.edittask.tags.value = item.tags.split(',').join(', ');
|
||||
document.edittask.duedate.value = item.duedate;
|
||||
sel = document.edittask.prio;
|
||||
for(i=0; i<sel.length; i++) {
|
||||
var sel = document.edittask.prio;
|
||||
for(var i=0; i<sel.length; i++) {
|
||||
if(sel.options[i].value == item.prio) sel.options[i].selected = true;
|
||||
}
|
||||
$('<div id="overlay"></div>').appendTo('body').css('opacity', 0.5).show();
|
||||
w = $('#page_taskedit');
|
||||
var w = $('#page_taskedit');
|
||||
if(!flag.windowTaskEditMoved)
|
||||
{
|
||||
var x,y;
|
||||
|
|
@ -302,6 +310,7 @@ function cancelEdit(e)
|
|||
document.edittask.note.value = '';
|
||||
document.edittask.tags.value = '';
|
||||
document.edittask.duedate.value = '';
|
||||
toggleEditAllTags(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -309,8 +318,8 @@ function saveTask(form)
|
|||
{
|
||||
if(flag.needAuth && !flag.isLogged && flag.canAllRead) return false;
|
||||
setAjaxErrorTrigger();
|
||||
nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?editTask='+form.id.value+nocache, { title: form.task.value, note:form.note.value, prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value }, function(json){
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?editTask='+form.id.value+nocache, { list:curList.id, title: form.task.value, note:form.note.value, prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
var item = json.list[0];
|
||||
|
|
@ -348,19 +357,19 @@ function orderChanged(event,ui)
|
|||
{
|
||||
if(!ui.item[0]) return;
|
||||
var itemId = ui.item[0].id;
|
||||
n = $(this).sortable('toArray');
|
||||
var n = $(this).sortable('toArray');
|
||||
// remove possible empty id's
|
||||
for(i=0; i<sortOrder.length; i++) {
|
||||
for(var i=0; i<sortOrder.length; i++) {
|
||||
if(sortOrder[i] == '') { sortOrder.splice(i,1); i--; }
|
||||
}
|
||||
if(n.toString() == sortOrder.toString()) return;
|
||||
// make assoc from array for easy index
|
||||
var h0 = new Array();
|
||||
for(j=0; j<sortOrder.length; j++) {
|
||||
for(var j=0; j<sortOrder.length; j++) {
|
||||
h0[sortOrder[j]] = j;
|
||||
}
|
||||
var h1 = new Array();
|
||||
for(j=0; j<n.length; j++) {
|
||||
for(var j=0; j<n.length; j++) {
|
||||
h1[n[j]] = j;
|
||||
taskOrder[j] = n[j].split('_')[1];
|
||||
}
|
||||
|
|
@ -368,18 +377,18 @@ function orderChanged(event,ui)
|
|||
var s = '';
|
||||
var diff;
|
||||
var replaceOW = taskList[sortOrder[h1[itemId]].split('_')[1]].ow;
|
||||
for(j in h0)
|
||||
for(var j in h0)
|
||||
{
|
||||
diff = h1[j] - h0[j];
|
||||
if(diff != 0) {
|
||||
a = j.split('_');
|
||||
var a = j.split('_');
|
||||
if(j == itemId) diff = replaceOW - taskList[a[1]].ow;
|
||||
s += a[1] +'='+ diff+ '&';
|
||||
taskList[a[1]].ow += diff;
|
||||
}
|
||||
}
|
||||
setAjaxErrorTrigger();
|
||||
nocache = '&rnd='+Math.random();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?changeOrder'+nocache, { order: s }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
}, 'json');
|
||||
|
|
@ -401,17 +410,6 @@ function searchTasks()
|
|||
return false;
|
||||
}
|
||||
|
||||
function tabSelected(event, ui)
|
||||
{
|
||||
// reload tasks when we return to task tab (from search tab)
|
||||
if(ui.index == 0 && filter.search != '') {
|
||||
filter.search = '';
|
||||
$('#searchbarkeyword').text('');
|
||||
$('#searchbar').hide();
|
||||
loadTasks();
|
||||
}
|
||||
}
|
||||
|
||||
function dehtml(str)
|
||||
{
|
||||
return str.replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
|
||||
|
|
@ -422,57 +420,54 @@ function errorDenied()
|
|||
flashError(lang.denied);
|
||||
}
|
||||
|
||||
function updateAccessStatus(onInit)
|
||||
function updateAccessStatus()
|
||||
{
|
||||
if(flag.needAuth && !flag.isLogged) $("#tasklist").sortable('disable').addClass('readonly');
|
||||
else if(sortBy == 0) $("#tasklist").sortable('enable').removeClass('readonly');
|
||||
else $("#tasklist").removeClass('readonly');
|
||||
|
||||
if(!flag.canAllRead && !flag.isLogged) {
|
||||
$('#page_tasks > h3,#taskcontainer').hide();
|
||||
$('#tabs').hide();
|
||||
// flag.needAuth is not changed after pageload
|
||||
if(flag.needAuth)
|
||||
{
|
||||
$('#bar_auth').show();
|
||||
if(flag.isLogged) {
|
||||
showhide($("#bar_logout"),$("#bar_login"));
|
||||
$('#bar .menu-owner').show();
|
||||
$('#bar .bar-delim').show();
|
||||
}
|
||||
else {
|
||||
showhide($("#bar_login"),$("#bar_logout"));
|
||||
$('#bar .menu-owner').hide();
|
||||
$('#bar .bar-delim').hide();
|
||||
}
|
||||
if(!flag.canAllRead && !flag.isLogged) {
|
||||
$('#page_tasks').hide();
|
||||
$('#lists').hide();
|
||||
} else {
|
||||
$('#page_tasks').show();
|
||||
}
|
||||
}
|
||||
if(flag.needAuth && flag.canAllRead && !flag.isLogged) {
|
||||
$("#tasklist").sortable('disable');
|
||||
$('#page_tasks').addClass('readonly')
|
||||
$("#authstr").text(lang.readonly).show();
|
||||
addsearchToggle(1);
|
||||
}
|
||||
else {
|
||||
$('#page_tasks > h3,#taskcontainer').show();
|
||||
$('#tabs').show();
|
||||
}
|
||||
if(flag.needAuth) {
|
||||
$('#bar_auth').show();
|
||||
showhide($("#bar_login"),$("#bar_logout"));
|
||||
}
|
||||
if(!flag.needAuth) {
|
||||
$('#page_tasks').removeClass('readonly')
|
||||
if(sortBy == 0) $("#tasklist").sortable('enable');
|
||||
$("#authstr").text('').hide();
|
||||
$('#bar_auth').hide();
|
||||
}
|
||||
else if(flag.canAllRead && !flag.isLogged) $("#authstr").text(lang.readonly).addClass('attention').show();
|
||||
else if(flag.isLogged) showhide($("#bar_logout"),$("#bar_login"));
|
||||
else if(!flag.canAllRead) $("#authstr").text('').hide();
|
||||
|
||||
if(onInit == null || !onInit)
|
||||
{
|
||||
if(flag.isLogged) $("#tabs").tabs('enable',0).tabs('enable',1).tabs('select',0);
|
||||
else if(flag.canAllRead) $("#tabs").tabs('enable',1).tabs('select', 1).tabs('disable',0);
|
||||
else $("#tabs").tabs('disable',0).tabs('disable',1);
|
||||
}
|
||||
}
|
||||
|
||||
function doAuth(form)
|
||||
{
|
||||
setAjaxErrorTrigger();
|
||||
nocache = '&rnd='+Math.random();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?login'+nocache, { password: form.password.value }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
form.password.value = '';
|
||||
if(json.logged)
|
||||
{
|
||||
flag.isLogged = true;
|
||||
if(filter.search != '') {
|
||||
filter.search = '';
|
||||
$('#searchbarkeyword').text('');
|
||||
$('#searchbar').hide();
|
||||
}
|
||||
updateAccessStatus();
|
||||
loadTasks();
|
||||
loadLists();
|
||||
}
|
||||
else {
|
||||
flashError(lang.invalidpass);
|
||||
|
|
@ -485,7 +480,7 @@ function doAuth(form)
|
|||
function logout()
|
||||
{
|
||||
setAjaxErrorTrigger();
|
||||
nocache = '&rnd='+Math.random();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?logout'+nocache, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
});
|
||||
|
|
@ -503,9 +498,9 @@ function logout()
|
|||
|
||||
function tasklistClick(e)
|
||||
{
|
||||
node = e.target.nodeName;
|
||||
var node = e.target.nodeName;
|
||||
if(node=='SPAN' || node=='LI' || node=='DIV') {
|
||||
li = getRecursParent(e.target, 'LI', 10);
|
||||
var li = getRecursParent(e.target, 'LI', 10);
|
||||
if(li) {
|
||||
if(selTask && li.id != selTask) $('#'+selTask).removeClass('clicked doubleclicked');
|
||||
selTask = li.id;
|
||||
|
|
@ -524,11 +519,11 @@ function getRecursParent(el, needle, level)
|
|||
return getRecursParent(el.parentNode, needle, level);
|
||||
}
|
||||
|
||||
function cancelTagFilter()
|
||||
function cancelTagFilter(dontLoadTasks)
|
||||
{
|
||||
$('#tagcloudbtn>.btnstr').text($('#tagcloudbtn').attr('title'));
|
||||
filter.tag = '';
|
||||
loadTasks();
|
||||
if(dontLoadTasks==null || !dontLoadTasks) loadTasks();
|
||||
}
|
||||
|
||||
function addFilterTag(tag)
|
||||
|
|
@ -540,10 +535,10 @@ function addFilterTag(tag)
|
|||
|
||||
function showAuth(el)
|
||||
{
|
||||
w = $('#authform');
|
||||
var w = $('#authform');
|
||||
if(w.css('display') == 'none')
|
||||
{
|
||||
offset = $(el).offset();
|
||||
var offset = $(el).offset();
|
||||
w.css({
|
||||
position: 'absolute',
|
||||
top: offset.top + el.offsetHeight + 3,
|
||||
|
|
@ -563,7 +558,7 @@ function prioPopup(act, el, id)
|
|||
clearTimeout(objPrio.timer);
|
||||
return;
|
||||
}
|
||||
offset = $(el).offset();
|
||||
var offset = $(el).offset();
|
||||
$('#priopopup').css({ position: 'absolute', top: offset.top + 1, left: offset.left + 1 });
|
||||
objPrio.taskId = id;
|
||||
objPrio.el = el;
|
||||
|
|
@ -575,7 +570,7 @@ function prioClick(prio, el)
|
|||
el.blur();
|
||||
prio = parseInt(prio);
|
||||
setAjaxErrorTrigger();
|
||||
nocache = '&rnd='+Math.random();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?setPrio='+objPrio.taskId+'&prio='+prio+nocache, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
});
|
||||
|
|
@ -588,10 +583,10 @@ function prioClick(prio, el)
|
|||
|
||||
function showSort(el)
|
||||
{
|
||||
w = $('#sortform');
|
||||
var w = $('#sortform');
|
||||
if(w.css('display') == 'none')
|
||||
{
|
||||
offset = $(el).offset();
|
||||
var offset = $(el).offset();
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left , 'min-width': $(el).width() }).show();
|
||||
$(document).bind("click", sortClose);
|
||||
}
|
||||
|
|
@ -613,7 +608,7 @@ function setSort(v, init)
|
|||
else $("#tasklist").sortable('disable');
|
||||
if(!init) {
|
||||
changeTaskOrder();
|
||||
exp = new Date();
|
||||
var exp = new Date();
|
||||
exp.setTime(exp.getTime() + 3650*86400*1000); //+10 years
|
||||
document.cookie = "sort="+sortBy+'; expires='+exp.toUTCString();
|
||||
}
|
||||
|
|
@ -640,7 +635,7 @@ function changeTaskOrder(id)
|
|||
{
|
||||
id = parseInt(id);
|
||||
if(taskOrder.length < 2) return;
|
||||
oldOrder = taskOrder.slice();
|
||||
var oldOrder = taskOrder.slice();
|
||||
if(sortBy == 0) taskOrder.sort( function(a,b){
|
||||
if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl;
|
||||
return taskList[a].ow-taskList[b].ow
|
||||
|
|
@ -662,55 +657,55 @@ function changeTaskOrder(id)
|
|||
if(id && taskList[id])
|
||||
{
|
||||
// optimization: determine where to insert task: top or after some task
|
||||
indx = $.inArray(id,taskOrder);
|
||||
var indx = $.inArray(id,taskOrder);
|
||||
if(indx ==0) {
|
||||
$('#tasklist').prepend($('#taskrow_'+id))
|
||||
} else {
|
||||
after = taskOrder[indx-1];
|
||||
var after = taskOrder[indx-1];
|
||||
$('#taskrow_'+after).after($('#taskrow_'+id));
|
||||
}
|
||||
}
|
||||
else {
|
||||
o = $('#tasklist');
|
||||
for(i in taskOrder) {
|
||||
var o = $('#tasklist');
|
||||
for(var i in taskOrder) {
|
||||
o.append($('#taskrow_'+taskOrder[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadTags(callback)
|
||||
{
|
||||
setAjaxErrorTrigger();
|
||||
$.getJSON('ajax.php?tagCloud&list='+curList.id+'&rnd='+Math.random(), function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) tagsList = [];
|
||||
else tagsList = json.cloud;
|
||||
var cloud = '';
|
||||
$.each(tagsList, function(i,item){
|
||||
cloud += '<a href="#" onClick=\'addFilterTag("'+item.tag+'");tagCloudClose();return false;\' class="tag w'+item.w+'" >'+item.tag+'</a>';
|
||||
});
|
||||
$('#tagcloudcontent').html(cloud)
|
||||
flag.tagsChanged = false;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function showTagCloud(el)
|
||||
{
|
||||
w = $('#tagcloud');
|
||||
var w = $('#tagcloud');
|
||||
if(w.css('display') == 'none')
|
||||
{
|
||||
if(flag.tagsChanged)
|
||||
{
|
||||
$('#tagcloudcontent').html('');
|
||||
$('#tagcloudload').show();
|
||||
offset = $(el).offset();
|
||||
l = Math.ceil(offset.left - w.outerWidth()/2 + $(el).outerWidth()/2);
|
||||
if(l<0) l=0;
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: l }).show();
|
||||
|
||||
setAjaxErrorTrigger();
|
||||
nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?tagCloud'+nocache, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
$('#tagcloudload').hide();
|
||||
if(!parseInt(json.total)) return;
|
||||
var cloud = '';
|
||||
$.each(json.cloud, function(i,item){
|
||||
cloud += '<a href="#" onClick=\'addFilterTag("'+item.tag+'");tagCloudClose();return false;\' class="tag w'+item.w+'" >'+item.tag+'</a>';
|
||||
});
|
||||
$('#tagcloudcontent').html(cloud)
|
||||
flag.tagsChanged = false;
|
||||
});
|
||||
var offset = $(el).offset();
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left }).show();
|
||||
loadTags(function(){$('#tagcloudload').hide();});
|
||||
}
|
||||
else {
|
||||
offset = $(el).offset();
|
||||
l = Math.ceil(offset.left - w.outerWidth()/2 + $(el).outerWidth()/2);
|
||||
if(l<0) l=0;
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: l }).show();
|
||||
var offset = $(el).offset();
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left }).show();
|
||||
}
|
||||
$(document).bind("click", tagCloudClose);
|
||||
}
|
||||
|
|
@ -731,12 +726,10 @@ function tagCloudClose(e)
|
|||
|
||||
function preloadImg()
|
||||
{
|
||||
for(i in img) {
|
||||
o = new Image();
|
||||
o.src = img[i][0];
|
||||
if(img[i][1] != img[i][0]) {
|
||||
o = new Image();
|
||||
o.src = img[i][1];
|
||||
for(var i in img) {
|
||||
for(var ii in img[i]) {
|
||||
var o = new Image();
|
||||
o.src = img[i][ii];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -745,7 +738,7 @@ function changeTaskCnt(cl, dir)
|
|||
{
|
||||
if(!dir) dir = 1;
|
||||
else if(dir > 0) dir = 1;
|
||||
else if(dir < 0) die = -1;
|
||||
else if(dir < 0) dir = -1;
|
||||
if(cl == 'soon') { taskCnt.soon += dir; return true; }
|
||||
else if(cl == 'today') { taskCnt.today += dir; return true; }
|
||||
else if(cl == 'past') { taskCnt.past+= dir; return true; }
|
||||
|
|
@ -760,10 +753,10 @@ function refreshTaskCnt()
|
|||
|
||||
function showTaskview(el)
|
||||
{
|
||||
w = $('#taskview');
|
||||
var w = $('#taskview');
|
||||
if(w.css('display') == 'none')
|
||||
{
|
||||
offset = $(el).offset();
|
||||
var offset = $(el).offset();
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left , 'min-width': $(el).width() }).show();
|
||||
$(document).bind("click", taskviewClose);
|
||||
}
|
||||
|
|
@ -782,7 +775,7 @@ function taskviewClose(e)
|
|||
$('#taskview').hide();
|
||||
}
|
||||
|
||||
function setTaskview(v)
|
||||
function setTaskview(v, dontLoadTasks)
|
||||
{
|
||||
if(v == 0)
|
||||
{
|
||||
|
|
@ -796,7 +789,7 @@ function setTaskview(v)
|
|||
if(filter.compl != 0) {
|
||||
filter.compl = 0;
|
||||
$('#total').text('...');
|
||||
loadTasks();
|
||||
if(dontLoadTasks==null || !dontLoadTasks) loadTasks();
|
||||
}
|
||||
}
|
||||
else if(v == 1)
|
||||
|
|
@ -829,15 +822,238 @@ function setTaskview(v)
|
|||
|
||||
function editFormResize(startstop, event)
|
||||
{
|
||||
f = $('#page_taskedit');
|
||||
var f = $('#page_taskedit');
|
||||
if(startstop == 1) {
|
||||
tmp.editformdiff = f.height() - $('#page_taskedit textarea').height();
|
||||
}
|
||||
else if(startstop == 2) {
|
||||
//to avoid bug http://dev.jqueryui.com/ticket/3628
|
||||
if(f.is('.ui-draggable')) {
|
||||
f.css('left',tmp.editformpos[0]).css('top',tmp.editformpos[1]).css('position', 'fixed');
|
||||
f.css( {left:tmp.editformpos[0], top:tmp.editformpos[1], height:''} ).css('position', 'fixed');
|
||||
}
|
||||
}
|
||||
else $('#page_taskedit textarea').height(f.height() - tmp.editformdiff);
|
||||
}
|
||||
|
||||
function mttTabSelected(el, indx)
|
||||
{
|
||||
|
||||
$(el.parentNode.parentNode).children('.mtt-tabs-selected').removeClass('mtt-tabs-selected');
|
||||
$(el.parentNode).addClass('mtt-tabs-selected');
|
||||
if(!tabLists[indx]) return;
|
||||
if(indx != curList.i) {
|
||||
$('#tasklist').html('');
|
||||
if(filter.search != '') {
|
||||
filter.search = '';
|
||||
$('#searchbarkeyword').text('');
|
||||
$('#searchbar').hide();
|
||||
}
|
||||
}
|
||||
curList = tabLists[indx];
|
||||
flag.tagsChanged = true;
|
||||
cancelTagFilter(1);
|
||||
setTaskview(0, 1);
|
||||
loadTasks();
|
||||
}
|
||||
|
||||
function btnMenu(el)
|
||||
{
|
||||
if(!el.id) return;
|
||||
oBtnMenu.container = el.id+'container';
|
||||
oBtnMenu.targets = [el.id, oBtnMenu.container];
|
||||
var w = $('#'+oBtnMenu.container);
|
||||
if(w.css('display') == 'none')
|
||||
{
|
||||
oBtnMenu.h = [];
|
||||
$(w).children('.li').each( function(i,o){
|
||||
if(o.onclick) {
|
||||
oBtnMenu.h[i] = o.onclick;
|
||||
$(o).bind("click2", o.onclick);
|
||||
o.onclick = function(event) { $('#'+oBtnMenu.container).hide(); $(o).trigger('click2'); btnMenuClose(); }
|
||||
} else {
|
||||
oBtnMenu.h[i] = null;
|
||||
}
|
||||
} );
|
||||
var offset = $(el).offset();
|
||||
w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left , 'min-width': $(el).width() }).show();
|
||||
$(document).bind("click", btnMenuClose);
|
||||
}
|
||||
else {
|
||||
el.blur();
|
||||
btnMenuClose();
|
||||
}
|
||||
}
|
||||
|
||||
function btnMenuClose(e)
|
||||
{
|
||||
if(e) {
|
||||
if(isParentId(e.target, oBtnMenu.targets)) return;
|
||||
}
|
||||
$(document).unbind("click", btnMenuClose);
|
||||
$('#'+oBtnMenu.container).hide().children('.li').each( function(i,o){
|
||||
if(oBtnMenu.h[i]) {
|
||||
o.onclick = oBtnMenu.h[i];
|
||||
$(o).unbind('click2');
|
||||
}
|
||||
});
|
||||
oBtnMenu = {};
|
||||
}
|
||||
|
||||
function toggleNote(id)
|
||||
{
|
||||
var o = $('#taskrow_'+id+'>div>div.task-note-block');
|
||||
if(o.is('.hidden')) $('#taskrow_'+id+' .mtt-toggle').addClass('mtt-toggle-expanded');
|
||||
else $('#taskrow_'+id+' .mtt-toggle').removeClass('mtt-toggle-expanded');
|
||||
o.toggleClass('hidden');
|
||||
}
|
||||
|
||||
function toggleAllNotes(show)
|
||||
{
|
||||
for(var id in taskList)
|
||||
{
|
||||
if(taskList[id].note == '') continue;
|
||||
if(show) {
|
||||
$('#taskrow_'+id+' .mtt-toggle').addClass('mtt-toggle-expanded');
|
||||
$('#taskrow_'+id+'>div>div.task-note-block').removeClass('hidden');
|
||||
}
|
||||
else {
|
||||
$('#taskrow_'+id+' .mtt-toggle').removeClass('mtt-toggle-expanded');
|
||||
$('#taskrow_'+id+'>div>div.task-note-block').addClass('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadLists(onInit)
|
||||
{
|
||||
if(flag.needAuth && !flag.isLogged && !flag.canAllRead) return false;
|
||||
if(filter.search != '') {
|
||||
filter.search = '';
|
||||
$('#searchbarkeyword').text('');
|
||||
$('#searchbar').hide();
|
||||
}
|
||||
setAjaxErrorTrigger();
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.getJSON('ajax.php?loadLists'+nocache, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) {
|
||||
$('#page_tasks').hide();
|
||||
return;
|
||||
}
|
||||
tabLists = new Array();
|
||||
var ti = '';
|
||||
$.each(json.list, function(i,item){
|
||||
item.i = i;
|
||||
tabLists[i] = item;
|
||||
ti += '<li class="'+(i==0?'mtt-tabs-selected':'')+'"><a href="#list'+item.id+'" onClick="mttTabSelected(this,'+i+');return false;">'+item.name+'</a></li>';
|
||||
});
|
||||
$('#lists>ul').html(ti);
|
||||
$('#lists').show();
|
||||
curList = tabLists[0];
|
||||
loadTasks();
|
||||
});
|
||||
}
|
||||
|
||||
function addList()
|
||||
{
|
||||
var r = prompt(lang.addList, lang.addListDefault);
|
||||
if(r == null) return;
|
||||
setAjaxErrorTrigger()
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?'+nocache, { addList:1, name:r }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
var item = json.list[0];
|
||||
var i = tabLists.length;
|
||||
item.i = i;
|
||||
tabLists[i] = item;
|
||||
$('#lists>ul').append('<li><a href="#list'+item.id+'" onClick="mttTabSelected(this,'+i+');return false;">'+item.name+'</a></li>');
|
||||
}, 'json');
|
||||
}
|
||||
|
||||
function renameCurList()
|
||||
{
|
||||
if(!curList) return;
|
||||
var r = prompt(lang.renameList, dehtml(curList.name));
|
||||
if(r == null || r == '') return;
|
||||
setAjaxErrorTrigger()
|
||||
var nocache = '&rnd='+Math.random();
|
||||
$.post('ajax.php?'+nocache, { renameList:1, id:curList.id, name:r }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
var item = json.list[0];
|
||||
item.i = curList.i;
|
||||
tabLists[curList.i] = item;
|
||||
curList = item;
|
||||
$('#lists>ul>.mtt-tabs-selected>a').html(item.name);
|
||||
}, 'json');
|
||||
}
|
||||
|
||||
function deleteCurList()
|
||||
{
|
||||
var r = confirm(lang.deleteList);
|
||||
if(!r) return;
|
||||
setAjaxErrorTrigger()
|
||||
$.post('ajax.php?'+'&rnd='+Math.random(), { deleteList:1, id:curList.id }, function(json){
|
||||
resetAjaxErrorTrigger();
|
||||
if(!parseInt(json.total)) return;
|
||||
loadLists();
|
||||
}, 'json');
|
||||
|
||||
}
|
||||
|
||||
function addsearchToggle(toSearch)
|
||||
{
|
||||
if(toSearch)
|
||||
{
|
||||
showhide($('#htab_search'), $('#htab_newtask'));
|
||||
$('#search').focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flag.needAuth && flag.canAllRead && !flag.isLogged) return false;
|
||||
showhide($('#htab_newtask'), $('#htab_search'));
|
||||
// reload tasks when we return to task tab (from search tab)
|
||||
if(filter.search != '') {
|
||||
filter.search = '';
|
||||
$('#searchbarkeyword').text('');
|
||||
$('#searchbar').hide();
|
||||
loadTasks();
|
||||
}
|
||||
$('#task').focus();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleEditAllTags(show)
|
||||
{
|
||||
if(show)
|
||||
{
|
||||
if(flag.tagsChanged) loadTags(fillEditAllTags);
|
||||
else fillEditAllTags();
|
||||
showhide($('#alltags_hide'), $('#alltags_show'));
|
||||
}
|
||||
else {
|
||||
$('#alltags').hide();
|
||||
showhide($('#alltags_show'), $('#alltags_hide'))
|
||||
}
|
||||
}
|
||||
|
||||
function fillEditAllTags()
|
||||
{
|
||||
var a = [];
|
||||
for(var i=tagsList.length-1; i>=0; i--) {
|
||||
a.push('<a href="#" class="tag" onClick=\'addEditTag("'+tagsList[i].tag+'");return false\'>'+tagsList[i].tag+'</a>');
|
||||
}
|
||||
$('#alltags .tags-list').html(a.join(', '));
|
||||
$('#alltags').show();
|
||||
}
|
||||
|
||||
function addEditTag(tag)
|
||||
{
|
||||
var v = $('#edittags').val();
|
||||
if(v == '') {
|
||||
$('#edittags').val(tag);
|
||||
return;
|
||||
}
|
||||
var r = v.search(new RegExp('(^|,)\\s*'+tag+'\\s*(,|$)'));
|
||||
if(r < 0) $('#edittags').val(v+', '+tag);
|
||||
}
|
||||
|
|
|
|||
105
src/ajax.php
105
src/ajax.php
|
|
@ -8,16 +8,31 @@ require_once('./lang/class.default.php');
|
|||
require_once('./lang/'.$config['lang'].'.php');
|
||||
$lang = new Lang();
|
||||
|
||||
if(isset($_GET['loadTasks']))
|
||||
if(isset($_GET['loadLists']))
|
||||
{
|
||||
check_read_access();
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$q = $db->dq("SELECT * FROM lists ORDER BY id ASC");
|
||||
while($r = $q->fetch_assoc($q))
|
||||
{
|
||||
$t['total']++;
|
||||
$t['list'][] = array('id'=>$r['id'], 'name'=>htmlarray($r['name']));
|
||||
}
|
||||
echo json_encode($t);
|
||||
exit;
|
||||
}
|
||||
elseif(isset($_GET['loadTasks']))
|
||||
{
|
||||
check_read_access();
|
||||
stop_gpc($_GET);
|
||||
if(_get('compl')) $sqlWhere = '';
|
||||
else $sqlWhere = ' AND compl=0';
|
||||
$listId = (int)_get('list');
|
||||
$sqlWhere = ' AND list_id='. $listId;
|
||||
if(_get('compl') == 0) $sqlWhere .= ' AND compl=0';
|
||||
$inner = '';
|
||||
$tag = trim(_get('t'));
|
||||
if($tag != '') {
|
||||
$tag_id = get_tag_id($tag);
|
||||
$tag_id = get_tag_id($tag, $listId);
|
||||
$inner = "INNER JOIN tag2task ON id=tag2task.task_id";
|
||||
$sqlWhere .= " AND tag_id=$tag_id ";
|
||||
}
|
||||
|
|
@ -48,6 +63,7 @@ elseif(isset($_GET['newTask']))
|
|||
stop_gpc($_POST);
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$listId = (int)_post('list');
|
||||
$title = trim(_post('title'));
|
||||
$prio = 0;
|
||||
$tags = '';
|
||||
|
|
@ -70,13 +86,13 @@ elseif(isset($_GET['newTask']))
|
|||
$tz = (int)_post('tz');
|
||||
if( (isset($config['autotz']) && $config['autotz']==0) || $tz<-720 || $tz>720 || $tz%30!=0 ) $d = strftime("%Y-%m-%d %H:%M:%S");
|
||||
else $d = gmdate("Y-m-d H:i:s", time()+$tz*60);
|
||||
$ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM todolist WHERE compl=0");
|
||||
$ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM todolist WHERE list_id=$listId AND compl=0");
|
||||
$db->ex("BEGIN");
|
||||
$db->dq("INSERT INTO todolist (title,d,ow,prio) VALUES (?,?,$ow,$prio)", array($title, $d));
|
||||
$db->dq("INSERT INTO todolist (list_id,title,d,ow,prio) VALUES ($listId,?,?,$ow,$prio)", array($title, $d));
|
||||
$id = $db->last_insert_id();
|
||||
if($tags)
|
||||
{
|
||||
$tag_ids = prepare_tags($tags);
|
||||
$tag_ids = prepare_tags($tags, $listId);
|
||||
if($tag_ids) {
|
||||
update_task_tags($id, $tag_ids);
|
||||
$db->ex("UPDATE todolist SET tags=? WHERE id=$id", $tags);
|
||||
|
|
@ -156,6 +172,7 @@ elseif(isset($_GET['editTask']))
|
|||
check_write_access();
|
||||
$id = (int)$_GET['editTask'];
|
||||
stop_gpc($_POST);
|
||||
$listId = (int)_post('list');
|
||||
$title = trim(_post('title'));
|
||||
$note = str_replace("\r\n", "\n", trim(_post('note')));
|
||||
$prio = (int)_post('prio');
|
||||
|
|
@ -170,7 +187,7 @@ elseif(isset($_GET['editTask']))
|
|||
}
|
||||
$tags = trim(_post('tags'));
|
||||
$db->ex("BEGIN");
|
||||
$tag_ids = prepare_tags($tags);
|
||||
$tag_ids = prepare_tags($tags, $listId);
|
||||
$cur_ids = get_task_tags($id);
|
||||
if($cur_ids) {
|
||||
$ids = implode(',', $cur_ids);
|
||||
|
|
@ -245,10 +262,11 @@ elseif(isset($_GET['logout']))
|
|||
elseif(isset($_GET['suggestTags']))
|
||||
{
|
||||
check_read_access();
|
||||
$listId = (int)_get('list');
|
||||
$begin = trim(_get('q'));
|
||||
$limit = (int)_get('limit');
|
||||
if($limit<1) $limit = 8;
|
||||
$q = $db->dq("SELECT name,id FROM tags WHERE name LIKE ". $db->quoteForLike('%s%%',$begin). " AND tags_count>0 ORDER BY name LIMIT $limit");
|
||||
$q = $db->dq("SELECT name,id FROM tags WHERE list_id=$listId AND name LIKE ". $db->quoteForLike('%s%%',$begin). " AND tags_count>0 ORDER BY name LIMIT $limit");
|
||||
$s = '';
|
||||
while($r = $q->fetch_row()) {
|
||||
$s .= "$r[0]|$r[1]\n";
|
||||
|
|
@ -272,8 +290,9 @@ elseif(isset($_GET['setPrio']))
|
|||
}
|
||||
elseif(isset($_GET['tagCloud']))
|
||||
{
|
||||
$listId = (int)_get('list');
|
||||
$a = array();
|
||||
$q = $db->dq("SELECT name,tags_count FROM tags WHERE tags_count>0 ORDER BY tags_count ASC");
|
||||
$q = $db->dq("SELECT name,tags_count FROM tags WHERE list_id=$listId AND tags_count>0 ORDER BY tags_count ASC");
|
||||
while($r = $q->fetch_row()) {
|
||||
$a[$r[0]] = $r[1];
|
||||
}
|
||||
|
|
@ -296,8 +315,60 @@ elseif(isset($_GET['tagCloud']))
|
|||
echo json_encode($t);
|
||||
exit;
|
||||
}
|
||||
elseif(isset($_POST['addList']))
|
||||
{
|
||||
check_write_access();
|
||||
stop_gpc($_POST);
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name')));
|
||||
$db->dq("INSERT INTO lists (name) VALUES (?)", array($name));
|
||||
$id = $db->last_insert_id();
|
||||
$t['total'] = 1;
|
||||
$r = $db->sqa("SELECT * FROM lists WHERE id=$id");
|
||||
$t['list'][] = array('id'=>$r['id'], 'name'=>htmlarray($r['name']));
|
||||
echo json_encode($t);
|
||||
exit;
|
||||
}
|
||||
elseif(isset($_POST['renameList']))
|
||||
{
|
||||
check_write_access();
|
||||
stop_gpc($_POST);
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$id = (int)_post('id');
|
||||
$name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name')));
|
||||
$db->dq("UPDATE lists SET name=? WHERE id=$id", array($name));
|
||||
$t['total'] = $db->affected();
|
||||
$r = $db->sqa("SELECT * FROM lists WHERE id=$id");
|
||||
$t['list'][] = array('id'=>$r['id'], 'name'=>htmlarray($r['name']));
|
||||
echo json_encode($t);
|
||||
exit;
|
||||
}
|
||||
elseif(isset($_POST['deleteList']))
|
||||
{
|
||||
check_write_access();
|
||||
stop_gpc($_POST);
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$id = (int)_post('id');
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("DELETE FROM lists WHERE id=$id");
|
||||
$t['total'] = $db->affected();
|
||||
if($t['total']) {
|
||||
$db->ex("DELETE FROM tags WHERE list_id=$id");
|
||||
# sqlite doesnt support DELETE FROM INNNER JOIN
|
||||
$db->ex("DELETE FROM tag2task WHERE task_id IN (SELECT id FROM todolist WHERE list_id=$id)");
|
||||
$db->ex("DELETE FROM todolist WHERE list_id=$id");
|
||||
}
|
||||
$db->ex("COMMIT");
|
||||
echo json_encode($t);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
###################################################################################################
|
||||
|
||||
function prepareTaskRow($r, $tz=null)
|
||||
{
|
||||
$dueA = prepare_duedate($r['duedate'], $tz);
|
||||
|
|
@ -334,7 +405,7 @@ function check_write_access()
|
|||
exit;
|
||||
}
|
||||
|
||||
function prepare_tags(&$tags_str)
|
||||
function prepare_tags(&$tags_str, $listId)
|
||||
{
|
||||
$tag_ids = array();
|
||||
$tag_names = array();
|
||||
|
|
@ -344,7 +415,7 @@ function prepare_tags(&$tags_str)
|
|||
# remove duplicate tags?
|
||||
$tag = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim($v));
|
||||
if($tag == '') continue;
|
||||
list($tag_id,$tag_name) = get_or_create_tag($tag);
|
||||
list($tag_id,$tag_name) = get_or_create_tag($tag, $listId);
|
||||
if($tag_id && !in_array($tag_id, $tag_ids)) {
|
||||
$tag_ids[] = $tag_id;
|
||||
$tag_names[] = $tag_name;
|
||||
|
|
@ -354,21 +425,21 @@ function prepare_tags(&$tags_str)
|
|||
return $tag_ids;
|
||||
}
|
||||
|
||||
function get_or_create_tag($name)
|
||||
function get_or_create_tag($name, $listId)
|
||||
{
|
||||
global $db;
|
||||
$tag = $db->sq("SELECT id,name FROM tags WHERE name=?", $name);
|
||||
$tag = $db->sq("SELECT id,name FROM tags WHERE list_id=? AND name=?", array($listId, $name));
|
||||
if($tag) return $tag;
|
||||
|
||||
# need to create tag
|
||||
$db->ex("INSERT INTO tags (name) VALUES (?)", $name);
|
||||
$db->ex("INSERT INTO tags (name,list_id) VALUES (?,?)", array($name,$listId));
|
||||
return array($db->last_insert_id(), $name);
|
||||
}
|
||||
|
||||
function get_tag_id($tag)
|
||||
function get_tag_id($tag, $listId)
|
||||
{
|
||||
global $db;
|
||||
$id = $db->sq("SELECT id FROM tags WHERE name=?", $tag);
|
||||
$id = $db->sq("SELECT id FROM tags WHERE list_id=? AND name=?", array($listId, $tag));
|
||||
return $id ? $id : 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,158 +0,0 @@
|
|||
<?php
|
||||
|
||||
class DatabaseResult_Sqlite
|
||||
{
|
||||
private $parent;
|
||||
private $q;
|
||||
var $query;
|
||||
private $rows = NULL;
|
||||
private $affected = NULL;
|
||||
|
||||
function __construct($query, &$h, $resultless = 0)
|
||||
{
|
||||
$this->parent = $h;
|
||||
$this->query = $query;
|
||||
|
||||
if($resultless) $this->q = @$this->parent->dbh->queryExec($query, $error);
|
||||
else $this->q = @$this->parent->dbh->query($query, 0, $error);
|
||||
|
||||
if(!$this->q)
|
||||
{
|
||||
if($error) throw new Exception($error);
|
||||
else throw new Exception(sqlite_error_string($this->parent->dbh->lastError()));
|
||||
}
|
||||
}
|
||||
|
||||
function rows()
|
||||
{
|
||||
if (!is_null($this->rows)) return $this->rows;
|
||||
$this->rows = $this->q->numRows();
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
function fetch_row()
|
||||
{
|
||||
return $this->q->fetch(SQLITE_NUM);
|
||||
}
|
||||
|
||||
function fetch_assoc()
|
||||
{
|
||||
return $this->q->fetch(SQLITE_ASSOC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Database_Sqlite
|
||||
{
|
||||
var $dbh;
|
||||
private $affected = null;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
function connect($filename, $mode=0666)
|
||||
{
|
||||
try {
|
||||
$this->dbh = new SQLiteDatabase($filename, 0666, $error);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
throw new Exception($error);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
if($q->rows()) $res = $q->fetch_row();
|
||||
else return NULL;
|
||||
|
||||
if(sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
if($q->rows()) $res = $q->fetch_assoc();
|
||||
else return NULL;
|
||||
|
||||
if(sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
|
||||
function dq($query, $p = NULL)
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
return $this->_dq($query, $p, 1);
|
||||
}
|
||||
|
||||
private function _dq($query, $p = NULL, $resultless = 0)
|
||||
{
|
||||
if(!isset($p)) $p = array();
|
||||
elseif(!is_array($p)) $p = array($p);
|
||||
|
||||
$m = explode('?', $query);
|
||||
|
||||
if(sizeof($p)>0)
|
||||
{
|
||||
if(sizeof($m)< sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if(sizeof($m)> sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for($i=0; $i<sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. $this->quote($p[$i]);
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
return new DatabaseResult_Sqlite($query, $this, $resultless);
|
||||
}
|
||||
|
||||
function affected()
|
||||
{
|
||||
if(is_null($this->affected))
|
||||
{
|
||||
$this->affected = $this->dbh->changes();
|
||||
}
|
||||
return $this->affected;
|
||||
}
|
||||
|
||||
function quote($s)
|
||||
{
|
||||
return '\''. sqlite_escape_string($s). '\'';
|
||||
}
|
||||
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('\\','%','_'), array('\\\\','\%','\_'), $s);
|
||||
return $this->quote(sprintf($format, $s));
|
||||
}
|
||||
|
||||
function last_insert_id()
|
||||
{
|
||||
return $this->dbh->lastInsertRowid();
|
||||
}
|
||||
|
||||
function table_exists($table)
|
||||
{
|
||||
$table = $this->quote($table);
|
||||
$q = @$this->dbh->query("SELECT 1 FROM $table WHERE 1=0");
|
||||
if($q === false) return false;
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -6,9 +6,6 @@ $config = array();
|
|||
# Uncomment this line if you want to use Mysql, in format: array("host","login","password","database");
|
||||
#$config['mysql'] = array("localhost","user","password", "mytinytodo");
|
||||
|
||||
# To use old SQLite2 (instead of SQLite3) uncomment the line below
|
||||
#$config['sqlite'] = 2;
|
||||
|
||||
# Language pack
|
||||
$config['lang'] = "en";
|
||||
|
||||
|
|
|
|||
BIN
src/images/toggle_minus.gif
Normal file
BIN
src/images/toggle_minus.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 83 B |
BIN
src/images/toggle_plus.gif
Normal file
BIN
src/images/toggle_plus.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 B |
|
|
@ -56,10 +56,9 @@ function __($s)
|
|||
|
||||
<script type="text/javascript">
|
||||
$().ready(function(){
|
||||
$("#tabs").tabs({ select: tabSelected <?php echo $tabDisabled; ?>});
|
||||
$("#tasklist").sortable({cancel:'span,input,a,textarea', delay: 150, update:orderChanged, start:sortStart, items:'> :not(.task-completed)'});
|
||||
$("#tasklist").bind("click", tasklistClick);
|
||||
$("#edittags").autocomplete('ajax.php?suggestTags', {scroll: false, multiple: true, selectFirst:false, max:8});
|
||||
$("#edittags").autocomplete('ajax.php?suggestTags', {scroll: false, multiple: true, selectFirst:false, max:8, extraParams:{list:function(){return curList.id}}});
|
||||
$("#priopopup").mouseleave(function(){$(this).hide()});
|
||||
setSort(<?php echo $sort; ?>,1);
|
||||
<?php
|
||||
|
|
@ -68,19 +67,17 @@ $().ready(function(){
|
|||
echo "\tflag.needAuth = true;\n";
|
||||
if(!canAllRead()) echo "\tflag.canAllRead = false;\n";
|
||||
if(is_logged()) echo "\tflag.isLogged = true;\n";
|
||||
if(is_logged() || canAllRead()) echo "\tloadTasks();\n";
|
||||
echo "\tupdateAccessStatus(1);\n";
|
||||
} else {
|
||||
echo "\tloadTasks();\n";
|
||||
echo "\tupdateAccessStatus();\n";
|
||||
}
|
||||
echo "\tloadLists(1)\n";
|
||||
?>
|
||||
preloadImg();
|
||||
$("#duedate").datepicker({dateFormat: '<?php echo $duedateformat; ?>', firstDay: <?php echo $config['firstdayofweek']; ?>,
|
||||
showOn: 'button', buttonImage: 'images/calendar.png', buttonImageOnly: true, changeMonth:true,
|
||||
changeYear:true, constrainInput: false, duration:'', nextText:'>', prevText:'<', dayNamesMin:lang.daysMin,
|
||||
monthNamesShort:lang.monthsShort });
|
||||
monthNamesShort:lang.monthsLong });
|
||||
<?php if(!isset($_GET['pda'])): ?>
|
||||
$("#page_taskedit").draggable({ stop: function(e,ui){ flag.windowTaskEditMoved=true; tmp.editformpos=[$(this).css('left'),$(this).css('top')]; } });
|
||||
$("#page_taskedit").draggable({ handle:'h3', stop: function(e,ui){ flag.windowTaskEditMoved=true; tmp.editformpos=[$(this).css('left'),$(this).css('top')]; } });
|
||||
$("#page_taskedit").resizable({ minWidth:$("#page_taskedit").width(), minHeight:$("#page_taskedit").height(), start:function(ui,e){editFormResize(1)}, resize:function(ui,e){editFormResize(0,e)}, stop:function(ui,e){editFormResize(2,e)} });
|
||||
<?php endif; ?>
|
||||
|
||||
|
|
@ -99,9 +96,17 @@ $().ajaxStop( function(r,s) {$("#loading").fadeOut();} );
|
|||
|
||||
<div id="bar">
|
||||
<div style="float:left"><span id="msg" onClick="toggleMsgDetails()"></span><div id="msgdetails"></div></div>
|
||||
<div id="bar_auth" align="right">
|
||||
<span id="bar_login"><span id="authstr"> </span> <a href="#" class="nodecor" onClick="showAuth(this);return false;"><u><?php __('a_login');?></u> <img src="images/arrdown.gif" border=0></a></span>
|
||||
<div align="right">
|
||||
<span class="menu-owner">
|
||||
<a href="#" id="mylists" class="nodecor" onClick="btnMenu(this);return false;"><u>My lists</u> <img src="images/arrdown.gif" border=0></a> |
|
||||
<a href="settings.php">Settings</a>
|
||||
</span>
|
||||
<span class="bar-delim" style="display:none"> | </span>
|
||||
<span id="bar_auth">
|
||||
<span id="bar_login"><a href="#" class="nodecor" onClick="showAuth(this);return false;"><u><?php __('a_login');?></u> <img src="images/arrdown.gif" border=0></a></span>
|
||||
<span id="authstr"> </span>
|
||||
<a href="#" id="bar_logout" onClick="logout();return false"><?php __('a_logout');?></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -109,23 +114,26 @@ $().ajaxStop( function(r,s) {$("#loading").fadeOut();} );
|
|||
|
||||
<div id="page_tasks">
|
||||
|
||||
<div id="tabs">
|
||||
<ul class="">
|
||||
<li><a href="#newtask"><?php __('tab_newtask');?></a></li>
|
||||
<li><a href="#searchtask"><?php __('tab_search');?></a></li>
|
||||
</ul><br clear="all">
|
||||
<div class="tab-content" id="newtask">
|
||||
<form onSubmit="return submitNewTask(this)"><input type="text" name="task" value="" maxlength="250" id="task"> <input type="submit" value="<?php __('btn_add');?>"></form>
|
||||
</div>
|
||||
<div class="tab-content" id="searchtask">
|
||||
<form onSubmit="return searchTasks()"><input type="text" name="search" value="" maxlength="250" id="search" onKeyUp="timerSearch()" autocomplete="off"> <input type="submit" value="<?php __('btn_search');?>"></form>
|
||||
<div id="searchbar"><?php __('searching');?> <span id="searchbarkeyword"></span></div>
|
||||
</div>
|
||||
<div id="lists" class="mtt-tabs">
|
||||
<ul class=""></ul>
|
||||
<div class="mtt-htabs">
|
||||
<span id="htab_newtask"><?php __('htab_newtask');?> <form onSubmit="return submitNewTask(this)"><input type="text" name="task" value="" maxlength="250" id="task"> <input type="submit" value="<?php __('btn_add');?>"></form>
|
||||
| <a href="#" class="htab-toggle" onClick="addsearchToggle(1);this.blur();return false;"><?php __('htab_search');?></a>
|
||||
</span>
|
||||
|
||||
<span id="htab_search" style="display:none">
|
||||
<a href="#" class="htab-toggle" onClick="addsearchToggle(0);this.blur();return false;"><?php __('htab_newtask');?></a> |
|
||||
<?php __('htab_search');?> <form onSubmit="return searchTasks()"><input type="text" name="search" value="" maxlength="250" id="search" onKeyUp="timerSearch()" autocomplete="off"> <input type="submit" value="<?php __('btn_search');?>"></form>
|
||||
<div id="searchbar"><?php __('searching');?> <span id="searchbarkeyword"></span></div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3><span id="taskviewcontainer" onClick="showTaskview(this);"><span class="btnstr"><?php __('tasks');?></span> (<span id="total">0</span>) <img src="images/arrdown.gif"></span>
|
||||
<span id="sort" onClick="showSort(this);"><span class="btnstr"></span> <img src="images/arrdown.gif"></span>
|
||||
|
||||
<h3>
|
||||
<span id="sort" onClick="showSort(this);" style="float:right"><span class="btnstr"></span> <img src="images/arrdown.gif"></span>
|
||||
<span id="taskviewcontainer" onClick="showTaskview(this);"><span class="btnstr"><?php __('tasks');?></span> (<span id="total">0</span>) <img src="images/arrdown.gif"></span>
|
||||
<span id="tagcloudbtn" onClick="showTagCloud(this);" title="<?php __('tags');?>"><span class="btnstr"><?php __('tags');?></span> <img src="images/arrdown.gif"></span>
|
||||
<span class="mtt-notes-showhide"><?php __('notes');?> <a href="#" onClick="toggleAllNotes(1);this.blur();return false;"><?php __('notes_show');?></a> / <a href="#" onClick="toggleAllNotes(0);this.blur();return false;"><?php __('notes_hide');?></a></span>
|
||||
</h3>
|
||||
|
||||
<div id="taskcontainer">
|
||||
|
|
@ -143,9 +151,17 @@ $().ajaxStop( function(r,s) {$("#loading").fadeOut();} );
|
|||
<input type="hidden" name="id" value="">
|
||||
<div class="form-row"><span class="h"><?php __('priority');?></span> <SELECT name="prio"><option value="2">+2</option><option value="1">+1</option><option value="0" selected>±0</option><option value="-1">−1</option></SELECT>
|
||||
<span class="h"><?php __('due');?> </span> <input name="duedate" id="duedate" value="" class="in100" title="Y-M-D, M/D/Y, D.M.Y, M/D, D.M" autocomplete="off"></div>
|
||||
<div class="form-row"><span class="h"><?php __('task');?></span><br> <input type="text" name="task" value="" class="in500" maxlength="250"></div>
|
||||
<div class="form-row"><span class="h"><?php __('note');?></span><br> <textarea name="note" class="in500"></textarea></div>
|
||||
<div class="form-row"><span class="h"><?php __('tags');?></span><br> <input type="text" name="tags" id="edittags" value="" class="in500" maxlength="250"></div>
|
||||
<div class="form-row"><div class="h"><?php __('task');?></div> <input type="text" name="task" value="" class="in500" maxlength="250"></div>
|
||||
<div class="form-row"><div class="h"><?php __('note');?></div> <textarea name="note" class="in500"></textarea></div>
|
||||
<div class="form-row"><div class="h"><?php __('tags');?></div>
|
||||
<table cellspacing="0" cellpadding="0" width="100%"><tr>
|
||||
<td><input type="text" name="tags" id="edittags" value="" class="in500" maxlength="250"></td>
|
||||
<td width="1" style="white-space:nowrap; padding-left:5px; text-align:right;">
|
||||
<a href="#" id="alltags_show" onClick="toggleEditAllTags(1);return false;"><?php __('alltags_show');?></a>
|
||||
<a href="#" id="alltags_hide" onClick="toggleEditAllTags(0);return false;" style="display:none"><?php __('alltags_hide');?></a></td>
|
||||
</tr></table>
|
||||
</div>
|
||||
<div class="form-row" id="alltags" style="display:none;"><?php __('alltags');?> <span class="tags-list"></span></div>
|
||||
<div class="form-row"><input type="submit" value="<?php __('save');?>" onClick="this.blur()"> <input type="button" value="<?php __('cancel');?>" onClick="cancelEdit();this.blur();return false"></div>
|
||||
</form>
|
||||
|
||||
|
|
@ -183,6 +199,12 @@ $().ajaxStop( function(r,s) {$("#loading").fadeOut();} );
|
|||
<div id="tagcloudcontent"></div>
|
||||
</div>
|
||||
|
||||
<div id="mylistscontainer" class="mtt-btnmenu-container" style="display:none">
|
||||
<div class="li" onClick="addList()"><?php __('list_new');?></div>
|
||||
<div class="li" onClick="renameCurList()"><?php __('list_rename');?></div>
|
||||
<div class="li" onClick="deleteCurList()"><?php __('list_delete');?></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="space"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,13 +20,17 @@ class DefaultLang
|
|||
'invalidpass' => "Wrong password",
|
||||
'readonly' => "read-only",
|
||||
'tagfilter' => "Tag:",
|
||||
'addList' => "Create new list",
|
||||
'addListDefault' => "Todo",
|
||||
'renameList' => "Rename list",
|
||||
'deleteList' => "This will delete current list with all tasks in it.\\nAre you sure?",
|
||||
);
|
||||
|
||||
private $default_inc = array
|
||||
(
|
||||
'My Tiny Todolist' => "My Tiny Todolist",
|
||||
'tab_newtask' => "new task",
|
||||
'tab_search' => "search",
|
||||
'htab_newtask' => "New task",
|
||||
'htab_search' => "Search",
|
||||
'btn_add' => "Add",
|
||||
'btn_search' => "Search",
|
||||
'searching' => "Searching for",
|
||||
|
|
@ -61,6 +65,15 @@ class DefaultLang
|
|||
'f_today' => "Today and tomorrow",
|
||||
'f_soon' => "Soon",
|
||||
'tasks_and_compl' => "Tasks + completed",
|
||||
'notes' => "Notes:",
|
||||
'notes_show' => "Show",
|
||||
'notes_hide' => "Hide",
|
||||
'list_new' => "New list",
|
||||
'list_rename' => "Rename",
|
||||
'list_delete' => "Delete",
|
||||
'alltags' => "All tags:",
|
||||
'alltags_show' => "Show all",
|
||||
'alltags_hide' => "Hide all",
|
||||
);
|
||||
|
||||
var $js = array();
|
||||
|
|
@ -83,8 +96,8 @@ class DefaultLang
|
|||
foreach($this->get('days_min') as $v) { $t[] = '"'.str_replace('"','\\"',$v).'"'; }
|
||||
$a[] = "daysMin: [". implode(',', $t). "]";
|
||||
$t = array();
|
||||
foreach($this->get('months_short') as $v) { $t[] = '"'.str_replace('"','\\"',$v).'"'; }
|
||||
$a[] = "monthsShort: [". implode(',', $t). "]";
|
||||
foreach($this->get('months_long') as $v) { $t[] = '"'.str_replace('"','\\"',$v).'"'; }
|
||||
$a[] = "monthsLong: [". implode(',', $t). "]";
|
||||
return "lang = {\n". implode(",\n", $a). "\n};";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,16 @@ class Lang extends DefaultLang
|
|||
'invalidpass' => "Wrong password",
|
||||
'readonly' => "read-only",
|
||||
'tagfilter' => "Tag:",
|
||||
'addList' => "Create new list",
|
||||
'renameList' => "Rename list",
|
||||
'deleteList' => "This will delete current list with all tasks in it.\\nAre you sure?",
|
||||
);
|
||||
|
||||
var $inc = array
|
||||
(
|
||||
'My Tiny Todolist' => "My Tiny Todolist",
|
||||
'tab_newtask' => "new task",
|
||||
'tab_search' => "search",
|
||||
'htab_newtask' => "New task",
|
||||
'htab_search' => "Search",
|
||||
'btn_add' => "Add",
|
||||
'btn_search' => "Search",
|
||||
'searching' => "Searching for",
|
||||
|
|
@ -57,6 +60,15 @@ class Lang extends DefaultLang
|
|||
'f_today' => "Today and tomorrow",
|
||||
'f_soon' => "Soon",
|
||||
'tasks_and_compl' => "Tasks + completed",
|
||||
'notes' => "Notes:",
|
||||
'notes_show' => "Show",
|
||||
'notes_hide' => "Hide",
|
||||
'list_new' => "New list",
|
||||
'list_rename' => "Rename",
|
||||
'list_delete' => "Delete",
|
||||
'alltags' => "All tags:",
|
||||
'alltags_show' => "Show all",
|
||||
'alltags_hide' => "Hide all",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
119
src/setup.php
119
src/setup.php
|
|
@ -14,15 +14,10 @@ if($needAuth && !is_logged())
|
|||
$dbclass = strtolower(get_class($db));
|
||||
$dbtype = ($dbclass == 'database_mysql') ? 'mysql' : 'sqlite';
|
||||
|
||||
$lastVer = '1.2';
|
||||
$lastVer = '1.3';
|
||||
echo '<html><head><meta name="robots" content="noindex,nofollow"></head><body>';
|
||||
echo "<b>myTinyTodo v$lastVer Setup</b><br><br>";
|
||||
|
||||
# exclude sqlite2
|
||||
if($dbclass == 'database_sqlite') {
|
||||
exitMessage("Install/update is not available for sqlite2. Use sqlite v3.");
|
||||
}
|
||||
|
||||
# determine current installed version
|
||||
$ver = get_ver($db, $dbtype);
|
||||
|
||||
|
|
@ -41,6 +36,7 @@ if(!$ver)
|
|||
"CREATE TABLE todolist (
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`d` DATETIME NOT NULL,
|
||||
`list_id` INT UNSIGNED NOT NULL default 0,
|
||||
`compl` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`title` VARCHAR(250) NOT NULL,
|
||||
`note` TEXT,
|
||||
|
|
@ -48,7 +44,8 @@ if(!$ver)
|
|||
`ow` INT NOT NULL default 0, /* order weight */
|
||||
`tags` VARCHAR(250) NOT NULL default '', /* denormalization - for fast access to task tags */
|
||||
`duedate` DATE default NULL,
|
||||
PRIMARY KEY(`id`)
|
||||
PRIMARY KEY(`id`),
|
||||
KEY(`list_id`)
|
||||
) CHARSET=utf8 ");
|
||||
|
||||
$db->ex(
|
||||
|
|
@ -56,8 +53,9 @@ if(!$ver)
|
|||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`name` VARCHAR(50) NOT NULL,
|
||||
`tags_count` INT default 0,
|
||||
`list_id` INT UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE KEY(`name`)
|
||||
UNIQUE KEY `listid_nmae` (`list_id`,`name`)
|
||||
) CHARSET=utf8 ");
|
||||
|
||||
$db->ex(
|
||||
|
|
@ -68,6 +66,13 @@ if(!$ver)
|
|||
KEY(`task_id`)
|
||||
) CHARSET=utf8 ");
|
||||
|
||||
$db->ex(
|
||||
"CREATE TABLE lists (
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`name` VARCHAR(50) NOT NULL default '',
|
||||
PRIMARY KEY(`id`)
|
||||
) CHARSET=utf8 ");
|
||||
|
||||
} catch (Exception $e) {
|
||||
exitMessage("<b>Error:</b> ". htmlarray($e->getMessage()));
|
||||
}
|
||||
|
|
@ -80,6 +85,7 @@ if(!$ver)
|
|||
"CREATE TABLE todolist (
|
||||
id INTEGER PRIMARY KEY,
|
||||
d DATETIME NOT NULL default '0000-00-00',
|
||||
list_id INTEGER UNSIGNED NOT NULL default 0,
|
||||
compl TINYINT UNSIGNED NOT NULL default 0,
|
||||
title VARCHAR(250) NOT NULL,
|
||||
note TEXT,
|
||||
|
|
@ -88,27 +94,37 @@ if(!$ver)
|
|||
tags VARCHAR(250) NOT NULL default '',
|
||||
duedate DATE default NULL
|
||||
) ");
|
||||
$db->ex("CREATE INDEX list_id ON todolist (list_id)");
|
||||
|
||||
$db->ex(
|
||||
"CREATE TABLE tags (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL COLLATE NOCASE UNIQUE,
|
||||
tags_count INT default 0
|
||||
name VARCHAR(50) NOT NULL,
|
||||
tags_count INT default 0,
|
||||
list_id INTEGER UNSIGNED NOT NULL default 0
|
||||
) ");
|
||||
$db->ex("CREATE UNIQUE INDEX tags_listid_name ON tags (list_id,name COLLATE NOCASE)");
|
||||
|
||||
$db->ex(
|
||||
"CREATE TABLE tag2task (
|
||||
tag_id INTEGER NOT NULL,
|
||||
task_id INTEGER NOT NULL
|
||||
) ");
|
||||
|
||||
$db->ex("CREATE INDEX tag_id ON tag2task (tag_id)");
|
||||
$db->ex("CREATE INDEX task_id ON tag2task (task_id)");
|
||||
|
||||
$db->ex(
|
||||
"CREATE TABLE lists (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL
|
||||
) ");
|
||||
|
||||
} catch (Exception $e) {
|
||||
exitMessage("<b>Error:</b> ". htmlarray($e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
createDefaultList($db);
|
||||
}
|
||||
elseif($ver == $lastVer)
|
||||
{
|
||||
|
|
@ -116,17 +132,22 @@ elseif($ver == $lastVer)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!in_array($ver, array('1.1'))) {
|
||||
exitMessage("Can not update database. Unsupported version ($ver).");
|
||||
if(!in_array($ver, array('1.1','1.2'))) {
|
||||
exitMessage("Can not update database. Unsupported version (v$ver).");
|
||||
}
|
||||
if(!isset($_POST['update'])) {
|
||||
exitMessage("Update database from v$ver to v1.2 <form method=post><input type=hidden name=update value=1><input type=submit value=' Update '></form>");
|
||||
exitMessage("Update database v$ver <form method=post><input type=hidden name=update value=1><input type=submit value=' Update '></form>");
|
||||
}
|
||||
|
||||
# update process
|
||||
if($ver == '1.1')
|
||||
if($ver == '1.2')
|
||||
{
|
||||
update_12_13($db, $dbtype);
|
||||
}
|
||||
elseif($ver == '1.1')
|
||||
{
|
||||
update_11_12($db, $dbtype);
|
||||
update_12_13($db, $dbtype);
|
||||
}
|
||||
}
|
||||
echo "Done<br><br> <b>Attention!</b> Delete this file for security reasons.";
|
||||
|
|
@ -145,6 +166,8 @@ function get_ver($db, $dbtype)
|
|||
if(!has_field_sqlite($db, 'todolist', 'duedate')) return $v;
|
||||
}
|
||||
$v = '1.2';
|
||||
if(!$db->table_exists('lists')) return $v;
|
||||
$v = '1.3';
|
||||
return $v;
|
||||
}
|
||||
|
||||
|
|
@ -182,11 +205,10 @@ function has_field_mysql($db, $table, $field)
|
|||
### 1.1-1.2 ##########
|
||||
function update_11_12($db, $dbtype)
|
||||
{
|
||||
echo "Changing database structure...<br>";
|
||||
if($dbtype == 'mysql') $db->ex("ALTER TABLE todolist ADD `duedate` DATE default NULL");
|
||||
else $db->ex("ALTER TABLE todolist ADD duedate DATE default NULL");
|
||||
|
||||
echo "Fixing broken tags...<br>";
|
||||
# Fixing broken tags
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("DELETE FROM tags");
|
||||
$db->ex("DELETE FROM tag2task");
|
||||
|
|
@ -242,4 +264,67 @@ function update_task_tags($id, $tag_ids)
|
|||
|
||||
### end 1.1-1.2 #####
|
||||
|
||||
### 1.2-1.3 ##########
|
||||
function update_12_13($db, $dbtype)
|
||||
{
|
||||
$db->ex("BEGIN");
|
||||
if($dbtype=='mysql')
|
||||
{
|
||||
$db->ex(
|
||||
"CREATE TABLE lists (
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`name` VARCHAR(50) NOT NULL default '',
|
||||
PRIMARY KEY(`id`)
|
||||
) CHARSET=utf8 ");
|
||||
$db->ex("ALTER TABLE todolist ADD `list_id` INT UNSIGNED NOT NULL default 0");
|
||||
$db->ex("ALTER TABLE tags ADD `list_id` INT UNSIGNED NOT NULL default 0");
|
||||
|
||||
$db->ex("ALTER TABLE todolist ADD KEY(`list_id`)");
|
||||
$db->ex("DROP INDEX `name` ON tags");
|
||||
$db->ex("ALTER TABLE tags ADD UNIQUE KEY `listid_name` (`list_id`,`name`)");
|
||||
}
|
||||
else
|
||||
{
|
||||
$db->ex(
|
||||
"CREATE TABLE lists (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL
|
||||
) ");
|
||||
$db->ex("ALTER TABLE todolist ADD list_id INTEGER UNSIGNED NOT NULL default 0");
|
||||
$db->ex("CREATE INDEX todolist_list_id ON todolist (list_id)");
|
||||
|
||||
$db->ex(
|
||||
"CREATE TEMPORARY TABLE tags_backup (
|
||||
id INTEGER,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
tags_count INT default 0
|
||||
) ");
|
||||
$db->ex("INSERT INTO tags_backup SELECT id,name,tags_count FROM tags");
|
||||
$db->ex("DROP TABLE tags");
|
||||
$db->ex(
|
||||
"CREATE TABLE tags (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
tags_count INT default 0,
|
||||
list_id INTEGER UNSIGNED NOT NULL default 0
|
||||
) ");
|
||||
$db->ex("INSERT INTO tags (id,name,tags_count) SELECT id,name,tags_count FROM tags_backup");
|
||||
$db->ex("CREATE UNIQUE INDEX tags_listid_name ON tags (list_id,name COLLATE NOCASE) ");
|
||||
$db->ex("DROP TABLE tags_backup");
|
||||
}
|
||||
$db->ex("COMMIT");
|
||||
|
||||
createDefaultList($db);
|
||||
}
|
||||
|
||||
function createDefaultList($db)
|
||||
{
|
||||
$db->ex("INSERT INTO lists (name) VALUES (?)", array('Todo'));
|
||||
|
||||
$db->ex("UPDATE todolist SET list_id=1");
|
||||
$db->ex("UPDATE tags SET list_id=1");
|
||||
}
|
||||
|
||||
### end 1.2-1.3 #####
|
||||
|
||||
?>
|
||||
|
|
@ -8,6 +8,7 @@ form { display: inline; }
|
|||
h2,h3 { margin:0; }
|
||||
h2 { font-size:15pt; float:left; padding-right:10px; background-color:#ffffff; }
|
||||
h3 { border-bottom:2px solid #B5D5FF; margin-bottom:10px; padding:6px 0; font-size:11pt; }
|
||||
#page_tasks h3 { padding-left:4px; padding-right:4px; }
|
||||
a { color:#0000ff; }
|
||||
#space { height:30px; }
|
||||
#footer { height:30px; margin-top:-30px; }
|
||||
|
|
@ -22,15 +23,15 @@ a { color:#0000ff; }
|
|||
#authform div { padding:2px 0px; }
|
||||
#authform div.h { font-weight:bold; }
|
||||
|
||||
#tabs ul { list-style: none; padding:0; margin:0; }
|
||||
#tabs ul li { margin:0; font-size: 9pt; font-weight:bold; float: left; width:89px; text-align:center; margin-right: 6px; border-left:1px solid #fff; }
|
||||
#tabs ul a { margin:0px; text-decoration: none; color:#444444; display: block; height:21px; width: 100%; padding-top: 6px; outline:none; }
|
||||
#tabs ul li.ui-tabs-selected { background:#ededed; border-left:1px solid #ededed; }
|
||||
#tabs ul li.ui-tabs-selected a { background:url(images/corner_right.gif) no-repeat top right; }
|
||||
#tabs ul li.ui-state-hover { border-left:1px solid #ededed; }
|
||||
#tabs ul li.ui-state-hover a { color: #888888; background:url(images/tab_hover.gif) no-repeat top right; }
|
||||
.ui-tabs .ui-tabs-hide { display: none; }
|
||||
#tabs ul li.ui-state-disabled a { color: #cccccc; }
|
||||
.mtt-tabs ul { list-style: none; padding:0; margin:0; }
|
||||
.mtt-tabs ul li { margin:0; font-size: 9pt; font-weight:bold; float: left; width:89px; text-align:center; margin-right: 6px; border-left:1px solid #fff; }
|
||||
.mtt-tabs ul a { margin:0px; text-decoration: none; color:#444444; display: block; height:21px; width: 100%; padding-top: 6px; outline:none; }
|
||||
.mtt-tabs ul li.mtt-tabs-selected { background:#ededed; border-left:1px solid #ededed; }
|
||||
.mtt-tabs ul li.mtt-tabs-selected a { background:url(images/corner_right.gif) no-repeat top right; }
|
||||
.mtt-tabs ul li:hover { border-left:1px solid #ededed; }
|
||||
.mtt-tabs ul li:hover a { color: #888888; background:url(images/tab_hover.gif) no-repeat top right; }
|
||||
.mtt-htabs { clear:both; background-color:#ededed; padding:8px; border-bottom:2px solid #DEDEDE; }
|
||||
#page_tasks.readonly #htab_search a.htab-toggle { color:#444; }
|
||||
|
||||
.tab-content { padding:8px; border-bottom:2px solid #DEDEDE; background:url(images/corner_right.gif) no-repeat top right #ededed; }
|
||||
#loading { float:left; padding-top:5px; background-color:#ffffff; display:none; padding-right:6px;}
|
||||
|
|
@ -48,9 +49,12 @@ a { color:#0000ff; }
|
|||
#sortform .li { margin:1px 0px; padding:2px; cursor:pointer; }
|
||||
#sortform .li:hover { background-color:#316AC5; color:white; }
|
||||
|
||||
.task-left { width:25px; float:left; }
|
||||
.task-middle { margin-left:25px; margin-right:65px; }
|
||||
.nobr input { margin-left:0px; margin-right:4px; }
|
||||
.mtt-notes-showhide { font-size:8pt; font-weight:normal; margin-left:5px; }
|
||||
|
||||
.task-left { float:left; }
|
||||
.task-left .mtt-toggle { margin-top:2px; cursor:pointer; width:15px; height:15px; float:left; background:url(images/toggle_plus.gif) left top no-repeat; }
|
||||
.task-left .mtt-toggle.mtt-toggle-expanded { background-image:url(images/toggle_minus.gif); }
|
||||
.task-middle { margin-left:40px; margin-right:65px; }
|
||||
#tasklist { list-style-type: none; margin: 0; padding: 0;}
|
||||
#tasklist li { padding:6px 2px 6px 6px; border-bottom:1px solid #DEDEDE; min-height:18px; margin-bottom:1px; background-color:#fff; }
|
||||
#tasklist li:hover { background-color:#f6f6f6; }
|
||||
|
|
@ -60,7 +64,7 @@ a { color:#0000ff; }
|
|||
.task-date { color:#999999; font-size:8pt; margin-left:4px; display:none; }
|
||||
.task-title a { color:#000000; }
|
||||
.task-title a:hover { color:#af0000; }
|
||||
#tasklist.readonly li .task-actions { display:none; }
|
||||
#page_tasks.readonly #tasklist li .task-actions { display:none; }
|
||||
.task-tags { margin-left:4px; padding:0px 2px; }
|
||||
.task-tags .tag { font-size:8pt; font-weight:bold; color:#333333; text-decoration:underline; }
|
||||
.task-tags .tag:hover { }
|
||||
|
|
@ -72,7 +76,8 @@ li.task-completed span.task-through { text-decoration:line-through; color:#77777
|
|||
li.task-completed .task-title a { color:#777777; }
|
||||
li.task-completed .task-actions a { color:#7070ff; }
|
||||
#tasklist li.task-completed .duedate { color:#777777; border-color:#777777; }
|
||||
li.task-completed { opacity:0.7; }
|
||||
li.task-completed { opacity:0.8; }
|
||||
li.task-completed .mtt-toggle { opacity:0.8; }
|
||||
|
||||
#tasklist.filter-past li, #tasklist.filter-today li, #tasklist.filter-soon li { display:none; }
|
||||
#tasklist.filter-past li.past, #tasklist.filter-today li.today, #tasklist.filter-soon li.soon { display:block; }
|
||||
|
|
@ -84,27 +89,29 @@ div.task-note-area { display:none; margin-bottom:5px; }
|
|||
div.task-note-area textarea { color:#999999; width:100%; display:block; height:65px; }
|
||||
.task-note-actions { font-size:8pt; }
|
||||
.hidden { display:none; }
|
||||
.invisible { visibility:hidden; }
|
||||
.in500 { width:500px; color:#444444; }
|
||||
.in100 { width:100px; color:#444444; }
|
||||
.task-note span a { color:#777777; }
|
||||
.task-note span a:hover { color:#af0000; }
|
||||
|
||||
.task-prio { padding-left:2px; padding-right:2px; margin-left: 2px; margin-right:3px; cursor:default; }
|
||||
.task-prio { padding-left:2px; padding-right:2px; margin-left:0px; margin-right:4px; cursor:default; }
|
||||
.prio-neg { background-color:#3377ff; color:#ffffff; }
|
||||
.prio-pos { background-color:#ff3030; color:#ffffff; }
|
||||
.prio-o { background-color:#dedede; }
|
||||
#tasklist li .prio-o { display:none; }
|
||||
.task-prio.prio-o { display:none; }
|
||||
|
||||
#authstr { display: none; color:#999999; }
|
||||
#authstr.attention { color:#ff0000; }
|
||||
#authstr { display: none; color:#ff0000; }
|
||||
|
||||
.form-row { margin-top:4px; margin-bottom:4px; }
|
||||
.form-row span.h { font-weight:bold; color:#333333; }
|
||||
.form-row .h { font-weight:bold; color:#333333; }
|
||||
#overlay { position:fixed; z-index:200; background-color:#111111; display:none; top:0px; left:0px; width:100%; height:100%; }
|
||||
#page_taskedit { position:fixed; z-index:201; background-color:#fdfdfd; padding:8px; border:1px solid #cccccc; width:510px; }
|
||||
#page_taskedit .form-row .in500 { width:99%; }
|
||||
#page_taskedit .form-row textarea.in500 { height:130px; /*resize:none;*/ }
|
||||
.ui-icon-gripsmall-diagonal-se { background-image:url(images/resizegrip.gif); }
|
||||
#alltags .tag { font-weight:bold; color:#333333; }
|
||||
#alltags .tag:hover { background-color:#999988; color:white; }
|
||||
|
||||
/* autocomplete */
|
||||
.ac_results { padding: 0px; border: 1px solid #cccccc; background-color: #f0f0f0; overflow: hidden; z-index: 99999; }
|
||||
|
|
@ -166,3 +173,7 @@ div.task-note-area textarea { color:#999999; width:100%; display:block; height:6
|
|||
.ui-resizable-s { cursor:s-resize; height:7px; width:100%; bottom:-5px; left:0px; }
|
||||
.ui-resizable-e { cursor:e-resize; width:7px; right:-5px; top:0px; height:100%; }
|
||||
.ui-resizable-se { cursor:se-resize; width:12px; height:12px; right:1px; bottom:1px; }
|
||||
|
||||
.mtt-btnmenu-container { overflow: hidden; z-index:103; background-color:#f9f9f9; border:1px solid #cccccc; padding:3px; }
|
||||
.mtt-btnmenu-container .li { margin:1px 0px; padding:2px; cursor:pointer; }
|
||||
.mtt-btnmenu-container .li:hover { background-color:#316AC5; color:white; }
|
||||
|
|
@ -1 +1 @@
|
|||
1.2.7
|
||||
1.3 dev
|
||||
Loading…
Reference in a new issue