diff --git a/src/ajax.js b/src/ajax.js deleted file mode 100644 index 9baa8f2..0000000 --- a/src/ajax.js +++ /dev/null @@ -1,1410 +0,0 @@ -/* - This file is part of myTinyTodo. - (C) Copyright 2009-2010 Max Pozdeev - Licensed under the GNU GPL v3 license. See file COPYRIGHT for details. -*/ - -theme = { - newTaskFlashColor: '#ffffaa', - editTaskFlashColor: '#bbffaa', - msgFlashColor: '#ffffff' -}; - -//Global vars -var taskList, taskOrder; -var filter = { compl:0, search:'', tag:'', due:'' }; -var sortOrder; //save task order before dragging -var searchTimer; -var objPrio = {}; -var selTask = 0; -var flag = { needAuth:false, isLogged:false, tagsChanged:true, windowTaskEditMoved:false, autoTag:true }; -var taskCnt = { total:0, past: 0, today:0, soon:0 }; -var tmp = {}; -var oBtnMenu = {}; -var cmenu; -var tabLists = []; -var curList = 0; -var tagsList = []; -var page = {cur:'', prev:''}; - -var mytinytodo = { - actions: {}, - menus: {}, - mttUrl: '', - options: { - openList: 0 - }, - - addAction: function(action, proc) - { - if(!this.actions[action]) this.actions[action] = new Array(); - this.actions[action].push(proc); - }, - - doAction: function(action, opts) - { - if(!this.actions[action]) return; - for(var i in this.actions[action]) { - this.actions[action][i](opts); - } - }, - - setOptions: function(opts) { - jQuery.extend(this.options, opts); - } -}; - -$().ajaxSend(function(r,s){ - $("#msg").hide().removeClass('mtt-error mtt-info'); - $("#loading").show(); -}); - -$().ajaxStop(function(r,s){ - $("#loading").fadeOut(); -}); - -$().ajaxError(function(event, request, settings){ - var errtxt; - if(request.status == 0) errtxt = 'Bad connection'; - else if(request.status != 200) errtxt = 'HTTP: '+request.status+'/'+request.statusText; - else errtxt = request.responseText; - flashError(lang.error, errtxt); -}); - -mytinytodo.addAction('listRenamed', cmenuListRenamed); -mytinytodo.addAction('listsLoaded', cmenuListsLoaded); -mytinytodo.addAction('listAdded', cmenuListAdded); -mytinytodo.addAction('listSelected', actionListSelected); - - -function loadTasks(opts) -{ - if(!curList) return false; - setSort(curList.sort, 1); - opts = opts || {}; - $('#tasklist').html(''); - $('#total').html('...'); - var search = filter.search ? '&s='+encodeURIComponent(filter.search) : ''; - var tag = filter.tag ? '&t='+encodeURIComponent(filter.tag) : ''; - var nocache = '&rnd='+Math.random(); - var setCompl = opts.setCompl != null ? '&setCompl=1' : ''; - $.getJSON(mytinytodo.mttUrl+'ajax.php?loadTasks&list='+curList.id+'&compl='+curList.showCompl+'&sort='+curList.sort+search+tag+'&tz='+tz()+setCompl+nocache, function(json){ - taskList = new Array(); - taskOrder = new Array(); - taskCnt.total = taskCnt.past = taskCnt.today = taskCnt.soon = 0; - var tasks = ''; - $.each(json.list, function(i,item){ - tasks += prepareTaskStr(item); - taskList[item.id] = item; - taskOrder.push(parseInt(item.id)); - changeTaskCnt(item, 1); - }); - refreshTaskCnt(); - $('#tasklist').html(tasks); - if(json.denied) errorDenied(); - }); -} - -function prepareTaskStr(item, noteExp) -{ - var id = parseInt(item.id); - var prio = parseInt(item.prio); - var readOnly = (flag.needAuth && !flag.isLogged) ? true : false; - return '
  • '+ - '
    '+ - '
    '+ - '
    '+ - '
    '+prepareDuedate(item.duedate, item.dueClass, item.dueStr)+ - '
    '+preparePrio(prio,id)+''+prepareHtml(item.title)+' '+ - prepareTagsStr(item.tags)+''+item.dateInline+'
    '+ - '
    '+ - '
    '+prepareHtml(item.note)+'
    '+ - ''+ - '
    '+ - "
  • \n"; -} - -function prepareHtml(s) -{ - // make URLs clickable - 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) -{ - var cl =''; var v = ''; - if(prio < 0) { cl = 'prio-neg prio-neg-'+Math.abs(prio); v = '−'+Math.abs(prio); } - else if(prio > 0) { cl = 'prio-pos prio-pos-'+prio; v = '+'+prio; } - else { cl = 'prio-zero'; v = '±0'; } - return ''+v+''; -} - -function prepareTagsStr(tags) -{ - if(!tags || tags == '') return ''; - var a = tags.split(','); - if(!a.length) return ''; - for(var i in a) { - a[i] = ''+a[i]+''; - } - return ''+a.join(', ')+''; -} - -function prepareDuedate(duedate, c, s) -{ - if(!duedate) return ''; - return ''+s+''; -} - -function submitNewTask(form) -{ - if(form.task.value == '') return false; - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?newTask'+nocache, { list:curList.id, title: form.task.value, tz:tz(), tag:filter.tag }, function(json){ - if(!parseInt(json.total)) return; - $('#total').text( parseInt($('#total').text()) + 1 ); - taskCnt.total++; - form.task.value = ''; - var item = json.list[0]; - taskList[item.id] = item; - taskOrder.push(parseInt(item.id)); - $('#tasklist').append(prepareTaskStr(item)); - changeTaskOrder(item.id); - $('#taskrow_'+item.id).effect("highlight", {color:theme.newTaskFlashColor}, 2000); - refreshTaskCnt(); - }, 'json'); - flag.tagsChanged = true; - return false; -} - -function flashError(str, details) -{ - $("#msg>.msg-text").text(str) - $("#msg>.msg-details").text(details); - $("#loading").hide(); - $("#msg").addClass('mtt-error').effect("highlight", {color:theme.msgFlashColor}, 700); -} - -function flashInfo(str, details) -{ - $("#msg>.msg-text").text(str) - $("#msg>.msg-details").text(details); - $("#loading").hide(); - $("#msg").addClass('mtt-info').effect("highlight", {color:theme.msgFlashColor}, 700); -} - -function toggleMsgDetails() -{ - var el = $("#msg>.msg-details"); - if(!el) return; - if(el.css('display') == 'none') el.show(); - else el.hide() -} - -function deleteTask(id) -{ - if(!confirm(lang.confirmDelete)) { - return false; - } - var nocache = '&rnd='+Math.random(); - $.getJSON(mytinytodo.mttUrl+'ajax.php?deleteTask='+id+nocache, function(json){ - if(!parseInt(json.total)) return; - var item = json.list[0]; - taskOrder.splice($.inArray(id,taskOrder), 1); - $('#taskrow_'+item.id).fadeOut('normal', function(){ $(this).remove() }); - changeTaskCnt(taskList[id], -1); - refreshTaskCnt(); - delete taskList[id]; - }); - flag.tagsChanged = true; - return false; -} - -function completeTask(id,ch) -{ - var compl = 0; - if(ch.checked) compl = 1; - var nocache = '&rnd='+Math.random(); - $.getJSON(mytinytodo.mttUrl+'ajax.php?completeTask='+id+'&compl='+compl+'&tz='+tz()+nocache, function(json){ - if(!parseInt(json.total)) return; - var item = json.list[0]; - if(item.compl) $('#taskrow_'+id).addClass('task-completed'); - else $('#taskrow_'+id).removeClass('task-completed'); - taskList[id].ow = item.ow; - taskList[id].compl = item.compl; - taskList[id].dateCompleted = item.dateCompleted; - changeTaskCnt(taskList[id], 0); - if(item.compl && !curList.showCompl) { - delete taskList[id]; - taskOrder.splice($.inArray(id,taskOrder), 1); - $('#taskrow_'+item.id).fadeOut('normal', function(){ $(this).remove() }); - } - else if(curList.showCompl) { - changeTaskOrder(id); - $('#taskrow_'+id).effect("highlight", {color:theme.editTaskFlashColor}, 'normal', function(){$(this).css('display','')} ); - } - refreshTaskCnt(); - }); - return false; -} - -function toggleTaskNote(id) -{ - var aArea = '#tasknotearea'+id; - if($(aArea).css('display') == 'none') - { - $('#notetext'+id).val(taskList[id].noteText); - $(aArea).show(); - $('#tasknote'+id).hide(); - $('#taskrow_'+id).addClass('task-expanded'); - $('#notetext'+id).focus(); - } else { - cancelTaskNote(id) - } - return false; -} - -function cancelTaskNote(id) -{ - if(taskList[id].note == '') $('#taskrow_'+id).removeClass('task-expanded'); - $('#tasknotearea'+id).hide(); - $('#tasknote'+id).show(); - return false; -} - -function saveTaskNote(id) -{ - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?editNote='+id+nocache, {note: $('#notetext'+id).val()}, function(json){ - if(!parseInt(json.total)) return; - var item = json.list[0]; - taskList[id].note = item.note; - taskList[id].noteText = item.noteText; - $('#tasknote'+item.id+'>span').html(prepareHtml(item.note)); - if(item.note == '') $('#taskrow_'+id).removeClass('task-has-note task-expanded'); - else $('#taskrow_'+id).addClass('task-has-note task-expanded'); - cancelTaskNote(item.id); - }, 'json'); - return false; -} - -function editTask(id) -{ - var item = taskList[id]; - if(!item) return false; - document.edittask.task.value = dehtml(item.title); - document.edittask.note.value = item.noteText; - document.edittask.id.value = item.id; - document.edittask.tags.value = item.tags.split(',').join(', '); - document.edittask.duedate.value = item.duedate; - document.edittask.prio.value = item.prio; - $('#taskedit-date .date-created>span').text(item.date); - if(item.compl) $('#taskedit-date .date-completed').show().find('span').text(item.dateCompleted); - else $('#taskedit-date .date-completed').hide(); - showEditForm(); - return false; -} - -function showEditForm(isAdd) -{ - if(isAdd) - { - $('#page_taskedit').removeClass('mtt-inedit').addClass('mtt-inadd'); - document.edittask.isadd.value = 1; - if($('#task').val() != '') - { - $.post(mytinytodo.mttUrl+'ajax.php?parseTaskStr'+'&rnd='+Math.random(), { list:curList.id, title: $('#task').val(), tz:tz(), tag:filter.tag }, function(json){ - if(!json) return; - document.edittask.task.value = json.title - document.edittask.tags.value = json.tags; - document.edittask.prio.value = json.prio; - $('#task').val(''); - }, 'json'); - } - } - else { - $('#page_taskedit').removeClass('mtt-inadd').addClass('mtt-inedit'); - document.edittask.isadd.value = 0; - } - - if(flag.pda) { - showhide($('#page_taskedit'), $('#page_tasks')); - return; - } - - $('
    ').appendTo('body').css('opacity', 0.5).show(); - //clear selection - if(document.selection && document.selection.empty && document.selection.createRange().text) document.selection.empty(); - else if(window.getSelection) window.getSelection().removeAllRanges(); - - var w = $('#page_taskedit'); - if(!flag.windowTaskEditMoved) - { - var x = Math.floor($(window).width()/2 - w.outerWidth()/2); - var y = Math.floor($(window).height()/2 - w.outerHeight()/2); - if(x < 0) x = 0; - if(y < 0) y = 0; - w.css({left:x, top:y}); - tmp.editformpos = [x, y]; - } - w.css('max-width', $(window).width() - (w.outerWidth() - w.width())); - w.fadeIn('fast'); //.show(); - $(document).bind('keydown', cancelEdit); -} - -function cancelEdit(e) -{ - if(e && e.keyCode != 27) return; - if(flag.pda) { - showhide($('#page_tasks'), $('#page_taskedit')); - } else - { - $(document).unbind('keydown', cancelEdit); - $('#page_taskedit').hide(); - $('#overlay').remove(); - } - document.edittask.task.value = ''; - document.edittask.note.value = ''; - document.edittask.tags.value = ''; - document.edittask.duedate.value = ''; - document.edittask.prio.value = '0'; - toggleEditAllTags(0); - return false; -} - -function saveTask(form) -{ - if(flag.needAuth && !flag.isLogged) return false; - if(form.isadd.value != 0) return submitFullTask(form); - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?editTask='+form.id.value+nocache, { list:curList.id, tz:tz(), title: form.task.value, note:form.note.value, prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value }, function(json){ - if(!parseInt(json.total)) return; - var item = json.list[0]; - changeTaskCnt(item, 0, taskList[item.id]); - taskList[item.id] = item; - var noteExpanded = (item.note != '' && $('#taskrow_'+item.id).is('.task-expanded')) ? 1 : 0; - $('#taskrow_'+item.id).replaceWith(prepareTaskStr(item, noteExpanded)); - if(curList.sort != 0) changeTaskOrder(item.id); - cancelEdit(); - refreshTaskCnt(); - $('#taskrow_'+item.id).effect("highlight", {color:theme.editTaskFlashColor}, 'normal', function(){$(this).css('display','')}); - }, 'json'); - $("#edittags").flushCache(); - flag.tagsChanged = true; - return false; -} - -function showhide(a,b) -{ - a.show(); - b.hide(); -} - -function sortStart(event,ui) -{ - // remember initial order before sorting - sortOrder = $(this).sortable('toArray'); -} - -function orderChanged(event,ui) -{ - if(!ui.item[0]) return; - var itemId = ui.item[0].id; - var n = $(this).sortable('toArray'); - // remove possible empty id's - for(var i=0; i').replace(/&/g,'&'); -} - -function errorDenied() -{ - flashError(lang.denied); -} - -function updateAccessStatus() -{ - // 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.needAuth && !flag.isLogged) { - $('#page_tasks').addClass('readonly') - addsearchToggle(1); - } - else { - $('#page_tasks').removeClass('readonly') - $("#bar_public").hide(); - addsearchToggle(0); - } - $('#page_ajax').hide(); - page.cur = ''; -} - -function doAuth(form) -{ - $.post(mytinytodo.mttUrl+'ajax.php?rnd='+Math.random(), { login:1, password: form.password.value }, function(json){ - form.password.value = ''; - if(json.logged) - { - flag.isLogged = true; - loadLists(0,1); - } - else { - flashError(lang.invalidpass); - $('#password').focus(); - } - }, 'json'); - $('#authform').hide(); -} - -function logout() -{ - $.post(mytinytodo.mttUrl+'ajax.php?rnd='+Math.random(), { logout:1 }, function(json){ - flag.isLogged = false; - loadLists(0,1); - }, 'json'); - return false; -} - -function tasklistClick(e) -{ - var node = e.target.nodeName; - if(node=='SPAN' || node=='LI' || node=='DIV') { - var li = getRecursParent(e.target, 'LI', 10); - if(li) { - if(selTask && li.id != selTask) $('#'+selTask).removeClass('clicked doubleclicked'); - selTask = li.id; - if($(li).is('.clicked')) $(li).toggleClass('doubleclicked'); - else $(li).addClass('clicked'); - } - } -} - -function getRecursParent(el, needle, level) -{ - if(el.nodeName == needle) return el; - if(!el.parentNode) return null; - level--; - if(level <= 0) return false; - return getRecursParent(el.parentNode, needle, level); -} - -function cancelTagFilter(dontLoadTasks) -{ - $('#tagcloudbtn>.btnstr').text(lang.tags); - filter.tag = ''; - if(dontLoadTasks==null || !dontLoadTasks) loadTasks(); -} - -function addFilterTag(tag) -{ - filter.tag = tag; - loadTasks(); - $('#tagcloudbtn>.btnstr').html(lang.tagfilter + ' '+tag+''); -} - -function showAuth(el) -{ - var w = $('#authform'); - if(w.css('display') == 'none') - { - var offset = $(el).offset(); - w.css({ - position: 'absolute', - top: offset.top + el.offsetHeight + 3, - left: offset.left + el.offsetWidth - w.outerWidth() - }).show(); - $('#password').focus(); - } - else { - w.hide(); - el.blur(); - } -} - -function prioPopup(act, el, id) -{ - if(act == 0) { - clearTimeout(objPrio.timer); - return; - } - var offset = $(el).offset(); - $('#priopopup').css({ position: 'absolute', top: offset.top + 1, left: offset.left + 1 }); - objPrio.taskId = id; - objPrio.el = el; - objPrio.timer = setTimeout("$('#priopopup').show()", 300); -} - -function prioClick(prio, el) -{ - el.blur(); - prio = parseInt(prio); - $('#priopopup').fadeOut('fast'); //.hide(); - setTaskPrio(objPrio.taskId, prio); -} - -function setTaskPrio(id, prio) -{ - $.getJSON(mytinytodo.mttUrl+'ajax.php?setPrio='+id+'&prio='+prio+'&rnd='+Math.random(), function(json){ - }); - taskList[id].prio = prio; - var $t = $('#taskrow_'+id); - $t.find('.task-prio').replaceWith(preparePrio(prio, id)); - if(curList.sort != 0) changeTaskOrder(id); - $t.effect("highlight", {color:theme.editTaskFlashColor}, 'normal'); -} - -function setSort(v, init) -{ - $('#mylistscontainer .sort-item').removeClass('mtt-item-checked'); - if(v == 0) $('#sortByHand').addClass('mtt-item-checked'); - else if(v == 1) $('#sortByPrio').addClass('mtt-item-checked'); - else if(v == 2) $('#sortByDueDate').addClass('mtt-item-checked'); - else return; - - if(flag.needAuth && !flag.isLogged) { - $("#tasklist").sortable('disable'); - return; - } - curList.sort = v; - if(v == 0) $("#tasklist").sortable('enable'); - else $("#tasklist").sortable('disable'); - - if(!init) - { - changeTaskOrder(); - $.post(mytinytodo.mttUrl+'ajax.php?setSort'+'&rnd='+Math.random(), { list:curList.id, sort:curList.sort }, function(json){ - }, 'json'); - } -} - -function isParentId(el, id) -{ - if(el.id && $.inArray(el.id, id) != -1) return true; - if(!el.parentNode) return null; - return isParentId(el.parentNode, id); -} - -function changeTaskOrder(id) -{ - id = parseInt(id); - if(taskOrder.length < 2) return; - var oldOrder = taskOrder.slice(); - if(curList.sort == 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 - }); - else if(curList.sort == 1) taskOrder.sort( function(a,b){ - if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; - if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; - if(taskList[a].dueInt != taskList[b].dueInt) return taskList[a].dueInt-taskList[b].dueInt; - return taskList[a].ow-taskList[b].ow; - }); - else if(curList.sort == 2) taskOrder.sort( function(a,b){ - if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; - if(taskList[a].dueInt != taskList[b].dueInt) return taskList[a].dueInt-taskList[b].dueInt; - if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; - return taskList[a].ow-taskList[b].ow; - }); - else return; - if(oldOrder.toString() == taskOrder.toString()) return; - if(id && taskList[id]) - { - // optimization: determine where to insert task: top or after some task - var indx = $.inArray(id,taskOrder); - if(indx ==0) { - $('#tasklist').prepend($('#taskrow_'+id)) - } else { - var after = taskOrder[indx-1]; - $('#taskrow_'+after).after($('#taskrow_'+id)); - } - } - else { - var o = $('#tasklist'); - for(var i in taskOrder) { - o.append($('#taskrow_'+taskOrder[i])); - } - } -} - -function loadTags(callback) -{ - $.getJSON(mytinytodo.mttUrl+'ajax.php?tagCloud&list='+curList.id+'&rnd='+Math.random(), function(json){ - 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) -{ - var w = $('#tagcloud'); - if(w.css('display') == 'none') - { - if(flag.tagsChanged) - { - $('#tagcloudcontent').html(''); - $('#tagcloudload').show(); - var offset = $(el).offset(); - w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left }).show(); - loadTags(function(){$('#tagcloudload').hide();}); - } - else { - var offset = $(el).offset(); - w.css({ position: 'absolute', top: offset.top+el.offsetHeight-1, left: offset.left }).show(); - } - $(document).bind("click", tagCloudClose); - } - else { - el.blur(); - tagCloudClose(); - } -} - -function tagCloudClose(e) -{ - if(e) { - if(isParentId(e.target, ['tagcloudbtn','tagcloud'])) return; - } - $(document).unbind("click", tagCloudClose); - $('#tagcloud').hide(); -} - -function changeTaskCnt(task, dir, old) -{ - if(dir > 0) dir = 1; - else if(dir < 0) dir = -1; - if(dir == 0 && old != null && task.dueClass != old.dueClass) //on saveTask - { - if(old.dueClass != '') taskCnt[old.dueClass]--; - if(task.dueClass != '') taskCnt[task.dueClass]++; - } - else if(dir == 0 && old == null) //on comleteTask - { - if(!curList.showCompl && task.compl) taskCnt.total--; - if(task.dueClass != '') taskCnt[task.dueClass] += task.compl ? -1 : 1; - } - if(dir != 0) { - if(task.dueClass != '' && !task.compl) taskCnt[task.dueClass] += dir; - taskCnt.total += dir; - } -} - -function refreshTaskCnt() -{ - $('#cnt_total').text(taskCnt.total); - $('#cnt_past').text(taskCnt.past); - $('#cnt_today').text(taskCnt.today); - $('#cnt_soon').text(taskCnt.soon); - if(filter.due == '') $('#total').text(taskCnt.total); - else if(taskCnt[filter.due] != null) $('#total').text(taskCnt[filter.due]); -} - -function setTaskview(v) -{ - if(v == 0) - { - if(filter.due == '') return; - $('#taskview .btnstr').text($('#view_tasks').text()); - $('#tasklist').removeClass('filter-'+filter.due); - filter.due = ''; - $('#total').text(taskCnt.total); - } - else if(v=='past' || v=='today' || v=='soon') - { - if(filter.due == v) return; - else if(filter.due != '') { - $('#tasklist').removeClass('filter-'+filter.due); - } - $('#tasklist').addClass('filter-'+v); - $('#taskview .btnstr').text($('#view_'+v).text()); - $('#total').text(taskCnt[v]); - filter.due = v; - } -} - -function editFormResize(startstop, event) -{ - 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], top:tmp.editformpos[1], height:''} ).css('position', 'fixed'); - } - } - else $('#page_taskedit textarea').height(f.height() - tmp.editformdiff); -} - -function mttTabSelected(id, indx) -{ - $('#lists .mtt-tabs-selected').removeClass('mtt-tabs-selected'); - $('#list_'+tabLists[indx].id).addClass('mtt-tabs-selected'); - if(!tabLists[indx]) return; - if(indx != curList.i) { - $('#tasklist').html(''); - if(filter.search != '') { - filter.search = ''; - $('#searchbarkeyword').text(''); - $('#searchbar').hide(); - } - //if(tabLists[indx].published) - $('#rss_icon').find('a').attr('href', mytinytodo.mttUrl+'feed.php?list='+tabLists[indx].id); - mytinytodo.doAction('listSelected', tabLists[indx]); - } - curList = tabLists[indx]; - flag.tagsChanged = true; - cancelTagFilter(1); - setTaskview(0); - 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).find('li').each( function(i,o){ - if(o.onclick) { - oBtnMenu.h[i] = o.onclick; - $(o).bind("click2", o.onclick); - if(!$(o).is('.mtt-disabled')) 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(), 'width':w.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().find('li').each( function(i,o){ - if(oBtnMenu.h[i]) { - o.onclick = oBtnMenu.h[i]; - $(o).unbind('click2'); - } - }); - oBtnMenu = {}; -} - -function toggleNote(id) -{ - $('#taskrow_'+id).toggleClass('task-expanded'); -} - -function toggleAllNotes(show) -{ - for(var id in taskList) - { - if(taskList[id].note == '') continue; - if(show) $('#taskrow_'+id).addClass('task-expanded'); - else $('#taskrow_'+id).removeClass('task-expanded'); - } -} - -function loadLists(onInit, updAccess) -{ - if(updAccess) mytinytodo.parseAnchor(); - if(filter.search != '') { - filter.search = ''; - $('#searchbarkeyword').text(''); - $('#searchbar').hide(); - } - var nocache = '&rnd='+Math.random(); - $.getJSON(mytinytodo.mttUrl+'ajax.php?loadLists'+nocache, function(json){ - tabLists = new Array(); - var ti = ''; - if(parseInt(json.total)) - { - var openIdx = 0; - if(mytinytodo.options.openList) { - for(var i in json.list) { - if(mytinytodo.options.openList == json.list[i].id) { - openIdx = i; - break; - } - } - } - $.each(json.list, function(i,item){ - item.i = i; - tabLists[i] = item; - ti += '
  • '+ - ''+item.name+''+ - '
  • '; - }); - if(!curList) { - $('#toolbar').children().removeClass('invisible'); - $('#page_tasks h3').children().removeClass('invisible'); - $('#mylistscontainer .mtt-need-list').removeClass('mtt-disabled'); - } - curList = tabLists[openIdx]; - loadTasks(); - //if(curList.published) - $('#rss_icon').find('a').attr('href', mytinytodo.mttUrl+'feed.php?list='+curList.id); - if(flag.needAuth && !flag.isLogged) $('#bar_public').show(); - } - else { - curList = 0; - $('#toolbar').children().addClass('invisible'); - $('#page_tasks h3').children().addClass('invisible'); - $('#mylistscontainer .mtt-need-list').addClass('mtt-disabled'); - $('#tasklist').html(''); - } - mytinytodo.options.openList = 0; - $('#lists ul').html(ti); - $('#lists').show(); - mytinytodo.doAction('listsLoaded'); - if(curList) mytinytodo.doAction('listSelected', curList); - if(!flag.needAuth || flag.isLogged || curList) $('#page_tasks').show(); - }); - $('#page_tasks').hide(); - if(updAccess) updateAccessStatus(); -} - -function addList() -{ - var r = prompt(lang.addList, lang.addListDefault); - if(r == null) return; - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?'+nocache, { addList:1, name:r }, function(json){ - if(!parseInt(json.total)) return; - var item = json.list[0]; - var i = tabLists.length; - item.i = i; - tabLists[i] = item; - if(i > 0) { - $('#lists ul').append('
  • '+ - ''+item.name+''+ - '
  • '); - mytinytodo.doAction('listAdded', item); - } - else loadLists(); - }, 'json'); -} - -function renameCurList() -{ - if(!curList) return; - var r = prompt(lang.renameList, dehtml(curList.name)); - if(r == null || r == '') return; - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?'+nocache, { renameList:1, id:curList.id, name:r }, function(json){ - 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').attr('title', item.name).find('span').html(item.name); - mytinytodo.doAction('listRenamed', item); - }, 'json'); -} - -function deleteCurList() -{ - if(!curList) return false; - var r = confirm(lang.deleteList); - if(!r) return; - $.post(mytinytodo.mttUrl+'ajax.php?'+'&rnd='+Math.random(), { deleteList:1, id:curList.id }, function(json){ - if(!parseInt(json.total)) return; - loadLists(); - }, 'json'); -} - -function addsearchToggle(toSearch) -{ - if(toSearch) - { - showhide($('#htab_search'), $('#htab_newtask')); - $('#search').focus(); - } - else - { - if(flag.needAuth && !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); -} - -function showSettings() -{ - if(page.cur == 'settings') return false; - $('#page_ajax').load(mytinytodo.mttUrl+'settings.php?ajax=yes',null,function(){ - showhide($('#page_ajax').addClass('mtt-page-settings'), $('#page_tasks')); - page.prev = page.cur; - page.cur = 'settings'; - }) -} - -function closeSettings() -{ - showhide($('#page_tasks'), $('#page_ajax').removeClass('mtt-page-settings')); - page.prev = page.cur; - page.cur = ''; -// $("#msg").hide(); -} - -function saveSettings(frm) -{ - if(!frm) return false; - var params = { save:'ajax' }; - $(frm).find("input:text,input:checked,select,:password").filter(":enabled").each(function() { params[this.name || '__'] = this.value; }); - $(frm).find(":submit").attr('disabled','disabled').blur(); - $.post(mytinytodo.mttUrl+'settings.php?'+'&rnd='+Math.random(), params, function(json){ - if(json.saved) { - flashInfo(lang.settingsSaved); - setTimeout('window.location.reload();', 1000); - } - }, 'json'); -} - -function submitFullTask(form) -{ - if(flag.needAuth && !flag.isLogged) return false; - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?fullNewTask'+nocache, { list:curList.id, tag:filter.tag, title: form.task.value, note:form.note.value, prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value }, function(json){ - if(!parseInt(json.total)) return; - form.task.value = ''; - var item = json.list[0]; - taskList[item.id] = item; - taskOrder.push(parseInt(item.id)); - $('#tasklist').append(prepareTaskStr(item)); - changeTaskOrder(item.id); - cancelEdit(); - $('#taskrow_'+item.id).effect("highlight", {color:theme.newTaskFlashColor}, 2000); - changeTaskCnt(item, 1); - refreshTaskCnt(); - }, 'json'); - $("#edittags").flushCache(); - flag.tagsChanged = true; - return false; -} - -function publishCurList() -{ - if(!curList) return false; - var nocache = '&rnd='+Math.random(); - $.post(mytinytodo.mttUrl+'ajax.php?publishList'+nocache, { list:curList.id, publish:curList.published?0:1 }, function(json){ - if(!parseInt(json.total)) return; - curList.published = curList.published?0:1; - if(curList.published) $('#btnPublish').addClass('mtt-item-checked'); - else $('#btnPublish').removeClass('mtt-item-checked'); - }, 'json'); -} - -function taskContextMenu(el, id) -{ - if(!cmenu) cmenu = new mttMenu('taskcontextcontainer', {onclick:taskContextClick}); - cmenu.tag = id; - cmenu.show(el); - return false; -} - -function taskContextClick(el, menu) -{ - if(!el.id) return; - var taskId = cmenu.tag; - var id = el.id, value; - var a = id.split(':'); - if(a.length == 2) { - id = a[0]; - value = a[1]; - } - switch(id) { - case 'cmenu_edit': editTask(taskId); break; - case 'cmenu_note': toggleTaskNote(taskId); break; - case 'cmenu_delete': deleteTask(taskId); break; - case 'cmenu_prio': setTaskPrio(taskId, parseInt(value)); break; - case 'cmenu_list': - if(menu.$caller && menu.$caller.attr('id')=='cmenu_move') moveTaskToList(taskId, value); - break; - } -} - -function mttMenu(container, options) -{ - var menu = this; - this.container = $('#'+container); - this.menuOpen = false; - this.options = options || {}; - this.submenu = []; - this.curSubmenu = null; - this.showTimer = null; - - this.container.find('li').click(function(){ - menu.onclick(this, menu); - return false; - }) - .each(function(){ - - var submenu = 0; - if($(this).is('.mtt-menu-indicator')) - { - submenu = new mttMenu($(this).attr('submenu')); - submenu.$caller = $(this); - submenu.parent = menu; - if(menu.root) submenu.root = menu.root; //!! be careful with circular references - else submenu.root = menu; - menu.submenu.push(submenu); - - submenu.container.find('li').click(function(){ - submenu.root.onclick(this, submenu); - return false; - }); - } - - $(this).hover( - function(){ - if(!$(this).is('.mtt-menu-item-active')) menu.container.find('li').removeClass('mtt-menu-item-active'); - clearTimeout(menu.showTimer); - if(menu.curSubmenu && menu.curSubmenu.menuOpen && menu.curSubmenu != submenu) - { - menu.container.find('li').removeClass('mtt-menu-item-active'); - var curSubmenu = menu.curSubmenu; - hideTimer = setTimeout(function(){ - curSubmenu.hide(); - }, 400); - } - - if(!submenu || menu.curSubmenu == submenu && menu.curSubmenu.menuOpen) return; - menu.curSubmenu = submenu; - menu.showTimer = setTimeout(function(){ - submenu.showSub(); - }, 300); - $(this).addClass('mtt-menu-item-active'); - }, - null - ); - - }); - - this.onclick = function(item, fromMenu) - { - if($(item).is('.mtt-disabled,.mtt-menu-indicator')) return; - menu.close(); - if(this.options.onclick) this.options.onclick(item, fromMenu); - } - - this.hide = function() - { - for(var i in this.submenu) this.submenu[i].hide(); - this.container.hide(); - this.container.find('li').removeClass('mtt-menu-item-active'); - this.menuOpen = false; - } - - this.close = function(event) - { - if(!this.menuOpen) return; - if(event) - { - var t = event.target; - if(t == this.caller) return; - while(t.parentNode) { - if(t.parentNode == this.caller) return; - t = t.parentNode; - } - } - this.hide(); - $(this.caller).removeClass('mtt-menu-button-active'); - $(document).unbind('click.mttmenuclose'); - } - - this.show = function(caller) - { - if(this.menuOpen) - { - this.close(); - if(this.caller && this.caller == caller) return; - } - $(document).triggerHandler('click.mttmenuclose'); //close any other open menu - this.caller = caller; - $caller = $(caller); - $caller.addClass('mtt-menu-button-active'); - var offset = $caller.offset(); - var x2 = $(window).width() + $(document).scrollLeft() - this.container.outerWidth(true) - 1; - var x = offset.left < x2 ? offset.left : x2; - if(x<0) x=0; - var y = offset.top+caller.offsetHeight-1; - if(y + this.container.outerHeight(true) > $(window).height() + $(document).scrollTop()) y = offset.top - this.container.outerHeight(); - if(y<0) y=0; - this.container.css({ position: 'absolute', top: y, left: x, width:this.container.width() /*, 'min-width': $caller.width()*/ }).show(); - var menu = this; - $(document).bind('click.mttmenuclose', function(e){ menu.close(e) }); - this.menuOpen = true; - } - - this.showSub = function() - { - var offset = this.$caller.offset(); - var x = offset.left+this.$caller.outerWidth(); - if(x + this.container.outerWidth(true) > $(window).width() + $(document).scrollLeft()) x = offset.left - this.container.outerWidth() - 1; - if(x<0) x=0; - var y = offset.top + this.parent.container.offset().top-this.parent.container.find('li:first').offset().top; - if(y + this.container.outerHeight(true) > $(window).height() + $(document).scrollTop()) y = $(window).height() + $(document).scrollTop()- this.container.outerHeight(true) - 1; - if(y<0) y=0; - this.container.css({ position: 'absolute', top: y, left: x, width:this.container.width() /*, 'min-width': this.$caller.outerWidth()*/ }).show(); - this.menuOpen = true; - } - - this.destroy = function() - { - for(var i in this.submenu) { - this.submenu[i].destroy(); - delete this.submenu[i]; - } - this.container.find('li').unbind(); //'click mouseenter mouseleave' - } - -} - -function moveTaskToList(taskId, listId) -{ - if(curList.id == listId) return; - $.post(mytinytodo.mttUrl+'ajax.php?moveTask&rnd='+Math.random(), { id:taskId, from:curList.id, to:listId }, function(json){ - if(!parseInt(json.total)) return; - changeTaskCnt(taskList[taskId], -1) - delete taskList[taskId]; - taskOrder.splice($.inArray(taskId,taskOrder), 1); - $('#taskrow_'+taskId).fadeOut('normal', function(){ $(this).remove() }); - refreshTaskCnt(); - }, 'json'); - $("#edittags").flushCache(); - flag.tagsChanged = true; -} - -function cmenuListsLoaded() -{ - if(cmenu) cmenu.destroy(); - cmenu = null; - var s = ''; - for(var i in tabLists) { - s += '
  • '+tabLists[i].name+'
  • '; - } - $('#listsmenucontainer ul').html(s); -} - -function cmenuListAdded(list) -{ - if(cmenu) cmenu.destroy(); - cmenu = null; - $('#listsmenucontainer ul').append('
  • '+list.name+'
  • '); -} - -function cmenuListRenamed(list) -{ - $('#cmenu_list\\:'+list.id).text(list.name); -} - -function showCompletedToggle() -{ - var act = curList.showCompl ? 0 : 1; - curList.showCompl = tabLists[curList.i].showCompl = act; - if(act) $('#btnShowCompleted').addClass('mtt-item-checked'); - else $('#btnShowCompleted').removeClass('mtt-item-checked'); - loadTasks({setCompl:1}); -} - -function listOrderChanged(event, ui) -{ - var order = $(this).sortable("serialize"); - $.post(mytinytodo.mttUrl+'ajax.php?changeListOrder'+'&rnd='+Math.random(), order, function(json){ - }, 'json'); -} - -function actionListSelected(list) -{ - if(list.published) $('#btnPublish').addClass('mtt-item-checked'); - else $('#btnPublish').removeClass('mtt-item-checked'); - if(list.showCompl) $('#btnShowCompleted').addClass('mtt-item-checked'); - else $('#btnShowCompleted').removeClass('mtt-item-checked'); - $('#listsmenucontainer li').removeClass('mtt-disabled'); - $('#cmenu_list\\:'+list.id).addClass('mtt-disabled'); -} - -function tz() -{ - return -1 * (new Date()).getTimezoneOffset(); -} - -function listMenu(el) -{ - if(!mytinytodo.menus.listMenu) mytinytodo.menus.listMenu = new mttMenu('mylistscontainer', {onclick:listMenuClick}); - mytinytodo.menus.listMenu.show(el); -} - -function listMenuClick(el, menu) -{ - if(!el.id) return; - switch(el.id) { - case 'btnAddList': addList(); break; - case 'btnRenameList': renameCurList(); break; - case 'btnDeleteList': deleteCurList(); break; - case 'btnPublish': publishCurList(); break; - case 'btnShowCompleted': showCompletedToggle(); break; - case 'btnClearCompleted': clearCompleted(); break; - case 'sortByHand': setSort(0); break; - case 'sortByPrio': setSort(1); break; - case 'sortByDueDate': setSort(2); break; - } -} - -function stopBubble(e) -{ - if(!e) e = window.event; - e.cancelBubble = true; - if(e.stopPropagation) e.stopPropagation(); - return false; -} - -mytinytodo.parseAnchor = function() -{ - if(location.hash == '') return false; - var h = location.hash.substr(1); - var a = h.split("/"); - if(a.length < 2) return false; - if(a[0] == 'list' && a[1].match(/^\d+$/)) { - this.options.openList = a[1]; - } -} - -function clearCompleted() -{ - if(!curList) return false; - var r = confirm(lang.clearCompleted); - if(!r) return; - $.post(mytinytodo.mttUrl+'ajax.php?clearCompletedInList', { list:curList.id }, function(json){ - if(!parseInt(json.total)) return; - flag.tagsChanged = true; - if(curList.showCompl) loadTasks(); - }, 'json'); -} diff --git a/src/ajax.php b/src/ajax.php index 7fff1fa..86d72a9 100644 --- a/src/ajax.php +++ b/src/ajax.php @@ -33,15 +33,42 @@ elseif(isset($_GET['loadTasks'])) stop_gpc($_GET); $listId = (int)_get('list'); check_read_access($listId); - $sqlWhere = ' AND list_id='. $listId; + $sqlWhere = " AND {$db->prefix}todolist.list_id=". $listId; if(_get('compl') == 0) $sqlWhere .= ' AND compl=0'; $inner = ''; + $tag = trim(_get('t')); - if($tag != '') { - $tag_id = get_tag_id($tag, $listId); - $inner = "INNER JOIN {$db->prefix}tag2task ON id=task_id"; - $sqlWhere .= " AND tag_id=$tag_id "; + if($tag != '') + { + $at = explode(',', $tag); + $tagIds = array(); + $tagExIds = array(); + foreach($at as $i=>$atv) { + $atv = trim($atv); + if($atv == '' || $atv == '^') continue; + if(substr($atv,0,1) == '^') { + $tagExIds[] = getTagId(substr($atv,1)); + } else { + $tagIds[] = getTagId($atv); + } + } + + if(sizeof($tagIds) > 1) { + $inner = "INNER JOIN (SELECT task_id, COUNT(tag_id) AS c FROM {$db->prefix}tag2task WHERE list_id=$listId AND tag_id IN (". + implode(',',$tagIds). ") GROUP BY task_id) ON id=task_id"; + $sqlWhere = " AND c=". sizeof($tagIds); //overwrite sqlWhere! + } + elseif($tagIds) { + $inner = "INNER JOIN {$db->prefix}tag2task ON id=task_id"; + $sqlWhere .= " AND tag_id = ". $tagIds[0]; + } + + if($tagExIds) { + $sqlWhere .= " AND id NOT IN (SELECT DISTINCT task_id FROM {$db->prefix}tag2task WHERE list_id=$listId AND tag_id IN (". + implode(',',$tagExIds). "))"; //DISTINCT ? + } } + $s = trim(_get('s')); if($s != '') $sqlWhere .= " AND (title LIKE ". $db->quoteForLike("%%%s%%",$s). " OR note LIKE ". $db->quoteForLike("%%%s%%",$s). ")"; $sort = (int)_get('sort'); @@ -97,14 +124,15 @@ elseif(isset($_GET['newTask'])) if(Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0 ) $tz = round(date('Z')/60); $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); $db->ex("BEGIN"); - $db->dq("INSERT INTO {$db->prefix}todolist (list_id,title,d_created,ow,prio) VALUES ($listId,?,?,$ow,$prio)", array($title, time())); + $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio) VALUES (?,?,?,?,?,?,?)", + array(generateUUID(), $listId, $title, time(), time(), $ow, $prio) ); $id = $db->last_insert_id(); - if($tags) + if($tags != '') { - $tag_ids = prepare_tags($tags, $listId); - if($tag_ids) { - update_task_tags($id, $tag_ids); - $db->ex("UPDATE {$db->prefix}todolist SET tags=? WHERE id=$id", $tags); + $aTags = prepareTags($tags); + if($aTags) { + addTaskTags($id, $aTags['ids'], $listId); + $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=$id", array(implode(',',$aTags['tags']), implode(',',$aTags['ids']))); } } $db->ex("COMMIT"); @@ -136,16 +164,16 @@ elseif(isset($_GET['fullNewTask'])) $tz = (int)_post('tz'); if( Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0 ) $tz = round(date('Z')/60); $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); - if(is_null($duedate)) $duedate = 'NULL'; else $duedate = $db->quote($duedate); $db->ex("BEGIN"); - $db->dq("INSERT INTO {$db->prefix}todolist (list_id,title,d_created,ow,prio,note,duedate) VALUES($listId,?,?,$ow,$prio,?,$duedate)", array($title,time(),$note)); + $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio,note,duedate) VALUES(?,?,?,?,?,?,?,?,?)", + array(generateUUID(), $listId, $title, time(), time(), $ow, $prio, $note, $duedate) ); $id = $db->last_insert_id(); - if($tags) + if($tags != '') { - $tag_ids = prepare_tags($tags, $listId); - if($tag_ids) { - update_task_tags($id, $tag_ids); - $db->ex("UPDATE {$db->prefix}todolist SET tags=? WHERE id=$id", $tags); + $aTags = prepareTags($tags); + if($aTags) { + addTaskTags($id, $aTags['ids'], $listId); + $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=$id", array(implode(',',$aTags['tags']), implode(',',$aTags['ids']))); } } $db->ex("COMMIT"); @@ -157,7 +185,7 @@ elseif(isset($_GET['fullNewTask'])) } elseif(isset($_GET['deleteTask'])) { - $id = (int)$_GET['deleteTask']; + $id = (int)_post('id'); $deleted = deleteTask($id); $t = array(); $t['total'] = $deleted; @@ -168,14 +196,15 @@ elseif(isset($_GET['deleteTask'])) elseif(isset($_GET['completeTask'])) { check_write_access(); - $id = (int)$_GET['completeTask']; - $compl = _get('compl') ? 1 : 0; + $id = (int)_post('id'); + $compl = _post('compl') ? 1 : 0; $listId = (int)$db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=$id"); if($compl) $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=1"); else $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); $dateCompleted = $compl ? time() : 0; - $db->dq("UPDATE {$db->prefix}todolist SET compl=$compl,ow=$ow,d_completed=? WHERE id=$id", array($dateCompleted)); - $tz = (int)_get('tz'); + $db->dq("UPDATE {$db->prefix}todolist SET compl=$compl,ow=$ow,d_completed=?,d_edited=? WHERE id=$id", + array($dateCompleted, time()) ); + $tz = (int)_post('tz'); if(Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0) $tz = round(date('Z')/60); $t = array(); $t['total'] = 1; @@ -186,10 +215,10 @@ elseif(isset($_GET['completeTask'])) elseif(isset($_GET['editNote'])) { check_write_access(); - $id = (int)$_GET['editNote']; + $id = (int)_post('id'); stop_gpc($_POST); $note = str_replace("\r\n", "\n", trim(_post('note'))); - $db->dq("UPDATE {$db->prefix}todolist SET note=? WHERE id=$id", $note); + $db->dq("UPDATE {$db->prefix}todolist SET note=?,d_edited=? WHERE id=$id", array($note, time()) ); $t = array(); $t['total'] = 1; $t['list'][] = array('id'=>$id, 'note'=>nl2br(escapeTags($note)), 'noteText'=>(string)$note); @@ -199,7 +228,7 @@ elseif(isset($_GET['editNote'])) elseif(isset($_GET['editTask'])) { check_write_access(); - $id = (int)$_GET['editTask']; + $id = (int)_post('id'); stop_gpc($_POST); $listId = (int)_post('list'); $title = trim(_post('title')); @@ -214,22 +243,19 @@ elseif(isset($_GET['editTask'])) echo json_encode($t); exit; } - $tags = trim(_post('tags')); $tz = (int)_post('tz'); if( Config::get('autotz')==0 || $tz<-720 || $tz>720 || $tz%30!=0 ) $tz = round(date('Z')/60); + $tags = trim(_post('tags')); $db->ex("BEGIN"); - $tag_ids = prepare_tags($tags, $listId); - $cur_ids = get_task_tags($id); - if($cur_ids) { - $ids = implode(',', $cur_ids); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); - $db->dq("UPDATE {$db->prefix}tags SET tags_count=tags_count-1 WHERE id IN ($ids)"); + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); + $aTags = prepareTags($tags); + if($aTags) { + $tags = implode(',', $aTags['tags']); + $tags_ids = implode(',',$aTags['ids']); + addTaskTags($id, $aTags['ids'], $listId); } - if($tag_ids) { - update_task_tags($id, $tag_ids); - } - if(is_null($duedate)) $duedate = 'NULL'; else $duedate = $db->quote($duedate); - $db->dq("UPDATE {$db->prefix}todolist SET title=?,note=?,prio=?,tags=?,duedate=$duedate WHERE id=$id", array($title,$note,$prio,$tags)); + $db->dq("UPDATE {$db->prefix}todolist SET title=?,note=?,prio=?,tags=?,tags_ids=?,duedate=?,d_edited=? WHERE id=$id", + array($title, $note, $prio, $tags, $tags_ids, $duedate, time()) ); $db->ex("COMMIT"); $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); if($r) { @@ -257,7 +283,7 @@ elseif(isset($_GET['changeOrder'])) foreach($ad as $diff=>$ids) { if($diff >=0) $set = "ow=ow+".$diff; else $set = "ow=ow-".abs($diff); - $db->dq("UPDATE {$db->prefix}todolist SET $set WHERE id IN (".implode(',',$ids).")"); + $db->dq("UPDATE {$db->prefix}todolist SET $set,d_edited=? WHERE id IN (".implode(',',$ids).")", array(time()) ); } $db->ex("COMMIT"); $t['total'] = 1; @@ -297,7 +323,8 @@ elseif(isset($_GET['suggestTags'])) $begin = trim(_get('q')); $limit = (int)_get('limit'); if($limit<1) $limit = 8; - $q = $db->dq("SELECT name,id FROM {$db->prefix}tags WHERE list_id=$listId AND name LIKE ". $db->quoteForLike('%s%%',$begin). " AND tags_count>0 ORDER BY name LIMIT $limit"); + $q = $db->dq("SELECT name,id FROM {$db->prefix}tags INNER JOIN {$db->prefix}tag2task ON id=tag_id WHERE list_id=$listId AND name LIKE ". + $db->quoteForLike('%s%%',$begin) ." GROUP BY tag_id ORDER BY name LIMIT $limit"); $s = ''; while($r = $q->fetch_row()) { $s .= "$r[0]|$r[1]\n"; @@ -312,7 +339,7 @@ elseif(isset($_GET['setPrio'])) $prio = (int)_get('prio'); if($prio < -1) $prio = -1; elseif($prio > 2) $prio = 2; - $db->ex("UPDATE {$db->prefix}todolist SET prio=$prio WHERE id=$id"); + $db->ex("UPDATE {$db->prefix}todolist SET prio=$prio,d_edited=? WHERE id=$id", array(time()) ); $t = array(); $t['total'] = 1; $t['list'][] = array('id'=>$id, 'prio'=>$prio); @@ -323,31 +350,38 @@ elseif(isset($_GET['tagCloud'])) { $listId = (int)_get('list'); check_read_access($listId); - $a = array(); - $q = $db->dq("SELECT name,tags_count FROM {$db->prefix}tags WHERE list_id=$listId AND tags_count>0 ORDER BY tags_count ASC"); - while($r = $q->fetch_row()) { - $a[$r[0]] = $r[1]; + + $q = $db->dq("SELECT name,tag_id,COUNT(tag_id) AS tags_count FROM {$db->prefix}tag2task INNER JOIN {$db->prefix}tags ON tag_id=id ". + "WHERE list_id=$listId GROUP BY (tag_id) ORDER BY tags_count ASC"); + $at = array(); + $ac = array(); + while($r = $q->fetch_assoc()) { + $at[] = array('name'=>$r['name'], 'id'=>$r['tag_id']); + $ac[] = $r['tags_count']; } + $t = array(); $t['total'] = 0; - $count = sizeof($a); + $count = sizeof($at); if(!$count) { echo json_encode($t); exit; } - $qmax = max(array_values($a)); - $qmin = min(array_values($a)); + + $qmax = max($ac); + $qmin = min($ac); if($count >= 10) $grades = 10; else $grades = $count; $step = ($qmax - $qmin)/$grades; - foreach($a as $tag=>$q) { - $t['cloud'][] = array('tag'=>htmlarray($tag), 'w'=> tag_size($qmin,$q,$step) ); + foreach($at as $i=>$tag) + { + $t['cloud'][] = array('tag'=>htmlarray($tag['name']), 'id'=>(int)$tag['id'], 'w'=> tag_size($qmin,$ac[$i],$step) ); } $t['total'] = $count; echo json_encode($t); exit; } -elseif(isset($_POST['addList'])) +elseif(isset($_GET['addList'])) { check_write_access(); stop_gpc($_POST); @@ -355,7 +389,8 @@ elseif(isset($_POST['addList'])) $t['total'] = 0; $name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name'))); $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}lists"); - $db->dq("INSERT INTO {$db->prefix}lists (name,ow) VALUES (?,?)", array($name,$ow)); + $db->dq("INSERT INTO {$db->prefix}lists (uuid,name,ow,d_created,d_edited) VALUES (?,?,?,?,?)", + array(generateUUID(), $name, $ow, time(), time()) ); $id = $db->last_insert_id(); $t['total'] = 1; $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); @@ -363,35 +398,33 @@ elseif(isset($_POST['addList'])) echo json_encode($t); exit; } -elseif(isset($_POST['renameList'])) +elseif(isset($_GET['renameList'])) { check_write_access(); stop_gpc($_POST); $t = array(); $t['total'] = 0; - $id = (int)_post('id'); + $id = (int)_post('list'); $name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name'))); - $db->dq("UPDATE {$db->prefix}lists SET name=? WHERE id=$id", array($name)); + $db->dq("UPDATE {$db->prefix}lists SET name=?,d_edited=? WHERE id=$id", array($name, time()) ); $t['total'] = $db->affected(); $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); $t['list'][] = prepareList($r); echo json_encode($t); exit; } -elseif(isset($_POST['deleteList'])) +elseif(isset($_GET['deleteList'])) { check_write_access(); stop_gpc($_POST); $t = array(); $t['total'] = 0; - $id = (int)_post('id'); + $id = (int)_post('list'); $db->ex("BEGIN"); $db->ex("DELETE FROM {$db->prefix}lists WHERE id=$id"); $t['total'] = $db->affected(); if($t['total']) { - $db->ex("DELETE FROM {$db->prefix}tags WHERE list_id=$id"); - # sqlite doesnt support DELETE FROM INNNER JOIN - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id IN (SELECT id FROM {$db->prefix}todolist WHERE list_id=$id)"); + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE list_id=$id"); $db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$id"); } $db->ex("COMMIT"); @@ -404,7 +437,7 @@ elseif(isset($_GET['setSort'])) $listId = (int)_post('list'); $sort = (int)_post('sort'); if($sort < 0 || $sort > 2) $sort = 0; - $db->ex("UPDATE {$db->prefix}lists SET sorting=$sort WHERE id=$listId"); + $db->ex("UPDATE {$db->prefix}lists SET sorting=$sort,d_edited=? WHERE id=$listId", array(time())); echo json_encode(array('total'=>1)); exit; } @@ -413,7 +446,7 @@ elseif(isset($_GET['publishList'])) check_write_access(); $listId = (int)_post('list'); $publish = (int)_post('publish'); - $db->ex("UPDATE {$db->prefix}lists SET published=? WHERE id=$listId", array($publish ? 1 : 0)); + $db->ex("UPDATE {$db->prefix}lists SET published=?,d_created=? WHERE id=$listId", array($publish ? 1 : 0, time())); echo json_encode(array('total'=>1)); exit; } @@ -431,7 +464,7 @@ elseif(isset($_GET['changeListOrder'])) { check_write_access(); stop_gpc($_POST); - $order = (array)_post('list'); + $order = (array)_post('order'); $t = array(); $t['total'] = 0; if($order) @@ -444,7 +477,8 @@ elseif(isset($_GET['changeListOrder'])) $setCase .= "WHEN id=$id THEN $ow\n"; } $ids = implode($a, ','); - $db->dq("UPDATE {$db->prefix}lists SET ow = CASE\n $setCase END WHERE id IN ($ids)"); + $db->dq("UPDATE {$db->prefix}lists SET d_edited=?, ow = CASE\n $setCase END WHERE id IN ($ids)", + array(time()) ); $t['total'] = 1; } echo json_encode($t); @@ -475,22 +509,10 @@ elseif(isset($_GET['clearCompletedInList'])) $t = array(); $t['total'] = 0; $listId = (int)_post('list'); - $setCase = ''; - $aId = array(); - $q = $db->dq("SELECT tag_id,COUNT(task_id) FROM {$db->prefix}tag2task INNER JOIN {$db->prefix}todolist ON task_id=id WHERE list_id=$listId AND compl=1 GROUP BY tag_id"); - while($r = $q->fetch_row()) { - $aId[] = $r[0]; - $setCase .= "WHEN id=$r[0] THEN $r[1]\n"; - } $db->ex("BEGIN"); - if($aId) { - $ids = implode(',', $aId); - $db->ex("UPDATE {$db->prefix}tags SET tags_count=tags_count - CASE\n $setCase END WHERE id IN ($ids)"); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id IN (SELECT id FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=1)"); - } + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id IN (SELECT id FROM {$db->prefix}todolist WHERE list_id=? and compl=1)", array($listId)); $db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$listId and compl=1"); $t['total'] = $db->affected(); - $db->ex("DELETE FROM {$db->prefix}tags WHERE tags_count < 1"); $db->ex("COMMIT"); echo json_encode($t); exit; @@ -502,23 +524,34 @@ function prepareTaskRow($r, $tz) { global $lang; $dueA = prepare_duedate($r['duedate'], $tz); + $formatCreatedInline = $formatCompletedInline = 'M d'; + if(date('Y') != date('Y',$r['d_created'])) $formatCreatedInline = 'M Y'; + if($r['d_completed'] && date('Y') != date('Y',$r['d_completed'])) $formatCompletedInline = 'M Y'; + $dCreated = timestampToDatetime($r['d_created'], $tz); + $dCompleted = $r['d_completed'] ? timestampToDatetime($r['d_completed'], $tz) : ''; + return array( 'id' => $r['id'], 'title' => escapeTags($r['title']), 'date' => htmlarray($dCreated), - 'dateInline' => htmlarray(sprintf($lang->get('taskdate_inline'), $dCreated)), - 'dateCompleted' => $r['d_completed'] ? htmlarray(timestampToDatetime($r['d_completed'], $tz)) : '', + 'dateInline' => htmlarray(formatTime($formatCreatedInline, $r['d_created'], $tz)), + 'dateInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_created'), $dCreated)), + 'dateCompleted' => htmlarray($dCompleted), + 'dateCompletedInline' => $r['d_completed'] ? htmlarray(formatTime($formatCompletedInline, $r['d_completed'], $tz)) : '', + 'dateCompletedInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_completed'), $dCompleted)), 'compl' => (int)$r['compl'], 'prio' => $r['prio'], 'note' => nl2br(escapeTags($r['note'])), 'noteText' => (string)$r['note'], 'ow' => (int)$r['ow'], 'tags' => htmlarray($r['tags']), + 'tags_ids' => htmlarray($r['tags_ids']), 'duedate' => $dueA['formatted'], 'dueClass' => $dueA['class'], - 'dueStr' => htmlarray($dueA['str']), + 'dueStr' => htmlarray($r['compl'] && $dueA['timestamp'] ? formatTime($formatCompletedInline, $dueA['timestamp'], $tz) : $dueA['str']), 'dueInt' => date2int($r['duedate']), + 'dueTitle' => htmlarray(sprintf($lang->get('taskdate_inline_duedate'), $dueA['formatted'])), ); } @@ -549,41 +582,57 @@ function check_write_access() exit; } -function prepare_tags(&$tags_str, $listId) +function inputTaskParams() { - $tag_ids = array(); - $tag_names = array(); - $tags = explode(',', $tags_str); - foreach($tags as $v) - { - # remove duplicate tags? - $tag = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim($v)); + $a = array( + 'id' => _post('id'), + 'title'=> trim(_post('title')), + 'note' => str_replace("\r\n", "\n", trim(_post('note'))), + 'prio' => (int)_post('prio'), + 'duedate' => '', + 'tags' => trim(_post('tags')), + 'listId' => (int)_post('list'), + + ); + if($a['prio'] < -1) $a['prio'] = -1; + elseif($a['prio'] > 2) $a['prio'] = 2; + return $a; +} + +function prepareTags($tagsStr) +{ + $tags = explode(',', $tagsStr); + if(!$tags) return 0; + + $aTags = array('tags'=>array(), 'ids'=>array()); + foreach($tags as $tag) + { + $tag = str_replace(array('"',"'",'<','>','&','/','\\','^'),'',trim($tag)); if($tag == '') continue; - 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; + + $aTag = getOrCreateTag($tag); + if($aTag && !in_array($aTag['id'], $aTags['ids'])) { + $aTags['tags'][] = $aTag['name']; + $aTags['ids'][] = $aTag['id']; } } - $tags_str = implode(',', $tag_names); - return $tag_ids; + return $aTags; } -function get_or_create_tag($name, $listId) +function getOrCreateTag($name) { global $db; - $tag = $db->sq("SELECT id,name FROM {$db->prefix}tags WHERE list_id=? AND name=?", array($listId, $name)); - if($tag) return $tag; + $tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name)); + if($tagId) return array('id'=>$tagId, 'name'=>$name); - # need to create tag - $db->ex("INSERT INTO {$db->prefix}tags (name,list_id) VALUES (?,?)", array($name,$listId)); - return array($db->last_insert_id(), $name); + $db->ex("INSERT INTO {$db->prefix}tags (name) VALUES (?)", array($name)); + return array('id'=>$db->last_insert_id(), 'name'=>$name); } -function get_tag_id($tag, $listId) +function getTagId($tag) { global $db; - $id = $db->sq("SELECT id FROM {$db->prefix}tags WHERE list_id=? AND name=?", array($listId, $tag)); + $id = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($tag)); return $id ? $id : 0; } @@ -598,13 +647,15 @@ function get_task_tags($id) return $a; } -function update_task_tags($id, $tag_ids) + +function addTaskTags($taskId, $tagIds, $listId) { global $db; - foreach($tag_ids as $v) { - $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id) VALUES ($id,$v)"); + if(!$tagIds) return; + foreach($tagIds as $tagId) + { + $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); } - $db->ex("UPDATE {$db->prefix}tags SET tags_count=tags_count+1 WHERE id IN (". implode(',', $tag_ids). ")"); } function parse_smartsyntax($title) @@ -677,12 +728,13 @@ function prepare_duedate($duedate, $tz) { global $lang; - $a = array( 'class'=>'', 'str'=>'', 'formatted'=>'' ); + $a = array( 'class'=>'', 'str'=>'', 'formatted'=>'', 'timestamp'=>0 ); if($duedate == '') { return $a; } $ad = explode('-', $duedate); $at = explode('-', gmdate('Y-m-d', time() + $tz*60)); + $a['timestamp'] = gmmktime(0,0,0,$ad[1],$ad[2],$ad[0]) + $tz*60; $diff = mktime(0,0,0,$ad[1],$ad[2],$ad[0]) - mktime(0,0,0,$at[1],$at[2],$at[0]); if($diff < -604800 && $ad[0] == $at[0]) { $a['class'] = 'past'; $a['str'] = formatDate3(Config::get('dateformatshort'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } @@ -739,9 +791,10 @@ function myErrorHandler($errno, $errstr, $errfile, $errline) function myExceptionHandler($e) { if(-1 == $e->getCode()) { - echo $e->getMessage(); exit; + echo $e->getMessage()."\n". $e->getTraceAsString(); + exit; } - echo 'Exception: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine(); + echo 'Exception: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine(); //."\n". $e->getTraceAsString(); exit; } @@ -749,14 +802,9 @@ function deleteTask($id) { check_write_access(); global $db; - $tags = get_task_tags($id); $db->ex("BEGIN"); - if($tags) { - $s = implode(',', $tags); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); - $db->ex("UPDATE {$db->prefix}tags SET tags_count=tags_count-1 WHERE id IN ($s)"); - $db->ex("DELETE FROM {$db->prefix}tags WHERE tags_count < 1"); # slow on large amount of tags - } + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); + //TODO: delete unused tags? $db->dq("DELETE FROM {$db->prefix}todolist WHERE id=$id"); $affected = $db->affected(); $db->ex("COMMIT"); @@ -767,23 +815,20 @@ function moveTask($id, $listId) { check_write_access(); global $db; + + // Check task exists and not in target list $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=?", array($id)); if(!$r || $listId == $r['list_id']) return false; + + // Check target list exists if(!$db->sq("SELECT COUNT(*) FROM {$db->prefix}lists WHERE id=?", $listId)) return false; $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=? AND compl=?", array($listId, $r['compl']?1:0)); - $tags = get_task_tags($id); + $db->ex("BEGIN"); - if($tags) - { - $s = implode(',', $tags); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=?", $id); - $db->ex("UPDATE {$db->prefix}tags SET tags_count=tags_count-1 WHERE id IN ($s)"); - $db->ex("DELETE FROM {$db->prefix}tags WHERE tags_count < 1"); #slow - update_task_tags($id, prepare_tags($r['tags'], $listId)); - } - $db->dq("UPDATE {$db->prefix}todolist SET list_id=?, ow=? WHERE id=?", array($listId, $ow, $id)); + $db->ex("UPDATE {$db->prefix}tag2task SET list_id=? WHERE task_id=?", array($listId, $id)); + $db->dq("UPDATE {$db->prefix}todolist SET list_id=?, ow=?, d_edited=? WHERE id=?", array($listId, $ow, time(), $id)); $db->ex("COMMIT"); return true; } @@ -797,7 +842,7 @@ function prepareList($row) 'sort' => (int)$row['sorting'], 'published' => $row['published'] ? 1 :0, 'showCompl' => $taskview & 1 ? 1 : 0, -// 'showNotes' => $taskview & 2 ? 1 : 0, + 'showNotes' => $taskview & 2 ? 1 : 0, ); } diff --git a/src/class.db.mysql.php b/src/class.db.mysql.php index b4c0742..6a77775 100644 --- a/src/class.db.mysql.php +++ b/src/class.db.mysql.php @@ -133,7 +133,7 @@ class Database_Mysql } $query = ""; for($i=0; $iquote($p[$i]); + $query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i])); } $query .= $m[$i]; } diff --git a/src/class.db.sqlite3.php b/src/class.db.sqlite3.php index 8b410b2..16d21fc 100644 --- a/src/class.db.sqlite3.php +++ b/src/class.db.sqlite3.php @@ -119,7 +119,7 @@ class Database_Sqlite3 } $query = ""; for($i=0; $iquote($p[$i]); + $query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i])); } $query .= $m[$i]; } diff --git a/src/common.php b/src/common.php index 5a447c9..b9b9d52 100644 --- a/src/common.php +++ b/src/common.php @@ -165,4 +165,16 @@ function escapeTags($s) return $s; } +/* found in comments on http://www.php.net/manual/en/function.uniqid.php#94959 */ +function generateUUID() +{ + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), + mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) + ); +} + + ?> \ No newline at end of file diff --git a/src/feed.php b/src/feed.php index b32f92d..4635f04 100644 --- a/src/feed.php +++ b/src/feed.php @@ -21,12 +21,27 @@ if(!$listData) { die("No such list"); } -$listData['_feed_title'] = sprintf($lang->get('feed_title'), $listData['name']); -$listData['_feed_descr'] = sprintf($lang->get('feed_description'), $listData['name']); +$feedType = _get('feed'); +$sqlWhere = ''; +if($feedType == 'completed') { + $listData['_uid_field'] = 'd_completed'; + $listData['_feed_descr'] = $lang->get('feed_completed_tasks'); + $sqlWhere = 'AND compl=1'; +} +elseif($feedType == 'modified') { + $listData['_uid_field'] = 'd_edited'; + $listData['_feed_descr'] = $lang->get('feed_modified_tasks'); +} +else { + $listData['_uid_field'] = 'd_created'; + $listData['_feed_descr'] = $lang->get('feed_new_tasks'); +} + +$listData['_feed_title'] = sprintf($lang->get('feed_title'), $listData['name']) . ' - '. $listData['_feed_descr']; htmlarray_ref($listData); $data = array(); -$q = $db->dq("SELECT * FROM {$db->prefix}todolist WHERE list_id=$listId ORDER BY d_created DESC LIMIT 100"); +$q = $db->dq("SELECT * FROM {$db->prefix}todolist WHERE list_id=$listId $sqlWhere ORDER BY ". $listData['_uid_field'] ." DESC LIMIT 100"); while($r = $q->fetch_assoc($q)) { if($r['prio'] > 0) $r['prio'] = '+'.$r['prio']; @@ -57,8 +72,8 @@ function printRss($listData, $data) foreach($data as $v) { - $d = gmdate('r', $v['d_created']); - $guid = $listData['id'].'-'.$v['id'].'-'.$v['d_created']; + $d = gmdate('r', $v[$listData['_uid_field']]); + $guid = $listData['id'].'-'.$v['id'].'-'.$v[$listData['_uid_field']]; $s .= "\n<![CDATA[". str_replace("]]>", "]]]]><![CDATA[>", $v['title']). "]]>\n". "$link\n". diff --git a/src/init.php b/src/init.php index c88c862..66da6ec 100644 --- a/src/init.php +++ b/src/init.php @@ -48,7 +48,7 @@ if($needAuth && !isset($dontStartSession)) { if(Config::get('session') == 'files') { - session_save_path(MTTPATH. 'tmp/sessions/'); + session_save_path(MTTPATH. 'tmp/sessions'); ini_set('session.gc_maxlifetime', '1209600'); # 14 days session file minimum lifetime ini_set('session.gc_probability', 1); ini_set('session.gc_divisor', 10); diff --git a/src/jquery/jquery-1.3.2.min.js b/src/jquery/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/src/jquery/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
    ","
    "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

    ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
    ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
    ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
    ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/src/jquery/jquery-1.4.2.min.js b/src/jquery/jquery-1.4.2.min.js new file mode 100644 index 0000000..7c24308 --- /dev/null +++ b/src/jquery/jquery-1.4.2.min.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
    a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

    ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
    ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
    ","
    "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
    ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
    "; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/src/jquery/jquery.autocomplete-1.1.js b/src/jquery/jquery.autocomplete-1.1.js new file mode 100644 index 0000000..a0daba2 --- /dev/null +++ b/src/jquery/jquery.autocomplete-1.1.js @@ -0,0 +1,839 @@ +/* + * jQuery Autocomplete plugin 1.1 + * + * Copyright (c) 2009 Jörn Zaefferer + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ + */ + +/* + * Changes for myTinyTodo, www.mytinytodo.net + * Copyright (c) 2010 Max Pozdeev + * Dual licensed under the MIT and GPL licenses + */ + +;(function($) { + +$.fn.extend({ + autocomplete: function(urlOrData, options) { + var isUrl = typeof urlOrData == "string"; + var isFunc = typeof urlOrData == "function"; + options = $.extend({}, $.Autocompleter.defaults, { + url: isUrl ? urlOrData : null, + data: !isUrl && !isFunc ? urlOrData : null, + func: isFunc ? urlOrData : null, + delay: isUrl ? $.Autocompleter.defaults.delay : 10, + max: options && !options.scroll ? 10 : 150 + }, options); + + // if highlight is set to false, replace it with a do-nothing function + options.highlight = options.highlight || function(value) { return value; }; + + // if the formatMatch option is not specified, then use formatItem for backwards compatibility + options.formatMatch = options.formatMatch || options.formatItem; + + return this.each(function() { + new $.Autocompleter(this, options); + }); + }, + result: function(handler) { + return this.bind("result", handler); + }, + search: function(handler) { + return this.trigger("search", [handler]); + }, + flushCache: function() { + return this.trigger("flushCache"); + }, + setOptions: function(options){ + return this.trigger("setOptions", [options]); + }, + unautocomplete: function() { + return this.trigger("unautocomplete"); + } +}); + +$.Autocompleter = function(input, options) { + + var KEY = { + UP: 38, + DOWN: 40, + DEL: 46, + TAB: 9, + RETURN: 13, + ESC: 27, + COMMA: 188, + PAGEUP: 33, + PAGEDOWN: 34, + BACKSPACE: 8 + }; + + // Create $ object for input element + var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); + + var timeout; + var previousValue = ""; + var cache = $.Autocompleter.Cache(options); + var hasFocus = 0; + var lastKeyPressCode; + var config = { + mouseDownOnSelect: false + }; + var select = $.Autocompleter.Select(options, input, selectCurrent, config); + + var blockSubmit; + + // prevent form submit in opera when selecting with return key + $.browser.opera && $(input.form).bind("submit.autocomplete", function() { + if (blockSubmit) { + blockSubmit = false; + return false; + } + }); + + // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all + $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { + // a keypress means the input has focus + // avoids issue where input had focus before the autocomplete was applied + hasFocus = 1; + // track last key pressed + lastKeyPressCode = event.keyCode; + switch(event.keyCode) { + + case KEY.UP: + event.preventDefault(); + if ( select.visible() ) { + select.prev(); + } else { + onChange(0, true); + } + break; + + case KEY.DOWN: + event.preventDefault(); + if ( select.visible() ) { + select.next(); + } else { + onChange(0, true); + } + break; + + case KEY.PAGEUP: + event.preventDefault(); + if ( select.visible() ) { + select.pageUp(); + } else { + onChange(0, true); + } + break; + + case KEY.PAGEDOWN: + event.preventDefault(); + if ( select.visible() ) { + select.pageDown(); + } else { + onChange(0, true); + } + break; + + // matches also semicolon + case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: + case KEY.TAB: + case KEY.RETURN: + if( selectCurrent() ) { + // stop default to prevent a form submit, Opera needs special handling + event.preventDefault(); + blockSubmit = true; + return false; + } + break; + + case KEY.ESC: + select.hide(); + break; + + default: + clearTimeout(timeout); + timeout = setTimeout(onChange, options.delay); + break; + } + }).focus(function(){ + // track whether the field has focus, we shouldn't process any + // results if the field no longer has focus + hasFocus++; + }).blur(function() { + hasFocus = 0; + if (!config.mouseDownOnSelect) { + hideResults(); + } + }).click(function() { + // show select when clicking in a focused field + if ( hasFocus++ > 1 && !select.visible() ) { + onChange(0, true); + } + }).bind("search", function() { + // TODO why not just specifying both arguments? + var fn = (arguments.length > 1) ? arguments[1] : null; + function findValueCallback(q, data) { + var result; + if( data && data.length ) { + for (var i=0; i < data.length; i++) { + if( data[i].result.toLowerCase() == q.toLowerCase() ) { + result = data[i]; + break; + } + } + } + if( typeof fn == "function" ) fn(result); + else $input.trigger("result", result && [result.data, result.value]); + } + $.each(trimWords($input.val()), function(i, value) { + request(value, findValueCallback, findValueCallback); + }); + }).bind("flushCache", function() { + cache.flush(); + }).bind("setOptions", function() { + $.extend(options, arguments[1]); + // if we've updated the data, repopulate + if ( "data" in arguments[1] ) + cache.populate(); + }).bind("unautocomplete", function() { + select.unbind(); + $input.unbind(); + $(input.form).unbind(".autocomplete"); + }); + + + function selectCurrent() { + var selected = select.selected(); + if( !selected ) + return false; + + var v = selected.result; + previousValue = v; + + if ( options.multiple ) { + var words = trimWords($input.val()); + if ( words.length > 1 ) { + var seperator = options.multipleSeparator.length; + var cursorAt = $(input).selection().start; + var wordAt, progress = 0; + $.each(words, function(i, word) { + progress += word.length; + if (cursorAt <= progress) { + wordAt = i; + return false; + } + progress += seperator; + }); + words[wordAt] = v; + // TODO this should set the cursor to the right position, but it gets overriden somewhere + //$.Autocompleter.Selection(input, progress + seperator, progress + seperator); + v = words.join( options.multipleSeparator ); + } + v += options.multipleSeparator; + } + + $input.val(v); + hideResultsNow(); + $input.trigger("result", [selected.data, selected.value]); + return true; + } + + function onChange(crap, skipPrevCheck) { + if( lastKeyPressCode == KEY.DEL ) { + select.hide(); + return; + } + + var currentValue = $input.val(); + + if ( !skipPrevCheck && currentValue == previousValue ) + return; + + previousValue = currentValue; + + currentValue = lastWord(currentValue); + if ( currentValue.length >= options.minChars) { + $input.addClass(options.loadingClass); + if (!options.matchCase) + currentValue = currentValue.toLowerCase(); + request(currentValue, receiveData, hideResultsNow); + } else { + stopLoading(); + select.hide(); + } + }; + + function trimWords(value) { + if (!value) + return [""]; + if (!options.multiple) + return [$.trim(value)]; + return $.map(value.split(options.multipleSeparator), function(word) { + return $.trim(value).length ? $.trim(word) : null; + }); + } + + function lastWord(value) { + if ( !options.multiple ) + return value; + var words = trimWords(value); + if (words.length == 1) + return words[0]; + var cursorAt = $(input).selection().start; + if (cursorAt == value.length) { + words = trimWords(value) + } else { + words = trimWords(value.replace(value.substring(cursorAt), "")); + } + return words[words.length - 1]; + } + + // fills in the input box w/the first match (assumed to be the best match) + // q: the term entered + // sValue: the first matching result + function autoFill(q, sValue){ + // autofill in the complete box w/the first match as long as the user hasn't entered in more data + // if the last user key pressed was backspace, don't autofill + if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) { + // fill in the value (keep the case the user has typed) + $input.val($input.val() + sValue.substring(lastWord(previousValue).length)); + // select the portion of the value not typed by the user (so the next character will erase) + $(input).selection(previousValue.length, previousValue.length + sValue.length); + } + }; + + function hideResults() { + clearTimeout(timeout); + timeout = setTimeout(hideResultsNow, 200); + }; + + function hideResultsNow() { + var wasVisible = select.visible(); + select.hide(); + clearTimeout(timeout); + stopLoading(); + if (options.mustMatch) { + // call search and run callback + $input.search( + function (result){ + // if no value found, clear the input box + if( !result ) { + if (options.multiple) { + var words = trimWords($input.val()).slice(0, -1); + $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") ); + } + else { + $input.val( "" ); + $input.trigger("result", null); + } + } + } + ); + } + }; + + function receiveData(q, data) { + if ( data && data.length && hasFocus ) { + stopLoading(); + select.display(data, q); + autoFill(q, data[0].value); + select.show(); + } else { + hideResultsNow(); + } + }; + + function request(term, success, failure) { + if (!options.matchCase) + term = term.toLowerCase(); + var data = cache.load(term); + // recieve the cached data + if (data && data.length) { + success(term, data); + } + // if function was supplied + else if(options.func) + { + var extraParams = { + timestamp: +new Date() + }; + $.each(options.extraParams, function(key, param) { + extraParams[key] = typeof param == "function" ? param() : param; + }); + + options.func({ + data: $.extend({ + q: lastWord(term), + limit: options.max + }, extraParams)}, + function(data){ + var parsed = options.parse && options.parse(data) || parse(data); + cache.add(term, parsed) + success(term, parsed); + } + ); + } + // if an AJAX url has been supplied, try loading the data now + else if( (typeof options.url == "string") && (options.url.length > 0) ){ + + var extraParams = { + timestamp: +new Date() + }; + $.each(options.extraParams, function(key, param) { + extraParams[key] = typeof param == "function" ? param() : param; + }); + + $.ajax({ + // try to leverage ajaxQueue plugin to abort previous requests + mode: "abort", + // limit abortion to this input + port: "autocomplete" + input.name, + dataType: options.dataType, + url: options.url, + data: $.extend({ + q: lastWord(term), + limit: options.max + }, extraParams), + success: function(data) { + var parsed = options.parse && options.parse(data) || parse(data); + cache.add(term, parsed); + success(term, parsed); + } + }); + } else { + // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match + select.emptyList(); + failure(term); + } + }; + + function parse(data) { + var parsed = []; + var rows = data.split("\n"); + for (var i=0; i < rows.length; i++) { + var row = $.trim(rows[i]); + if (row) { + row = row.split("|"); + parsed[parsed.length] = { + data: row, + value: row[0], + result: options.formatResult && options.formatResult(row, row[0]) || row[0] + }; + } + } + return parsed; + }; + + function stopLoading() { + $input.removeClass(options.loadingClass); + }; + +}; + +$.Autocompleter.defaults = { + inputClass: "ac_input", + resultsClass: "ac_results", + loadingClass: "ac_loading", + minChars: 1, + delay: 400, + matchCase: false, + matchSubset: true, + matchContains: false, + cacheLength: 10, + max: 100, + mustMatch: false, + extraParams: {}, + selectFirst: true, + formatItem: function(row) { return row[0]; }, + formatMatch: null, + autoFill: false, + width: 0, + multiple: false, + multipleSeparator: ", ", + highlight: function(value, term) { + return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); + }, + scroll: true, + scrollHeight: 180 +}; + +$.Autocompleter.Cache = function(options) { + + var data = {}; + var length = 0; + + function matchSubset(s, sub) { + if (!options.matchCase) + s = s.toLowerCase(); + var i = s.indexOf(sub); + if (options.matchContains == "word"){ + i = s.toLowerCase().search("\\b" + sub.toLowerCase()); + } + if (i == -1) return false; + return i == 0 || options.matchContains; + }; + + function add(q, value) { + if (length > options.cacheLength){ + flush(); + } + if (!data[q]){ + length++; + } + data[q] = value; + } + + function populate(){ + if( !options.data ) return false; + // track the matches + var stMatchSets = {}, + nullData = 0; + + // no url was specified, we need to adjust the cache length to make sure it fits the local data store + if( !options.url && !options.func ) options.cacheLength = 1; + + // track all options for minChars = 0 + stMatchSets[""] = []; + + // loop through the array and create a lookup structure + for ( var i = 0, ol = options.data.length; i < ol; i++ ) { + var rawValue = options.data[i]; + // if rawValue is a string, make an array otherwise just reference the array + rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; + + var value = options.formatMatch(rawValue, i+1, options.data.length); + if ( value === false ) + continue; + + var firstChar = value.charAt(0).toLowerCase(); + // if no lookup array for this character exists, look it up now + if( !stMatchSets[firstChar] ) + stMatchSets[firstChar] = []; + + // if the match is a string + var row = { + value: value, + data: rawValue, + result: options.formatResult && options.formatResult(rawValue) || value + }; + + // push the current match into the set list + stMatchSets[firstChar].push(row); + + // keep track of minChars zero items + if ( nullData++ < options.max ) { + stMatchSets[""].push(row); + } + }; + + // add the data items to the cache + $.each(stMatchSets, function(i, value) { + // increase the cache size + options.cacheLength++; + // add to the cache + add(i, value); + }); + } + + // populate any existing data + setTimeout(populate, 25); + + function flush(){ + data = {}; + length = 0; + } + + return { + flush: flush, + add: add, + populate: populate, + load: function(q) { + if (!options.cacheLength || !length) + return null; + /* + * if dealing w/local data and matchContains than we must make sure + * to loop through all the data collections looking for matches + */ + if( (!options.url && !options.func) && options.matchContains ){ + // track all matches + var csub = []; + // loop through all the data grids for matches + for( var k in data ){ + // don't search through the stMatchSets[""] (minChars: 0) cache + // this prevents duplicates + if( k.length > 0 ){ + var c = data[k]; + $.each(c, function(i, x) { + // if we've got a match, add it to the array + if (matchSubset(x.value, q)) { + csub.push(x); + } + }); + } + } + return csub; + } else + // if the exact item exists, use it + if (data[q]){ + return data[q]; + } else + if (options.matchSubset) { + for (var i = q.length - 1; i >= options.minChars; i--) { + var c = data[q.substr(0, i)]; + if (c) { + var csub = []; + $.each(c, function(i, x) { + if (matchSubset(x.value, q)) { + csub[csub.length] = x; + } + }); + return csub; + } + } + } + return null; + } + }; +}; + +$.Autocompleter.Select = function (options, input, select, config) { + var CLASSES = { + ACTIVE: "ac_over" + }; + + var listItems, + active = -1, + data, + term = "", + needsInit = true, + element, + list; + + // Create results + function init() { + if (!needsInit) + return; + element = $("
    ") + .hide() + .addClass(options.resultsClass) + .css("position", "absolute") + .appendTo(document.body); + + list = $("
      ").appendTo(element).mouseover( function(event) { + if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { + active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); + $(target(event)).addClass(CLASSES.ACTIVE); + } + }).click(function(event) { + $(target(event)).addClass(CLASSES.ACTIVE); + select(); + // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus + input.focus(); + return false; + }).mousedown(function() { + config.mouseDownOnSelect = true; + }).mouseup(function() { + config.mouseDownOnSelect = false; + }); + + if( options.width > 0 ) + element.css("width", options.width); + + needsInit = false; + } + + function target(event) { + var element = event.target; + while(element && element.tagName.toUpperCase() != "LI") + element = element.parentNode; + // more fun with IE, sometimes event.target is empty, just ignore it then + if(!element) + return []; + return element; + } + + function moveSelect(step) { + listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE); + movePosition(step); + var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE); + if(options.scroll) { + var offset = 0; + listItems.slice(0, active).each(function() { + offset += this.offsetHeight; + }); + if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) { + list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight()); + } else if(offset < list.scrollTop()) { + list.scrollTop(offset); + } + } + }; + + function movePosition(step) { + active += step; + if (active < 0) { + active = listItems.size() - 1; + } else if (active >= listItems.size()) { + active = 0; + } + } + + function limitNumberOfItems(available) { + return options.max && options.max < available + ? options.max + : available; + } + + function fillList() { + list.empty(); + var max = limitNumberOfItems(data.length); + for (var i=0; i < max; i++) { + if (!data[i]) + continue; + var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term); + if ( formatted === false ) + continue; + var li = $("
    • ").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0]; + $.data(li, "ac_data", data[i]); + } + listItems = list.find("li"); + if ( options.selectFirst ) { + listItems.slice(0, 1).addClass(CLASSES.ACTIVE); + active = 0; + } + // apply bgiframe if available + if ( $.fn.bgiframe ) + list.bgiframe(); + } + + return { + display: function(d, q) { + init(); + data = d; + term = q; + fillList(); + }, + next: function() { + moveSelect(1); + }, + prev: function() { + moveSelect(-1); + }, + pageUp: function() { + if (active != 0 && active - 8 < 0) { + moveSelect( -active ); + } else { + moveSelect(-8); + } + }, + pageDown: function() { + if (active != listItems.size() - 1 && active + 8 > listItems.size()) { + moveSelect( listItems.size() - 1 - active ); + } else { + moveSelect(8); + } + }, + hide: function() { + element && element.hide(); + listItems && listItems.removeClass(CLASSES.ACTIVE); + active = -1; + }, + visible : function() { + return element && element.is(":visible"); + }, + current: function() { + return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]); + }, + show: function() { + var offset = $(input).offset(); + element.css({ + width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(), + top: offset.top + input.offsetHeight, + left: offset.left + }).show(); + if(options.scroll) { + list.scrollTop(0); + list.css({ + maxHeight: options.scrollHeight, + overflow: 'auto' + }); + + if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { + var listHeight = 0; + listItems.each(function() { + listHeight += this.offsetHeight; + }); + var scrollbarsVisible = listHeight > options.scrollHeight; + list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight ); + if (!scrollbarsVisible) { + // IE doesn't recalculate width when scrollbar disappears + listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) ); + } + } + + } + }, + selected: function() { + var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE); + return selected && selected.length && $.data(selected[0], "ac_data"); + }, + emptyList: function (){ + list && list.empty(); + }, + unbind: function() { + element && element.remove(); + } + }; +}; + +$.fn.selection = function(start, end) { + if (start !== undefined) { + return this.each(function() { + if( this.createTextRange ){ + var selRange = this.createTextRange(); + if (end === undefined || start == end) { + selRange.move("character", start); + selRange.select(); + } else { + selRange.collapse(true); + selRange.moveStart("character", start); + selRange.moveEnd("character", end); + selRange.select(); + } + } else if( this.setSelectionRange ){ + this.setSelectionRange(start, end); + } else if( this.selectionStart ){ + this.selectionStart = start; + this.selectionEnd = end; + } + }); + } + var field = this[0]; + if ( field.createTextRange ) { + var range = document.selection.createRange(), + orig = field.value, + teststring = "<->", + textLength = range.text.length; + range.text = teststring; + var caretAt = field.value.indexOf(teststring); + field.value = orig; + this.selection(caretAt, caretAt + textLength); + return { + start: caretAt, + end: caretAt + textLength + } + } else if( field.selectionStart !== undefined ){ + return { + start: field.selectionStart, + end: field.selectionEnd + } + } +}; + +})(jQuery); \ No newline at end of file diff --git a/src/jquery/jquery.autocomplete.min.js b/src/jquery/jquery.autocomplete.min.js deleted file mode 100644 index c9ddfb2..0000000 --- a/src/jquery/jquery.autocomplete.min.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Autocomplete - jQuery plugin 1.0.2 - * - * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Revision: $Id: jquery.autocomplete.js 5747 2008-06-25 18:30:55Z joern.zaefferer $ - * - */;(function($){$.fn.extend({autocomplete:function(urlOrData,options){var isUrl=typeof urlOrData=="string";options=$.extend({},$.Autocompleter.defaults,{url:isUrl?urlOrData:null,data:isUrl?null:urlOrData,delay:isUrl?$.Autocompleter.defaults.delay:10,max:options&&!options.scroll?10:150},options);options.highlight=options.highlight||function(value){return value;};options.formatMatch=options.formatMatch||options.formatItem;return this.each(function(){new $.Autocompleter(this,options);});},result:function(handler){return this.bind("result",handler);},search:function(handler){return this.trigger("search",[handler]);},flushCache:function(){return this.trigger("flushCache");},setOptions:function(options){return this.trigger("setOptions",[options]);},unautocomplete:function(){return this.trigger("unautocomplete");}});$.Autocompleter=function(input,options){var KEY={UP:38,DOWN:40,DEL:46,TAB:9,RETURN:13,ESC:27,COMMA:188,PAGEUP:33,PAGEDOWN:34,BACKSPACE:8};var $input=$(input).attr("autocomplete","off").addClass(options.inputClass);var timeout;var previousValue="";var cache=$.Autocompleter.Cache(options);var hasFocus=0;var lastKeyPressCode;var config={mouseDownOnSelect:false};var select=$.Autocompleter.Select(options,input,selectCurrent,config);var blockSubmit;$.browser.opera&&$(input.form).bind("submit.autocomplete",function(){if(blockSubmit){blockSubmit=false;return false;}});$input.bind(($.browser.opera?"keypress":"keydown")+".autocomplete",function(event){lastKeyPressCode=event.keyCode;switch(event.keyCode){case KEY.UP:event.preventDefault();if(select.visible()){select.prev();}else{onChange(0,true);}break;case KEY.DOWN:event.preventDefault();if(select.visible()){select.next();}else{onChange(0,true);}break;case KEY.PAGEUP:event.preventDefault();if(select.visible()){select.pageUp();}else{onChange(0,true);}break;case KEY.PAGEDOWN:event.preventDefault();if(select.visible()){select.pageDown();}else{onChange(0,true);}break;case options.multiple&&$.trim(options.multipleSeparator)==","&&KEY.COMMA:case KEY.TAB:case KEY.RETURN:if(selectCurrent()){event.preventDefault();blockSubmit=true;return false;}break;case KEY.ESC:select.hide();break;default:clearTimeout(timeout);timeout=setTimeout(onChange,options.delay);break;}}).focus(function(){hasFocus++;}).blur(function(){hasFocus=0;if(!config.mouseDownOnSelect){hideResults();}}).click(function(){if(hasFocus++>1&&!select.visible()){onChange(0,true);}}).bind("search",function(){var fn=(arguments.length>1)?arguments[1]:null;function findValueCallback(q,data){var result;if(data&&data.length){for(var i=0;i1){v=words.slice(0,words.length-1).join(options.multipleSeparator)+options.multipleSeparator+v;}v+=options.multipleSeparator;}$input.val(v);hideResultsNow();$input.trigger("result",[selected.data,selected.value]);return true;}function onChange(crap,skipPrevCheck){if(lastKeyPressCode==KEY.DEL){select.hide();return;}var currentValue=$input.val();if(!skipPrevCheck&¤tValue==previousValue)return;previousValue=currentValue;currentValue=lastWord(currentValue);if(currentValue.length>=options.minChars){$input.addClass(options.loadingClass);if(!options.matchCase)currentValue=currentValue.toLowerCase();request(currentValue,receiveData,hideResultsNow);}else{stopLoading();select.hide();}};function trimWords(value){if(!value){return[""];}var words=value.split(options.multipleSeparator);var result=[];$.each(words,function(i,value){if($.trim(value))result[i]=$.trim(value);});return result;}function lastWord(value){if(!options.multiple)return value;var words=trimWords(value);return words[words.length-1];}function autoFill(q,sValue){if(options.autoFill&&(lastWord($input.val()).toLowerCase()==q.toLowerCase())&&lastKeyPressCode!=KEY.BACKSPACE){$input.val($input.val()+sValue.substring(lastWord(previousValue).length));$.Autocompleter.Selection(input,previousValue.length,previousValue.length+sValue.length);}};function hideResults(){clearTimeout(timeout);timeout=setTimeout(hideResultsNow,200);};function hideResultsNow(){var wasVisible=select.visible();select.hide();clearTimeout(timeout);stopLoading();if(options.mustMatch){$input.search(function(result){if(!result){if(options.multiple){var words=trimWords($input.val()).slice(0,-1);$input.val(words.join(options.multipleSeparator)+(words.length?options.multipleSeparator:""));}else -$input.val("");}});}if(wasVisible)$.Autocompleter.Selection(input,input.value.length,input.value.length);};function receiveData(q,data){if(data&&data.length&&hasFocus){stopLoading();select.display(data,q);autoFill(q,data[0].value);select.show();}else{hideResultsNow();}};function request(term,success,failure){if(!options.matchCase)term=term.toLowerCase();var data=cache.load(term);if(data&&data.length){success(term,data);}else if((typeof options.url=="string")&&(options.url.length>0)){var extraParams={timestamp:+new Date()};$.each(options.extraParams,function(key,param){extraParams[key]=typeof param=="function"?param():param;});$.ajax({mode:"abort",port:"autocomplete"+input.name,dataType:options.dataType,url:options.url,data:$.extend({q:lastWord(term),limit:options.max},extraParams),success:function(data){var parsed=options.parse&&options.parse(data)||parse(data);cache.add(term,parsed);success(term,parsed);}});}else{select.emptyList();failure(term);}};function parse(data){var parsed=[];var rows=data.split("\n");for(var i=0;i]*)("+term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")+")(?![^<>]*>)(?![^&;]+;)","gi"),"$1");},scroll:true,scrollHeight:180};$.Autocompleter.Cache=function(options){var data={};var length=0;function matchSubset(s,sub){if(!options.matchCase)s=s.toLowerCase();var i=s.indexOf(sub);if(i==-1)return false;return i==0||options.matchContains;};function add(q,value){if(length>options.cacheLength){flush();}if(!data[q]){length++;}data[q]=value;}function populate(){if(!options.data)return false;var stMatchSets={},nullData=0;if(!options.url)options.cacheLength=1;stMatchSets[""]=[];for(var i=0,ol=options.data.length;i0){var c=data[k];$.each(c,function(i,x){if(matchSubset(x.value,q)){csub.push(x);}});}}return csub;}else -if(data[q]){return data[q];}else -if(options.matchSubset){for(var i=q.length-1;i>=options.minChars;i--){var c=data[q.substr(0,i)];if(c){var csub=[];$.each(c,function(i,x){if(matchSubset(x.value,q)){csub[csub.length]=x;}});return csub;}}}return null;}};};$.Autocompleter.Select=function(options,input,select,config){var CLASSES={ACTIVE:"ac_over"};var listItems,active=-1,data,term="",needsInit=true,element,list;function init(){if(!needsInit)return;element=$("
      ").hide().addClass(options.resultsClass).css("position","absolute").appendTo(document.body);list=$("
        ").appendTo(element).mouseover(function(event){if(target(event).nodeName&&target(event).nodeName.toUpperCase()=='LI'){active=$("li",list).removeClass(CLASSES.ACTIVE).index(target(event));$(target(event)).addClass(CLASSES.ACTIVE);}}).click(function(event){$(target(event)).addClass(CLASSES.ACTIVE);select();input.focus();return false;}).mousedown(function(){config.mouseDownOnSelect=true;}).mouseup(function(){config.mouseDownOnSelect=false;});if(options.width>0)element.css("width",options.width);needsInit=false;}function target(event){var element=event.target;while(element&&element.tagName!="LI")element=element.parentNode;if(!element)return[];return element;}function moveSelect(step){listItems.slice(active,active+1).removeClass(CLASSES.ACTIVE);movePosition(step);var activeItem=listItems.slice(active,active+1).addClass(CLASSES.ACTIVE);if(options.scroll){var offset=0;listItems.slice(0,active).each(function(){offset+=this.offsetHeight;});if((offset+activeItem[0].offsetHeight-list.scrollTop())>list[0].clientHeight){list.scrollTop(offset+activeItem[0].offsetHeight-list.innerHeight());}else if(offset=listItems.size()){active=0;}}function limitNumberOfItems(available){return options.max&&options.max").html(options.highlight(formatted,term)).addClass(i%2==0?"ac_even":"ac_odd").appendTo(list)[0];$.data(li,"ac_data",data[i]);}listItems=list.find("li");if(options.selectFirst){listItems.slice(0,1).addClass(CLASSES.ACTIVE);active=0;}if($.fn.bgiframe)list.bgiframe();}return{display:function(d,q){init();data=d;term=q;fillList();},next:function(){moveSelect(1);},prev:function(){moveSelect(-1);},pageUp:function(){if(active!=0&&active-8<0){moveSelect(-active);}else{moveSelect(-8);}},pageDown:function(){if(active!=listItems.size()-1&&active+8>listItems.size()){moveSelect(listItems.size()-1-active);}else{moveSelect(8);}},hide:function(){element&&element.hide();listItems&&listItems.removeClass(CLASSES.ACTIVE);active=-1;},visible:function(){return element&&element.is(":visible");},current:function(){return this.visible()&&(listItems.filter("."+CLASSES.ACTIVE)[0]||options.selectFirst&&listItems[0]);},show:function(){var offset=$(input).offset();element.css({width:typeof options.width=="string"||options.width>0?options.width:$(input).width(),top:offset.top+input.offsetHeight,left:offset.left}).show();if(options.scroll){list.scrollTop(0);list.css({maxHeight:options.scrollHeight,overflow:'auto'});if($.browser.msie&&typeof document.body.style.maxHeight==="undefined"){var listHeight=0;listItems.each(function(){listHeight+=this.offsetHeight;});var scrollbarsVisible=listHeight>options.scrollHeight;list.css('height',scrollbarsVisible?options.scrollHeight:listHeight);if(!scrollbarsVisible){listItems.width(list.width()-parseInt(listItems.css("padding-left"))-parseInt(listItems.css("padding-right")));}}}},selected:function(){var selected=listItems&&listItems.filter("."+CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);return selected&&selected.length&&$.data(selected[0],"ac_data");},emptyList:function(){list&&list.empty();},unbind:function(){element&&element.remove();}};};$.Autocompleter.Selection=function(field,start,end){if(field.createTextRange){var selRange=field.createTextRange();selRange.collapse(true);selRange.moveStart("character",start);selRange.moveEnd("character",end);selRange.select();}else if(field.setSelectionRange){field.setSelectionRange(start,end);}else{if(field.selectionStart){field.selectionStart=start;field.selectionEnd=end;}}field.focus();};})(jQuery); \ No newline at end of file diff --git a/src/lang/class.default.php b/src/lang/class.default.php index dea019e..b60a6f1 100644 --- a/src/lang/class.default.php +++ b/src/lang/class.default.php @@ -36,9 +36,12 @@ class DefaultLang 'advanced_add' => "Advanced", 'searching' => "Searching for", 'tasks' => "Tasks", - 'taskdate_inline' => "added at %s", - 'taskdate_created' => "Date of creation", - 'taskdate_completed' => "Date of completion", + 'taskdate_inline_created' => "Created: %s", + 'taskdate_inline_completed' => "Completed: %s", + 'taskdate_inline_duedate' => "Due: %s", + 'taskdate_created' => "Created", + 'taskdate_completed' => "Completed", + 'go_back' => "<< Back", 'edit_task' => "Edit Task", 'add_task' => "New Task", 'priority' => "Priority", @@ -83,13 +86,18 @@ class DefaultLang 'list_publish' => "Publish list", 'list_showcompleted' => "Show completed tasks", 'list_clearcompleted' => "Clear completed tasks", + 'list_select' => "Select list", + 'list_exportcsv' => "Export to CSV", + 'list_rssfeed' => "RSS Feed", 'alltags' => "All tags:", 'alltags_show' => "Show all", 'alltags_hide' => "Hide all", 'a_settings' => "Settings", 'rss_feed' => "RSS Feed", 'feed_title' => "%s", - 'feed_description' => "New tasks in %s", + 'feed_completed_tasks' => "Completed tasks", + 'feed_modified_tasks' => "Modified tasks", + 'feed_new_tasks' => "New tasks", /* Settings */ 'set_header' => "Settings", @@ -147,8 +155,17 @@ class DefaultLang $t = array(); foreach($this->get('months_long') as $v) { $t[] = '"'.str_replace('"','\\"',$v).'"'; } $a[] = "monthsLong: [". implode(',', $t). "]"; - $a[] = "tags: \"". str_replace('"','\\"',$this->get('tags')). "\""; - return "lang = {\n". implode(",\n", $a). "\n};"; + $a[] = $this->_2js('tags'); + $a[] = $this->_2js('tasks'); + $a[] = $this->_2js('f_past'); + $a[] = $this->_2js('f_today'); + $a[] = $this->_2js('f_soon'); + return "{\n". implode(",\n", $a). "\n}"; + } + + function _2js($v) + { + return "$v: \"". str_replace('"','\\"',$this->get($v)). "\""; } function get($key) diff --git a/src/lang/en.php b/src/lang/en.php index dc71120..0374455 100644 --- a/src/lang/en.php +++ b/src/lang/en.php @@ -38,9 +38,12 @@ class Lang extends DefaultLang 'advanced_add' => "Advanced", 'searching' => "Searching for", 'tasks' => "Tasks", - 'taskdate_inline' => "added at %s", - 'taskdate_created' => "Date of creation", - 'taskdate_completed' => "Date of completion", + 'taskdate_inline_created' => "Created: %s", + 'taskdate_inline_completed' => "Completed: %s", + 'taskdate_inline_duedate' => "Due: %s", + 'taskdate_created' => "Created", + 'taskdate_completed' => "Completed", + 'go_back' => "<< Back", 'edit_task' => "Edit Task", 'add_task' => "New Task", 'priority' => "Priority", @@ -85,13 +88,18 @@ class Lang extends DefaultLang 'list_publish' => "Publish list", 'list_showcompleted' => "Show completed tasks", 'list_clearcompleted' => "Clear completed tasks", + 'list_select' => "Select list", + 'list_exportcsv' => "Export to CSV", + 'list_rssfeed' => "RSS Feed", 'alltags' => "All tags:", 'alltags_show' => "Show all", 'alltags_hide' => "Hide all", 'a_settings' => "Settings", 'rss_feed' => "RSS Feed", 'feed_title' => "%s", - 'feed_description' => "New tasks in %s", + 'feed_completed_tasks' => "Completed tasks", + 'feed_modified_tasks' => "Modified tasks", + 'feed_new_tasks' => "New tasks", /* Settings */ 'set_header' => "Settings", diff --git a/src/mytinytodo.js b/src/mytinytodo.js new file mode 100644 index 0000000..9ce1eb1 --- /dev/null +++ b/src/mytinytodo.js @@ -0,0 +1,1936 @@ +/* + This file is part of myTinyTodo. + (C) Copyright 2009-2010 Max Pozdeev + Licensed under the GNU GPL v3 license. See file COPYRIGHT for details. +*/ + +(function(){ + +var taskList = new Array(), taskOrder = new Array(); +var filter = { compl:0, search:'', due:'' }; +var sortOrder; //save task order before dragging +var searchTimer; +var objPrio = {}; +var selTask = 0; +var flag = { needAuth:false, isLogged:false, tagsChanged:true, readOnly:false }; +var taskCnt = { total:0, past: 0, today:0, soon:0 }; +var cmenu; +var tabLists = { + _lists: {}, + _length: 0, + _order: [], + clear: function(){ this._lists = {}; this._length = 0; this._order = []; }, + length: function(){ return this._length; }, + exists: function(id){ if(this._lists[id]) return true; else return false; }, + add: function(list){ this._lists[list.id] = list; this._length++; this._order.push(list.id); }, + replace: function(list){ this._lists[list.id] = list; }, + get: function(id){ return this._lists[id]; }, + getAll: function(){ var r = []; for(var i in this._order) { r.push(this._lists[this._order[i]]); }; return r; }, + reorder: function(order){ this._order = order; } +}; +var curList = 0; +var tagsList = []; + +var mytinytodo = window.mytinytodo = _mtt = { + + theme: { + newTaskFlashColor: '#ffffaa', + editTaskFlashColor: '#bbffaa', + msgFlashColor: '#ffffff' + }, + + actions: {}, + menus: {}, + mttUrl: '', + templateUrl: '', + options: { + openList: 0, + singletab: false, + autotag: false, + tagPreview: true + }, + + timers: { + previewtag: 0 + }, + + lang: { + __lang: null, + + daysMin: [], + daysLong: [], + monthsShort: [], + monthsLong: [], + + get: function(v) { + if(this.__lang[v]) return this.__lang[v]; + else return v; + }, + + init: function(lang) + { + this.__lang = lang; + this.daysMin = this.__lang.daysMin; + this.daysLong = this.__lang.daysLong; + this.monthsShort = this.__lang.monthsMin; + this.monthsLong = this.__lang.monthsLong; + } + }, + + pages: { + current: { page:'tasks', pageClass:'' }, + prev: [] + }, + + // procs + init: function(options) + { + jQuery.extend(this.options, options); + + flag.needAuth = options.needAuth ? true : false; + flag.isLogged = options.isLogged ? true : false; + + if(this.options.showdate) $('#page_tasks').addClass('show-inline-date'); + if(this.options.singletab) $('#lists .mtt-tabs').addClass('mtt-tabs-only-one'); + + + // handlers + $('.mtt-tabs-add-button').click(function(){ + addList(); + }); + + $('.mtt-tabs-select-button').click(function(event){ + if(event.metaKey || event.ctrlKey) { + // toggle singetab interface + _mtt.applySingletab(!_mtt.options.singletab); + return false; + } + if(!_mtt.menus.selectlist) _mtt.menus.selectlist = new mttMenu('slmenucontainer', {onclick:slmenuSelect}); + _mtt.menus.selectlist.show(this); + }); + + + $('#newtask_form').submit(function(){ + submitNewTask(this); + return false; + }); + + $('#newtask_submit').click(function(){ + $('#newtask_form').submit(); + }); + + $('#newtask_adv').click(function(){ + showEditForm(1); + return false; + }); + + $('#task').keydown(function(event){ + if(event.keyCode == 27) { + $(this).val(''); + } + }).focusin(function(){ + $('#task_placeholder').removeClass('placeholding'); + $('#toolbar').addClass('mtt-intask'); + }).focusout(function(){ + if('' == $(this).val()) $('#task_placeholder').addClass('placeholding'); + $('#toolbar').removeClass('mtt-intask'); + }); + + + $('#search_form').submit(function(){ + searchTasks(1); + return false; + }); + + $('#search_close').click(function(){ + liveSearchToggle(0); + return false; + }); + + $('#search').keyup(function(event){ + if(event.keyCode == 27) return; + if($(this).val() == '') $('#search_close').hide(); //actual value is only on keyup + else $('#search_close').show(); + clearTimeout(searchTimer); + searchTimer = setTimeout(function(){searchTasks()}, 400); + }) + .keydown(function(event){ + if(event.keyCode == 27) { // cancel on Esc (NB: no esc event on keypress in Chrome and on keyup in Opera) + if($(this).val() != '') { + $(this).val(''); + $('#search_close').hide(); + searchTasks(); + } + else { + liveSearchToggle(0); + } + return false; //need to return false in firefox (for AJAX?) + } + }).focusin(function(){ + $('#toolbar').addClass('mtt-insearch'); + $(this).focus(); + }).focusout(function(){ + $('#toolbar').removeClass('mtt-insearch'); + }); + + + $('#taskview').click(function(){ + if(!_mtt.menus.taskview) _mtt.menus.taskview = new mttMenu('taskviewcontainer'); + _mtt.menus.taskview.show(this); + }); + + $('#mtt_filters .tag-filter .mtt-filter-close').live('click', function(){ + cancelTagFilter($(this).attr('tagid')); + }); + + $('#tagcloudbtn').click(function(){ + if(!_mtt.menus.tagcloud) _mtt.menus.tagcloud = new mttMenu('tagcloud', { + beforeShow: function(){ + if(flag.tagsChanged) { + $('#tagcloudcontent').html(''); + $('#tagcloudload').show(); + loadTags(function(){$('#tagcloudload').hide();}); + } + }, adjustWidth:true + }); + _mtt.menus.tagcloud.show(this); + }); + + $('#tagcloudcancel').click(function(){ + if(_mtt.menus.tagcloud) _mtt.menus.tagcloud.close(); + }); + + $('#tagcloudcontent .tag').live('click', function(){ + addFilterTag($(this).attr('tag'), $(this).attr('tagid')); + if(_mtt.menus.tagcloud) _mtt.menus.tagcloud.close(); + return false; + }); + + $('#mtt-notes-show').click(function(){ + toggleAllNotes(1); + this.blur(); + return false; + }); + + $('#mtt-notes-hide').click(function(){ + toggleAllNotes(0); + this.blur(); + return false; + }); + + $('#taskviewcontainer li').click(function(){ + if(this.id == 'view_tasks') setTaskview(0); + else if(this.id == 'view_past') setTaskview('past'); + else if(this.id == 'view_today') setTaskview('today'); + else if(this.id == 'view_soon') setTaskview('soon'); + }); + + $("#tasklist").bind("click", tasklistClick); + + + // Tabs + $('#lists li.mtt-tab').live('click', function(event){ + tabSelected(this); + if(event.metaKey || event.ctrlKey) { + // toggle singetab interface + _mtt.applySingletab(!_mtt.options.singletab); + } + return false; + }); + + $('#lists li.mtt-tab .list-action').live('click', function(){ + listMenu(this); + return false; //stop bubble to tab click + }); + + //Priority popup + $('#priopopup .prio-neg-1').click(function(){ + prioClick(-1,this); + }); + + $('#priopopup .prio-zero').click(function(){ + prioClick(0,this); + }); + + $('#priopopup .prio-pos-1').click(function(){ + prioClick(1,this); + }); + + $('#priopopup .prio-pos-2').click(function(){ + prioClick(2,this); + }); + + $('#priopopup').mouseleave(function(){ + $(this).hide()} + ); + + + // edit form handlers + $('#alltags_show').click(function(){ + toggleEditAllTags(1); + return false; + }); + + $('#alltags_hide').click(function(){ + toggleEditAllTags(0); + return false; + }); + + $('#taskedit_form').submit(function(){ + return saveTask(this); + }); + + $('#alltags .tag').live('click', function(){ + addEditTag($(this).attr('tag')); + return false; + }); + + + // tasklist handlers + $('#tasklist li').live('dblclick', function(){ + var li = findParentNode(this, 'LI'); + if(li && li.id) { + var id = li.id.split('_',2)[1]; + if(id) editTask(parseInt(id)); + } + }); + + $('#tasklist .taskactionbtn').live('click', function(){ + var id = parseInt(getLiTaskId(this)); + if(id) taskContextMenu(this, id); + return false; + }); + + $('#tasklist input[type=checkbox]').live('click', function(){ + var id = parseInt(getLiTaskId(this)); + if(id) completeTask(id, this); + //return false; + }); + + $('#tasklist .task-toggle').live('click', function(){ + var id = getLiTaskId(this); + if(id) $('#taskrow_'+id).toggleClass('task-expanded'); + return false; + }); + + $('#tasklist .tag').live('click', function(event){ + clearTimeout(_mtt.timers.previewtag); + $('#tasklist li').removeClass('not-in-tagpreview'); + addFilterTag($(this).attr('tag'), $(this).attr('tagid'), (event.metaKey || event.ctrlKey ? true : false) ); + return false; + }); + + $('#tasklist .task-prio').live('mouseover mouseout', function(event){ + var id = parseInt(getLiTaskId(this)); + if(!id) return; + if(event.type == 'mouseover') prioPopup(1, this, id); + else prioPopup(0, this); + }); + + $('#tasklist .mtt-action-note-cancel').live('click', function(){ + var id = parseInt(getLiTaskId(this)); + if(id) cancelTaskNote(id); + return false; + }); + + $('#tasklist .mtt-action-note-save').live('click', function(){ + var id = parseInt(getLiTaskId(this)); + if(id) saveTaskNote(id); + return false; + }); + + if(this.options.tagPreview) { + $('#tasklist .tag').live('mouseover mouseout', function(event){ + var cl = 'tag-id-' + $(this).attr('tagid'); + var sel = (event.metaKey || event.ctrlKey) ? 'li.'+cl : 'li:not(.'+cl+')'; + if(event.type == 'mouseover') { + _mtt.timers.previewtag = setTimeout( function(){$('#tasklist '+sel).addClass('not-in-tagpreview');}, 700); + } + else { + clearTimeout(_mtt.timers.previewtag); + $('#tasklist li').removeClass('not-in-tagpreview'); + } + }); + } + + $("#tasklist").sortable({ + items:'> :not(.task-completed)', cancel:'span,input,a,textarea', + delay:150, start:sortStart, update:orderChanged, + placeholder:'mtt-task-placeholder' + }); + + $("#lists ul").sortable({delay:150, update:listOrderChanged}); + this.applySingletab(); + + $("#duedate").datepicker({ + dateFormat: _mtt.datepickerformat(), + firstDay: _mtt.options.firstdayofweek, + showOn: 'button', + buttonImage: _mtt.templateUrl + 'images/calendar.png', buttonImageOnly: true, + constrainInput: false, + duration:'', + dayNamesMin:_mtt.lang.daysMin, dayNames:_mtt.lang.daysLong, monthNamesShort:_mtt.lang.monthsLong + }); + + $("#edittags").autocomplete('ajax.php?suggestTags', {scroll: false, multiple: true, selectFirst:false, max:8, extraParams:{list:function(){return curList.id}}}); + + + // AJAX Errors + $('#msg').ajaxSend(function(r,s){ + $("#msg").hide().removeClass('mtt-error mtt-info').find('.msg-details').hide(); + $("#loading").show(); + }); + + $('#msg').ajaxStop(function(r,s){ + $("#loading").fadeOut(); + }); + + $('#msg').ajaxError(function(event, request, settings){ + var errtxt; + if(request.status == 0) errtxt = 'Bad connection'; + else if(request.status != 200) errtxt = 'HTTP: '+request.status+'/'+request.statusText; + else errtxt = request.responseText; + flashError(_mtt.lang.get('error'), errtxt); + }); + + + // Error Message details + $("#msg>.msg-text").click(function(){ + $("#msg>.msg-details").toggle(); + }); + + + // Authorization + $('#bar_login').click(function(){ + showAuth(this); + return false; + }); + + $('#bar_logout').click(function(){ + logout(); + return false; + }); + + $('#login_form').submit(function(){ + doAuth(this); + return false; + }); + + + // Settings + $("#settings").click(showSettings); + $("#settings_form").live('submit', function() { + saveSettings(this); + return false; + }); + + $(".mtt-back-button").live('click', function(){ _mtt.pageBack(); this.blur(); return false; } ); + + + // tab menu + this.addAction('listSelected', tabmenuOnListSelected); + + // task context menu + this.addAction('listsLoaded', cmenuOnListsLoaded); + this.addAction('listRenamed', cmenuOnListRenamed); + this.addAction('listAdded', cmenuOnListAdded); + this.addAction('listSelected', cmenuOnListSelected); + this.addAction('listOrderChanged', cmenuOnListOrderChanged); + + // select list menu + this.addAction('listsLoaded', slmenuOnListsLoaded); + this.addAction('listRenamed', slmenuOnListRenamed); + this.addAction('listAdded', slmenuOnListAdded); + this.addAction('listSelected', slmenuOnListSelected); + this.addAction('listOrderChanged', slmenuOnListsLoaded); + + return this; + }, + + log: function(v) + { + console.log.apply(this, arguments); + }, + + addAction: function(action, proc) + { + if(!this.actions[action]) this.actions[action] = new Array(); + this.actions[action].push(proc); + }, + + doAction: function(action, opts) + { + if(!this.actions[action]) return; + for(var i in this.actions[action]) { + this.actions[action][i](opts); + } + }, + + setOptions: function(opts) { + jQuery.extend(this.options, opts); + }, + + loadLists: function(onInit) + { + if(filter.search != '') { + filter.search = ''; + $('#searchbarkeyword').text(''); + $('#searchbar').hide(); + } + $('#page_tasks').hide(); + + tabLists.clear(); + + this.db.loadLists(null, function(res) + { + var ti = ''; + if(res && res.total) + { + // determine if need to open specific tab + var openId = res.list[0].id; + if(_mtt.options.openList) { + for(var i in res.list) { + if(_mtt.options.openList == res.list[i].id) { + openId = res.list[i].id; + break; + } + } + } + + $.each(res.list, function(i,item){ + tabLists.add(item); + ti += '
      • '+ + ''+item.name+''+ + '
      • '; + }); + + //TODO: replace 'chilren', with 'addClass'! + if(!curList) { + $('#toolbar').children().removeClass('invisible'); + $('#page_tasks h3').children().removeClass('invisible'); + $('#mylistscontainer .mtt-need-list').removeClass('mtt-disabled'); + } + + curList = tabLists.get(openId); + loadTasks(); + } + else + { + curList = 0; + $('#toolbar').children().addClass('invisible'); + $('#page_tasks h3').children().addClass('invisible'); + $('#mylistscontainer .mtt-need-list').addClass('mtt-disabled'); + $('#tasklist').html(''); + } + + _mtt.options.openList = 0; + $('#lists ul').html(ti); + $('#lists').show(); + _mtt.doAction('listsLoaded'); + if(curList) _mtt.doAction('listSelected', curList); + $('#page_tasks').show(); + + }); + + if(onInit) updateAccessStatus(); + }, + + datepickerformat: function() + { + var fmt = 'yy-mm-dd'; + if(this.options.duedateformat == 2) fmt = 'm/d/yy'; + else if(this.options.duedateformat == 3) fmt = 'dd.mm.yy'; + else if(this.options.duedateformat == 4) fmt = 'dd/mm/yy'; + return fmt; + }, + + errorDenied: function() + { + flashError(this.lang.get('denied')); + }, + + pageSet: function(page, pageClass) + { + var prev = this.pages.current; + this.pages.prev.push(this.pages.current); + this.pages.current = {page:page, pageClass:pageClass}; + showhide($('#page_'+ this.pages.current.page).addClass('mtt-page-'+ this.pages.current.pageClass), $('#page_'+ prev.page)); + }, + + pageBack: function() + { + if(this.pages.current.page == 'tasks') return false; + var prev = this.pages.current; + this.pages.current = this.pages.prev.pop(); + showhide($('#page_'+ this.pages.current.page), $('#page_'+ prev.page).removeClass('mtt-page-'+prev.page.pageClass)); + }, + + applySingletab: function(yesno) + { + if(yesno == null) yesno = this.options.singletab; + else this.options.singletab = yesno; + + if(yesno) { + $('#lists .mtt-tabs').addClass('mtt-tabs-only-one'); + $("#lists ul").sortable('disable'); + } + else { + $('#lists .mtt-tabs').removeClass('mtt-tabs-only-one'); + $("#lists ul").sortable('enable'); + } + }, + + filter: { + _filters: [], + clear: function() { + this._filters = []; + $('#mtt_filters').html(''); + }, + addTag: function(tagId, tag, exclude) + { + for(var i in this._filters) { + if(this._filters[i].tagId && this._filters[i].tagId == tagId) return false; + } + this._filters.push({tagId:tagId, tag:tag, exclude:exclude}); + $('#mtt_filters').append(''+ + _mtt.lang.get('tagfilter')+''+tag+''); + return true; + }, + cancelTag: function(tagId) + { + for(var i in this._filters) { + if(this._filters[i].tagId && this._filters[i].tagId == tagId) { + this._filters.splice(i,1); + $('#mtt_filters .tag-filter.tag-id-'+tagId).remove(); + return true; + } + } + return false; + }, + getTags: function(withExcluded) + { + var a = []; + for(var i in this._filters) { + if(this._filters[i].tagId) { + if(this._filters[i].exclude && withExcluded) a.push('^'+ this._filters[i].tag); + else if(!this._filters[i].exclude) a.push(this._filters[i].tag) + } + } + return a.join(', '); + } + } + +}; + +function addList() +{ + var r = prompt(_mtt.lang.get('addList'), _mtt.lang.get('addListDefault')); + if(r == null) return; + + _mtt.db.request('addList', {name:r}, function(json){ + if(!parseInt(json.total)) return; + var item = json.list[0]; + var i = tabLists.length(); + tabLists.add(item); + if(i > 0) { + $('#lists ul').append('
      • '+ + ''+item.name+''+ + '
      • '); + mytinytodo.doAction('listAdded', item); + } + else _mtt.loadLists(); + }); +}; + +function renameCurList() +{ + if(!curList) return; + var r = prompt(_mtt.lang.get('renameList'), dehtml(curList.name)); + if(r == null || r == '') return; + + _mtt.db.request('renameList', {list:curList.id, name:r}, function(json){ + if(!parseInt(json.total)) return; + var item = json.list[0]; + curList = item; + tabLists.replace(item); + $('#lists ul>.mtt-tabs-selected>a').attr('title', item.name).find('span').html(item.name); + mytinytodo.doAction('listRenamed', item); + }); +}; + +function deleteCurList() +{ + if(!curList) return false; + var r = confirm(_mtt.lang.get('deleteList')); + if(!r) return; + + _mtt.db.request('deleteList', {list:curList.id}, function(json){ + if(!parseInt(json.total)) return; + _mtt.loadLists(); + }) +}; + +function publishCurList() +{ + if(!curList) return false; + _mtt.db.request('publishList', { list:curList.id, publish:curList.published?0:1 }, function(json){ + if(!parseInt(json.total)) return; + curList.published = curList.published?0:1; + if(curList.published) { + $('#btnPublish').addClass('mtt-item-checked'); + $('#btnRssFeed').removeClass('mtt-disabled'); + } + else { + $('#btnPublish').removeClass('mtt-item-checked'); + $('#btnRssFeed').addClass('mtt-disabled'); + } + }); +}; + + +function loadTasks(opts) +{ + if(!curList) return false; + setSort(curList.sort, 1); + opts = opts || {}; + $('#tasklist').html(''); + $('#total').html('...'); + + _mtt.db.request('loadTasks', { + list: curList.id, + compl: curList.showCompl, + sort: curList.sort, + search: filter.search, + tag: _mtt.filter.getTags(true), + tz: tz(), + setCompl: opts.setCompl + }, function(json){ + taskList.length = 0; + taskOrder.length = 0; + taskCnt.total = taskCnt.past = taskCnt.today = taskCnt.soon = 0; + var tasks = ''; + $.each(json.list, function(i,item){ + tasks += prepareTaskStr(item); + taskList[item.id] = item; + taskOrder.push(parseInt(item.id)); + changeTaskCnt(item, 1); + }); + if(opts.beforeShow && opts.beforeShow.call) { + opts.beforeShow(); + } + refreshTaskCnt(); + $('#tasklist').html(tasks); + }); +}; + + +function prepareTaskStr(item, noteExp) +{ + var id = item.id; + var prio = item.prio; + return '
      • ' + + '
        '+"\n"+ + '
        '+ + '
        '+"\n"+ + '
        '+prepareDuedate(item)+ + ''+item.dateCompletedInline+'
        '+"\n"+ + '
        '+item.dateInline+''+preparePrio(prio,id)+ + ''+prepareHtml(item.title)+' '+"\n"+ + prepareTagsStr(item)+'
        '+ + '
        '+ + '
        '+prepareHtml(item.note)+'
        '+ + ''+ + '
        '+ + "
      • \n"; +}; + + +function prepareHtml(s) +{ + // make URLs clickable + 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) +{ + var cl =''; var v = ''; + if(prio < 0) { cl = 'prio-neg prio-neg-'+Math.abs(prio); v = '−'+Math.abs(prio); } // − = − = − + else if(prio > 0) { cl = 'prio-pos prio-pos-'+prio; v = '+'+prio; } + else { cl = 'prio-zero'; v = '±0'; } // ± = ± = ± + return ''+v+''; +}; + +function prepareTagsStr(item) +{ + if(!item.tags || item.tags == '') return ''; + var a = item.tags.split(','); + if(!a.length) return ''; + var b = item.tags_ids.split(',') + for(var i in a) { + a[i] = ''+a[i]+''; + } + return ''+a.join(', ')+''; +}; + +function prepareTagsClass(ids) +{ + if(!ids || ids == '') return ''; + var a = ids.split(','); + if(!a.length) return ''; + for(var i in a) { + a[i] = 'tag-id-'+a[i]; + } + return ' '+a.join(' '); +}; + +function prepareDuedate(item) +{ + if(!item.duedate) return ''; + return '→ '+item.dueStr+''; +}; + + +function submitNewTask(form) +{ + if(form.task.value == '') return false; + _mtt.db.request('newTask', { list:curList.id, title: form.task.value, tz:tz(), tag:_mtt.filter.getTags() }, function(json){ + if(!json.total) return; + $('#total').text( parseInt($('#total').text()) + 1 ); + taskCnt.total++; + form.task.value = ''; + var item = json.list[0]; + taskList[item.id] = item; + taskOrder.push(parseInt(item.id)); + $('#tasklist').append(prepareTaskStr(item)); + changeTaskOrder(item.id); + $('#taskrow_'+item.id).effect("highlight", {color:_mtt.theme.newTaskFlashColor}, 2000); + refreshTaskCnt(); + }); + flag.tagsChanged = true; + return false; +}; + + +function changeTaskOrder(id) +{ + id = parseInt(id); + if(taskOrder.length < 2) return; + var oldOrder = taskOrder.slice(); + if(curList.sort == 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 + }); + else if(curList.sort == 1) taskOrder.sort( function(a,b){ + if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; + if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; + if(taskList[a].dueInt != taskList[b].dueInt) return taskList[a].dueInt-taskList[b].dueInt; + return taskList[a].ow-taskList[b].ow; + }); + else if(curList.sort == 2) taskOrder.sort( function(a,b){ + if(taskList[a].compl != taskList[b].compl) return taskList[a].compl-taskList[b].compl; + if(taskList[a].dueInt != taskList[b].dueInt) return taskList[a].dueInt-taskList[b].dueInt; + if(taskList[a].prio != taskList[b].prio) return taskList[b].prio-taskList[a].prio; + return taskList[a].ow-taskList[b].ow; + }); + else return; + if(oldOrder.toString() == taskOrder.toString()) return; + if(id && taskList[id]) + { + // optimization: determine where to insert task: top or after some task + var indx = $.inArray(id,taskOrder); + if(indx ==0) { + $('#tasklist').prepend($('#taskrow_'+id)) + } else { + var after = taskOrder[indx-1]; + $('#taskrow_'+after).after($('#taskrow_'+id)); + } + } + else { + var o = $('#tasklist'); + for(var i in taskOrder) { + o.append($('#taskrow_'+taskOrder[i])); + } + } +}; + + +function prioPopup(act, el, id) +{ + if(act == 0) { + clearTimeout(objPrio.timer); + return; + } + var offset = $(el).offset(); + $('#priopopup').css({ position: 'absolute', top: offset.top + 1, left: offset.left + 1 }); + objPrio.taskId = id; + objPrio.el = el; + objPrio.timer = setTimeout("$('#priopopup').show()", 300); +}; + +function prioClick(prio, el) +{ + el.blur(); + prio = parseInt(prio); + $('#priopopup').fadeOut('fast'); //.hide(); + setTaskPrio(objPrio.taskId, prio); +}; + +function setTaskPrio(id, prio) +{ + _mtt.db.request('setPrio', {id:id, prio:prio}); + taskList[id].prio = prio; + var $t = $('#taskrow_'+id); + $t.find('.task-prio').replaceWith(preparePrio(prio, id)); + if(curList.sort != 0) changeTaskOrder(id); + $t.effect("highlight", {color:_mtt.theme.editTaskFlashColor}, 'normal'); +}; + +function setSort(v, init) +{ + $('#mylistscontainer .sort-item').removeClass('mtt-item-checked'); + if(v == 0) $('#sortByHand').addClass('mtt-item-checked'); + else if(v == 1) $('#sortByPrio').addClass('mtt-item-checked'); + else if(v == 2) $('#sortByDueDate').addClass('mtt-item-checked'); + else return; + +/* //port: + if(flag.needAuth && !flag.isLogged) { + $("#tasklist").sortable('disable'); + return; + } +*/ + curList.sort = v; + if(v == 0) $("#tasklist").sortable('enable'); + else $("#tasklist").sortable('disable'); + + if(!init) + { + changeTaskOrder(); + _mtt.db.request('setSort', {list:curList.id, sort:curList.sort}); + } +}; + + +function tz() +{ + return -1 * (new Date()).getTimezoneOffset(); +}; + +function changeTaskCnt(task, dir, old) +{ + if(dir > 0) dir = 1; + else if(dir < 0) dir = -1; + if(dir == 0 && old != null && task.dueClass != old.dueClass) //on saveTask + { + if(old.dueClass != '') taskCnt[old.dueClass]--; + if(task.dueClass != '') taskCnt[task.dueClass]++; + } + else if(dir == 0 && old == null) //on comleteTask + { + if(!curList.showCompl && task.compl) taskCnt.total--; + if(task.dueClass != '') taskCnt[task.dueClass] += task.compl ? -1 : 1; + } + if(dir != 0) { + if(task.dueClass != '' && !task.compl) taskCnt[task.dueClass] += dir; + taskCnt.total += dir; + } +}; + +function refreshTaskCnt() +{ + $('#cnt_total').text(taskCnt.total); + $('#cnt_past').text(taskCnt.past); + $('#cnt_today').text(taskCnt.today); + $('#cnt_soon').text(taskCnt.soon); + if(filter.due == '') $('#total').text(taskCnt.total); + else if(taskCnt[filter.due] != null) $('#total').text(taskCnt[filter.due]); +}; + + +function setTaskview(v) +{ + if(v == 0) + { + if(filter.due == '') return; + $('#taskview .btnstr').text(_mtt.lang.get('tasks')); + $('#tasklist').removeClass('filter-'+filter.due); + filter.due = ''; + $('#total').text(taskCnt.total); + } + else if(v=='past' || v=='today' || v=='soon') + { + if(filter.due == v) return; + else if(filter.due != '') { + $('#tasklist').removeClass('filter-'+filter.due); + } + $('#tasklist').addClass('filter-'+v); + $('#taskview .btnstr').text(_mtt.lang.get('f_'+v)); + $('#total').text(taskCnt[v]); + filter.due = v; + } +}; + + +function toggleAllNotes(show) +{ + for(var id in taskList) + { + if(taskList[id].note == '') continue; + if(show) $('#taskrow_'+id).addClass('task-expanded'); + else $('#taskrow_'+id).removeClass('task-expanded'); + } + curList.showNotes = show; +}; + + +function tabSelected(elementOrId) +{ + var id; + if(typeof elementOrId == 'number') id = elementOrId; + else { + id = $(elementOrId).attr('id'); + if(!id) return; + id = parseInt(id.split('_', 2)[1]); + } + if(!tabLists.exists(id)) return; + $('#lists .mtt-tabs-selected').removeClass('mtt-tabs-selected'); + $('#list_'+id).addClass('mtt-tabs-selected'); + if(curList.id != id) + { + $('#tasklist').html(''); + if(filter.search != '') liveSearchToggle(0, 1); + mytinytodo.doAction('listSelected', tabLists.get(id)); + } + curList = tabLists.get(id); + flag.tagsChanged = true; + cancelTagFilter(0, 1); + setTaskview(0); + loadTasks(); +}; + + + +function listMenu(el) +{ + if(!mytinytodo.menus.listMenu) mytinytodo.menus.listMenu = new mttMenu('mylistscontainer', {onclick:listMenuClick}); + mytinytodo.menus.listMenu.show(el); +}; + +function listMenuClick(el, menu) +{ + if(!el.id) return; + switch(el.id) { + case 'btnAddList': addList(); break; + case 'btnRenameList': renameCurList(); break; + case 'btnDeleteList': deleteCurList(); break; + case 'btnPublish': publishCurList(); break; + case 'btnExportCSV': exportCurListToCSV(); break; + case 'btnRssFeed': feedCurList(); break; + case 'btnShowCompleted': showCompletedToggle(); break; + case 'btnClearCompleted': clearCompleted(); break; + case 'sortByHand': setSort(0); break; + case 'sortByPrio': setSort(1); break; + case 'sortByDueDate': setSort(2); break; + } +}; + +function deleteTask(id) +{ + if(!confirm(_mtt.lang.get('confirmDelete'))) { + return false; + } + _mtt.db.request('deleteTask', {id:id}, function(json){ + if(!parseInt(json.total)) return; + var item = json.list[0]; + taskOrder.splice($.inArray(id,taskOrder), 1); + $('#taskrow_'+id).fadeOut('normal', function(){ $(this).remove() }); + changeTaskCnt(taskList[id], -1); + refreshTaskCnt(); + delete taskList[id]; + }); + flag.tagsChanged = true; + return false; +}; + +function completeTask(id, ch) +{ + if(!taskList[id]) return; //click on already removed from the list while anim. effect + var compl = 0; + if(ch.checked) compl = 1; + _mtt.db.request('completeTask', {id:id, compl:compl, list:curList.id, tz:tz()}, function(json){ + if(!parseInt(json.total)) return; + var item = json.list[0]; + if(item.compl) $('#taskrow_'+id).addClass('task-completed'); + else $('#taskrow_'+id).removeClass('task-completed'); + taskList[id].ow = item.ow; + taskList[id].compl = item.compl; + taskList[id].dateCompleted = item.dateCompleted; + changeTaskCnt(taskList[id], 0); + if(item.compl && !curList.showCompl) { + delete taskList[id]; + taskOrder.splice($.inArray(id,taskOrder), 1); + $('#taskrow_'+id).fadeOut('normal', function(){ $(this).remove() }); + } + else if(curList.showCompl) { + $('#taskrow_'+id).fadeOut('fast', function(){ + changeTaskOrder(id); + $(this).effect("highlight", {color:_mtt.theme.editTaskFlashColor}, 'normal', function(){$(this).css('display','')}); + }); + } + refreshTaskCnt(); + }); + return false; +}; + +function toggleTaskNote(id) +{ + var aArea = '#tasknotearea'+id; + if($(aArea).css('display') == 'none') + { + $('#notetext'+id).val(taskList[id].noteText); + $(aArea).show(); + $('#tasknote'+id).hide(); + $('#taskrow_'+id).addClass('task-expanded'); + $('#notetext'+id).focus(); + } else { + cancelTaskNote(id) + } + return false; +}; + +function cancelTaskNote(id) +{ + if(taskList[id].note == '') $('#taskrow_'+id).removeClass('task-expanded'); + $('#tasknotearea'+id).hide(); + $('#tasknote'+id).show(); + return false; +}; + +function saveTaskNote(id) +{ + _mtt.db.request('editNote', {id:id, note:$('#notetext'+id).val()}, function(json){ + if(!parseInt(json.total)) return; + var item = json.list[0]; + taskList[id].note = item.note; + taskList[id].noteText = item.noteText; + $('#tasknote'+id+'>span').html(prepareHtml(item.note)); + if(item.note == '') $('#taskrow_'+id).removeClass('task-has-note task-expanded'); + else $('#taskrow_'+id).addClass('task-has-note task-expanded'); + cancelTaskNote(id); + }); + return false; +}; + +function editTask(id) +{ + var item = taskList[id]; + if(!item) return false; + // no need to clear form + var form = document.getElementById('taskedit_form'); + form.task.value = dehtml(item.title); + form.note.value = item.noteText; + form.id.value = item.id; + form.tags.value = item.tags.split(',').join(', '); + form.duedate.value = item.duedate; + form.prio.value = item.prio; + $('#taskedit-date .date-created>span').text(item.date); + if(item.compl) $('#taskedit-date .date-completed').show().find('span').text(item.dateCompleted); + else $('#taskedit-date .date-completed').hide(); + toggleEditAllTags(0); + showEditForm(); + return false; +}; + +function clearEditForm() +{ + var form = document.getElementById('taskedit_form'); + form.task.value = ''; + form.note.value = ''; + form.tags.value = ''; + form.duedate.value = ''; + form.prio.value = '0'; + toggleEditAllTags(0); +}; + +function showEditForm(isAdd) +{ + var form = document.getElementById('taskedit_form'); + if(isAdd) + { + clearEditForm(); + $('#page_taskedit').removeClass('mtt-inedit').addClass('mtt-inadd'); + form.isadd.value = 1; + if(_mtt.options.autotag) form.tags.value = _mtt.filter.getTags(); + if($('#task').val() != '') + { + _mtt.db.request('parseTaskStr', { list:curList.id, title:$('#task').val(), tz:tz(), tag:_mtt.filter.getTags() }, function(json){ + if(!json) return; + form.task.value = json.title + form.tags.value = (form.tags.value != '') ? form.tags.value +', '+ json.tags : json.tags; + form.prio.value = json.prio; + $('#task').val(''); + + }); + } + } + else { + $('#page_taskedit').removeClass('mtt-inadd').addClass('mtt-inedit'); + form.isadd.value = 0; + } + + _mtt.pageSet('taskedit'); +}; + +function saveTask(form) +{ +//port: if(flag.needAuth && !flag.isLogged) return false; + if(form.isadd.value != 0) + return submitFullTask(form); + + _mtt.db.request('editTask', {id:form.id.value, list:curList.id, tz:tz(), title: form.task.value, note:form.note.value, + prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value}, + function(json){ + if(!parseInt(json.total)) return; + var item = json.list[0]; + changeTaskCnt(item, 0, taskList[item.id]); + taskList[item.id] = item; + var noteExpanded = (item.note != '' && $('#taskrow_'+item.id).is('.task-expanded')) ? 1 : 0; + $('#taskrow_'+item.id).replaceWith(prepareTaskStr(item, noteExpanded)); + if(curList.sort != 0) changeTaskOrder(item.id); + _mtt.pageBack(); //back to list + refreshTaskCnt(); + $('#taskrow_'+item.id).effect("highlight", {color:_mtt.theme.editTaskFlashColor}, 'normal', function(){$(this).css('display','')}); + }); + $("#edittags").flushCache(); + flag.tagsChanged = true; + return false; +}; + +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); +}; + +function loadTags(callback) +{ + _mtt.db.request('tagCloud', {list:curList.id}, function(json){ + 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 cancelTagFilter(tagId, dontLoadTasks) +{ + if(tagId) _mtt.filter.cancelTag(tagId); + else _mtt.filter.clear(); + if(dontLoadTasks==null || !dontLoadTasks) loadTasks(); +}; + +function addFilterTag(tag, tagId, exclude) +{ + if(!_mtt.filter.addTag(tagId, tag, exclude)) return false; + loadTasks(); +}; + +function liveSearchToggle(toSearch, dontLoad) +{ + if(toSearch) + { + if(flag.readOnly) $('#htab_newtask').hide(); + $('#search').focus(); + } + else + { + if(!flag.readOnly) $('#htab_newtask').show(); + + if($('#search').val() != '') { + filter.search = ''; + $('#search').val(''); + $('#searchbarkeyword').text(''); + $('#searchbar').hide(); + $('#search_close').hide(); + if(!dontLoad) loadTasks(); + } + + $('#search').blur(); + } +}; + +function searchTasks(force) +{ + var newkeyword = $('#search').val(); + if(newkeyword == filter.search && !force) return false; + filter.search = newkeyword; + $('#searchbarkeyword').text(filter.search); + if(filter.search != '') $('#searchbar').fadeIn('fast'); + else $('#searchbar').fadeOut('fast'); + loadTasks(); + return false; +}; + + +function submitFullTask(form) +{ +//port: if(flag.needAuth && !flag.isLogged) return false; + + _mtt.db.request('fullNewTask', { list:curList.id, tag:_mtt.filter.getTags(), title: form.task.value, note:form.note.value, + prio:form.prio.value, tags:form.tags.value, duedate:form.duedate.value }, function(json){ + if(!parseInt(json.total)) return; + form.task.value = ''; + var item = json.list[0]; + taskList[item.id] = item; + taskOrder.push(parseInt(item.id)); + $('#tasklist').append(prepareTaskStr(item)); + changeTaskOrder(item.id); + _mtt.pageBack(); + $('#taskrow_'+item.id).effect("highlight", {color:_mtt.theme.newTaskFlashColor}, 2000); + changeTaskCnt(item, 1); + refreshTaskCnt(); + }); + + $("#edittags").flushCache(); + flag.tagsChanged = true; + return false; +}; + + +function sortStart(event,ui) +{ + // remember initial order before sorting + sortOrder = $(this).sortable('toArray'); +}; + +function orderChanged(event,ui) +{ + if(!ui.item[0]) return; + var itemId = ui.item[0].id; + var n = $(this).sortable('toArray'); + + // remove possible empty id's + for(var i=0; iposition + var h0 = {}; //before + for(var j=0; j $(window).width()) + this.$container.width($(window).width() - (this.$container.outerWidth(true) - this.$container.width())); + + $caller.addClass('mtt-menu-button-active'); + var offset = $caller.offset(); + var x2 = $(window).width() + $(document).scrollLeft() - this.$container.outerWidth(true) - 1; + var x = offset.left < x2 ? offset.left : x2; + if(x<0) x=0; + var y = offset.top+caller.offsetHeight-1; + if(y + this.$container.outerHeight(true) > $(window).height() + $(document).scrollTop()) y = offset.top - this.$container.outerHeight(); + if(y<0) y=0; + this.$container.css({ position: 'absolute', top: y, left: x, width:this.$container.width() /*, 'min-width': $caller.width()*/ }).show(); + var menu = this; + $(document).bind('mousedown.mttmenuclose', function(e){ menu.close(e) }); + this.menuOpen = true; + }; + + this.showSub = function() + { + this.$caller.addClass('mtt-menu-item-active'); + var offset = this.$caller.offset(); + var x = offset.left+this.$caller.outerWidth(); + if(x + this.$container.outerWidth(true) > $(window).width() + $(document).scrollLeft()) x = offset.left - this.$container.outerWidth() - 1; + if(x<0) x=0; + var y = offset.top + this.parent.$container.offset().top-this.parent.$container.find('li:first').offset().top; + if(y + this.$container.outerHeight(true) > $(window).height() + $(document).scrollTop()) y = $(window).height() + $(document).scrollTop()- this.$container.outerHeight(true) - 1; + if(y<0) y=0; + this.$container.css({ position: 'absolute', top: y, left: x, width:this.$container.width() /*, 'min-width': this.$caller.outerWidth()*/ }).show(); + this.menuOpen = true; + }; + + this.destroy = function() + { + for(var i in this.submenu) { + this.submenu[i].destroy(); + delete this.submenu[i]; + } + this.$container.find('li').unbind(); //'click mouseenter mouseleave' + }; +}; + + +function taskContextMenu(el, id) +{ + if(!cmenu) cmenu = new mttMenu('taskcontextcontainer', {onclick:taskContextClick}); + cmenu.tag = id; + cmenu.show(el); +}; + +function taskContextClick(el, menu) +{ + if(!el.id) return; + var taskId = parseInt(cmenu.tag); + var id = el.id, value; + var a = id.split(':'); + if(a.length == 2) { + id = a[0]; + value = a[1]; + } + switch(id) { + case 'cmenu_edit': editTask(taskId); break; + case 'cmenu_note': toggleTaskNote(taskId); break; + case 'cmenu_delete': deleteTask(taskId); break; + case 'cmenu_prio': setTaskPrio(taskId, parseInt(value)); break; + case 'cmenu_list': + if(menu.$caller && menu.$caller.attr('id')=='cmenu_move') moveTaskToList(taskId, value); + break; + } +}; + + +function moveTaskToList(taskId, listId) +{ + if(curList.id == listId) return; + _mtt.db.request('moveTask', {id:taskId, from:curList.id, to:listId}, function(json){ + if(!parseInt(json.total)) return; + changeTaskCnt(taskList[taskId], -1) + delete taskList[taskId]; + taskOrder.splice($.inArray(taskId,taskOrder), 1); + $('#taskrow_'+taskId).fadeOut('normal', function(){ $(this).remove() }); + refreshTaskCnt(); + }); + + $("#edittags").flushCache(); + flag.tagsChanged = true; +}; + + +function cmenuOnListsLoaded() +{ + if(cmenu) cmenu.destroy(); + cmenu = null; + var s = ''; + var all = tabLists.getAll(); + for(var i in all) { + s += '
      • '+all[i].name+'
      • '; + } + $('#listsmenucontainer ul').html(s); +}; + +function cmenuOnListAdded(list) +{ + if(cmenu) cmenu.destroy(); + cmenu = null; + $('#listsmenucontainer ul').append('
      • '+list.name+'
      • '); +}; + +function cmenuOnListRenamed(list) +{ + $('#cmenu_list\\:'+list.id).text(list.name); +}; + +function cmenuOnListSelected(list) +{ + $('#listsmenucontainer li').removeClass('mtt-disabled'); + $('#cmenu_list\\:'+list.id).addClass('mtt-disabled'); +}; + +function cmenuOnListOrderChanged() +{ + cmenuOnListsLoaded(); + $('#cmenu_list\\:'+curList.id).addClass('mtt-disabled'); +}; + + +function tabmenuOnListSelected(list) +{ + if(list.published) { + $('#btnPublish').addClass('mtt-item-checked'); + $('#btnRssFeed').removeClass('mtt-disabled'); + } + else { + $('#btnPublish').removeClass('mtt-item-checked'); + $('#btnRssFeed').addClass('mtt-disabled'); + } + if(list.showCompl) $('#btnShowCompleted').addClass('mtt-item-checked'); + else $('#btnShowCompleted').removeClass('mtt-item-checked'); +}; + + +function listOrderChanged(event, ui) +{ + var a = $(this).sortable("toArray"); + var order = []; + for(var i in a) { + order.push(a[i].split('_')[1]); + } + tabLists.reorder(order); + _mtt.db.request('changeListOrder', {order:order}); + _mtt.doAction('listOrderChanged', {order:order}); +}; + +function showCompletedToggle() +{ + var act = curList.showCompl ? 0 : 1; + curList.showCompl = tabLists.get(curList.id).showCompl = act; + if(act) $('#btnShowCompleted').addClass('mtt-item-checked'); + else $('#btnShowCompleted').removeClass('mtt-item-checked'); + loadTasks({setCompl:1}); +}; + +function clearCompleted() +{ + if(!curList) return false; + var r = confirm(_mtt.lang.get('clearCompleted')); + if(!r) return; + _mtt.db.request('clearCompletedInList', {list:curList.id}, function(json){ + if(!parseInt(json.total)) return; + flag.tagsChanged = true; + if(curList.showCompl) loadTasks(); + }); +}; + +function tasklistClick(e) +{ + var node = e.target.nodeName.toUpperCase(); + if(node=='SPAN' || node=='LI' || node=='DIV') + { + var li = findParentNode(e.target, 'LI'); + if(li) { + if(selTask && li.id != selTask) $('#'+selTask).removeClass('clicked doubleclicked'); + selTask = li.id; + if($(li).is('.clicked')) $(li).toggleClass('doubleclicked'); + else $(li).addClass('clicked'); + } + } +}; + + +function showhide(a,b) +{ + a.show(); + b.hide(); +}; + +function findParentNode(el, node) +{ + // in html nodename is in uppercase, in xhtml nodename in in lowercase + if(el.nodeName.toUpperCase() == node) return el; + if(!el.parentNode) return null; + while(el.parentNode) { + el = el.parentNode; + if(el.nodeName.toUpperCase() == node) return el; + } +}; + +function getLiTaskId(el) +{ + var li = findParentNode(el, 'LI'); + if(!li || !li.id) return 0; + return li.id.split('_',2)[1]; +}; + +function isParentId(el, id) +{ + if(el.id && $.inArray(el.id, id) != -1) return true; + if(!el.parentNode) return null; + return isParentId(el.parentNode, id); +}; + +function dehtml(str) +{ + return str.replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); +}; + + +function slmenuOnListsLoaded() +{ + if(_mtt.menus.selectlist) { + _mtt.menus.selectlist.destroy(); + _mtt.menus.selectlist = null; + } + + var s = ''; + var all = tabLists.getAll(); + for(var i in all) { + s += '
      • '+all[i].name+'
      • '; + } + $('#slmenucontainer ul').html(s); +}; + +function slmenuOnListRenamed(list) +{ + $('#slmenucontainer li.list-id-'+list.id).find('a').html(list.name); +}; + +function slmenuOnListAdded(list) +{ + if(_mtt.menus.selectlist) { + _mtt.menus.selectlist.destroy(); + _mtt.menus.selectlist = null; + } + $('#slmenucontainer ul').append('
      • '+list.name+'
      • '); +}; + +function slmenuOnListSelected(list) +{ + $('#slmenucontainer li').removeClass('mtt-item-checked'); + $('#slmenucontainer li.list-id-'+list.id).addClass('mtt-item-checked'); + +}; + +function slmenuSelect(el, menu) +{ + if(!el.id) return; + var id = el.id, value; + var a = id.split(':'); + if(a.length == 2) { + id = a[0]; + value = a[1]; + } + if(id == 'slmenu_list') { + tabSelected(parseInt(value)); + } + return false; +}; + + +function exportCurListToCSV() +{ + if(!curList) return; + window.location.href = _mtt.mttUrl + 'export.php?list='+curList.id +'&format=csv'; +}; + +function feedCurList() +{ + if(!curList) return; + window.location.href = _mtt.mttUrl + 'feed.php?list='+curList.id; +} + + +/* + Errors and Info messages +*/ + +function flashError(str, details) +{ + $("#msg>.msg-text").text(str) + $("#msg>.msg-details").text(details); + $("#loading").hide(); + $("#msg").addClass('mtt-error').effect("highlight", {color:_mtt.theme.msgFlashColor}, 700); +} + +function flashInfo(str, details) +{ + $("#msg>.msg-text").text(str) + $("#msg>.msg-details").text(details); + $("#loading").hide(); + $("#msg").addClass('mtt-info').effect("highlight", {color:_mtt.theme.msgFlashColor}, 700); +} + +function toggleMsgDetails() +{ + var el = $("#msg>.msg-details"); + if(!el) return; + if(el.css('display') == 'none') el.show(); + else el.hide() +} + + +/* + Authorization +*/ +function updateAccessStatus() +{ + // 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.needAuth && !flag.isLogged) { + flag.readOnly = true; + $("#bar_public").show(); + $('#page_tasks').addClass('readonly') + liveSearchToggle(1); + } + else { + flag.readOnly = false; + $('#page_tasks').removeClass('readonly') + $("#bar_public").hide(); + liveSearchToggle(0); + } + $('#page_ajax').hide(); +} + +function showAuth(el) +{ + var w = $('#authform'); + if(w.css('display') == 'none') + { + var offset = $(el).offset(); + w.css({ + position: 'absolute', + top: offset.top + el.offsetHeight + 3, + left: offset.left + el.offsetWidth - w.outerWidth() + }).show(); + $('#password').focus(); + } + else { + w.hide(); + el.blur(); + } +} + +function doAuth(form) +{ + $.post(mytinytodo.mttUrl+'ajax.php?login', { login:1, password: form.password.value }, function(json){ + form.password.value = ''; + if(json.logged) + { + flag.isLogged = true; + _mtt.loadLists(1); + } + else { + flashError(_mtt.lang.get('invalidpass')); + $('#password').focus(); + } + }, 'json'); + $('#authform').hide(); +} + +function logout() +{ + $.post(mytinytodo.mttUrl+'ajax.php?logout', { logout:1 }, function(json){ + flag.isLogged = false; + _mtt.loadLists(1); + }, 'json'); + return false; +} + + +/* + Settings +*/ + +function showSettings() +{ + if(_mtt.pages.current.page == 'ajax' && _mtt.pages.current.pageClass == 'settings') return false; + $('#page_ajax').load(_mtt.mttUrl+'settings.php?ajax=yes',null,function(){ + //showhide($('#page_ajax').addClass('mtt-page-settings'), $('#page_tasks')); + _mtt.pageSet('ajax','settings'); + }) + return false; +} + +function saveSettings(frm) +{ + if(!frm) return false; + var params = { save:'ajax' }; + $(frm).find("input:text,input:checked,select,:password").filter(":enabled").each(function() { params[this.name || '__'] = this.value; }); + $(frm).find(":submit").attr('disabled','disabled').blur(); + $.post(_mtt.mttUrl+'settings.php', params, function(json){ + if(json.saved) { + flashInfo(_mtt.lang.get('settingsSaved')); + setTimeout('window.location.reload();', 1000); + } + }, 'json'); +} + +})(); \ No newline at end of file diff --git a/src/mytinytodo_ajax_storage.js b/src/mytinytodo_ajax_storage.js new file mode 100644 index 0000000..67d77c9 --- /dev/null +++ b/src/mytinytodo_ajax_storage.js @@ -0,0 +1,168 @@ +/* + This file is a part of myTinyTodo. + (C) Copyright 2010 Max Pozdeev + Licensed under the GNU GPL v3 license. See file COPYRIGHT for details. +*/ + +// AJAX myTinyTodo Storage + +(function(){ + +var mtt; + +function mytinytodoStorageAjax(amtt) +{ + this.mtt = mtt = amtt; +} + +window.mytinytodoStorageAjax = mytinytodoStorageAjax; + +mytinytodoStorageAjax.prototype = +{ + /* required method */ + request:function(action, params, callback) + { + if(!this[action]) throw "Unknown storage action: "+action; + + this[action](params, function(json){ + if(json.denied) mtt.errorDenied(); + if(callback) callback.call(mtt, json) + }); + }, + + + loadLists: function(params, callback) + { + $.getJSON(this.mtt.mttUrl+'ajax.php?loadLists'+'&rnd='+Math.random(), callback); + }, + + + loadTasks: function(params, callback) + { + var q = ''; + if(params.search && params.search != '') q += '&s='+encodeURIComponent(params.search); + if(params.tag && params.tag != '') q += '&t='+encodeURIComponent(params.tag); + if(params.setCompl && params.setCompl != 0) q += '&setCompl=1'; + q += '&rnd='+Math.random(); + +/* $.getJSON(mtt.mttUrl+'ajax.php?loadTasks&list='+params.list+'&compl='+params.compl+'&sort='+params.sort+'&tz='+params.tz+q, function(json){ + callback.call(mtt, json); + }) +*/ + + $.getJSON(this.mtt.mttUrl+'ajax.php?loadTasks&list='+params.list+'&compl='+params.compl+'&sort='+params.sort+'&tz='+params.tz+q, callback); + }, + + + newTask: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?newTask', + { list:params.list, title: params.title, tz:params.tz, tag:params.tag }, callback, 'json'); + }, + + + fullNewTask: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?fullNewTask', + { list:params.list, tz:params.tz, title:params.title, note:params.note, prio:params.prio, tags:params.tags, duedate:params.duedate }, + callback, 'json'); + }, + + + editTask: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?editTask='+params.id, + { id:params.id, list:params.list, tz:params.tz, title:params.title, note:params.note, prio:params.prio, tags:params.tags, duedate:params.duedate }, + callback, 'json'); + }, + + + editNote: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?editNote='+params.id, {id:params.id, note: params.note}, callback, 'json'); + }, + + + completeTask: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?completeTask='+params.id, { id:params.id, compl:params.compl, tz:params.tz }, callback, 'json'); + }, + + + deleteTask: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?deleteTask='+params.id, { id:params.id }, callback, 'json'); + }, + + + setPrio: function(params, callback) + { + $.getJSON(this.mtt.mttUrl+'ajax.php?setPrio='+params.id+'&prio='+params.prio+'&rnd='+Math.random(), callback); + }, + + + setSort: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?setSort', { list:params.list, sort:params.sort }, callback, 'json'); + }, + + changeOrder: function(params, callback) + { + var order = ''; + for(var i in params.order) { + order += params.order[i].id +'='+ params.order[i].diff + '&'; + } + $.post(this.mtt.mttUrl+'ajax.php?changeOrder', { order:order }, callback, 'json'); + }, + + tagCloud: function(params, callback) + { + $.getJSON(this.mtt.mttUrl+'ajax.php?tagCloud&list='+params.list+'&rnd='+Math.random(), callback); + }, + + moveTask: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?moveTask', { id:params.id, from:params.from, to:params.to }, callback, 'json'); + }, + + parseTaskStr: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?parseTaskStr', { list:params.list, title:params.title, tz:params.tz, tag:params.tag }, callback, 'json'); + }, + + + // Lists + addList: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?addList', { name:params.name }, callback, 'json'); + + }, + + renameList: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?renameList', { list:params.list, name:params.name }, callback, 'json'); + }, + + deleteList: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?deleteList', { list:params.list }, callback, 'json'); + }, + + publishList: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?publishList', { list:params.list, publish:params.publish }, callback, 'json'); + }, + + changeListOrder: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?changeListOrder', { order:params.order }, callback, 'json'); + }, + + clearCompletedInList: function(params, callback) + { + $.post(this.mtt.mttUrl+'ajax.php?clearCompletedInList', { list:params.list }, callback, 'json'); + } + +}; + +})(); \ No newline at end of file diff --git a/src/ajax.lang.php b/src/mytinytodo_lang.php similarity index 80% rename from src/ajax.lang.php rename to src/mytinytodo_lang.php index c47b5cc..6c1c369 100644 --- a/src/ajax.lang.php +++ b/src/mytinytodo_lang.php @@ -7,6 +7,6 @@ require_once(MTTPATH. 'lang/class.default.php'); require_once(MTTPATH. 'lang/'. $config['lang']. '.php'); header('Content-type: text/javascript'); -echo Lang::instance()->makeJS(); +echo "mytinytodo.lang.init(". Lang::instance()->makeJS() .");"; ?> \ No newline at end of file diff --git a/src/settings.php b/src/settings.php index 508787f..7a60c1e 100644 --- a/src/settings.php +++ b/src/settings.php @@ -12,7 +12,7 @@ $lang = Lang::instance(); if($needAuth && !is_logged()) { - die("Access denied!
        Disable password protection or Log in."); + die("Access denied!
        Disable password protection or Log in."); } if(isset($_POST['save'])) @@ -67,120 +67,122 @@ function selectOptions($a, $value, $default=null) $s = ''; if($default !== null && !isset($a[$value])) $value = $default; foreach($a as $k=>$v) { - $s .= ''; + $s .= ''; } return $s; } ?> +
        +

        -
        + - - + + - + - - + + - + - + - +
        :
        :
        :
        : -
        -
        +
        +
        :
        > :
        />
        :
        :
        -
        - +
        +
        :
        :
        -
        - +
        +
        :
        :
        -
        - +
        +
        : -
        - (<mytinytodo_dir>/tmp/sessions) +
        + (<mytinytodo_dir>/tmp/sessions)
        : - +
        : - +
        : - - + +
        : - - + +
        : - +
        : -
        - +
        +
        - - + +
        diff --git a/src/setup.php b/src/setup.php index 7fbdc12..fe9e3e1 100644 --- a/src/setup.php +++ b/src/setup.php @@ -6,6 +6,8 @@ Licensed under the GNU GPL v3 license. See file COPYRIGHT for details. */ +set_exception_handler('myExceptionHandler'); + # Check old config file (prior v1.3) require_once('./db/config.php'); if(!isset($config['db'])) @@ -42,7 +44,7 @@ else $dbtype = ''; } -$lastVer = '1.3.1'; +$lastVer = '1.4'; echo 'myTinyTodo @VERSION Setup'; echo "myTinyTodo @VERSION Setup

        "; @@ -91,111 +93,136 @@ if(!$ver) { try { + + $db->ex( +"CREATE TABLE {$db->prefix}lists ( + `id` INT UNSIGNED NOT NULL auto_increment, + `uuid` CHAR(36) NOT NULL default '', + `ow` INT NOT NULL default 0, + `name` VARCHAR(50) NOT NULL default '', + `d_created` INT UNSIGNED NOT NULL default 0, + `d_edited` INT UNSIGNED NOT NULL default 0, + `sorting` TINYINT UNSIGNED NOT NULL default 0, + `published` TINYINT UNSIGNED NOT NULL default 0, + `taskview` INT UNSIGNED NOT NULL default 0, + PRIMARY KEY(`id`), + UNIQUE KEY(`uuid`) +) CHARSET=utf8 "); + + $db->ex( "CREATE TABLE {$db->prefix}todolist ( `id` INT UNSIGNED NOT NULL auto_increment, + `uuid` CHAR(36) NOT NULL default '', `list_id` INT UNSIGNED NOT NULL default 0, - `d_created` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ - `d_completed` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ + `d_created` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ + `d_completed` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ + `d_edited` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ `compl` TINYINT UNSIGNED NOT NULL default 0, `title` VARCHAR(250) NOT NULL, `note` TEXT, `prio` TINYINT NOT NULL default 0, /* priority -,0,+ */ `ow` INT NOT NULL default 0, /* order weight */ - `tags` VARCHAR(250) NOT NULL default '', /* denormalization - for fast access to task tags */ + `tags` VARCHAR(600) NOT NULL default '', /* for fast access to task tags */ + `tags_ids` VARCHAR(250) NOT NULL default '', /* no more than 22 tags (x11 chars) */ `duedate` DATE default NULL, PRIMARY KEY(`id`), - KEY(`list_id`) + KEY(`list_id`), + UNIQUE KEY(`uuid`) ) CHARSET=utf8 "); + $db->ex( "CREATE TABLE {$db->prefix}tags ( `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 `listid_nmae` (`list_id`,`name`) + UNIQUE KEY `name` (`name`) ) CHARSET=utf8 "); + $db->ex( "CREATE TABLE {$db->prefix}tag2task ( `tag_id` INT UNSIGNED NOT NULL, `task_id` INT UNSIGNED NOT NULL, + `list_id` INT UNSIGNED NOT NULL, KEY(`tag_id`), - KEY(`task_id`) + KEY(`task_id`), + KEY(`list_id`) /* for tagcloud */ ) CHARSET=utf8 "); - $db->ex( -"CREATE TABLE {$db->prefix}lists ( - `id` INT UNSIGNED NOT NULL auto_increment, - `ow` INT NOT NULL default 0, - `name` VARCHAR(50) NOT NULL default '', - `d_created` INT UNSIGNED NOT NULL default 0, - `sorting` TINYINT UNSIGNED NOT NULL default 0, - `published` TINYINT UNSIGNED NOT NULL default 0, - `taskview` INT UNSIGNED NOT NULL default 0, - PRIMARY KEY(`id`) -) CHARSET=utf8 "); } catch (Exception $e) { exitMessage("Error: ". htmlarray($e->getMessage())); } } - else + else #sqlite { try { - $db->ex( -"CREATE TABLE {$db->prefix}todolist ( - id INTEGER PRIMARY KEY, - list_id INTEGER UNSIGNED NOT NULL default 0, - d_created INTEGER UNSIGNED NOT NULL default 0, - d_completed INTEGER UNSIGNED NOT NULL default 0, - compl TINYINT UNSIGNED NOT NULL default 0, - title VARCHAR(250) NOT NULL, - note TEXT, - prio TINYINT NOT NULL default 0, - ow INTEGER NOT NULL default 0, - tags VARCHAR(250) NOT NULL default '', - duedate DATE default NULL -) "); - $db->ex("CREATE INDEX list_id ON {$db->prefix}todolist (list_id)"); - - $db->ex( -"CREATE TABLE {$db->prefix}tags ( - id INTEGER PRIMARY KEY, - name VARCHAR(50) NOT NULL, - tags_count INTEGER default 0, - list_id INTEGER UNSIGNED NOT NULL default 0 -) "); - $db->ex("CREATE UNIQUE INDEX tags_listid_name ON {$db->prefix}tags (list_id,name COLLATE NOCASE)"); - - $db->ex( -"CREATE TABLE {$db->prefix}tag2task ( - tag_id INTEGER NOT NULL, - task_id INTEGER NOT NULL -) "); - $db->ex("CREATE INDEX tag_id ON {$db->prefix}tag2task (tag_id)"); - $db->ex("CREATE INDEX task_id ON {$db->prefix}tag2task (task_id)"); $db->ex( "CREATE TABLE {$db->prefix}lists ( id INTEGER PRIMARY KEY, + uuid CHAR(36) NOT NULL, ow INTEGER NOT NULL default 0, name VARCHAR(50) NOT NULL, d_created INTEGER UNSIGNED NOT NULL default 0, + d_edited INTEGER UNSIGNED NOT NULL default 0, sorting TINYINT UNSIGNED NOT NULL default 0, published TINYINT UNSIGNED NOT NULL default 0, taskview INTEGER UNSIGNED NOT NULL default 0 ) "); + $db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)"); + + $db->ex( +"CREATE TABLE {$db->prefix}todolist ( + id INTEGER PRIMARY KEY, + uuid CHAR(36) NOT NULL, + list_id INTEGER UNSIGNED NOT NULL default 0, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_completed INTEGER UNSIGNED NOT NULL default 0, + d_edited INTEGER UNSIGNED NOT NULL default 0, + compl TINYINT UNSIGNED NOT NULL default 0, + title VARCHAR(250) NOT NULL, + note TEXT, + prio TINYINT NOT NULL default 0, + ow INTEGER NOT NULL default 0, + tags VARCHAR(600) NOT NULL default '', + tags_ids VARCHAR(250) NOT NULL default '', + duedate DATE default NULL +) "); + $db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)"); + $db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)"); + + + $db->ex( +"CREATE TABLE {$db->prefix}tags ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(50) NOT NULL COLLATE NOCASE +) "); + $db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)"); + + + $db->ex( +"CREATE TABLE {$db->prefix}tag2task ( + tag_id INTEGER NOT NULL, + task_id INTEGER NOT NULL, + list_id INTEGER NOT NULL +) "); + $db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)"); + $db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)"); + $db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); /* for tagcloud */ + } catch (Exception $e) { exitMessage("Error: ". htmlarray($e->getMessage())); } } + + # create default list + $db->ex("INSERT INTO {$db->prefix}lists (uuid,name,d_created) VALUES (?,?,?)", array(generateUUID(), 'Todo', time())); - createDefaultList($db); } elseif($ver == $lastVer) { @@ -203,7 +230,7 @@ elseif($ver == $lastVer) } else { - if(!in_array($ver, array('1.1','1.2','1.3.0'))) { + if(!in_array($ver, array('1.1','1.2','1.3.0','1.3.1'))) { exitMessage("Can not update. Unsupported database version ($ver)."); } if(!isset($_POST['update'])) { @@ -214,20 +241,27 @@ else } # update process + if($ver == '1.3.1') + { + update_131_14($db, $dbtype); + } if($ver == '1.3.0') { update_130_131($db, $dbtype); + update_131_14($db, $dbtype); } if($ver == '1.2') { update_12_13($db, $dbtype); update_130_131($db, $dbtype); + update_131_14($db, $dbtype); } elseif($ver == '1.1') { update_11_12($db, $dbtype); update_12_13($db, $dbtype); update_130_131($db, $dbtype); + update_131_14($db, $dbtype); } } echo "Done

        Attention! Delete this file for security reasons."; @@ -255,6 +289,12 @@ function get_ver($db, $dbtype) if(!has_field_sqlite($db, $db->prefix.'todolist', 'd_completed')) return $v; } $v = '1.3.1'; + if($dbtype == 'mysql') { + if(!has_field_mysql($db, $db->prefix.'todolist', 'd_edited')) return $v; + } else { + if(!has_field_sqlite($db, $db->prefix.'todolist', 'd_edited')) return $v; + } + $v = '1.4'; return $v; } @@ -316,6 +356,14 @@ function testConnect(&$error) return 1; } +function myExceptionHandler($e) +{ + echo '
        Fatal Error: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine() . ''. + "\n
        ". $e->getTraceAsString() . "
        \n"; + exit; +} + + ### 1.1-1.2 ########## function update_11_12($db, $dbtype) { @@ -431,20 +479,15 @@ function update_12_13($db, $dbtype) $db->ex("DROP TABLE tags_backup"); } $db->ex("COMMIT"); + + $db->ex("INSERT INTO lists (name,d_created) VALUES (?,?)", array('Todo', time())); + $db->ex("UPDATE todolist SET list_id=1"); - createDefaultList($db); -} - -function createDefaultList($db) -{ - $db->ex("INSERT INTO {$db->prefix}lists (name,d_created) VALUES (?,?)", array('Todo', time())); - - $db->ex("UPDATE {$db->prefix}todolist SET list_id=1"); - $db->ex("UPDATE {$db->prefix}tags SET list_id=1"); } ### end 1.2-1.3 ##### + ### 1.3.0 to 1.3.1 ########## function update_130_131($db, $dbtype) { @@ -558,4 +601,170 @@ function update_130_131($db, $dbtype) ### end of 1.3.0 to 1.3.1 ########## +### update v1.3.1 to v1.4 ########## +function update_131_14($db, $dbtype) +{ + $db->ex("BEGIN"); + if($dbtype=='mysql') + { + $db->ex("DROP TABLE {$db->prefix}tags"); + $db->ex( + "CREATE TABLE {$db->prefix}tags ( + `id` INT UNSIGNED NOT NULL auto_increment, + `name` VARCHAR(50) NOT NULL, + PRIMARY KEY(`id`), + UNIQUE KEY `name` (`name`) + ) CHARSET=utf8 "); + + $db->ex("ALTER TABLE {$db->prefix}todolist CHANGE `tags` `tags` VARCHAR(600) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD `tags_ids` VARCHAR(250) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD `uuid` CHAR(36) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD `d_edited` INT UNSIGNED NOT NULL default 0"); + + $db->ex("ALTER TABLE {$db->prefix}tag2task ADD `list_id` INT UNSIGNED NOT NULL"); + $db->ex("ALTER TABLE {$db->prefix}tag2task ADD KEY(`list_id`)"); + + $db->ex("ALTER TABLE {$db->prefix}lists ADD `uuid` CHAR(36) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}lists ADD `d_edited` INT UNSIGNED NOT NULL default 0"); + + } + else #sqlite + { + # changes in tags table: fully new + $db->ex("DROP TABLE {$db->prefix}tags"); //index will be deleted too + $db->ex( + "CREATE TABLE {$db->prefix}tags ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(50) NOT NULL COLLATE NOCASE + ) "); + $db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)"); + + # changes in todolist table: uuid, d_edited, tags, tags_ids + $db->ex( + "CREATE TABLE todolist_new ( + id INTEGER PRIMARY KEY, + uuid CHAR(36) NOT NULL default '', + list_id INTEGER UNSIGNED NOT NULL default 0, + d_created INTEGER UNSIGNED NOT NULL default 0, + d_completed INTEGER UNSIGNED NOT NULL default 0, + d_edited INTEGER UNSIGNED NOT NULL default 0, + compl TINYINT UNSIGNED NOT NULL default 0, + title VARCHAR(250) NOT NULL, + note TEXT, + prio TINYINT NOT NULL default 0, + ow INTEGER NOT NULL default 0, + tags VARCHAR(600) NOT NULL default '', + tags_ids VARCHAR(250) NOT NULL default '', + duedate DATE default NULL + ) "); + $db->ex("INSERT INTO todolist_new (id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate)". + " SELECT id,list_id,d_created,d_completed,compl,title,note,prio,ow,tags,duedate FROM {$db->prefix}todolist"); + $db->ex("DROP TABLE {$db->prefix}todolist"); + $db->ex("ALTER TABLE todolist_new RENAME TO {$db->prefix}todolist"); + $db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)"); #1st index of 2 + + # changes in tag2task table: new column and index, new names of indexes + $db->ex("ALTER TABLE {$db->prefix}tag2task ADD list_id INTEGER NOT NULL default 0"); + $db->ex("DROP INDEX tag_id"); + $db->ex("DROP INDEX task_id "); + $db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)"); + $db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)"); + $db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); + + # changes in lists table: uuid, d_edited + $db->ex("ALTER TABLE {$db->prefix}lists ADD uuid CHAR(36) NOT NULL default ''"); + $db->ex("ALTER TABLE {$db->prefix}lists ADD d_edited INTEGER UNSIGNED NOT NULL default 0"); + + } + + # recreate tags + $db->ex("DELETE FROM {$db->prefix}tag2task"); + + $q = $db->dq("SELECT id,list_id,tags FROM {$db->prefix}todolist WHERE tags != ''"); + while($r = $q->fetch_assoc()) + { + $aTags = v14_prepareTags($r['tags']); + if($aTags) + { + v14_addTaskTags($r['id'], $aTags['ids'], $r['list_id']); + $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=".$r['id'], + array(implode(',',$aTags['tags']), implode(',',$aTags['ids'])) ); + } + } + + # fix bug with empty lists.d_created + $db->ex("UPDATE {$db->prefix}lists SET d_created=?", time()); + + # init d_edited + $db->ex("UPDATE {$db->prefix}todolist SET d_edited=d_created"); + $db->ex("UPDATE {$db->prefix}todolist SET d_edited=d_completed WHERE d_completed > d_edited"); + $db->ex("UPDATE {$db->prefix}lists SET d_edited=d_created"); + + # add UUID + $q = $db->dq("SELECT id FROM {$db->prefix}todolist"); + while($r = $q->fetch_assoc()) { + $db->ex("UPDATE {$db->prefix}todolist SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); + } + $q = $db->dq("SELECT id FROM {$db->prefix}lists"); + while($r = $q->fetch_assoc()) { + $db->ex("UPDATE {$db->prefix}lists SET uuid=? WHERE id=".$r['id'], array(generateUUID()) ); + } + + # create unique indexes for UUID + if($dbtype=='mysql') + { + $db->ex("ALTER TABLE {$db->prefix}lists ADD UNIQUE KEY (`uuid`)"); + $db->ex("ALTER TABLE {$db->prefix}todolist ADD UNIQUE KEY (`uuid`)"); + } + else + { + $db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)"); + $db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)"); + } + + $db->ex("COMMIT"); +} + +function v14_prepareTags($tagsStr) +{ + $tags = explode(',', $tagsStr); + if(!$tags) return 0; + + $aTags = array('tags'=>array(), 'ids'=>array()); + foreach($tags as $tag) + { + $tag = str_replace(array('"',"'",'<','>','&','/','\\','^'),'',trim($tag)); + if($tag == '') continue; + + $aTag = v14_getOrCreateTag($tag); + if($aTag && !in_array($aTag['id'], $aTags['ids'])) { + $aTags['tags'][] = $aTag['name']; + $aTags['ids'][] = $aTag['id']; + } + } + return $aTags; +} + +function v14_getOrCreateTag($name) +{ + global $db; + $tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name)); + if($tagId) return array('id'=>$tagId, 'name'=>$name); + + $db->ex("INSERT INTO {$db->prefix}tags (name) VALUES (?)", array($name)); + return array('id'=>$db->last_insert_id(), 'name'=>$name); +} + +function v14_addTaskTags($taskId, $tagIds, $listId) +{ + global $db; + if(!$tagIds) return; + foreach($tagIds as $tagId) + { + $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); + } +} +### end of 1.4 ##### + + ?> \ No newline at end of file diff --git a/src/themes/default/images/COPYRIGHT b/src/themes/default/images/COPYRIGHT index f519e2a..ee5191b 100644 --- a/src/themes/default/images/COPYRIGHT +++ b/src/themes/default/images/COPYRIGHT @@ -1,8 +1,13 @@ -Image files (page_white_edit_bw.png, feed_bw.png) are based on icons from Silk Icons set, -and icons page_white_text.png, page_white_edit.png and calendar.png are part of Silk Icons set -by Mark James (http://www.famfamfam.com/lab/icons/silk/), licensed under the -Creative Commons Attribution 2.5 License (http://creativecommons.org/licenses/by/2.5/). +Image files page_white_text.png and calendar.png and some icons in buttons.png +are (or based on) icons from Silk Icons set by Mark James (http://www.famfamfam.com/lab/icons/silk/), +licensed under the Creative Commons Attribution 2.5 License (http://creativecommons.org/licenses/by/2.5/). -bullet_plus.png is based on "Silk Companion 1" icons set by Damien Guard +Some icons in buttons.png are based on "Silk Companion 1" icons set by Damien Guard (http://damieng.com/creative/icons/silk-companion-1-icons), licensed under the Creative Commons Attribution 2.5 License (http://creativecommons.org/licenses/by/2.5/). + +Icons in mzl.png are (or based on) icons from Mozilla Source Code, +(http://www.mozilla.org/MPL/#source-code), licensed under the terms +of tri-license (MPL 1.1/GPL 2.0/LGPL 2.1). + +Other images in this directory were made by Max Pozdeev and licensed under the terms of GNU GPL v3. \ No newline at end of file diff --git a/src/themes/default/images/arrdown2.gif b/src/themes/default/images/arrdown2.gif new file mode 100644 index 0000000..5934ee4 Binary files /dev/null and b/src/themes/default/images/arrdown2.gif differ diff --git a/src/themes/default/images/bullet_plus.png b/src/themes/default/images/bullet_plus.png deleted file mode 100644 index fb47633..0000000 Binary files a/src/themes/default/images/bullet_plus.png and /dev/null differ diff --git a/src/themes/default/images/buttons.png b/src/themes/default/images/buttons.png new file mode 100755 index 0000000..68763d4 Binary files /dev/null and b/src/themes/default/images/buttons.png differ diff --git a/src/themes/default/images/closetag.gif b/src/themes/default/images/closetag.gif new file mode 100644 index 0000000..bfea142 Binary files /dev/null and b/src/themes/default/images/closetag.gif differ diff --git a/src/themes/default/images/feed.png b/src/themes/default/images/feed.png deleted file mode 100644 index 315c4f4..0000000 Binary files a/src/themes/default/images/feed.png and /dev/null differ diff --git a/src/themes/default/images/feed_bw.png b/src/themes/default/images/feed_bw.png deleted file mode 100644 index 669fcbf..0000000 Binary files a/src/themes/default/images/feed_bw.png and /dev/null differ diff --git a/src/themes/default/images/icons.gif b/src/themes/default/images/icons.gif index 32b49f8..84e18e0 100644 Binary files a/src/themes/default/images/icons.gif and b/src/themes/default/images/icons.gif differ diff --git a/src/themes/default/images/mzl.png b/src/themes/default/images/mzl.png new file mode 100755 index 0000000..2707c97 Binary files /dev/null and b/src/themes/default/images/mzl.png differ diff --git a/src/themes/default/images/page_white_edit.png b/src/themes/default/images/page_white_edit.png deleted file mode 100644 index b93e776..0000000 Binary files a/src/themes/default/images/page_white_edit.png and /dev/null differ diff --git a/src/themes/default/images/page_white_edit_bw.png b/src/themes/default/images/page_white_edit_bw.png deleted file mode 100644 index d427f0e..0000000 Binary files a/src/themes/default/images/page_white_edit_bw.png and /dev/null differ diff --git a/src/themes/default/index.php b/src/themes/default/index.php index fb24330..b476a53 100644 --- a/src/themes/default/index.php +++ b/src/themes/default/index.php @@ -1,76 +1,54 @@ - - - - - + + + + <?php mttinfo('title'); ?> - + - + - - + + - + - + - + - - - + + + + @@ -80,50 +58,78 @@ $().ready(function(){

        -
        +
        -
        +
        - - + - - + +
        -
        +
        -