'+
'
'+prepareHtml(item.note)+'
'+
'
'+
'
'+lang.actionNoteSave+
@@ -79,13 +84,13 @@ function prepareTaskStr(item)
function prepareHtml(s)
{
// make URLs clickable
- s = s.replace(/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/gi, '$1$2$4');
+ var s = s.replace(/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/gi, '$1$2$4');
return s.replace(/(^|\s|>)((?:http|https|ftp):\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/ig, '$1$2$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[i]+'';
}
return ''+a.join(', ')+'';
@@ -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').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
').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 += ''+item.tag+'';
+ });
+ $('#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 += ''+item.tag+'';
- });
- $('#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 += ''+item.name+'';
+ });
+ $('#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(''+item.name+'');
+ }, '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(''+tagsList[i].tag+'');
+ }
+ $('#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);
+}
diff --git a/src/ajax.php b/src/ajax.php
index 7e2e32a..895cbf4 100644
--- a/src/ajax.php
+++ b/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;
}
diff --git a/src/class.db.sqlite.php b/src/class.db.sqlite.php
deleted file mode 100644
index fcadcb1..0000000
--- a/src/class.db.sqlite.php
+++ /dev/null
@@ -1,158 +0,0 @@
-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; $iquote($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;
- }
-}
-
-?>
\ No newline at end of file
diff --git a/src/db/config.php.default b/src/db/config.php.default
index 2250ccc..4027271 100644
--- a/src/db/config.php.default
+++ b/src/db/config.php.default
@@ -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";
diff --git a/src/images/toggle_minus.gif b/src/images/toggle_minus.gif
new file mode 100644
index 0000000..19d433b
Binary files /dev/null and b/src/images/toggle_minus.gif differ
diff --git a/src/images/toggle_plus.gif b/src/images/toggle_plus.gif
new file mode 100644
index 0000000..14a7ab2
Binary files /dev/null and b/src/images/toggle_plus.gif differ
diff --git a/src/index.php b/src/index.php
index 9a61a50..6c6fb10 100644
--- a/src/index.php
+++ b/src/index.php
@@ -56,10 +56,9 @@ function __($s)