diff --git a/.gitignore b/.gitignore index 54c1fc8..9503390 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ *.orig results/ img/ +coverage/ diff --git a/.travis.yml b/.travis.yml index 70a7e60..d029ed0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: node_js node_js: - - 0.10 -before_install: - - npm install -g grunt-cli \ No newline at end of file + - 10.16.3 +addons: + chrome: stable + firefox: latest \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..47adbad --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 0f6b350..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,95 +0,0 @@ -module.exports = function(grunt) { - - // Project configuration. - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - files: { - js: [ - "js/todoTxt.js", - "js/objects/utils.js", - "js/classes/task.js", - "js/objects/view.js", - "js/objects/resources.js", - "js/objects/resources/en-us.js", - "js/wrapper.js", - ], - css: [ - "css/todoTxt.css", - ], - tests: "tests/qunit/allTests.html", - functionalTests: ["tests/pft/tests/**/*.js"] - }, - clean: { - build: { - src: ['dist/**/*','results/**/*','img/**/*'], - filter: 'isFile', - }, - }, - uglify: { - options: { - mangle: true, - compress: {}, - sourceMap: true, - }, - build: { - options: { - banner: '/*! <%= pkg.name %> v<%= pkg.version %>, created by: <%= pkg.author %> <%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %> */' - }, - files: { - 'dist/<%= pkg.main %>.min.js': ['<%= files.js %>'] - } - }, - }, - cssmin: { - build: { - files: { - 'dist/<%= pkg.main %>.min.css': ['<%= files.css %>'] - } - }, - }, - qunit: { - all: ['<%= files.tests %>'] - }, - pft: { - options: { - parallel: 3, - // debug: true - }, - src: ['<%= files.functionalTests %>'] - }, - jsdoc: { - dist: { - src: ['<%= files.js %>'], - dest: 'dist/doc' - } - } - }); - - // Load the plugin that provides the "uglify" task. - grunt.loadNpmTasks('grunt-contrib-uglify'); - - // Load the plugin that provides the "cssmin" task. - grunt.loadNpmTasks('grunt-contrib-cssmin'); - - // Load the plugin that provides the "clean" task. - grunt.loadNpmTasks('grunt-contrib-clean'); - - // This plugin provides the "qunit" task. - grunt.loadNpmTasks('grunt-contrib-qunit'); - - // This plugin provides the "casper" task. - grunt.loadNpmTasks('grunt-pft'); - - // This plugin provides the "qunit" task. - grunt.loadNpmTasks('grunt-jsdoc'); - - // Default task(s). - grunt.registerTask('default', ['clean','qunit','uglify','cssmin','pft','jsdoc']); - - // Build only task(s). - grunt.registerTask('build', ['clean','uglify','cssmin']); - - // document only task(s). - grunt.registerTask('doc', ['jsdoc']); - -}; diff --git a/COPYING.txt b/LICENSE similarity index 100% rename from COPYING.txt rename to LICENSE diff --git a/README.md b/README.md index 43c4953..67dbfa9 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,24 @@ -todoTxtWebUi ![build status](https://travis-ci.org/bicarbon8/todoTxtWebUi.svg) -============ +# todoTxtWebUi ![build status](https://travis-ci.org/bicarbon8/todoTxtWebUi.svg) + @Created: 08/14/2012 @Author: Jason Holt Smith () -DESCRIPTION: ------------- +## DESCRIPTION: + A web UI to use with a todo.txt file. This project is an extention to the project providing a rich web user interface for interacting with one's todo.txt file. The requirements of this project are that it only use HTML, Javascript and CSS to accomplish all functionality in a Webkit compatible browser. There must be no back-end server code, no local executables and no browser plugins utilized in supporting the functionality of this project. -DEMO: ------------- +## DEMO: + [ResponsiveDemo](https://rawgit.com/bicarbon8/todoTxtWebUi/master/index.html) -FEATURES: ------------- -- Can easily be added to any existing webpage by simply adding a ```
``` element and the external dependencies +## FEATURES: + +- Can easily be added to any existing webpage by simply adding a `
` element and the external dependencies - Allows users to drag-and-drop in their todo.txt file (or select through a file dialog) for instant syncronization with existing task list - Allows exporting of displayed tasks back out of the browser to the user's local filesystem thereby supporting saving of updates to the task list - Stores the task list in the browser's localStorage cache so that changes are not lost between browser page reloads / refreshes. @@ -29,39 +29,53 @@ FEATURES: - Supports both mouse clicks and keyboard shortcuts for command and control such as adding new tasks, saving edits to tasks, deleting tasks currently being edited, and saving the task list to an external file - Sorts the task list by Status (closed or active), Priority, Created Date, and then Completed Date with older items (those with an older created date) displaying higher than newer items -EXTERNAL DEPENDENCIES: ------------- +## EXTERNAL DEPENDENCIES: + - [Bootstrap 3.3.1](http://getbootstrap.com/) - [JQuery 1.11.1](http://jquery.com/) -RUNNING LOCALLY: ------------- +## RUNNING LOCALLY: + - download the latest from: [github](https://github.com/bicarbon8/todoTxtWebUi/archive/master.zip) -- extract the download and open the ```todoTxtWebUi-master``` folder -- open the ```index.html``` file in a Webkit compatible browser - -KEYBOARD SHORTCUTS: ------------- -- ```Alt-t``` add a new task -- ```Alt-Enter``` save an open task -- ```Alt-p``` preview changes to an open task -- ```Alt-s``` export tasks -- ```Alt-c``` clear any filters - -INCLUDING IN OTHER WEBSITES: ------------- -- download the latest minified script from [github](https://rawgit.com/bicarbon8/todoTxtWebUi/master/dist/todoTxt.min.js) +- extract the download and open the `todoTxtWebUi-master` folder +- open the `index.html` file in a Webkit compatible browser + +## KEYBOARD SHORTCUTS: + +- `Alt-t` add a new task +- `Alt-Enter` save an open task +- `Alt-p` preview changes to an open task +- `Alt-s` export tasks +- `Alt-c` clear any filters + +## INCLUDING IN OTHER WEBSITES: + +- download the latest bundle from [github](https://rawgit.com/bicarbon8/todoTxtWebUi/master/dist/bundle.js) - ensure you have the following css and javascript references in your html file: ```html - + - + ``` -- place a ```div``` element in your html body with an id of ```todotxt```. Ex: +- place a `div` element in your html body with an id of `todotxt`. Ex: ```html
``` -- open the webpage and the magic happens automatically :) +- open the webpage and the magic happens automatically + +## NOTE: +- if you are tracking more than 1000 Tasks, the performance will start to degrade (~5 seconds per add / edit / delete operation) +- it is not recommended to track more than 5000 Tasks +- exporting your _todo-txt_ file will exclude all closed tasks so exporting and re-importing can serve as a way of keeping the number of tracked tasks under control + +## Contributing to the Project: + +- create a Fork of the repo in _GitHub_ +- clone the code using `git clone https://github.com//todoTxtWebUi todoTxtWebUi` where `` is replaced with the location of your Fork +- run `npm install` to install all dev dependencies +- build using `npm run build` +- test using `npm test` +- when you are happy with your changes, submit a Pull Request back to the _master_ branch at `https://github.com/bicarbon8/todoTxtWebUi` \ No newline at end of file diff --git a/css/todoTxt.css b/css/todo-txt.css similarity index 100% rename from css/todoTxt.css rename to css/todo-txt.css diff --git a/dist/bundle.js b/dist/bundle.js new file mode 100644 index 0000000..27fe8cb --- /dev/null +++ b/dist/bundle.js @@ -0,0 +1,2 @@ +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var a=t[o]={i:o,l:!1,exports:{}};return e[o].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(o,a,function(t){return e[t]}.bind(null,a));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=5)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.formatDate=function(e){var t=e.getFullYear(),n=(e.getMonth()+1).toString();n=n.length<2?"0"+n:n;var o=e.getDate().toString();return o=o.length<2?"0"+o:o,String(t+"-"+n+"-"+o)},e.getLanguage=function(){return(window.navigator.userLanguage||window.navigator.language).toLowerCase()},e.guid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){var t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},e.htmlEncode=function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/\s{2}/g,"  ")},e.htmlUnencode=function(e){return String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/ /g," ")}}(t.TodoTxtUtils||(t.TodoTxtUtils={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(0),a=function(){function e(e){this.projects=[],this.contexts=[],this.metadatas=[],this.id=o.TodoTxtUtils.guid(),this.isActive=!0,this.parseInput(e)}return e.prototype.parseInput=function(e){e&&(this.text=e,this.parseStatus(),this.parsePriority(),this.parseCompletedDate(),this.parseCreatedDate(),this.parseProjects(),this.parseContexts())},e.prototype.parseStatus=function(){var e=this.text.match(/^(x )/);e&&e.length>0?this.isActive=!1:this.isActive=!0},e.prototype.parsePriority=function(){var e=null,t=this.text.match(/^(\([A-Z]\)[\s]+)/);t&&(e=t[0].replace(/[\s]*/g,"")),this.priority=e},e.prototype.parseCompletedDate=function(){var e=null;if(!this.isActive){var t=this.getDatesFromText();t&&(e=t[0]?t[0].replace(/[\s]*/g,""):null)}this.completedDate=e},e.prototype.parseCreatedDate=function(){var e=null,t=this.getDatesFromText();t&&(this.isActive?e=t[0]?t[0].replace(/[\s]*/g,""):null:t.length>1&&(e=t[1]?t[1].replace(/[\s]*/g,""):null)),this.createdDate=e},e.prototype.getDatesFromText=function(){var e=[],t=this.text.match(/(?:\s|^)(\d{4}-\d{2}-\d{2})(?=\s)/g);if(t)for(var n=0;n0&&a[a.length-1])&&(6===r[0]||2===r[0])){i=0;continue}if(3===r[0]&&(!a||r[1]>a[0]&&r[1]",t}function p(){var e=document.querySelector("#filter-input").value,t=i.TodoTxt.getFilteredTaskArray(e);if(!u.TodoTxtVault.getConfig().showClosed){var n=t.filter((function(e){return e.isActive}));t=n}t&&t.length>0&&t.forEach((function(e){f(e)}))}function f(e){document.querySelector("#listContainer-div").appendChild(t(e))}function v(t){var n,o=!1;t?n=i.TodoTxt.getTask(t):(n=new r.TodoTxtTask,o=!0),k(e.mainEventHandlers);var a=function(e,t){var n=document.createElement("span");s(n).attr("aria-hidden","true"),n.innerHTML=" ×";var o=document.createElement("button");o.type="button",o.id="modalEditClose-button",o.classList.add("close"),s(o).attr("data-dismiss","modal"),s(o).attr("aria-label",c.TodoTxtResources.get("CLOSE")),o.onclick=function(e){g()},o.appendChild(n);var a=document.createElement("h4");a.classList.add("modal-title"),a.id="modalEdit-label";var r=document.createElement("div");r.classList.add("modal-header"),r.appendChild(o),r.appendChild(a);var i=document.createElement("div");i.id="modalEdit-textarea",i.classList.add("textarea"),i.contentEditable="true";var l=$(e).replace(/hidden-xs/,"");i.innerHTML=l;var d=document.createElement("div");d.classList.add("modal-body"),d.appendChild(i);var u=document.createElement("span");u.classList.add("hidden-xs");var p=t?c.TodoTxtResources.get("ADD"):c.TodoTxtResources.get("UPDATE");u.innerText=" "+p;var f=document.createElement("span");f.classList.add("glyphicon"),f.classList.add("glyphicon-ok");var v=document.createElement("a");v.type="button",v.id="modalEditSave-button",v.classList.add("btn"),v.classList.add("btn-lg"),v.classList.add("btn-success"),s(v).attr("data-toggle","tooltip"),s(v).attr("data-placement","top"),s(v).attr("text",p),v.onclick=function(e){D()},v.appendChild(f),v.appendChild(u);var h=document.createElement("span");h.classList.add("hidden-xs"),h.innerText=" "+c.TodoTxtResources.get("PREVIEW");var m=document.createElement("span");m.classList.add("glyphicon"),m.classList.add("glyphicon-eye-open");var x=document.createElement("a");x.type="button",x.id="modalEditPreview-button",x.classList.add("btn"),x.classList.add("btn-lg"),x.classList.add("btn-primary"),s(x).attr("data-toggle","tooltip"),s(x).attr("data-placement","top"),s(x).attr("text",c.TodoTxtResources.get("PREVIEW")),x.onclick=function(e){T()},x.appendChild(m),x.appendChild(h);var y=document.createElement("span");y.classList.add("hidden-xs"),y.innerText=" "+c.TodoTxtResources.get("DELETE");var b=document.createElement("span");b.classList.add("glyphicon"),b.classList.add("glyphicon-floppy-remove");var E=document.createElement("a");E.type="button",E.id="modalEditDelete-button",E.classList.add("btn"),E.classList.add("btn-lg"),E.classList.add("btn-danger"),s(E).attr("data-toggle","tooltip"),s(E).attr("data-placement","top"),s(E).attr("text",c.TodoTxtResources.get("DELETE")),E.onclick=function(e){_()},E.appendChild(b),E.appendChild(y);var C=document.createElement("div");C.classList.add("btn-group"),C.classList.add("btn-group-justified"),C.appendChild(v),C.appendChild(x),t||C.appendChild(E);var k=document.createElement("div");k.classList.add("modal-footer"),k.appendChild(C);var S=document.createElement("div");S.classList.add("modal-content"),S.appendChild(r),S.appendChild(d),S.appendChild(k);var w=document.createElement("div");w.classList.add("modal-dialog"),w.appendChild(S);var L=document.createElement("div");return L.classList.add("modal"),L.id="modalEdit-div",L.tabIndex=-1,s(L).attr("role","dialog"),s(L).attr("aria-labelledby","modalEdit-label"),s(L).attr("aria-hidden","true"),s(L).attr("task-id",e.id),L.appendChild(w),L}(n,o);document.body.appendChild(a),C(e.modalEventHandlers),s(a).show(0),document.querySelector("#modalEdit-textarea").focus()}function T(){var e=document.querySelector("#modalEdit-textarea");if(e){var t=e.textContent,n=new r.TodoTxtTask(t);e.innerHTML=$(n)}}function g(){k(e.modalEventHandlers),s("#modalEdit-div").remove(),C(e.mainEventHandlers),q()}function h(){var e=document.querySelector("#priorities-ul");d.TodoTxtAttributes.priorities.forEach((function(t){if(t||u.TodoTxtVault.getConfig().showClosed){var o=n(t);e.appendChild(o)}}))}function m(){document.querySelector("#priorities-ul").innerHTML=""}function x(){var e=document.querySelector("#projects-ul");d.TodoTxtAttributes.projects.forEach((function(t){if(t||u.TodoTxtVault.getConfig().showClosed){var o=n(t);e.appendChild(o)}}))}function y(){document.querySelector("#projects-ul").innerHTML=""}function b(){var e=document.querySelector("#contexts-ul");d.TodoTxtAttributes.contexts.forEach((function(t){if(t||u.TodoTxtVault.getConfig().showClosed){var o=n(t);e.appendChild(o)}}))}function E(){document.querySelector("#contexts-ul").innerHTML=""}function C(e){e.forEach((function(e){var t=!1;e.uc&&(t=e.uc);try{e.el().addEventListener(e.ev,e.fn,t)}catch(e){console.error(e)}}))}function k(e){e.forEach((function(e){var t=!1;e.uc&&(t=e.uc);try{e.el().removeEventListener(e.ev,e.fn,t)}catch(e){console.error(e)}}))}function S(e){83==e.keyCode&&e.altKey&&J()}function w(e){67==e.keyCode&&e.altKey&&q()}function L(e){84==e.keyCode&&e.altKey&&v()}function A(e){B(e)}function R(e){e.keyCode&&13===e.keyCode&&e.altKey&&D()}function D(){var e=document.querySelector("#modalEdit-div"),t=s(e).attr("task-id"),n=document.querySelector("#modalEdit-textarea").textContent;if(n=l.TodoTxtUtils.htmlUnencode(n),i.TodoTxt.updateTask(t,n)){q();try{g()}catch(e){}}}function P(e){27!==e.keyCode&&0!==e.keyCode||g()}function _(){var e=document.querySelector("#modalEdit-div"),t=s(e).attr("task-id"),n=i.TodoTxt.getTask(t);if(n&&confirm(c.TodoTxtResources.get("DELETE_CONFIRM")+'\n\t"'+n.text+'"')&&u.TodoTxtVault.removeTask(t)){q();try{g()}catch(e){}}}var O;function j(){O&&window.clearTimeout(O),O=window.setTimeout((function(){H()}),500)}function M(e){e.keyCode&&80===e.keyCode&&e.altKey&&T()}function q(){U(u.TodoTxtVault.getConfig().showClosed),k(e.mainEventHandlers),N(),m(),y(),E(),F(),p(),h(),x(),b(),C(e.mainEventHandlers)}function I(e){e&&(document.querySelector("#filter-input").value=e,j())}function F(){document.querySelector("#filter-input").value=""}function N(){document.querySelector("#listContainer-div").innerHTML=""}function H(){N(),p()}function V(){U(!!!document.querySelector("#showClosed-label").className.match(/(( |^)btn-success)/))}function U(e){var t=document.querySelector("#showClosed-label");t.className=e?t.className.replace(/(( |^)btn-danger)/," btn-success"):t.className.replace(/(( |^)btn-success)/," btn-danger"),u.TodoTxtVault.setConfig({showClosed:e})}function K(e){var t=document.querySelector("#"+e+" .panel-heading"),n=document.querySelector("#"+e+" .panel-body");!!n.className.match(/(( |^)collapse)/)?W(t,n):X(t,n)}function W(e,t){var n=e.querySelector(".glyphicon");t.className=t.className.replace(/(( |^)collapse)/g,""),n.className=n.className.replace(/(( |^)glyphicon-chevron-down)/," glyphicon-chevron-up")}function X(e,t){var n=e.querySelector(".glyphicon");t.className+=" collapse",n.className=n.className.replace(/(( |^)glyphicon-chevron-up)/," glyphicon-chevron-down")}function z(e){var t=i.TodoTxt.getTask(e);t&&(t.isActive?i.TodoTxt.closeTask(e):i.TodoTxt.activateTask(e))}function B(e){e.stopPropagation(),e.preventDefault();var t=e.dataTransfer.files;if(t.length>0){var n=t[0],o=new FileReader;o.onloadend=function(e){confirm(c.TodoTxtResources.get("OVERWRITE_CONFIRM"))&&(i.TodoTxt.parseTodoTxtFile(e.target.result.toString()),q())},o.readAsText(n,"UTF-8")}}function Z(e){e.stopPropagation(),e.preventDefault(),e.dataTransfer.dropEffect="copy"}function J(){for(var e=i.TodoTxt.getSortedTaskArray(),t=[],n=0;n'+e.priority+""),e.projects.forEach((function(e){var n=new RegExp(e.replace(/\+/g,"\\+")+"(?![0-9A-Za-z])","g");t=t.replace(n,''+e+"")})),e.contexts.forEach((function(e){var n=new RegExp(e+"(?![0-9A-Za-z])","g");t=t.replace(n,''+e+"")}));var o=e.createdDate;return o&&(t=t.replace(o,'")),t}function G(e){var t="";return null!==e.priority&&e.isActive&&("(A)"===e.priority&&(t+=" text-danger"),"(B)"===e.priority&&(t+=" text-warning"),"(C)"===e.priority&&(t+=" text-primary")),t}e.generateTaskElement=t,e.generateListElement=n,e.displayTasks=p,e.displayTask=f,e.removeTask=function(e){document.querySelector("#listContainer-div").removeChild(document.querySelector("#"+e))},e.displayModalForTask=v,e.updateModalPreview=T,e.removeModal=g,e.modalEventHandlers=[{el:function(){return document},ev:"keydown",fn:function(e){R(e)}},{el:function(){return document},ev:"keydown",fn:function(e){P(e)}},{el:function(){return document},ev:"keydown",fn:function(e){M(e)}}],e.displayPriorities=h,e.clearPriorities=m,e.displayProjects=x,e.clearProjects=y,e.displayContexts=b,e.clearContexts=E,e.mainEventHandlers=[{el:function(){return document},ev:"keydown",fn:function(e){S(e)}},{el:function(){return document},ev:"keydown",fn:function(e){w(e)}},{el:function(){return document},ev:"keydown",fn:function(e){L(e)}},{el:function(){return document.querySelector("#fileDrop-div")},ev:"dragover",fn:function(e){Z(e)}},{el:function(){return document.querySelector("#fileDrop-div")},ev:"drop",fn:function(e){A(e)}},{el:function(){return document.querySelector("#fileUpload-input")},ev:"change",fn:function(e){A(e)}},{el:function(){return document.querySelector("#showClosed-label")},ev:"click",fn:function(){V(),q()}},{el:function(){return document.querySelector("#addTaskButton-button")},ev:"click",fn:function(){v()}},{el:function(){return document.querySelector("#saveFileButton-button")},ev:"click",fn:function(){J()}},{el:function(){return document.querySelector("#filter-input")},ev:"keyup",fn:function(){j()}},{el:function(){return document.querySelector("#clearFilter-button")},ev:"click",fn:function(){q()}},{el:function(){return document.querySelector("#priorities-div .panel-heading")},ev:"click",fn:function(){K("priorities-div")}},{el:function(){return document.querySelector("#projects-div .panel-heading")},ev:"click",fn:function(){K("projects-div")}},{el:function(){return document.querySelector("#contexts-div .panel-heading")},ev:"click",fn:function(){K("contexts-div")}}],e.bindControlEvents=C,e.unbindControlEvents=k,e.handleAltS=S,e.handleAltC=w,e.handleAltT=L,e.handleDrop=A,e.handleAltEnter=R,e.handleEsc=P,e.handleDeleteClick=_,e.handleFilter=j,e.handleAltP=M,e.refreshUi=q,e.setFilters=I,e.clearFilters=F,e.clearTasks=N,e.filterDisplayedTasks=H,e.toggleShowClosedStatus=V,e.setShowClosed=U,e.togglePanel=K,e.showPanel=W,e.hidePanel=X,e.toggleTaskStatus=z,e.getTodoTxtFile=function(e){return o(this,void 0,void 0,(function(){return a(this,(function(t){switch(t.label){case 0:return[4,new Promise((function(t,n){try{s.ajax({url:e,cache:!1,error:function(e,t){alert(t)},success:function(e){i.TodoTxt.parseTodoTxtFile(e),q(),t()}})}catch(e){n(e)}}))];case 1:return t.sent(),[2]}}))}))},e.handleFileSelect=B,e.handleDragOver=Z,e.exportTodoTxtFile=J,e.getMarkupForTask=$,e.getDisplayClassForTask=G,e.initializeElements=function(){var e='

'+c.TodoTxtResources.get("PRIORITIES")+'

    '+c.TodoTxtResources.get("PROJECTS")+'

      '+c.TodoTxtResources.get("CONTEXTS")+'

        ',t=document.getElementById("todotxt");t&&(t.innerHTML=e)}}(t.TodoTxtView||(t.TodoTxtView={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(3),a=n(1),r=n(0),i=n(4);!function(e){function t(e){var t=e||"",n=new a.TodoTxtTask(t);return c(n),n.id}function n(e){return i.TodoTxtVault.getTask(e)}function s(t,o){var r;try{r=n(t)}catch(e){r=new a.TodoTxtTask}return r.parseInput(o),e.addTask(r),!0}function c(e){i.TodoTxtVault.addTask(e),l(e)}function l(e){e.priority&&o.TodoTxtAttributes.priorities.add(e.priority),e.projects.forEach((function(e){e&&o.TodoTxtAttributes.projects.add(e)})),e.contexts.forEach((function(e){e&&o.TodoTxtAttributes.contexts.add(e)}))}function d(e,t){var n=e.isActive,o=t.isActive,a=e.priority,r=t.priority,i=e.createdDate,s=t.createdDate,c=e.completedDate,l=t.completedDate;if(n!==o)return n?-1:1;if(a!==r){if(!r||ar)return 1}else{if(i!==s)return il?-1:1}return 0}e.getSortedTaskArray=function(){var e=i.TodoTxtVault.getAllTasks();o.TodoTxtAttributes.reset();for(var t=0;t - - - - JSDoc: Class: Task - - - - - - - - - - -
        - -

        Class: Task

        - - - - - -
        - -
        -

        - TodoTxt. - - Task -

        - -
        - -
        -
        - - - - -
        -

        new Task(taskString)

        - - -
        -
        - - -
        - this represents a TodoTxt.Task Class to be used as a container for metadata about some type of object. In this case that object is a task. the constructor will create a new taskObj populated with all it's data. The format expected is as follows:

        Active: '[createdDate ]task text string'
        Closed: 'x closedDate [createdDate ]task text string'

        where a closed date should only exist if the task is closed -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeArgumentDefaultDescription
        taskString - - -string - - - - - - <optional>
        - - - - - -
        - - "" - - taskString a single line from the todo.txt file to be parsed into a Task Object
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - - - -
        - - -
        - - - - - - - - - - - - -

        Members

        - -
        - -
        -

        completedDate :string

        - - -
        -
        - -
        - string of the format YYYY-MM-DD that is only present on closed tasks -
        - - - -
        Type:
        -
          -
        • - -string - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • null
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        contexts :array

        - - -
        -
        - -
        - array of strings for words starting with @ representing any contexts in this task -
        - - - -
        Type:
        -
          -
        • - -array - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • []
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        createdDate :string

        - - -
        -
        - -
        - string of the format YYYY-MM-DD representing the task created date -
        - - - -
        Type:
        -
          -
        • - -string - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • null
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        id :string

        - - -
        -
        - -
        - an autogenerated unique identifier -
        - - - -
        Type:
        -
          -
        • - -string - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • GUID
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        isActive :boolean

        - - -
        -
        - -
        - flag to indicate task status -
        - - - -
        Type:
        -
          -
        • - -boolean - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • true
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        metadatas :array

        - - -
        -
        - -
        - additional metadata in the form of key:value -
        - - - -
        Type:
        -
          -
        • - -array - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • []
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        priority :string

        - - -
        -
        - -
        - a string of the format (A) representing the task priority -
        - - - -
        Type:
        -
          -
        • - -string - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • null
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        projects :array

        - - -
        -
        - -
        - array of strings for words starting with + representing any projects in this task -
        - - - -
        Type:
        -
          -
        • - -array - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • []
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - - - -
        -

        text :string

        - - -
        -
        - -
        - full, raw task text string -
        - - - -
        Type:
        -
          -
        • - -string - - -
        • -
        - - - -
        - - - - - - - - - - - - - - - - - -
        Default Value:
        -
          -
        • ""
        • -
        - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - -
        - - - -

        Methods

        - -
        - -
        -

        toString()

        - - -
        -
        - - -
        - override toString() to output the raw TodoTxt format -
        - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - - - -
        - -
        - - - - - -
        - -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - \ No newline at end of file diff --git a/dist/doc/TodoTxt.Utils.html b/dist/doc/TodoTxt.Utils.html deleted file mode 100644 index 5ba8164..0000000 --- a/dist/doc/TodoTxt.Utils.html +++ /dev/null @@ -1,679 +0,0 @@ - - - - - JSDoc: Namespace: Utils - - - - - - - - - - -
        - -

        Namespace: Utils

        - - - - - -
        - -
        -

        - TodoTxt. - - Utils -

        - -
        - -
        -
        - - - - -
        Utility methods used by the project library
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - -
        - - - - - - - - - - - - - - -

        Methods

        - -
        - -
        -

        <static> formatDate() → {string}

        - - -
        -
        - - -
        - function will format a Date object to a string of YYYY-MM-DD -
        - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - formatted date -
        - - - -
        -
        - Type -
        -
        - -string - - -
        -
        - - - - -
        - - - -
        -

        <static> getLanguage() → {string}

        - - -
        -
        - - -
        - function will get the current browser language-locale -
        - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a ISO language-locale for the browser -
        - - - -
        -
        - Type -
        -
        - -string - - -
        -
        - - - - -
        - - - -
        -

        <static> guid() → {string}

        - - -
        -
        - - -
        - function generates a GUID -
        - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a GUID (NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN) -
        - - - -
        -
        - Type -
        -
        - -string - - -
        -
        - - - - -
        - - - -
        -

        <static> htmlEncode(str) → {string}

        - - -
        -
        - - -
        - function will strip out any characters from the passed in string that are not compatible with html and replace with html-friendly versions -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        str - - -string - - - - the string to be html encoded
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a html encoded version of the string that can be used safely within a html page -
        - - - -
        -
        - Type -
        -
        - -string - - -
        -
        - - - - -
        - - - -
        -

        <static> htmlUnencode(str) → {string}

        - - -
        -
        - - -
        - function will strip out any characters from the passed in string that are html character entities and replace with standard string versions -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        str - - -string - - - - the string to be html unencoded
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a version of the string that can contains non-html-friendly strings -
        - - - -
        -
        - Type -
        -
        - -string - - -
        -
        - - - - -
        - -
        - - - - - -
        - -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - \ No newline at end of file diff --git a/dist/doc/TodoTxt.html b/dist/doc/TodoTxt.html deleted file mode 100644 index a5b24d9..0000000 --- a/dist/doc/TodoTxt.html +++ /dev/null @@ -1,1587 +0,0 @@ - - - - - JSDoc: Namespace: TodoTxt - - - - - - - - - - -
        - -

        Namespace: TodoTxt

        - - - - - -
        - -
        -

        - TodoTxt -

        - -
        - -
        -
        - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - -
        - - - - - - - - -

        Classes

        - -
        -
        Task
        -
        -
        - - - -

        Namespaces

        - -
        -
        Utils
        -
        -
        - - - -

        Members

        - -
        - -
        -

        <static> Attributes

        - - -
        -
        - -
        - this function represents a Filters tracking object used to limit the list of Tasks displayed at any one time. -
        - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - -
        - -
        - - - -

        Methods

        - -
        - -
        -

        <static> activateTask(taskId) → {boolean}

        - - -
        -
        - - -
        - function will remove "x YYYY-MM-DD " from a stored task if not already active -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        taskId - - -string - - - - unique ID used to retrieve the task from localStorage
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - true if task could be activated, otherwise false -
        - - - -
        -
        - Type -
        -
        - -boolean - - -
        -
        - - - - -
        - - - -
        -

        <static> addTask(task)

        - - -
        -
        - - -
        - function adds this task to the browser's local cache allowing for retained data on subsequent reloads of the page -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        task - - -TodoTxt.Task - - - - a task to be added to localStorage
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - - - -
        - - - -
        -

        <static> closeTask(taskId) → {boolean}

        - - -
        -
        - - -
        - function will append an "x YYYY-MM-DD " to a stored task if not already closed -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        taskId - - -string - - - - unique ID used to retrieve the task from localStorage
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - true if task could be closed, otherwise false -
        - - - -
        -
        - Type -
        -
        - -boolean - - -
        -
        - - - - -
        - - - -
        -

        <static> createTask(textStr)

        - - -
        -
        - - -
        - function creates a new task and saves to localStorage -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        textStr - - -string - - - - a string representing a raw task
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - - - -
        - - - -
        -

        <static> deleteAllTasks()

        - - -
        -
        - - -
        - function will remove all existing tasks from localStorage -
        - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - - - -
        - - - -
        -

        <static> deleteTask(taskId) → {boolean}

        - - -
        -
        - - -
        - function will remove an existing task from localStorage -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        taskId - - -string - - - - the id of the task to remove from localStorage
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - true if task could be deleted otherwise false -
        - - - -
        -
        - Type -
        -
        - -boolean - - -
        -
        - - - - -
        - - - -
        -

        <static> getFilteredTaskArray(filterStr) → {array}

        - - -
        -
        - - -
        - function will return a filtered array of tasks based on the passed in filter string. Matching uses an ordered fuzzy match so for the following: "(A) 2014-03-02 don't forget to file @report with +John" a passed in filter string of "for John" will match, but "John report" will not match -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        filterStr - - -string - - - - a string containing characters to match against the existing tasks
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a sorted list of tasks matching the passed in filterStr -
        - - - -
        -
        - Type -
        -
        - -array - - -
        -
        - - - - -
        - - - -
        -

        <static> getSortedTaskArray() → {array}

        - - -
        -
        - - -
        - function will return a sorted array of tasks as pulled from localStorage. -
        - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a sorted list of tasks from localStorage -
        - - - -
        -
        - Type -
        -
        - -array - - -
        -
        - - - - -
        - - - -
        -

        <static> getTask(taskId) → {TodoTxt.Task}

        - - -
        -
        - - -
        - function will get a specified task from localstorage by id -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        taskId - - -string - - - - the unique id of the task to be returned
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - a task or null if task not found -
        - - - -
        -
        - Type -
        -
        - -TodoTxt.Task - - -
        -
        - - - - -
        - - - -
        -

        <static> parseTodoTxtFile(todoTxt, append)

        - - -
        -
        - - -
        - function will process each line of the todo.txt, sort by priority, creationDate, and state (active or closed). -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        todoTxt - - -string - - - - the "\n" delimited lines from a todo.txt file
        append - - -boolean - - - - a boolean indicating if existing tasks should be cleared first or just appended to with the new file
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - - - -
        - - - -
        -

        <static> updateTask(taskId, newText) → {boolean}

        - - -
        -
        - - -
        - function updates the task and saves it to the local storage cache -
        - - - - - - - -
        Parameters:
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        NameTypeDescription
        taskId - - -string - - - - unique ID used to retrieve the task from localStorage
        newText - - -string - - - - a string representing the updated, raw task text
        - - - -
        - - - - - - - - - - - - - - - - - - - -
        Source:
        -
        - - - - - - - -
        - - - - - - - - - - - -
        Returns:
        - - -
        - true if task could be updated otherwise false -
        - - - -
        -
        - Type -
        -
        - -boolean - - -
        -
        - - - - -
        - -
        - - - - - -
        - -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - \ No newline at end of file diff --git a/dist/doc/index.html b/dist/doc/index.html deleted file mode 100644 index 20246fc..0000000 --- a/dist/doc/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - JSDoc: Index - - - - - - - - - - -
        - -

        Index

        - - - - - - - -

        - - - - - - - - - - - - - - - - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - \ No newline at end of file diff --git a/dist/doc/scripts/linenumber.js b/dist/doc/scripts/linenumber.js deleted file mode 100644 index 613865d..0000000 --- a/dist/doc/scripts/linenumber.js +++ /dev/null @@ -1,17 +0,0 @@ -(function() { - var counter = 0; - var numbered; - var source = document.getElementsByClassName('prettyprint source'); - - if (source && source[0]) { - source = source[0].getElementsByTagName('code')[0]; - - numbered = source.innerHTML.split('\n'); - numbered = numbered.map(function(item) { - counter++; - return '' + item; - }); - - source.innerHTML = numbered.join('\n'); - } -})(); diff --git a/dist/doc/scripts/prettify/Apache-License-2.0.txt b/dist/doc/scripts/prettify/Apache-License-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/dist/doc/scripts/prettify/Apache-License-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/dist/doc/scripts/prettify/lang-css.js b/dist/doc/scripts/prettify/lang-css.js deleted file mode 100644 index 041e1f5..0000000 --- a/dist/doc/scripts/prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/dist/doc/scripts/prettify/prettify.js b/dist/doc/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7..0000000 --- a/dist/doc/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p - - - - JSDoc: Source: classes/task.js - - - - - - - - - - -
        - -

        Source: classes/task.js

        - - - - - -
        -
        -
        /**********************************************************************
        - * This javascript was created according to the specifications at
        - * http://todotxt.com/ and is intended to allow users to access their
        - * todo.txt files in a user-friendly and easy to visualize manner.
        - *
        - * Once initially uploaded, the todo.txt file will
        - * be loaded into an HTML5 localStorage and managed from there.
        - * The web page then allows downloading changes back to the user
        - * in a txt format compliant with the todo.txt specifications, but
        - * having re-sorted the tasks.
        - * 
        - * @Created: 08/14/2012
        - * @Author: Jason Holt Smith (bicarbon8@gmail.com)
        - * @Version: 0.0.1
        - * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under
        - * the terms of the GNU General Public License.
        - * 
        - * This file is part of todoTxtWebUi.
        - * 
        - * todoTxtWebUi is free software: you can redistribute it and/or modify
        - * it under the terms of the GNU General Public License as published by
        - * the Free Software Foundation, either version 3 of the License, or
        - * (at your option) any later version.
        - * 
        - * todoTxtWebUi is distributed in the hope that it will be useful,
        - * but WITHOUT ANY WARRANTY; without even the implied warranty of
        - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        - * GNU General Public License for more details.
        - * 
        - * You should have received a copy of the GNU General Public License
        - * along with todoTxtWebUi.  If not, see <http://www.gnu.org/licenses/>.
        - **********************************************************************/
        -var TodoTxt = TodoTxt || {};
        -/**
        - * this represents a TodoTxt.Task Class to be used as a container for metadata 
        - * about some type of object.  In this case that object is a
        - * task. the constructor will create a new taskObj populated with all it's data.
        - * The format expected is as follows:
        - * <p>Active: '[createdDate ]task text string'<br />
        - * Closed: 'x closedDate [createdDate ]task text string'</p>
        - * where a closed date should only exist if the task is closed
        - * 
        - * @constructor
        - * @param {string} [taskString=""] - taskString a single line from the todo.txt file to be parsed
        - * into a Task Object
        - */
        -TodoTxt.Task = function (taskString) {
        -	/** @ignore */
        -	this.namespace = TodoTxt.namespace + "Task.";
        -	/**
        -	 * an autogenerated unique identifier
        -	 * @type {string}
        -	 * @defaultvalue GUID
        -	 */
        -	this.id = this.namespace + TodoTxt.Utils.guid();
        -	/**
        -	 * a string of the format <i>(A)</i> representing the task priority
        -	 * @type {string}
        -	 * @defaultvalue null
        -	 */
        -	this.priority = null;
        -	/**
        -	 * string of the format <i>YYYY-MM-DD</i> representing the task created date
        -	 * @type {string}
        -	 * @defaultvalue null 
        -	 */
        -	this.createdDate = null;
        -	/**
        -	 * string of the format <i>YYYY-MM-DD</i> that is only present on closed tasks
        -	 * @type {string}
        -	 * @defaultvalue null
        -	 */
        -	this.completedDate = null;
        -	/**
        -	 * array of strings for words starting with <b><i>+</i></b> representing any projects
        -	 * in this task
        -	 * @type {array}
        -	 * @defaultvalue []
        -	 */
        -	this.projects = [];
        -	/**
        -	 * array of strings for words starting with <b><i>@</i></b> representing any contexts
        -	 * in this task
        -	 * @type {array}
        -	 * @defaultvalue []
        -	 */
        -	this.contexts = [];
        -	/**
        -	 * additional metadata in the form of <b><i>key:value</b></i>
        -	 * @type {array}
        -	 * @defaultvalue []
        -	 */
        -	this.metadatas = [];
        -	/**
        -	 * flag to indicate task status
        -	 * @type {boolean}
        -	 * @defaultvalue true
        -	 */
        -	this.isActive = true;
        -	/**
        -	 * full, raw task text string
        -	 * @type {string}
        -	 * @defaultvalue ""
        -	 */
        -	this.text = "";
        -
        -	if (taskString) {
        -		this._parseFromString(taskString);
        -	}
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseFromString = function (textLine) {
        -	if (typeof textLine === "string") {
        -		// assign the text
        -		this.text = textLine;
        -
        -		// parse out the Active / Closed state (starts with "x " for closed)
        -		this._parseStatusFromString(textLine);
        -
        -		// get the priority of the task EX: (A)
        -		this._parsePriorityFromString(textLine);
        -		
        -		// get the completed date of the task EX: 2012-09-23
        -		this._parseCompletedDateFromString(textLine);
        -		
        -		// get the created date of the task EX: 2012-09-23
        -		this._parseCreatedDateFromString(textLine);
        -		
        -		// parse out any Projects (items starting with "+" like "+ProjectName")
        -		this._parseProjectsFromString(textLine);
        -		
        -		// parse out any Context (items starting with "@" like "@ContextName")
        -		this._parseContextsFromString(textLine);
        -	} else {
        -		throw "cannot parse input of type: " + typeof(textLine) + ". only strings are accepted.";
        -	}
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseStatusFromString = function (str) {
        -	// check for strings starting with something like "x "
        -	if (str && str.match(/^(x )/)) {
        -		this.isActive = false;
        -	} else {
        -		this.isActive = true;
        -	}
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parsePriorityFromString = function (str) {
        -	var pri = null; // used to hold the priority if set
        -	if (str) {
        -		// parse out the priority RegEx: /\^([A-Z]\).*/ 
        -		// check for strings starting with something like "(A) "
        -		var priPattern = /^(\([A-Z]\)[\s]+)/;
        -		var match = str.match(priPattern); // returns null if not found
        -		if (match) {
        -			// found an active match so get the priority
        -			pri = match[0].replace(/[\s]*/g, "");
        -		}
        -	}
        -	
        -	this.priority = pri;
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseCompletedDateFromString = function (str) {
        -	var completed = null;
        -	if (str) {
        -		// parse out the completedDate if closed (starts with "x ")
        -		if (!this.isActive) {
        -			var dates = this._parseDatesFromString(str);
        -			if (dates) {
        -				completed = dates[0].replace(/[\s]*/g, "");
        -			}
        -		}
        -	}
        -	
        -	this.completedDate = completed;
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseCreatedDateFromString = function (str) {
        -	var created = null;
        -	if (str) {
        -		// parse out the createdDate (will be 2nd if item is closed)
        -		var dates = this._parseDatesFromString(str);
        -		if (dates) {
        -			if (!this.isActive) {
        -				if (dates.length > 1) { // we have created and completed
        -					created = dates[1].replace(/[\s]*/g, "");
        -				}
        -			} else {
        -				created = dates[0].replace(/[\s]*/g, "");
        -			}
        -		}
        -	}
        -	
        -	this.createdDate = created;
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseDatesFromString = function (str) {
        -	var dates = null;
        -	if (str) {
        -		// check for strings with something like "2012-08-09"
        -		var datePattern = /(?:\s|^)(\d{4}-\d{2}-\d{2})(?=\s)/g;
        -		match = str.match(datePattern); // returns null if not found
        -		if (match) {
        -			dates = match;
        -		}
        -	}
        -	
        -	return dates;
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseProjectsFromString = function (str) {
        -	var projArray = []; // used to hold the project if set
        -	if (str) {
        -		// parse out the projects RegEx: /\+[0-9A-Za-z]+\s/ (words starting with "+")
        -		// check for strings like "+ABC123"
        -		var projPattern = /((\s|^)[\(\{\["']?\+[0-9A-Za-z]+[\)\}\]"']?(?=\s|$))/g;
        -		var match = str.match(projPattern); // returns null if not found
        -		if (match) {
        -			// only store one instance of duplicate project entries
        -			var tmpHash = {};
        -			for (var i=0; i<match.length; i++) {
        -				var p = match[i].replace(/[\s]*/g, "").replace(/[\(\{\[\)\}\]"']/g, "");;
        -				tmpHash[p] = true;
        -			}
        -			for (var key in tmpHash) {
        -				projArray.push(key);
        -			}
        -		}
        -	}
        -	
        -	this.projects = projArray;
        -};
        -
        -/** @ignore */
        -TodoTxt.Task.prototype._parseContextsFromString = function (str) {
        -	var ctxArray = []; // used to hold the context if set
        -	if (str) {
        -		// parse out the contexts RegEx: /\@[0-9A-Za-z]+\s/ (words starting with "+")
        -		// check for strings like "@ABC123"
        -		var ctxPattern = /((\s|^)[\(\{\["']?\@[0-9A-Za-z]+[\)\}\]"']?(?=\s|$))/g;
        -		var match = str.match(ctxPattern); // returns null if not found
        -		if (match) {
        -			// only store one instance of duplicate project entries
        -			var tmpHash = {};
        -			for (var i=0; i<match.length; i++) {
        -				var c = match[i].replace(/[\s]*/g, "").replace(/[\(\{\[\)\}\]"']/g, "");;
        -				tmpHash[c] = true;
        -			}
        -			for (var key in tmpHash) {
        -				ctxArray.push(key);
        -			}
        -		}
        -	}
        -	
        -	this.contexts = ctxArray;
        -};
        -
        -/**
        - * override toString() to output the raw TodoTxt format
        - */
        -TodoTxt.Task.prototype.toString = function () {
        -	return this.text;
        -};
        -
        -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - diff --git a/dist/doc/todoTxt.js.html b/dist/doc/todoTxt.js.html deleted file mode 100644 index 5c126de..0000000 --- a/dist/doc/todoTxt.js.html +++ /dev/null @@ -1,379 +0,0 @@ - - - - - JSDoc: Source: todoTxt.js - - - - - - - - - - -
        - -

        Source: todoTxt.js

        - - - - - -
        -
        -
        /**********************************************************************
        - * This javascript was created according to the specifications at
        - * http://todotxt.com/ and is intended to allow users to access their
        - * todo.txt files in a user-friendly and easy to visualize manner.
        - *
        - * Once initially uploaded, the todo.txt file will
        - * be loaded into an HTML5 localStorage and managed from there.
        - * The web page then allows downloading changes back to the user
        - * in a txt format compliant with the todo.txt specifications, but
        - * having re-sorted the tasks.
        - *
        - * @Created: 08/14/2012
        - * @Author: Jason Holt Smith (bicarbon8@gmail.com)
        - * @Version: 0.0.1
        - * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under
        - * the terms of the GNU General Public License.
        - *
        - * This file is part of todoTxtWebUi.
        - *
        - * todoTxtWebUi is free software: you can redistribute it and/or modify
        - * it under the terms of the GNU General Public License as published by
        - * the Free Software Foundation, either version 3 of the License, or
        - * (at your option) any later version.
        - *
        - * todoTxtWebUi is distributed in the hope that it will be useful,
        - * but WITHOUT ANY WARRANTY; without even the implied warranty of
        - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        - * GNU General Public License for more details.
        - *
        - * You should have received a copy of the GNU General Public License
        - * along with todoTxtWebUi.  If not, see <http://www.gnu.org/licenses/>.
        - **********************************************************************/
        -
        -/** @namespace */
        -var TodoTxt = {
        -    /** @ignore */
        -    namespace: "TodoTxt.",
        -
        -    /**
        -     * this function represents a Filters tracking object used to
        -     * limit the list of Tasks displayed at any one time.
        -     */
        -    Attributes: {
        -        /** hash containing all referenced priorities */
        -        priorities: {},
        -        /** hash containing all referenced projects */
        -        projects: {},
        -        /** hash containing all referenced contexts */
        -        contexts: {},
        -    },
        -
        -    /**
        -     * function will return a sorted array of tasks as pulled from
        -     * localStorage.
        -     * @returns {array} a sorted list of tasks from localStorage
        -     */
        -    getSortedTaskArray: function () {
        -        // sort the list and then add it
        -        var taskArray = [];
        -        var taskMatcher = new RegExp("^(" + new TodoTxt.Task().namespace + ")");
        -        TodoTxt._clearAttributes();
        -        for (var key in localStorage) {
        -            if (key.match(taskMatcher)) {
        -                var t = TodoTxt.getTask(key);
        -                if (t) {
        -                    t.id = key;
        -                    taskArray.push(t);
        -                    TodoTxt._updateAttributes(t);
        -                }
        -            }
        -        }
        -        taskArray.sort(TodoTxt._compareTasks);
        -
        -        return taskArray;
        -    },
        -
        -    /**
        -     * function will return a filtered array of tasks based on the passed in
        -     * filter string.  Matching uses an ordered fuzzy match so for the following:
        -     * "(A) 2014-03-02 don't forget to file @report with +John" a passed in filter
        -     * string of "for John" will match, but "John report" will not match
        -     * @param {string} filterStr - a string containing characters to match against the existing tasks
        -     * @returns {array} a sorted list of tasks matching the passed in <b><i>filterStr</i></b>
        -     */
        -    getFilteredTaskArray: function (filterStr) {
        -        var filteredTasks = TodoTxt.getSortedTaskArray();
        -        if (filterStr && filterStr !== "") {
        -            // create the regex matcher
        -            var filters = filterStr.split(" ");
        -            var rStr = ".*";
        -            for (var i=0; i<filters.length; i++) {
        -                var filter = filters[i].replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').replace(/\x08/g, '\\x08');
        -                rStr += "(" + filter + ").*";
        -            }
        -            var regex = new RegExp(rStr, "i");
        -            var tasks = filteredTasks.filter(function (t) {
        -                return t.toString().match(regex);
        -            });
        -            filteredTasks = tasks;
        -        }
        -
        -        return filteredTasks;
        -    },
        -
        -    /**
        -     * function will process each line of the todo.txt, sort by priority,
        -     * creationDate, and state (active or closed).
        -     *
        -     * @param {string} todoTxt - the "\n" delimited lines from a todo.txt file
        -     * @param {boolean} append - a boolean indicating if existing tasks should be cleared
        -     * first or just appended to with the new file
        -     */
        -    parseTodoTxtFile: function (todoTxt, append) {
        -        if (!append) {
        -            // clear the localStorage
        -            TodoTxt.deleteAllTasks();
        -        }
        -        var lines = todoTxt.split("\n");
        -        for (var i in lines) {
        -            if (typeof lines[i] === "string") {
        -                var line = lines[i];
        -                // ignore empty lines
        -                if (line && line !== "") {
        -                    // parse the individual line and return a Task
        -                    var task = new TodoTxt.Task(line);
        -
        -                    // add this taskObj to our global list in it's proper location
        -                    TodoTxt.addTask(task);
        -                }
        -            }
        -        }
        -    },
        -
        -    /**
        -     * function creates a new task and saves to localStorage
        -     * @param {string} textStr - a string representing a raw task
        -     */
        -    createTask: function (textStr) {
        -        var text = textStr || "";
        -        var t = new TodoTxt.Task(textStr);
        -        TodoTxt.addTask(t);
        -    },
        -
        -    /**
        -     * function will get a specified task from localstorage by id
        -     * @param {string} taskId - the unique id of the task to be returned
        -     * @returns {TodoTxt.Task} a task or null if task not found
        -     */
        -    getTask: function (taskId) {
        -        var task,
        -            text = localStorage.getItem(taskId);
        -        if (text !== null && text !== undefined) {
        -            task = new TodoTxt.Task(text);
        -            task.id = taskId;
        -        }
        -        return task;
        -    },
        -
        -    /**
        -     * function updates the task and saves it to the local storage cache
        -     * @param {string} taskId - unique ID used to retrieve the task from localStorage
        -     * @param {string} newText - a string representing the updated, raw task text
        -     * @returns {boolean} true if task could be updated otherwise false
        -     */
        -    updateTask: function (taskId, newText) {
        -        // re-parse task
        -        var task = new TodoTxt.Task(newText);
        -        task.id = taskId;
        -
        -        // overwrite localstorage with updated task
        -        TodoTxt.addTask(task);
        -
        -        return true;
        -    },
        -
        -    /**
        -     * function adds this task to the browser's local cache allowing for
        -     * retained data on subsequent reloads of the page
        -     * @param {TodoTxt.Task} task - a task to be added to localStorage
        -     */
        -    addTask: function (task) {
        -        localStorage.setItem(task.id, task.toString());
        -        TodoTxt._updateAttributes(task);
        -    },
        -
        -    /**
        -     * function will append an "x YYYY-MM-DD " to a stored
        -     * task if not already closed
        -     * @param {string} taskId - unique ID used to retrieve the task from localStorage
        -     * @returns {boolean} true if task could be closed, otherwise false
        -     */
        -    closeTask: function (taskId) {
        -        var task = TodoTxt.getTask(taskId);
        -        if (task && task.isActive) {
        -            var text = task.toString();
        -            if (task.priority) {
        -                text = text.replace(task.priority, "");
        -            }
        -            text = "x " + TodoTxt.Utils.formatDate(new Date()) + " " + text;
        -            TodoTxt.updateTask(task.id, text);
        -            return true;
        -        }
        -        
        -        return false;
        -    },
        -
        -    /**
        -     * function will remove "x YYYY-MM-DD " from a stored
        -     * task if not already active
        -     * @param {string} taskId - unique ID used to retrieve the task from localStorage
        -     * @returns {boolean} true if task could be activated, otherwise false
        -     */
        -    activateTask: function (taskId) {
        -        var task = TodoTxt.getTask(taskId);
        -        if (task && !task.isActive) {
        -            var text = task.toString();
        -            text = text.replace(/^(x )/, "").replace(task.completedDate + " ", "");
        -            TodoTxt.updateTask(task.id, text);
        -            return true;
        -        }
        -        
        -        return false;
        -    },
        -
        -    /**
        -     * function will remove an existing task from localStorage
        -     * @param {string} taskId - the id of the task to remove from localStorage
        -     * @returns {boolean} true if task could be deleted otherwise false
        -     */
        -    deleteTask: function (taskId) {
        -        localStorage.removeItem(taskId);
        -        return true;
        -    },
        -
        -    /**
        -     * function will remove all existing tasks from localStorage
        -     */
        -    deleteAllTasks: function () {
        -        var taskMatcher = new RegExp("^(" + new TodoTxt.Task().namespace + ")");
        -        for (var key in localStorage) {
        -            if (key.match(taskMatcher)) {
        -                TodoTxt.deleteTask(key);
        -            }
        -        }
        -    },
        -
        -    /** @ignore */
        -    _updateAttributes: function (task) {
        -        // get the priority and add to global filter hashset
        -        if (task.priority) {
        -            TodoTxt.Attributes.priorities[task.priority] = task.isActive;
        -        }
        -
        -        // get each project and add to the global filter hashset
        -        for (var i in task.projects) {
        -            if (typeof task.projects[i] === "string") {
        -                TodoTxt.Attributes.projects[task.projects[i]] = task.isActive;
        -            }
        -        }
        -
        -        // get each context and add to the global filter hashset
        -        for (var j in task.contexts) {
        -            if (typeof task.contexts[j] === "string") {
        -                TodoTxt.Attributes.contexts[task.contexts[j]] = task.isActive;
        -            }
        -        }
        -    },
        -
        -    /** @ignore */
        -    _clearAttributes: function () {
        -        TodoTxt.Attributes.priorities = {};
        -        TodoTxt.Attributes.projects = {};
        -        TodoTxt.Attributes.contexts = {};
        -    },
        -
        -    /** @ignore */
        -    _compareTasks: function (taskA, taskB) {
        -        // function will allow sorting of tasks by the following
        -        // criteria: (1) active vs. closed (2) priority (3) created date
        -        // (4) completed date
        -        var aActive = taskA.isActive;
        -        var bActive = taskB.isActive;
        -        var aPri = taskA.priority;
        -        var bPri = taskB.priority;
        -        var aCreated = taskA.createdDate;
        -        var bCreated = taskB.createdDate;
        -        var aCompleted = taskA.completedDate;
        -        var bCompleted = taskB.completedDate;
        -
        -        // (1) compare active vs. closed
        -        if (aActive !== bActive) {
        -            // prioritize active over closed
        -            if (aActive) {
        -                return -1;
        -            } else {
        -                return 1;
        -            }
        -        } else { // (2) compare priority
        -            if (aPri !== bPri) {
        -                // order by priority, but favor having priority over not
        -                if (!bPri || aPri < bPri) {
        -                    return -1;
        -                } else if (!aPri || aPri > bPri) {
        -                    return 1;
        -                }
        -            } else { // (3) compare created date
        -                if (aCreated !== bCreated) {
        -                    // order by created date ascending (oldest ones first)
        -                    if (aCreated < bCreated) {
        -                        return -1;
        -                    } else {
        -                        return 1;
        -                    }
        -                } else { // (4) compare completed date
        -                    if (aCompleted !== bCompleted) {
        -                        // order by completed date descending (latest ones first)
        -                        if (aCompleted > bCompleted) {
        -                            return -1;
        -                        } else {
        -                            return 1;
        -                        }
        -                    }
        -                }
        -            }
        -        }
        -
        -        // objects are equivalent
        -        return 0;
        -    },
        -};
        -
        -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - diff --git a/dist/doc/utils.js.html b/dist/doc/utils.js.html deleted file mode 100644 index d198496..0000000 --- a/dist/doc/utils.js.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - JSDoc: Source: objects/utils.js - - - - - - - - - - -
        - -

        Source: objects/utils.js

        - - - - - -
        -
        -
        /**********************************************************************
        - * This javascript was created according to the specifications at
        - * http://todotxt.com/ and is intended to allow users to access their
        - * todo.txt files in a user-friendly and easy to visualize manner.
        - *
        - * Once initially uploaded, the todo.txt file will
        - * be loaded into an HTML5 localStorage and managed from there.
        - * The web page then allows downloading changes back to the user
        - * in a txt format compliant with the todo.txt specifications, but
        - * having re-sorted the tasks.
        - * 
        - * @Created: 08/14/2012
        - * @Author: Jason Holt Smith (bicarbon8@gmail.com)
        - * @Version: 0.0.1
        - * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under
        - * the terms of the GNU General Public License.
        - * 
        - * This file is part of todoTxtWebUi.
        - * 
        - * todoTxtWebUi is free software: you can redistribute it and/or modify
        - * it under the terms of the GNU General Public License as published by
        - * the Free Software Foundation, either version 3 of the License, or
        - * (at your option) any later version.
        - * 
        - * todoTxtWebUi is distributed in the hope that it will be useful,
        - * but WITHOUT ANY WARRANTY; without even the implied warranty of
        - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        - * GNU General Public License for more details.
        - * 
        - * You should have received a copy of the GNU General Public License
        - * along with todoTxtWebUi.  If not, see <http://www.gnu.org/licenses/>.
        - **********************************************************************/
        -var TodoTxt = TodoTxt || {};
        -
        -/**
        - * Utility methods used by the project library
        - * @namespace
        - */
        -TodoTxt.Utils = {
        -	/**
        -	 * function will format a Date object to a string of YYYY-MM-DD
        -	 * @returns {string} formatted date
        -	 */
        -	formatDate: function (dateObj) {
        -		var yyyy = dateObj.getFullYear();
        -		var mm = (dateObj.getMonth()+1).toString(); // getMonth() is zero-based
        -        mm = mm.length < 2 ? "0" + mm : mm;
        -		var dd  = (dateObj.getDate()).toString();
        -        dd = dd.length < 2 ? "0" + dd : dd;
        -		return String(yyyy + "-" + mm + "-" + dd); // Leading zeros for mm and dd
        -	},
        -
        -	/**
        -	 * function will get the current browser language-locale
        -	 * @returns {string} a ISO language-locale for the browser
        -	 */
        -	getLanguage: function () {
        -		var langLocale = window.navigator.userLanguage || window.navigator.language;
        -		return langLocale.toLowerCase();
        -	},
        -
        -	/**
        -	 * function generates a GUID
        -	 * @returns {string} a GUID (NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN)
        -	 */
        -	guid: function () {
        -        function s4() {
        -            return Math.floor((1 + Math.random()) * 0x10000)
        -                .toString(16)
        -                .substring(1);
        -        }
        -        return s4()+s4()+'-'+s4()+'-'+s4()+'-'+s4()+'-'+s4()+s4()+s4();
        -    },
        -
        -    /**
        -     * function will strip out any characters from the passed in string that are
        -     * not compatible with html and replace with html-friendly versions
        -     * @param {string} str - the string to be html encoded
        -     * @returns {string} a html encoded version of the string that can be used safely
        -     * within a html page
        -     */
        -    htmlEncode: function (str) {
        -        return String(str)
        -            .replace(/&/g, '&')
        -            .replace(/</g, '<')
        -            .replace(/>/g, '>')
        -            .replace(/"/g, '"')
        -            .replace(/\s{2}/g, '  ');
        -    },
        -
        -    /**
        -     * function will strip out any characters from the passed in string that are
        -     * html character entities and replace with standard string versions
        -     * @param {string} str - the string to be html unencoded
        -     * @returns {string} a version of the string that can contains non-html-friendly
        -     * strings
        -     */
        -    htmlUnencode: function (str) {
        -        return String(str)
        -            .replace(/&/g, '&')
        -            .replace(/</g, '<')
        -            .replace(/>/g, '>')
        -            .replace(/"/g, '"')
        -            .replace(/ /g, ' ');
        -    }
        -};
        -
        -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - diff --git a/dist/doc/view.js.html b/dist/doc/view.js.html deleted file mode 100644 index 907b2b7..0000000 --- a/dist/doc/view.js.html +++ /dev/null @@ -1,758 +0,0 @@ - - - - - JSDoc: Source: objects/view.js - - - - - - - - - - -
        - -

        Source: objects/view.js

        - - - - - -
        -
        -
        /**********************************************************************
        - * This javascript was created according to the specifications at
        - * http://todotxt.com/ and is intended to allow users to access their
        - * todo.txt files in a user-friendly and easy to visualize manner.
        - *
        - * Once initially uploaded, the todo.txt file will
        - * be loaded into an HTML5 localStorage and managed from there.
        - * The web page then allows downloading changes back to the user
        - * in a txt format compliant with the todo.txt specifications, but
        - * having re-sorted the tasks.
        - *
        - * @Created: 08/14/2012
        - * @Author: Jason Holt Smith (bicarbon8@gmail.com)
        - * @Version: 0.0.1
        - * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under
        - * the terms of the GNU General Public License.
        - *
        - * This file is part of todoTxtWebUi.
        - *
        - * todoTxtWebUi is free software: you can redistribute it and/or modify
        - * it under the terms of the GNU General Public License as published by
        - * the Free Software Foundation, either version 3 of the License, or
        - * (at your option) any later version.
        - *
        - * todoTxtWebUi is distributed in the hope that it will be useful,
        - * but WITHOUT ANY WARRANTY; without even the implied warranty of
        - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        - * GNU General Public License for more details.
        - *
        - * You should have received a copy of the GNU General Public License
        - * along with todoTxtWebUi.  If not, see <http://www.gnu.org/licenses/>.
        - **********************************************************************/
        -var TodoTxt = TodoTxt || {};
        -TodoTxt.View = {
        -    /** @ignore */
        -    namespace: TodoTxt.namespace + "View.",
        -
        -    /**
        -     * function generates the DOM element for the passed in task
        -     */
        -    generateTaskElement: function (task) {
        -        var icon = "glyphicon-ok";
        -        var status = "btn-default";
        -        var htmlText = TodoTxt.View.taskToMarkupString(task);
        -        if (!task.isActive) {
        -            icon = "glyphicon-remove";
        -            status = "btn-danger";
        -        }
        -
        -        var element = document.createElement("div");
        -        element.className = "btn-group btn-block";
        -        element.id = task.id;
        -
        -        /*jshint multistr: true */
        -        var elementTxt = ' \
        -<span class="col-xs-2 btn btn-lg ' + status + '" onclick="TodoTxt.View.toggleTaskStatus(\'' + task.id + '\');"> \
        -    <span class="glyphicon ' + icon + '"></span> \
        -</span> \
        -<button class="col-xs-10 ellipsis btn btn-lg ' + status + '" onclick="TodoTxt.View.displayModalForTask(\'' + task.id + '\');">' + htmlText + '</button>';
        -
        -        element.innerHTML = elementTxt;
        -        return element;
        -    },
        -
        -    generateListElement: function (text) {
        -        var element = document.createElement("li");
        -        element.id = TodoTxt.View.namespace + text;
        -        element.className = "list-group-item";
        -        element.onclick = function (e) {
        -            TodoTxt.View.setFilters(text);
        -        };
        -        element.onmouseover = function (e) {
        -            element.className += " active";
        -        };
        -        element.onmouseout = function (e) {
        -            element.className = element.className.replace(/(( |^)active)/, "");
        -        };
        -        element.innerHTML = '<h4 class="ellipsis">' + text + '</h4>';
        -
        -        return element;
        -    },
        -
        -    /**
        -     * function will attempt to get all localStorage tasks and display them
        -     * in the DOM if any exist.  This will add to any existing tasks so you
        -     * will need to clear the DOM first if you want to update the entire list
        -     * instead of just appending to the list.
        -     */
        -    displayTasks: function () {
        -        // get the list of selected priorities from the filter
        -        var filterStr = document.querySelector("#filter-input").value;
        -
        -        // filter list by those matching selected filters
        -        var filteredTasks = TodoTxt.getFilteredTaskArray(filterStr);
        -
        -        if (!TodoTxt.View.getShowClosedStatus()) {
        -            // filter out closed tasks
        -            var tasks = filteredTasks.filter(function (t) {
        -                return t.isActive;
        -            });
        -            filteredTasks = tasks;
        -        }
        -
        -        if (filteredTasks && filteredTasks.length > 0) {
        -            // add tasks to DOM
        -            filteredTasks.forEach(function (t) {
        -                TodoTxt.View.displayTask(t);
        -            });
        -        }
        -    },
        -
        -    displayTask: function (task) {
        -        // add task to DOM
        -        document.querySelector("#listContainer-div").appendChild(TodoTxt.View.generateTaskElement(task));
        -    },
        -
        -    removeTask: function (taskId) {
        -        // delete the task from the DOM
        -        document.querySelector("#listContainer-div").removeChild(document.querySelector("#" + taskId));
        -    },
        -
        -    /**
        -     * function opens the specified task in an editing window
        -     */
        -    displayModalForTask: function (taskId) {
        -        // populate the modal textarea with this task string
        -        var task = TodoTxt.getTask(taskId) || new TodoTxt.Task();
        -
        -        TodoTxt.View.unbindControlEvents(TodoTxt.View.mainEventHandlers);
        -
        -        var htmlText = TodoTxt.View.taskToMarkupString(task).replace(/hidden-xs/,"");
        -
        -        /*jshint multistr: true */
        -        var modal = ' \
        -<div class="modal" id="modalEdit-div" tabindex="-1" role="dialog" aria-labelledby="modalEdit-label" aria-hidden="true"> \
        -    <div class="modal-dialog"> \
        -        <div class="modal-content"> \
        -            <div class="modal-header"> \
        -                <button type="button" id="modalEditClose-button" class="close" data-dismiss="modal" aria-label="' + TodoTxt.Resources.get("CLOSE") + '"><span aria-hidden="true"> ×</span></button> \
        -                <h4 class="modal-title" id="modalEdit-label"> ' + TodoTxt.Resources.get("EDIT_TASK_HEADER") + '</h4> \
        -            </div> \
        -            <div class="modal-body"> \
        -                <div id="modalEdit-textarea" class="textarea" contenteditable>' + htmlText + '</div> \
        -                <input type="text" id="modalEditTaskId-input" hidden value="' + task.id + '" /> \
        -            </div> \
        -            <div class="modal-footer"> \
        -                <div class="btn-group btn-group-justified"> \
        -                    <a type="button" id="modalEditSave-button" class="btn btn-lg btn-success" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("UPDATE") + '"><span class="glyphicon glyphicon-ok"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("UPDATE") + '</span></a> \
        -                    <a type="button" id="modalEditPreview-button" class="btn btn-lg btn-primary" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("PREVIEW") + '"><span class="glyphicon glyphicon-eye-open"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("PREVIEW") + '</span</a> \
        -                    <a type="button" id="modalEditDelete-button" class="btn btn-lg btn-danger" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("DELETE") + '"><span class="glyphicon glyphicon-floppy-remove"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("DELETE") + '</span></a> \
        -                </div> \
        -            </div> \
        -        </div> \
        -    </div> \
        -</div>';
        -
        -        document.body.innerHTML += modal;
        -
        -        $('#modalEdit-div').modal("show");
        -
        -        TodoTxt.View.bindControlEvents(TodoTxt.View.modalEventHandlers);
        -
        -        // place focus on the textarea
        -        document.querySelector("#modalEdit-textarea").focus();
        -    },
        -
        -    updateModalPreview: function () {
        -        var el = document.querySelector('#modalEdit-textarea');
        -        if (el) {
        -            var text = el.textContent;
        -            var task = new TodoTxt.Task(text);
        -            el.innerHTML = TodoTxt.View.taskToMarkupString(task);
        -        }
        -    },
        -
        -    closeModal: function () {
        -        TodoTxt.View.removeModal();
        -        TodoTxt.View.refreshUi();
        -    },
        -
        -    modalEventHandlers: [
        -        { el: function () { return document; }, ev: "keydown", fn: function (e) { TodoTxt.View.handleAltEnter(e); } },
        -        { el: function () { return document; }, ev: "keydown", fn: function (e) { TodoTxt.View.handleEsc(e); } },
        -        { el: function () { return document; }, ev: "keydown", fn: function (e) { TodoTxt.View.handleAltP(e); } },
        -        { el: function () { return document.querySelector('#modalEditSave-button'); }, ev: "click", fn: function (e) { TodoTxt.View.handleAltEnter(e); } },
        -        { el: function () { return document.querySelector('#modalEditClose-button'); }, ev: "click", fn: function (e) { TodoTxt.View.closeModal(); } },
        -        { el: function () { return document.querySelector('#modalEditDelete-button'); }, ev: "click", fn: function (e) { TodoTxt.View.handleDeleteClick(e); } },
        -        { el: function () { return document.querySelector('#modalEditPreview-button'); }, ev: "click", fn: function (e) { TodoTxt.View.handleAltP(e); } },
        -    ],
        -
        -    removeModal: function () {
        -        $('#modalEdit-div').modal("hide");
        -        TodoTxt.View.unbindControlEvents(TodoTxt.View.modalEventHandlers);
        -        var modal = document.querySelector("#modalEdit-div");
        -        document.body.removeChild(modal);
        -        TodoTxt.View.bindControlEvents(TodoTxt.View.mainEventHandlers);
        -    },
        -
        -    displayPriorities: function () {
        -        var priList = document.querySelector('#priorities-ul');
        -        for (var i in TodoTxt.Attributes.priorities) {
        -            var attr = i;
        -            // only display active
        -            if (TodoTxt.Attributes.priorities[i] || TodoTxt.View.getShowClosedStatus()) {
        -                var element = TodoTxt.View.generateListElement(attr);
        -                priList.appendChild(element);
        -            }
        -        }
        -    },
        -
        -    clearPriorities: function () {
        -        document.querySelector('#priorities-ul').innerHTML = "";
        -    },
        -
        -    displayProjects: function () {
        -        var projList = document.querySelector('#projects-ul');
        -        for (var i in TodoTxt.Attributes.projects) {
        -            var attr = i;
        -            // only display active
        -            if (TodoTxt.Attributes.projects[i] || TodoTxt.View.getShowClosedStatus()) {
        -                var element = TodoTxt.View.generateListElement(attr);
        -                projList.appendChild(element);
        -            }
        -        }
        -    },
        -
        -    clearProjects: function () {
        -        document.querySelector('#projects-ul').innerHTML = "";
        -    },
        -
        -    displayContexts: function () {
        -        var ctxList = document.querySelector('#contexts-ul');
        -        for (var i in TodoTxt.Attributes.contexts) {
        -            var attr = i;
        -            // only display active
        -            if (TodoTxt.Attributes.contexts[i] || TodoTxt.View.getShowClosedStatus()) {
        -                var element = TodoTxt.View.generateListElement(attr);
        -                ctxList.appendChild(element);
        -            }
        -        }
        -    },
        -
        -    clearContexts: function () {
        -        document.querySelector('#contexts-ul').innerHTML = "";
        -    },
        -
        -    mainEventHandlers: [
        -        { el: function () { return document; }, ev: "keydown", fn: function (e) { TodoTxt.View.handleAltS(e); } },
        -        { el: function () { return document; }, ev: "keydown", fn: function (e) { TodoTxt.View.handleAltC(e); } },
        -        { el: function () { return document; }, ev: "keydown", fn: function (e) { TodoTxt.View.handleAltT(e); } },
        -        { el: function () { return document.querySelector("#fileDrop-div"); }, ev: "dragover", fn: function (e) { TodoTxt.View.handleDragOver(e); } },
        -        { el: function () { return document.querySelector("#fileDrop-div"); }, ev: "drop", fn: function (e) { TodoTxt.View.handleDrop(e); } },
        -        { el: function () { return document.querySelector("#fileUpload-input"); }, ev: "change", fn: function (e) { TodoTxt.View.handleDrop(e); } },
        -        { el: function () { return document.querySelector("#showClosed-label"); }, ev: "click", fn: function (e) { TodoTxt.View.toggleShowClosedStatus(); } },
        -        { el: function () { return document.querySelector("#addTaskButton-button"); }, ev: "click", fn: function (e) { TodoTxt.View.displayModalForTask(); } },
        -        { el: function () { return document.querySelector("#saveFileButton-button"); }, ev: "click", fn: function (e) { TodoTxt.View.exportTodoTxtFile(); } },
        -        { el: function () { return document.querySelector("#filter-input"); }, ev: "keyup", fn: function (e) { TodoTxt.View.handleFilter(); } },
        -        { el: function () { return document.querySelector("#clearFilter-button"); }, ev: "click", fn: function (e) { TodoTxt.View.refreshUi(); } },
        -        { el: function () { return document.querySelector("#priorities-div .panel-heading"); }, ev: "click", fn: function (e) { TodoTxt.View.togglePanel('priorities-div'); } },
        -        { el: function () { return document.querySelector("#projects-div .panel-heading"); }, ev: "click", fn: function (e) { TodoTxt.View.togglePanel('projects-div'); } },
        -        { el: function () { return document.querySelector("#contexts-div .panel-heading"); }, ev: "click", fn: function (e) { TodoTxt.View.togglePanel('contexts-div'); } },
        -    ],
        -
        -    bindControlEvents: function (handlers) {
        -        handlers.forEach(function (handler) {
        -            var useCapture = false;
        -            if (handler.uc) {
        -                useCapture = handler.uc;
        -            }
        -            try {
        -              handler.el().addEventListener(handler.ev, handler.fn, useCapture);
        -            } catch (e) {
        -              // TODO: log this
        -            }
        -        });
        -    },
        -
        -    unbindControlEvents: function (handlers) {
        -        handlers.forEach(function (handler) {
        -            var useCapture = false;
        -            if (handler.uc) {
        -                useCapture = handler.uc;
        -            }
        -            try {
        -              handler.el().removeEventListener(handler.ev, handler.fn, useCapture);
        -            } catch (e) {
        -              // TODO: Log this
        -            }
        -        });
        -    },
        -
        -    handleAltS: function(e) {
        -        if (e.keyCode == 83 && e.altKey) { // Alt + s
        -            TodoTxt.View.exportTodoTxtFile();
        -        }
        -    },
        -
        -    handleAltC: function(e) {
        -        if (e.keyCode == 67 && e.altKey) { // Alt + c
        -            TodoTxt.View.refreshUi();
        -        }
        -    },
        -
        -    handleAltT: function(e) {
        -        if (e.keyCode == 84 && e.altKey) { // Alt + t
        -            TodoTxt.View.displayModalForTask();
        -        }
        -    },
        -
        -    handleDrop: function (e) {
        -        TodoTxt.View.handleFileSelect(e);
        -    },
        -
        -    handleAltEnter: function (e) {
        -        if ((e.keyCode && (e.keyCode === 13 && e.altKey)) || (e.type && e.type == "click")) { // Alt + Enter
        -            var taskId = document.querySelector("#modalEditTaskId-input").value;
        -            var text = document.querySelector("#modalEdit-textarea").textContent;
        -            text = TodoTxt.Utils.htmlUnencode(text);
        -            if (TodoTxt.updateTask(taskId, text)) {
        -                TodoTxt.View.refreshUi();
        -                try {
        -                    TodoTxt.View.removeModal();
        -                } catch (ex) {
        -                    // TODO: log this
        -                }
        -            } else {
        -                // TODO: display error toast
        -            }
        -        }
        -    },
        -
        -    handleEsc: function (e) {
        -        if (e.keyCode === 27 || e.keyCode === 0) { // Esc
        -            TodoTxt.View.closeModal();
        -        }
        -    },
        -
        -    handleDeleteClick: function () {
        -        var taskId = document.querySelector("#modalEditTaskId-input").value;
        -        var task = TodoTxt.getTask(taskId);
        -        if (task)
        -        {
        -            if (confirm(TodoTxt.Resources.get("DELETE_CONFIRM") + "\n\t\"" + task.toString() + "\"")) {
        -                if (TodoTxt.deleteTask(taskId)) {
        -                    TodoTxt.View.refreshUi();
        -                    try {
        -                        TodoTxt.View.removeModal();
        -                    } catch (e) {
        -                        // TODO: log this
        -                    }
        -                } else {
        -                    // TODO: display error toast
        -                }
        -            }
        -        }
        -    },
        -
        -    filterTimeoutId: null,
        -    handleFilter: function () {
        -        if (TodoTxt.View.filterTimoutId) {
        -            window.clearTimeout(TodoTxt.View.filterTimeoutId);
        -        }
        -        TodoTxt.View.filterTimeoutId = setTimeout(function () {
        -            // get the list of selected priorities from the filter
        -            TodoTxt.View.filterDisplayedTasks();
        -        }, 500);
        -    },
        -
        -    handleAltP: function (e) {
        -        if ((e.keyCode && (e.keyCode === 80 && e.altKey)) || (e.type && e.type == "click")) { // Alt + p
        -            // update the markup of the displayed task in the Modal
        -            TodoTxt.View.updateModalPreview();
        -        }
        -    },
        -
        -    /**
        -     * function will reload the list of tasks from localStorage to ensure it
        -     * is sorted and displaying properly
        -     */
        -    refreshUi: function () {
        -        if (TodoTxt.View.getShowClosedStatus()) {
        -            TodoTxt.View.setShowClosedActive();
        -        } else {
        -            TodoTxt.View.setShowClosedInactive();
        -        }
        -
        -        // unbind any event handling
        -        TodoTxt.View.unbindControlEvents(TodoTxt.View.mainEventHandlers);
        -
        -        // clear the list
        -        TodoTxt.View.clearTasks();
        -
        -        // clear the attributes
        -        TodoTxt.View.clearPriorities();
        -        TodoTxt.View.clearProjects();
        -        TodoTxt.View.clearContexts();
        -
        -        // clear filter input
        -        TodoTxt.View.clearFilters();
        -
        -        // now rebuild from localStorage
        -        TodoTxt.View.displayTasks();
        -
        -        // update the DOM with task attributes
        -        TodoTxt.View.displayPriorities();
        -        TodoTxt.View.displayProjects();
        -        TodoTxt.View.displayContexts();
        -
        -        // enable keyboard shortcuts and click events for the controls area
        -        TodoTxt.View.bindControlEvents(TodoTxt.View.mainEventHandlers);
        -    },
        -
        -    setFilters: function (filterStr) {
        -        if (filterStr) {
        -            // set filter text input
        -            var input = document.querySelector("#filter-input");
        -            input.value = filterStr;
        -            TodoTxt.View.handleFilter();
        -        }
        -    },
        -
        -    clearFilters: function () {
        -        // update filter input
        -        document.querySelector("#filter-input").value = "";
        -    },
        -
        -    clearTasks: function () {
        -        document.querySelector("#listContainer-div").innerHTML = "";
        -    },
        -
        -    filterDisplayedTasks: function () {
        -        TodoTxt.View.clearTasks();
        -
        -        // honors any specified filters
        -        TodoTxt.View.displayTasks();
        -    },
        -
        -    toggleShowClosedStatus: function () {
        -        var el = document.querySelector('#showClosed-label');
        -        var active = el.className.match(/(( |^)btn-success)/) ? true : false;
        -        // if active toggle to inactive
        -        if (active) {
        -            TodoTxt.View.setShowClosedInactive();
        -        } else {
        -            TodoTxt.View.setShowClosedActive();
        -        }
        -        TodoTxt.View.refreshUi();
        -    },
        -
        -    setShowClosedActive: function () {
        -        var el = document.querySelector('#showClosed-label');
        -        el.className = el.className.replace(/(( |^)btn-danger)/, " btn-success");
        -        localStorage.setItem(TodoTxt.View.namespace + "showClosed", true);
        -    },
        -
        -    setShowClosedInactive: function () {
        -        var el = document.querySelector('#showClosed-label');
        -        el.className = el.className.replace(/(( |^)btn-success)/, " btn-danger");
        -        localStorage.setItem(TodoTxt.View.namespace + "showClosed", false);
        -    },
        -
        -    getShowClosedStatus: function () {
        -        var showClosed = localStorage.getItem(TodoTxt.View.namespace + "showClosed");
        -        if (showClosed) {
        -            if (showClosed === "true") {
        -                return true;
        -            }
        -        }
        -        return false;
        -    },
        -
        -    togglePanel: function (name) {
        -        var heading = document.querySelector('#' + name + ' .panel-heading');
        -        var body = document.querySelector('#' + name + ' .panel-body');
        -        var hidden = body.className.match(/(( |^)collapse)/) ? true : false;
        -        if (hidden) {
        -            TodoTxt.View.showPanel(heading, body);
        -        } else {
        -            TodoTxt.View.hidePanel(heading, body);
        -        }
        -    },
        -
        -    showPanel: function (heading, body) {
        -        var indicator = heading.querySelector(".glyphicon");
        -        body.className = body.className.replace(/(( |^)collapse)/g, "");
        -        indicator.className = indicator.className.replace(/(( |^)glyphicon-chevron-down)/, " glyphicon-chevron-up");
        -    },
        -
        -    hidePanel: function (heading, body) {
        -        var indicator = heading.querySelector(".glyphicon");
        -        body.className += " collapse";
        -        indicator.className = indicator.className.replace(/(( |^)glyphicon-chevron-up)/, " glyphicon-chevron-down");
        -    },
        -
        -    toggleTaskStatus: function (taskId) {
        -        var task = TodoTxt.getTask(taskId);
        -        if (task) {
        -            if (task.isActive) {
        -                TodoTxt.closeTask(taskId);
        -            } else {
        -                TodoTxt.activateTask(taskId);
        -            }
        -            TodoTxt.View.refreshUi();
        -        }
        -    },
        -
        -    /**
        -     * function will retrieve the todo.txt file from the passed in
        -     * fileName.
        -     *
        -     * @param fileName the String name of the todo.txt file to be opened
        -     * file.
        -     * EX: "todo.txt"
        -     */
        -    getTodoTxtFile: function (fileName) {
        -        // load via AJAX call to local file system
        -        $.ajax({
        -            url: fileName,
        -            cache: false,
        -            //crossDomain: true,
        -            error: function(jqXHR, textStatus) {
        -                // TODO: display a proper error message
        -                alert(textStatus);
        -            },
        -            success: function(data) {
        -                // pass the response on to the next call
        -                (function () {
        -                    TodoTxt.parseTodoTxtFile(data);
        -                    TodoTxt.View.refreshUi();
        -                })();
        -            }
        -        });
        -    },
        -
        -    handleFileSelect: function (e) {
        -        e.stopPropagation();
        -        e.preventDefault();
        -
        -        var files = e.target.files || e.dataTransfer.files; // FileList object.
        -
        -        // files is a FileList of File objects.
        -        if (files.length > 0) {
        -            var f = files[0];
        -
        -            // process using a FileReader
        -            var reader = new FileReader();
        -
        -            // get the content as a String
        -            reader.onloadend = function (e) {
        -                if (confirm(TodoTxt.Resources.get("OVERWRITE_CONFIRM"))) {
        -                    TodoTxt.parseTodoTxtFile(e.target.result);
        -                    TodoTxt.View.refreshUi();
        -                }
        -            };
        -            reader.readAsText(f, "UTF-8");
        -        }
        -    },
        -
        -    handleDragOver: function (e) {
        -        e.stopPropagation();
        -        e.preventDefault();
        -        e.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy.
        -    },
        -
        -    /**
        -     * function will allow the user to download a copy of the todo.txt file
        -     */
        -    exportTodoTxtFile: function () {
        -        var taskArray = TodoTxt.getSortedTaskArray();
        -
        -        // create the output string to be written
        -        var content = taskArray.join("\n");
        -
        -        // set datatype to text/csv to initiate download prompt
        -        var data = encodeURI("data:text/csv;charset=utf-8," + content);
        -
        -        window.open(data);
        -    },
        -
        -    /**
        -     * function will generate a html-markup version of the task
        -     * @param {TodoTxt.Task} task - the task to generate for
        -     * @returns {string} the HTML marked up task text
        -     */
        -    taskToMarkupString: function (task) {
        -        var text = task.toString();
        -
        -        // make html compatible
        -        text = TodoTxt.Utils.htmlEncode(text);
        -
        -        // markup priority
        -        var priCls = TodoTxt.View.getDisplayClassForTask(task);
        -        text = text.replace(task.priority, "<span class=\"" + priCls + "\"><b>" + task.priority + "</b></span>");
        -
        -        // markup projects
        -        var projects = task.projects;
        -        for (var i=0; i<projects.length; i++) {
        -            var project = projects[i];
        -            var regex = new RegExp(project.replace(/\+/g, "\\+") + "(?![0-9A-Za-z])", "g");
        -            text = text.replace(regex, "<span class=\"text-muted\"><b><i>" + project + "</i></b></span>");
        -        }
        -
        -        // markup contexts
        -        var contexts = task.contexts;
        -        for (var j=0; j<contexts.length; j++) {
        -            var context = contexts[j];
        -            var regex = new RegExp(context + "(?![0-9A-Za-z])", "g");
        -            text = text.replace(regex, "<span class=\"text-muted\"><b><i>" + context + "</i></b></span>");
        -        }
        -
        -        // markup created date
        -        var date = task.createdDate;
        -        if (date) {
        -            text = text.replace(date, "<span class=\"text-muted hidden-xs\"><b><i>" + date + "</i></b></span>");
        -        }
        -
        -        return text;
        -    },
        -
        -    /**
        -     * function returns the appropriate display classes for this task
        -     */
        -    getDisplayClassForTask: function (task) {
        -        // get a list of the current tasks and iterate through
        -        var cls = "";
        -        if (task.priority !== null && task.isActive) {
        -            if (task.priority === "(A)") {
        -                cls += " text-danger";
        -            }
        -            if (task.priority === "(B)") {
        -                cls += " text-warning";
        -            }
        -            if (task.priority === "(C)") {
        -                cls += " text-primary";
        -            }
        -        }
        -
        -        return cls;
        -    },
        -
        -    /** @ignore */
        -    initializeElements: function () {
        -        /*jshint multistr: true */
        -        var baseElements = ' \
        -<div class="container-fluid" id="fileDrop-div"> \
        -    <div class="col-md-9"> \
        -        <div class="row"> \
        -            <div class="btn-group btn-group-justified"> \
        -                <a class="btn btn-block btn-primary btn-lg btn-file ellipsis" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("IMPORT") + '"> \
        -                    <span class="glyphicon glyphicon-open"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("IMPORT") + '</span> <input id="fileUpload-input" type="file" placeholder="Select todo.txt File"> \
        -                </a> \
        -                <a id="addTaskButton-button" class="btn btn-lg btn-primary ellipsis" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("ADD_TASK") + '"> \
        -                    <span class="glyphicon glyphicon-plus"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("ADD_TASK") + '</span> \
        -                </a> \
        -                <a id="saveFileButton-button" class="btn btn-lg btn-primary ellipsis" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("EXPORT") + '"> \
        -                    <span class="glyphicon glyphicon-save"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("EXPORT") + '</span> \
        -                </a> \
        -                <a id="showClosed-label" class="btn btn-lg btn-danger ellipsis" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("SHOW_CLOSED") + '"> \
        -                    <span class="glyphicon glyphicon-ok-circle"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("SHOW_CLOSED") + '</span> \
        -                </a> \
        -            </div> \
        -        </div> \
        -        <div class="row"> \
        -            <div class="input-group input-group-lg"> \
        -                <input id="filter-input" type="text" class="form-control" placeholder="' + TodoTxt.Resources.get("FILTER_PLACEHOLDER_TEXT") + '"> \
        -                <span class="input-group-btn"> \
        -                    <button id="clearFilter-button" class="btn btn-primary" type="button" data-toggle="tooltip" data-placement="top" text="' + TodoTxt.Resources.get("CLEAR_FILTER") + '"><span class="glyphicon glyphicon-remove-circle"></span> <span class="hidden-xs">' + TodoTxt.Resources.get("CLEAR_FILTER") + '</span></button> \
        -                </span> \
        -            </div> \
        -        </div> \
        -        <div class="row"> \
        -            <div id="listContainer-div"></div> \
        -        </div> \
        -    </div> \
        -    <div class="col-md-3"> \
        -        <div id="priorities-div" class="panel panel-primary"> \
        -            <div class="panel-heading"> \
        -                <h3 class="panel-title"><span class="glyphicon glyphicon-chevron-up" aria-hidden="true"></span> ' + TodoTxt.Resources.get("PRIORITIES") + '</h3> \
        -            </div> \
        -            <div class="panel-body"> \
        -                <ul id="priorities-ul" class="list-group"></ul> \
        -            </div> \
        -        </div> \
        -        <div id="projects-div" class="panel panel-primary"> \
        -            <div class="panel-heading"> \
        -                <h3 class="panel-title"><span class="glyphicon glyphicon-chevron-up" aria-hidden="true"></span> ' + TodoTxt.Resources.get("PROJECTS") + '</h3> \
        -            </div> \
        -            <div class="panel-body"> \
        -                <ul id="projects-ul" class="list-group"></ul> \
        -            </div> \
        -        </div> \
        -        <div id="contexts-div" class="panel panel-primary"> \
        -            <div class="panel-heading"> \
        -                <h3 class="panel-title"><span class="glyphicon glyphicon-chevron-up" aria-hidden="true"></span> ' + TodoTxt.Resources.get("CONTEXTS") + '</h3> \
        -            </div> \
        -            <div class="panel-body"> \
        -                <ul id="contexts-ul" class="list-group"></ul> \
        -            </div> \
        -        </div> \
        -    </div> \
        -</div>';
        -
        -        var container = document.getElementById('todotxt');
        -        if (container) {
        -            container.innerHTML = baseElements;
        -        }
        -    },
        -};
        -
        -
        -
        - - - - -
        - - - -
        - -
        - Documentation generated by JSDoc 3.2.2 on Wed Jan 10 2018 15:03:40 GMT-0000 (GMT) -
        - - - - - diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..509db18 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/src/helpers/file-drop-event.d.ts b/dist/src/helpers/file-drop-event.d.ts new file mode 100644 index 0000000..8ef08b6 --- /dev/null +++ b/dist/src/helpers/file-drop-event.d.ts @@ -0,0 +1,3 @@ +export interface FileDropEvent extends Event { + dataTransfer: DataTransfer; +} diff --git a/dist/src/helpers/todo-txt-utils.d.ts b/dist/src/helpers/todo-txt-utils.d.ts new file mode 100644 index 0000000..16d2ff4 --- /dev/null +++ b/dist/src/helpers/todo-txt-utils.d.ts @@ -0,0 +1,69 @@ +/********************************************************************** + * This javascript was created according to the specifications at + * http://todotxt.com/ and is intended to allow users to access their + * todo.txt files in a user-friendly and easy to visualize manner. + * + * Once initially uploaded, the todo.txt file will + * be loaded into an HTML5 localStorage and managed from there. + * The web page then allows downloading changes back to the user + * in a txt format compliant with the todo.txt specifications, but + * having re-sorted the tasks. + * + * @Created: 08/14/2012 + * @Author: Jason Holt Smith (bicarbon8@gmail.com) + * @Version: 0.0.1 + * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under + * the terms of the GNU General Public License. + * + * This file is part of todoTxtWebUi. + * + * todoTxtWebUi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * todoTxtWebUi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with todoTxtWebUi. If not, see . + **********************************************************************/ +/** + * Utility methods used by the project library + * @namespace + */ +export declare module TodoTxtUtils { + /** + * function will format a Date object to a string of YYYY-MM-DD + * @returns {string} formatted date + */ + function formatDate(dateObj: Date): string; + /** + * function will get the current browser language-locale + * @returns {string} a ISO language-locale for the browser + */ + function getLanguage(): string; + /** + * function generates a GUID + * @returns {string} a GUID (NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN) + */ + function guid(): string; + /** + * function will strip out any characters from the passed in string that are + * not compatible with html and replace with html-friendly versions + * @param {string} str - the string to be html encoded + * @returns {string} a html encoded version of the string that can be used safely + * within a html page + */ + function htmlEncode(str: string): string; + /** + * function will strip out any characters from the passed in string that are + * html character entities and replace with standard string versions + * @param {string} str - the string to be html unencoded + * @returns {string} a version of the string that can contains non-html-friendly + * strings + */ + function htmlUnencode(str: string): string; +} diff --git a/tests/qunit/allTests.html b/dist/src/storage/todo-txt-cache.d.ts similarity index 64% rename from tests/qunit/allTests.html rename to dist/src/storage/todo-txt-cache.d.ts index c317e83..0a2779e 100644 --- a/tests/qunit/allTests.html +++ b/dist/src/storage/todo-txt-cache.d.ts @@ -1,54 +1,44 @@ - - - - - -TodoTxtWebUi Tests - - - - -
        -
        - - - - - - - - - +/********************************************************************** + * This javascript was created according to the specifications at + * http://todotxt.com/ and is intended to allow users to access their + * todo.txt files in a user-friendly and easy to visualize manner. + * + * Once initially uploaded, the todo.txt file will + * be loaded into an HTML5 localStorage and managed from there. + * The web page then allows downloading changes back to the user + * in a txt format compliant with the todo.txt specifications, but + * having re-sorted the tasks. + * + * @Created: 08/14/2012 + * @Author: Jason Holt Smith (bicarbon8@gmail.com) + * @Version: 0.0.1 + * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under + * the terms of the GNU General Public License. + * + * This file is part of todoTxtWebUi. + * + * todoTxtWebUi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * todoTxtWebUi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with todoTxtWebUi. If not, see . + **********************************************************************/ +import { TodoTxtConfig } from "./todo-txt-config"; +import { TodoTxtTask } from "../tasks/todo-txt-task"; +export declare class TodoTextPersistance { + tasks: TaskItem[]; + config: TodoTxtConfig; + constructor(tasks?: Map, config?: TodoTxtConfig); +} +interface TaskItem { + id: string; + text: string; +} +export {}; diff --git a/dist/src/storage/todo-txt-config.d.ts b/dist/src/storage/todo-txt-config.d.ts new file mode 100644 index 0000000..58b8331 --- /dev/null +++ b/dist/src/storage/todo-txt-config.d.ts @@ -0,0 +1,35 @@ +/********************************************************************** + * This javascript was created according to the specifications at + * http://todotxt.com/ and is intended to allow users to access their + * todo.txt files in a user-friendly and easy to visualize manner. + * + * Once initially uploaded, the todo.txt file will + * be loaded into an HTML5 localStorage and managed from there. + * The web page then allows downloading changes back to the user + * in a txt format compliant with the todo.txt specifications, but + * having re-sorted the tasks. + * + * @Created: 08/14/2012 + * @Author: Jason Holt Smith (bicarbon8@gmail.com) + * @Version: 0.0.1 + * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under + * the terms of the GNU General Public License. + * + * This file is part of todoTxtWebUi. + * + * todoTxtWebUi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * todoTxtWebUi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with todoTxtWebUi. If not, see . + **********************************************************************/ +export interface TodoTxtConfig { + showClosed: boolean; +} diff --git a/dist/src/storage/todo-txt-vault.d.ts b/dist/src/storage/todo-txt-vault.d.ts new file mode 100644 index 0000000..51d5c1e --- /dev/null +++ b/dist/src/storage/todo-txt-vault.d.ts @@ -0,0 +1,48 @@ +/********************************************************************** + * This javascript was created according to the specifications at + * http://todotxt.com/ and is intended to allow users to access their + * todo.txt files in a user-friendly and easy to visualize manner. + * + * Once initially uploaded, the todo.txt file will + * be loaded into an HTML5 localStorage and managed from there. + * The web page then allows downloading changes back to the user + * in a txt format compliant with the todo.txt specifications, but + * having re-sorted the tasks. + * + * @Created: 08/14/2012 + * @Author: Jason Holt Smith (bicarbon8@gmail.com) + * @Version: 0.0.1 + * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under + * the terms of the GNU General Public License. + * + * This file is part of todoTxtWebUi. + * + * todoTxtWebUi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * todoTxtWebUi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with todoTxtWebUi. If not, see . + **********************************************************************/ +import { TodoTxtTask } from "../tasks/todo-txt-task"; +import { TodoTxtConfig } from "./todo-txt-config"; +export declare module TodoTxtVault { + function addTask(task: TodoTxtTask): void; + function removeTask(taskId: string): boolean; + function removeAllTasks(): void; + function getTask(taskId: string): TodoTxtTask; + function getAllTasks(): TodoTxtTask[]; + function getConfig(): TodoTxtConfig; + function setConfig(cfg: TodoTxtConfig): void; + /** + * WARNING!! removes all cached data including tasks and configuration. + * only to be used after you've exported your tasks to a file + */ + function _clear(): void; +} diff --git a/dist/src/tasks/todo-txt-attributes.d.ts b/dist/src/tasks/todo-txt-attributes.d.ts new file mode 100644 index 0000000..d35441d --- /dev/null +++ b/dist/src/tasks/todo-txt-attributes.d.ts @@ -0,0 +1,38 @@ +/********************************************************************** + * This javascript was created according to the specifications at + * http://todotxt.com/ and is intended to allow users to access their + * todo.txt files in a user-friendly and easy to visualize manner. + * + * Once initially uploaded, the todo.txt file will + * be loaded into an HTML5 localStorage and managed from there. + * The web page then allows downloading changes back to the user + * in a txt format compliant with the todo.txt specifications, but + * having re-sorted the tasks. + * + * @Created: 08/14/2012 + * @Author: Jason Holt Smith (bicarbon8@gmail.com) + * @Version: 0.0.1 + * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under + * the terms of the GNU General Public License. + * + * This file is part of todoTxtWebUi. + * + * todoTxtWebUi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * todoTxtWebUi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with todoTxtWebUi. If not, see . + **********************************************************************/ +export declare module TodoTxtAttributes { + var priorities: Set; + var projects: Set; + var contexts: Set; + function reset(): void; +} diff --git a/dist/src/tasks/todo-txt-task.d.ts b/dist/src/tasks/todo-txt-task.d.ts new file mode 100644 index 0000000..797c7cc --- /dev/null +++ b/dist/src/tasks/todo-txt-task.d.ts @@ -0,0 +1,20 @@ +export declare class TodoTxtTask { + id: string; + priority: string; + createdDate: string; + completedDate: string; + projects: string[]; + contexts: string[]; + metadatas: string[]; + isActive: boolean; + text: string; + constructor(text?: string); + parseInput(input: string): void; + private parseStatus; + private parsePriority; + private parseCompletedDate; + private parseCreatedDate; + private getDatesFromText; + private parseProjects; + private parseContexts; +} diff --git a/dist/src/todo-txt.d.ts b/dist/src/todo-txt.d.ts new file mode 100644 index 0000000..d6607e7 --- /dev/null +++ b/dist/src/todo-txt.d.ts @@ -0,0 +1,67 @@ +import { TodoTxtTask } from './tasks/todo-txt-task'; +export declare module TodoTxt { + /** + * function will return a sorted array of tasks as pulled from + * localStorage. + * @returns {array} a sorted list of tasks from localStorage + */ + function getSortedTaskArray(): TodoTxtTask[]; + /** + * function will return a filtered array of tasks based on the passed in + * filter string. Matching uses an ordered fuzzy match so for the following: + * "(A) 2014-03-02 don't forget to file @report with +John" a passed in filter + * string of "for John" will match, but "John report" will not match + * @param {string} filterStr - a string containing characters to match against the existing tasks + * @returns {array} a sorted list of tasks matching the passed in filterStr + */ + function getFilteredTaskArray(filterStr: string): TodoTxtTask[]; + /** + * function will process each line of the todo.txt, sort by priority, + * creationDate, and state (active or closed). + * + * @param {string} todoTxt - the "\n" delimited lines from a todo.txt file + * @param {boolean} append - a boolean indicating if existing tasks should be cleared + * first or just appended to with the new file + */ + function parseTodoTxtFile(todoTxt: string, append?: boolean): void; + /** + * function creates a new task and saves to {TodoTxtVault} + * @param {string} textStr - a string representing a raw task + * @returns {string} the ID of the newly created {TodoTxt.Task} + */ + function createTask(textStr: string): string; + /** + * function will get a specified task from TodoTxtVault by id + * @param {string} taskId - the unique id of the task to be returned + * @returns {TodoTxtTask} a task or null if task not found + */ + function getTask(taskId: string): TodoTxtTask; + /** + * function updates the task and saves it to the TodoTxtVault cache + * @param {string} taskId - unique ID used to retrieve the task from Storage + * @param {string} newText - a string representing the updated, raw task text + * @returns {boolean} true if task could be updated otherwise false + */ + function updateTask(taskId: string, newText: string): boolean; + /** + * function adds this task to the browser's local cache allowing for + * retained data on subsequent reloads of the page + * @param {TodoTxtTask} task - a task to be added to Storage + */ + function addTask(task: TodoTxtTask): void; + /** + * function will append an "x YYYY-MM-DD " to a stored + * task if not already closed and will remove any priority + * declarations in the text of the Task + * @param {string} taskId - unique ID used to retrieve the task from Storage + * @returns {boolean} true if task could be closed, otherwise false + */ + function closeTask(taskId: string): boolean; + /** + * function will remove "x YYYY-MM-DD " from a stored + * task if not already active + * @param {string} taskId - unique ID used to retrieve the task from Storage + * @returns {boolean} true if task could be activated, otherwise false + */ + function activateTask(taskId: string): boolean; +} diff --git a/dist/src/ui/todo-txt-resources.d.ts b/dist/src/ui/todo-txt-resources.d.ts new file mode 100644 index 0000000..0338239 --- /dev/null +++ b/dist/src/ui/todo-txt-resources.d.ts @@ -0,0 +1,4 @@ +export declare module TodoTxtResources { + function register(langLocale: string, resourceObj: any): void; + function get(key: string): string; +} diff --git a/dist/src/ui/todo-txt-view.d.ts b/dist/src/ui/todo-txt-view.d.ts new file mode 100644 index 0000000..9f825d6 --- /dev/null +++ b/dist/src/ui/todo-txt-view.d.ts @@ -0,0 +1,120 @@ +/********************************************************************** + * This javascript was created according to the specifications at + * http://todotxt.com/ and is intended to allow users to access their + * todo.txt files in a user-friendly and easy to visualize manner. + * + * Once initially uploaded, the todo.txt file will + * be loaded into an HTML5 localStorage and managed from there. + * The web page then allows downloading changes back to the user + * in a txt format compliant with the todo.txt specifications, but + * having re-sorted the tasks. + * + * @Created: 08/14/2012 + * @Author: Jason Holt Smith (bicarbon8@gmail.com) + * @Version: 0.0.1 + * Copyright (c) 2012 Jason Holt Smith. todoTxtWebUi is distributed under + * the terms of the GNU General Public License. + * + * This file is part of todoTxtWebUi. + * + * todoTxtWebUi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * todoTxtWebUi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with todoTxtWebUi. If not, see . + **********************************************************************/ +import { TodoTxtTask } from "../tasks/todo-txt-task"; +import { FileDropEvent } from "../helpers/file-drop-event"; +export declare module TodoTxtView { + /** + * function generates the DOM element for the passed in task + * @param {TodoTxtTask} task - the task object to be converted to HTMLDivElement + * @returns a {HTMLDivElement} from the passed in {Task} + */ + function generateTaskElement(task: TodoTxtTask): HTMLDivElement; + function generateListElement(text: string): HTMLLIElement; + /** + * function will attempt to get all tasks and display them + * in the DOM if any exist. This will add to any existing tasks so you + * will need to clear the DOM first if you want to update the entire list + * instead of just appending to the list. + */ + function displayTasks(): void; + function displayTask(task: TodoTxtTask): void; + function removeTask(taskId: string): void; + /** + * function opens the specified task in an editing window + */ + function displayModalForTask(taskId?: string): void; + function updateModalPreview(): void; + function removeModal(): void; + const modalEventHandlers: any[]; + function displayPriorities(): void; + function clearPriorities(): void; + function displayProjects(): void; + function clearProjects(): void; + function displayContexts(): void; + function clearContexts(): void; + const mainEventHandlers: any[]; + function bindControlEvents(handlers: any[]): void; + function unbindControlEvents(handlers: any[]): void; + function handleAltS(e: KeyboardEvent): void; + function handleAltC(e: KeyboardEvent): void; + function handleAltT(e: KeyboardEvent): void; + function handleDrop(e: FileDropEvent): void; + function handleAltEnter(e: KeyboardEvent): void; + function handleEsc(e: KeyboardEvent): void; + function handleDeleteClick(): void; + function handleFilter(): void; + function handleAltP(e: KeyboardEvent): void; + /** + * function will reload the list of tasks from Storage to ensure it + * is sorted and displaying properly + */ + function refreshUi(): void; + function setFilters(filterStr: string): void; + function clearFilters(): void; + function clearTasks(): void; + function filterDisplayedTasks(): void; + function toggleShowClosedStatus(): void; + function setShowClosed(active: boolean): void; + function togglePanel(name: string): void; + function showPanel(heading: HTMLElement, body: HTMLElement): void; + function hidePanel(heading: HTMLElement, body: HTMLElement): void; + function toggleTaskStatus(taskId: string): void; + /** + * function will retrieve the todo.txt file from the passed in + * fileName. + * + * @param fileName the String name of the todo.txt file to be opened + * file. + * EX: "todo.txt" + */ + function getTodoTxtFile(fileName: string): Promise; + function handleFileSelect(e: FileDropEvent): void; + function handleDragOver(e: DragEvent): void; + /** + * function will allow the user to download a copy of the todo.txt file + */ + function exportTodoTxtFile(): void; + /** + * function will generate a html-markup version of the task + * @param {TodoTxtTask} task - the task to generate for + * @returns {string} the HTML marked up task text + */ + function getMarkupForTask(task: TodoTxtTask): string; + /** + * function returns the appropriate display classes for this task + * + * @returns {string} the priority based class to apply to a Task element + */ + function getDisplayClassForTask(task: TodoTxtTask): string; + function initializeElements(): void; +} diff --git a/dist/test/storage/todo-txt-vault-spec.d.ts b/dist/test/storage/todo-txt-vault-spec.d.ts new file mode 100644 index 0000000..509db18 --- /dev/null +++ b/dist/test/storage/todo-txt-vault-spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/test/tasks/todo-txt-task-spec.d.ts b/dist/test/tasks/todo-txt-task-spec.d.ts new file mode 100644 index 0000000..509db18 --- /dev/null +++ b/dist/test/tasks/todo-txt-task-spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/test/test-helper.d.ts b/dist/test/test-helper.d.ts new file mode 100644 index 0000000..1443868 --- /dev/null +++ b/dist/test/test-helper.d.ts @@ -0,0 +1,2 @@ +export declare function wait(ms: number): Promise; +export declare function waitUntil(returnsTrueEventually: Function, maxMs?: number): Promise; diff --git a/dist/test/todo-txt-spec.d.ts b/dist/test/todo-txt-spec.d.ts new file mode 100644 index 0000000..509db18 --- /dev/null +++ b/dist/test/todo-txt-spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/test/ui/todo-txt-view-spec.d.ts b/dist/test/ui/todo-txt-view-spec.d.ts new file mode 100644 index 0000000..509db18 --- /dev/null +++ b/dist/test/ui/todo-txt-view-spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/todoTxt.min.css b/dist/todoTxt.min.css deleted file mode 100644 index b759101..0000000 --- a/dist/todoTxt.min.css +++ /dev/null @@ -1 +0,0 @@ -@media (max-width:800px){.container,.modal-dialog,.panel-body,.row,[class*=col-md-],body{padding:0;margin:0}[class*=col-md-]{margin-bottom:20px}.container .btn{margin-bottom:0}}@media (min-width:801px){.container .btn{margin-bottom:20px}}.btn-file{position:relative;overflow:hidden}.btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;outline:0;background:#fff;cursor:inherit;display:block}.list-group{margin-bottom:0}.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-group button{text-align:left}#listContainer-div{margin-bottom:20px}.panel-body button{width:100%}.textarea{border:2px dashed;border-radius:4px;padding:5px} \ No newline at end of file diff --git a/dist/todoTxt.min.js b/dist/todoTxt.min.js deleted file mode 100644 index aeccd84..0000000 --- a/dist/todoTxt.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! todoTxtWebUi v1.0.2, created by: Jason Holt Smith 2018-01-10 15:03:33 */ -var TodoTxt={namespace:"TodoTxt.",Attributes:{priorities:{},projects:{},contexts:{}},getSortedTaskArray:function(){var a=[],b=new RegExp("^("+(new TodoTxt.Task).namespace+")");TodoTxt._clearAttributes();for(var c in localStorage)if(c.match(b)){var d=TodoTxt.getTask(c);d&&(d.id=c,a.push(d),TodoTxt._updateAttributes(d))}return a.sort(TodoTxt._compareTasks),a},getFilteredTaskArray:function(a){var b=TodoTxt.getSortedTaskArray();if(a&&""!==a){for(var c=a.split(" "),d=".*",e=0;ef)return 1}else{if(g!==h)return gj?-1:1}return 0}},TodoTxt=TodoTxt||{};TodoTxt.Utils={formatDate:function(a){var b=a.getFullYear(),c=(a.getMonth()+1).toString();c=c.length<2?"0"+c:c;var d=a.getDate().toString();return d=d.length<2?"0"+d:d,String(b+"-"+c+"-"+d)},getLanguage:function(){return(window.navigator.userLanguage||window.navigator.language).toLowerCase()},guid:function(){function a(){return Math.floor(65536*(1+Math.random())).toString(16).substring(1)}return a()+a()+"-"+a()+"-"+a()+"-"+a()+"-"+a()+a()+a()},htmlEncode:function(a){return String(a).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/\s{2}/g,"  ")},htmlUnencode:function(a){return String(a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/ /g," ")}};var TodoTxt=TodoTxt||{};TodoTxt.Task=function(a){this.namespace=TodoTxt.namespace+"Task.",this.id=this.namespace+TodoTxt.Utils.guid(),this.priority=null,this.createdDate=null,this.completedDate=null,this.projects=[],this.contexts=[],this.metadatas=[],this.isActive=!0,this.text="",a&&this._parseFromString(a)},TodoTxt.Task.prototype._parseFromString=function(a){if("string"!=typeof a)throw"cannot parse input of type: "+typeof a+". only strings are accepted.";this.text=a,this._parseStatusFromString(a),this._parsePriorityFromString(a),this._parseCompletedDateFromString(a),this._parseCreatedDateFromString(a),this._parseProjectsFromString(a),this._parseContextsFromString(a)},TodoTxt.Task.prototype._parseStatusFromString=function(a){a&&a.match(/^(x )/)?this.isActive=!1:this.isActive=!0},TodoTxt.Task.prototype._parsePriorityFromString=function(a){var b=null;if(a){var c=/^(\([A-Z]\)[\s]+)/,d=a.match(c);d&&(b=d[0].replace(/[\s]*/g,""))}this.priority=b},TodoTxt.Task.prototype._parseCompletedDateFromString=function(a){var b=null;if(a&&!this.isActive){var c=this._parseDatesFromString(a);c&&(b=c[0].replace(/[\s]*/g,""))}this.completedDate=b},TodoTxt.Task.prototype._parseCreatedDateFromString=function(a){var b=null;if(a){var c=this._parseDatesFromString(a);c&&(this.isActive?b=c[0].replace(/[\s]*/g,""):c.length>1&&(b=c[1].replace(/[\s]*/g,"")))}this.createdDate=b},TodoTxt.Task.prototype._parseDatesFromString=function(a){var b=null;if(a){var c=/(?:\s|^)(\d{4}-\d{2}-\d{2})(?=\s)/g;match=a.match(c),match&&(b=match)}return b},TodoTxt.Task.prototype._parseProjectsFromString=function(a){var b=[];if(a){var c=/((\s|^)[\(\{\["']?\+[0-9A-Za-z]+[\)\}\]"']?(?=\s|$))/g,d=a.match(c);if(d){for(var e={},f=0;f ";return e.innerHTML=f,e},generateListElement:function(a){var b=document.createElement("li");return b.id=TodoTxt.View.namespace+a,b.className="list-group-item",b.onclick=function(b){TodoTxt.View.setFilters(a)},b.onmouseover=function(a){b.className+=" active"},b.onmouseout=function(a){b.className=b.className.replace(/(( |^)active)/,"")},b.innerHTML='

        '+a+"

        ",b},displayTasks:function(){var a=document.querySelector("#filter-input").value,b=TodoTxt.getFilteredTaskArray(a);if(!TodoTxt.View.getShowClosedStatus()){b=b.filter(function(a){return a.isActive})}b&&b.length>0&&b.forEach(function(a){TodoTxt.View.displayTask(a)})},displayTask:function(a){document.querySelector("#listContainer-div").appendChild(TodoTxt.View.generateTaskElement(a))},removeTask:function(a){document.querySelector("#listContainer-div").removeChild(document.querySelector("#"+a))},displayModalForTask:function(a){var b=TodoTxt.getTask(a)||new TodoTxt.Task;TodoTxt.View.unbindControlEvents(TodoTxt.View.mainEventHandlers);var c=TodoTxt.View.taskToMarkupString(b).replace(/hidden-xs/,""),d=' ";document.body.innerHTML+=d,$("#modalEdit-div").modal("show"),TodoTxt.View.bindControlEvents(TodoTxt.View.modalEventHandlers),document.querySelector("#modalEdit-textarea").focus()},updateModalPreview:function(){var a=document.querySelector("#modalEdit-textarea");if(a){var b=a.textContent,c=new TodoTxt.Task(b);a.innerHTML=TodoTxt.View.taskToMarkupString(c)}},closeModal:function(){TodoTxt.View.removeModal(),TodoTxt.View.refreshUi()},modalEventHandlers:[{el:function(){return document},ev:"keydown",fn:function(a){TodoTxt.View.handleAltEnter(a)}},{el:function(){return document},ev:"keydown",fn:function(a){TodoTxt.View.handleEsc(a)}},{el:function(){return document},ev:"keydown",fn:function(a){TodoTxt.View.handleAltP(a)}},{el:function(){return document.querySelector("#modalEditSave-button")},ev:"click",fn:function(a){TodoTxt.View.handleAltEnter(a)}},{el:function(){return document.querySelector("#modalEditClose-button")},ev:"click",fn:function(a){TodoTxt.View.closeModal()}},{el:function(){return document.querySelector("#modalEditDelete-button")},ev:"click",fn:function(a){TodoTxt.View.handleDeleteClick(a)}},{el:function(){return document.querySelector("#modalEditPreview-button")},ev:"click",fn:function(a){TodoTxt.View.handleAltP(a)}}],removeModal:function(){$("#modalEdit-div").modal("hide"),TodoTxt.View.unbindControlEvents(TodoTxt.View.modalEventHandlers);var a=document.querySelector("#modalEdit-div");document.body.removeChild(a),TodoTxt.View.bindControlEvents(TodoTxt.View.mainEventHandlers)},displayPriorities:function(){var a=document.querySelector("#priorities-ul");for(var b in TodoTxt.Attributes.priorities){var c=b;if(TodoTxt.Attributes.priorities[b]||TodoTxt.View.getShowClosedStatus()){var d=TodoTxt.View.generateListElement(c);a.appendChild(d)}}},clearPriorities:function(){document.querySelector("#priorities-ul").innerHTML=""},displayProjects:function(){var a=document.querySelector("#projects-ul");for(var b in TodoTxt.Attributes.projects){var c=b;if(TodoTxt.Attributes.projects[b]||TodoTxt.View.getShowClosedStatus()){var d=TodoTxt.View.generateListElement(c);a.appendChild(d)}}},clearProjects:function(){document.querySelector("#projects-ul").innerHTML=""},displayContexts:function(){var a=document.querySelector("#contexts-ul");for(var b in TodoTxt.Attributes.contexts){var c=b;if(TodoTxt.Attributes.contexts[b]||TodoTxt.View.getShowClosedStatus()){var d=TodoTxt.View.generateListElement(c);a.appendChild(d)}}},clearContexts:function(){document.querySelector("#contexts-ul").innerHTML=""},mainEventHandlers:[{el:function(){return document},ev:"keydown",fn:function(a){TodoTxt.View.handleAltS(a)}},{el:function(){return document},ev:"keydown",fn:function(a){TodoTxt.View.handleAltC(a)}},{el:function(){return document},ev:"keydown",fn:function(a){TodoTxt.View.handleAltT(a)}},{el:function(){return document.querySelector("#fileDrop-div")},ev:"dragover",fn:function(a){TodoTxt.View.handleDragOver(a)}},{el:function(){return document.querySelector("#fileDrop-div")},ev:"drop",fn:function(a){TodoTxt.View.handleDrop(a)}},{el:function(){return document.querySelector("#fileUpload-input")},ev:"change",fn:function(a){TodoTxt.View.handleDrop(a)}},{el:function(){return document.querySelector("#showClosed-label")},ev:"click",fn:function(a){TodoTxt.View.toggleShowClosedStatus()}},{el:function(){return document.querySelector("#addTaskButton-button")},ev:"click",fn:function(a){TodoTxt.View.displayModalForTask()}},{el:function(){return document.querySelector("#saveFileButton-button")},ev:"click",fn:function(a){TodoTxt.View.exportTodoTxtFile()}},{el:function(){return document.querySelector("#filter-input")},ev:"keyup",fn:function(a){TodoTxt.View.handleFilter()}},{el:function(){return document.querySelector("#clearFilter-button")},ev:"click",fn:function(a){TodoTxt.View.refreshUi()}},{el:function(){return document.querySelector("#priorities-div .panel-heading")},ev:"click",fn:function(a){TodoTxt.View.togglePanel("priorities-div")}},{el:function(){return document.querySelector("#projects-div .panel-heading")},ev:"click",fn:function(a){TodoTxt.View.togglePanel("projects-div")}},{el:function(){return document.querySelector("#contexts-div .panel-heading")},ev:"click",fn:function(a){TodoTxt.View.togglePanel("contexts-div")}}],bindControlEvents:function(a){a.forEach(function(a){var b=!1;a.uc&&(b=a.uc);try{a.el().addEventListener(a.ev,a.fn,b)}catch(a){}})},unbindControlEvents:function(a){a.forEach(function(a){var b=!1;a.uc&&(b=a.uc);try{a.el().removeEventListener(a.ev,a.fn,b)}catch(a){}})},handleAltS:function(a){83==a.keyCode&&a.altKey&&TodoTxt.View.exportTodoTxtFile()},handleAltC:function(a){67==a.keyCode&&a.altKey&&TodoTxt.View.refreshUi()},handleAltT:function(a){84==a.keyCode&&a.altKey&&TodoTxt.View.displayModalForTask()},handleDrop:function(a){TodoTxt.View.handleFileSelect(a)},handleAltEnter:function(a){if(a.keyCode&&13===a.keyCode&&a.altKey||a.type&&"click"==a.type){var b=document.querySelector("#modalEditTaskId-input").value,c=document.querySelector("#modalEdit-textarea").textContent;if(c=TodoTxt.Utils.htmlUnencode(c),TodoTxt.updateTask(b,c)){TodoTxt.View.refreshUi();try{TodoTxt.View.removeModal()}catch(a){}}}},handleEsc:function(a){27!==a.keyCode&&0!==a.keyCode||TodoTxt.View.closeModal()},handleDeleteClick:function(){var a=document.querySelector("#modalEditTaskId-input").value,b=TodoTxt.getTask(a);if(b&&confirm(TodoTxt.Resources.get("DELETE_CONFIRM")+'\n\t"'+b.toString()+'"')&&TodoTxt.deleteTask(a)){TodoTxt.View.refreshUi();try{TodoTxt.View.removeModal()}catch(a){}}},filterTimeoutId:null,handleFilter:function(){TodoTxt.View.filterTimoutId&&window.clearTimeout(TodoTxt.View.filterTimeoutId),TodoTxt.View.filterTimeoutId=setTimeout(function(){TodoTxt.View.filterDisplayedTasks()},500)},handleAltP:function(a){(a.keyCode&&80===a.keyCode&&a.altKey||a.type&&"click"==a.type)&&TodoTxt.View.updateModalPreview()},refreshUi:function(){TodoTxt.View.getShowClosedStatus()?TodoTxt.View.setShowClosedActive():TodoTxt.View.setShowClosedInactive(),TodoTxt.View.unbindControlEvents(TodoTxt.View.mainEventHandlers),TodoTxt.View.clearTasks(),TodoTxt.View.clearPriorities(),TodoTxt.View.clearProjects(),TodoTxt.View.clearContexts(),TodoTxt.View.clearFilters(),TodoTxt.View.displayTasks(),TodoTxt.View.displayPriorities(),TodoTxt.View.displayProjects(),TodoTxt.View.displayContexts(),TodoTxt.View.bindControlEvents(TodoTxt.View.mainEventHandlers)},setFilters:function(a){if(a){document.querySelector("#filter-input").value=a,TodoTxt.View.handleFilter()}},clearFilters:function(){document.querySelector("#filter-input").value=""},clearTasks:function(){document.querySelector("#listContainer-div").innerHTML=""},filterDisplayedTasks:function(){TodoTxt.View.clearTasks(),TodoTxt.View.displayTasks()},toggleShowClosedStatus:function(){document.querySelector("#showClosed-label").className.match(/(( |^)btn-success)/)?TodoTxt.View.setShowClosedInactive():TodoTxt.View.setShowClosedActive(),TodoTxt.View.refreshUi()},setShowClosedActive:function(){var a=document.querySelector("#showClosed-label");a.className=a.className.replace(/(( |^)btn-danger)/," btn-success"),localStorage.setItem(TodoTxt.View.namespace+"showClosed",!0)},setShowClosedInactive:function(){var a=document.querySelector("#showClosed-label");a.className=a.className.replace(/(( |^)btn-success)/," btn-danger"),localStorage.setItem(TodoTxt.View.namespace+"showClosed",!1)},getShowClosedStatus:function(){var a=localStorage.getItem(TodoTxt.View.namespace+"showClosed");return!(!a||"true"!==a)},togglePanel:function(a){var b=document.querySelector("#"+a+" .panel-heading"),c=document.querySelector("#"+a+" .panel-body");!c.className.match(/(( |^)collapse)/)?TodoTxt.View.hidePanel(b,c):TodoTxt.View.showPanel(b,c)},showPanel:function(a,b){var c=a.querySelector(".glyphicon");b.className=b.className.replace(/(( |^)collapse)/g,""),c.className=c.className.replace(/(( |^)glyphicon-chevron-down)/," glyphicon-chevron-up")},hidePanel:function(a,b){var c=a.querySelector(".glyphicon");b.className+=" collapse",c.className=c.className.replace(/(( |^)glyphicon-chevron-up)/," glyphicon-chevron-down")},toggleTaskStatus:function(a){var b=TodoTxt.getTask(a);b&&(b.isActive?TodoTxt.closeTask(a):TodoTxt.activateTask(a),TodoTxt.View.refreshUi())},getTodoTxtFile:function(a){$.ajax({url:a,cache:!1,error:function(a,b){alert(b)},success:function(a){!function(){TodoTxt.parseTodoTxtFile(a),TodoTxt.View.refreshUi()}()}})},handleFileSelect:function(a){a.stopPropagation(),a.preventDefault();var b=a.target.files||a.dataTransfer.files;if(b.length>0){var c=b[0],d=new FileReader;d.onloadend=function(a){confirm(TodoTxt.Resources.get("OVERWRITE_CONFIRM"))&&(TodoTxt.parseTodoTxtFile(a.target.result),TodoTxt.View.refreshUi())},d.readAsText(c,"UTF-8")}},handleDragOver:function(a){a.stopPropagation(),a.preventDefault(),a.dataTransfer.dropEffect="copy"},exportTodoTxtFile:function(){var a=TodoTxt.getSortedTaskArray(),b=a.join("\n"),c=encodeURI("data:text/csv;charset=utf-8,"+b);window.open(c)},taskToMarkupString:function(a){var b=a.toString();b=TodoTxt.Utils.htmlEncode(b);var c=TodoTxt.View.getDisplayClassForTask(a);b=b.replace(a.priority,''+a.priority+"");for(var d=a.projects,e=0;e'+f+"")}for(var h=a.contexts,i=0;i'+j+"")}var k=a.createdDate;return k&&(b=b.replace(k,'")),b},getDisplayClassForTask:function(a){var b="";return null!==a.priority&&a.isActive&&("(A)"===a.priority&&(b+=" text-danger"),"(B)"===a.priority&&(b+=" text-warning"),"(C)"===a.priority&&(b+=" text-primary")),b},initializeElements:function(){var a='

        '+TodoTxt.Resources.get("PRIORITIES")+'

          '+TodoTxt.Resources.get("PROJECTS")+'

            '+TodoTxt.Resources.get("CONTEXTS")+'

              ',b=document.getElementById("todotxt");b&&(b.innerHTML=a)}};var TodoTxt=TodoTxt||{};TodoTxt.Resources={recs:{},register:function(a,b){TodoTxt.Resources.recs[a]=b},get:function(a){var b=TodoTxt.Resources.recs[TodoTxt.Utils.getLanguage()];b||(b=TodoTxt.Resources.recs["en-us"]);var c=b[a];if(!c)throw"requested resource not found: "+a;return c}},TodoTxt.Resources.register("en-us",{OVERWRITE_CONFIRM:"This will overwrite any existing list. Are you sure you wish to proceed?",DELETE_CONFIRM:"Are you sure you want to delete task?",IMPORT:"Import",ADD_TASK:"Add Task",EXPORT:"Export",SHOW_CLOSED:"Show Closed",FILTER_PLACEHOLDER_TEXT:"Type filter(s)",CLEAR_FILTER:"Clear Filter",PRIORITIES:"Priorities",PROJECTS:"Projects",CONTEXTS:"Contexts",CLOSE:"Close",EDIT_TASK_HEADER:"Edit Task",UPDATE:"Update",PREVIEW:"Preview",DELETE:"Delete"}),$(document).ready(function(a){TodoTxt.View.initializeElements(),TodoTxt.View.refreshUi()}); -//# sourceMappingURL=todoTxt.min.js.map \ No newline at end of file diff --git a/dist/todoTxt.min.js.map b/dist/todoTxt.min.js.map deleted file mode 100644 index 4d79417..0000000 --- a/dist/todoTxt.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../js/todoTxt.js","../js/objects/utils.js","../js/classes/task.js","../js/objects/view.js","../js/objects/resources.js","../js/objects/resources/en-us.js","../js/wrapper.js"],"names":["TodoTxt","namespace","Attributes","priorities","projects","contexts","getSortedTaskArray","taskArray","taskMatcher","RegExp","Task","_clearAttributes","key","localStorage","match","t","getTask","id","push","_updateAttributes","sort","_compareTasks","getFilteredTaskArray","filterStr","filteredTasks","filters","split","rStr","i","length","replace","regex","filter","toString","parseTodoTxtFile","todoTxt","append","deleteAllTasks","lines","line","task","addTask","createTask","textStr","taskId","text","getItem","undefined","updateTask","newText","setItem","closeTask","isActive","priority","Utils","formatDate","Date","activateTask","completedDate","deleteTask","removeItem","j","taskA","taskB","aActive","bActive","aPri","bPri","aCreated","createdDate","bCreated","aCompleted","bCompleted","dateObj","yyyy","getFullYear","mm","getMonth","dd","getDate","String","getLanguage","window","navigator","userLanguage","language","toLowerCase","guid","s4","Math","floor","random","substring","htmlEncode","str","htmlUnencode","taskString","this","metadatas","_parseFromString","prototype","textLine","_parseStatusFromString","_parsePriorityFromString","_parseCompletedDateFromString","_parseCreatedDateFromString","_parseProjectsFromString","_parseContextsFromString","pri","priPattern","completed","dates","_parseDatesFromString","created","datePattern","projArray","projPattern","tmpHash","ctxArray","ctxPattern","View","generateTaskElement","icon","status","htmlText","taskToMarkupString","element","document","createElement","className","elementTxt","innerHTML","generateListElement","onclick","e","setFilters","onmouseover","onmouseout","displayTasks","querySelector","value","getShowClosedStatus","forEach","displayTask","appendChild","removeTask","removeChild","displayModalForTask","unbindControlEvents","mainEventHandlers","modal","Resources","get","body","$","bindControlEvents","modalEventHandlers","focus","updateModalPreview","el","textContent","closeModal","removeModal","refreshUi","ev","fn","handleAltEnter","handleEsc","handleAltP","handleDeleteClick","displayPriorities","priList","attr","clearPriorities","displayProjects","projList","clearProjects","displayContexts","ctxList","clearContexts","handleAltS","handleAltC","handleAltT","handleDragOver","handleDrop","toggleShowClosedStatus","exportTodoTxtFile","handleFilter","togglePanel","handlers","handler","useCapture","uc","addEventListener","removeEventListener","keyCode","altKey","handleFileSelect","type","ex","confirm","filterTimeoutId","filterTimoutId","clearTimeout","setTimeout","filterDisplayedTasks","setShowClosedActive","setShowClosedInactive","clearTasks","clearFilters","showClosed","name","heading","hidePanel","showPanel","indicator","toggleTaskStatus","getTodoTxtFile","fileName","ajax","url","cache","error","jqXHR","textStatus","alert","success","data","stopPropagation","preventDefault","files","target","dataTransfer","f","reader","FileReader","onloadend","result","readAsText","dropEffect","content","join","encodeURI","open","priCls","getDisplayClassForTask","project","context","date","cls","initializeElements","baseElements","container","getElementById","recs","register","langLocale","resourceObj","rec","val","OVERWRITE_CONFIRM","DELETE_CONFIRM","IMPORT","ADD_TASK","EXPORT","SHOW_CLOSED","FILTER_PLACEHOLDER_TEXT","CLEAR_FILTER","PRIORITIES","PROJECTS","CONTEXTS","CLOSE","EDIT_TASK_HEADER","UPDATE","PREVIEW","DELETE","ready"],"mappings":"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","file":"todoTxt.min.js"} \ No newline at end of file diff --git a/fonts/glyphicons-halflings-regular.ttf b/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..67fa00b Binary files /dev/null and b/fonts/glyphicons-halflings-regular.ttf differ diff --git a/fonts/glyphicons-halflings-regular.woff b/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..8c54182 Binary files /dev/null and b/fonts/glyphicons-halflings-regular.woff differ diff --git a/index.html b/index.html index d63c66d..8f7abfa 100644 --- a/index.html +++ b/index.html @@ -38,14 +38,15 @@ - + - +
              +