Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE HTML>
- <html>
- <head>
- <title></title>
- <style>
- .clearfix:after {clear: both; content: "."; display: block; height: 0; line-height: 0; visibility: hidden;}
- .clearfix {display: inline-block;} * html .clearfix {height: 1%;} .clearfix {display: block;} html[xmlns] .clearfix {display:block;}
- body {
- background: rgba(237, 243, 247, 1);
- color: rgba(0, 0, 0, .7);
- font-family: Arial, Verdana, sans-serif;
- font-size: 62.5%;
- margin: 0;
- padding: 0;
- }
- h1 {
- color: rgba(0, 0, 0, .2);
- font-size: 1.5em;
- margin: 40px auto 0;
- padding: 0 20px 1px 0;
- text-align: right;
- text-transform: uppercase;
- width: 740px;
- }
- ul, li {list-style: none; margin: 0; padding: 0;}
- li {clear: both; font-size: 1.2em; line-height: 1.2; margin: 3px 0; padding: 2px 0;}
- li input {display: block; float: left; margin-right: 8px; margin-top: 0;}
- h2 {font-size: 1.5em;}
- #wrapper {margin: 0 auto; width: 740px;}
- nav {float: left; margin: 3px 0 0; width: 240px;}
- nav li {margin: 1px 0;}
- nav li a, nav li a:hover {
- background: rgba(255, 255, 255, .5);
- border: 4px solid rgba(212, 218, 222, 1);
- border-right: none;
- clear: right;
- color: rgba(100, 110, 103, .6);
- display: block;
- padding: 8px 12px;
- text-decoration: none;
- border-bottom-left-radius: 6px;
- border-top-left-radius: 6px;
- }
- nav a em {display: block; float: right; font-style: normal;}
- nav li a.active, nav li a:hover {background: rgba(255, 255, 255, 1); color: rgba(100, 110, 103, 1);}
- #tasks-wrapper {
- background: rgb(255, 255, 255);
- border: 1px solid rgba(212, 218, 222, .9);
- border-top: 4px solid rgba(212, 218, 222, .9);
- float: left;
- width: 67%;
- }
- #archive-list li {border-bottom: 1px solid rgba(217, 223, 227, .5); padding-bottom: 3px;}
- #date-picker {color: rgba(80, 180, 80, 1); display: none; margin: 3em auto 0; text-indent: 1em; width: 420px;}
- #today-wrapper, #archive-wrapper {min-height: 75px; padding: 0 20px 20px;}
- #new-task {margin-bottom: 12px; padding: 5px;}
- #task-list li span, #archive-list li span {
- color: rgba(0, 0, 0, .35); /* set this based on user prefs. must set in dom creation */
- float: right;
- font-size: 11px;
- font-weight: 600;
- margin: 0 6px 0 0;
- text-align: right;
- }
- .cat-1, .cat-2, .cat-3 {
- padding: 4px 0;
- }
- .cat-1 {background: rgba(220, 230, 215, .6);}
- .cat-1.complete {background: rgba(220, 230, 215, .25); color: rgba(0, 0, 0, .2)}
- .cat-2 {background: rgba(220, 220, 230, .6);}
- .cat-2.complete {background: rgba(220, 220, 230, .25); color: rgba(0, 0, 0, .2);}
- .cat-3 {background: rgba(220, 210, 195, .6);}
- </style>
- </head>
- <body>
- <h1>Memero</h1>
- <div class="clearfix" id="wrapper">
- <nav>
- <ul></ul>
- </nav>
- <div id="tasks-wrapper"></div>
- </div>
- <script>
- (function() {
- var $ = {};
- $.props = {
- days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
- html: {
- checkboxClass: 'task-checkbox',
- completeClass: 'complete',
- dateHeadline: 'date-headline',
- archiveWrapper: 'archive-wrapper',
- archiveList: 'archive-list',
- taskInput: 'new-task',
- taskList: 'task-list',
- tasksWrapper: 'tasks-wrapper',
- todayWrapper: 'today-wrapper'
- },
- months:['January', 'February', 'March', 'April', 'May', 'June', 'July',
- 'August', 'September', 'October', 'November', 'December'],
- nav: {
- ul: document.getElementsByTagName('nav')[0].getElementsByTagName('ul')[0],
- tagsId: 'tags-tab',
- todayId: 'today-tab',
- previousDayId: 'previous-day-tab',
- lastWorkdayText: 'completed tasks',
- todayText: 'Todays Tasks',
- tagsText: 'Tags'
- },
- taskCheckbox: document.getElementsByClassName('task-checkbox')
- };
- $.find = function(id) {
- return document.getElementById(id);
- };
- $.capture = function(id, eventType, callback) { // Find dynamically created object by binding event
- var elem;
- window.document.addEventListener(eventType, function(e) {
- if (e.target.getAttribute('id') === id) {
- elem = e.target;
- callback(elem);
- e.preventDefault();
- }
- }, false);
- };
- $.Helpers = {
- changeClass: function(elem, newClassName) {
- var classes = [], _change;
- _change = function(elem, newClassName, index) {
- if (elem.className) { // Has a class already
- classes = elem.className.split(' ');
- }
- if (!$.Helpers.contains(classes, newClassName) && index === 0) { // Doesn't have this class assigned
- classes.push(newClassName);
- elem.setAttribute('class', classes.join(' '));
- } else { // Does have this class, so remove it
- elem.removeAttribute('class');
- if (classes.length > 0) {
- classes.splice(classes.indexOf(newClassName));
- elem.setAttribute('class', classes.join(' '))
- }
- }
- };
- return function() {
- if (elem instanceof Array) {
- for (var i=0; i<elem.length; i++) {
- _change(elem[i][0], elem[i][1], i);
- }
- } else {
- _change(elem, newClassName, 0);
- }
- }();
- },
- contains: function(arr, matcher) {
- if (typeof arr === 'object') {
- for (var i=0; i<arr.length; i++) {
- if (arr[i] === matcher) {
- return true;
- }
- }
- }
- return false;
- },
- toObject: function(array) {
- var size = array.length,
- obj = {};
- for (var i=0; i<size; i++) {
- obj[i+1] = array[i];
- }
- return obj;
- }
- };
- $.Storage = {
- has: function(obj) {
- if (window.localStorage) {
- if (localStorage[obj]) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- },
- totalItems: function(obj) {
- var ln = 0;
- if (obj === undefined) {
- return 0;
- }
- if (typeof obj === 'string') {
- obj = JSON.parse(obj);
- }
- for (o in obj) {
- ln += 1;
- }
- return ln;
- }
- };
- $.Tag = function(name) {
- this.id = 0;
- this.name = name;
- };
- $.Tag.prototype.save = function() {
- var allTags;
- if ($.Tag.find(this.name)) {return this;}
- this.id = $.Storage.totalItems(localStorage.tags) + 1;
- if ($.Storage.has('tags')) {
- allTags = JSON.parse(localStorage.tags);
- } else {
- allTags = {};
- }
- allTags[this.id] = this;
- localStorage.setItem('tags', JSON.stringify(allTags));
- return this;
- };
- $.Tag.exp = /\[[\w*(\s|\-)?]*\]$/;
- $.Tag.getTag = function(taskName) {
- return taskName.match($.Tag.exp)[0].slice(1, -1);
- };
- $.Tag.find = function(name) {
- var tags, tag;
- if ($.Storage.has('tags')) {
- tags = JSON.parse(localStorage.tags);
- for (t in tags) {
- if (tags[t].name.toLowerCase() === name.toLowerCase()) {
- tag = new $.Tag(tags[t].name);
- tag.id = tags[t].id;
- tag.colorCode = tags[t].colorCode;
- return tag;
- }
- }
- }
- return false;
- };
- $.Tag.trimTagFromTaskName = function(taskName) {
- var pos = taskName.search(this.exp),
- cleanName = taskName.substr(0, pos);
- if (cleanName.charAt(cleanName.length-1) == ' ') {
- cleanName = cleanName.substr(0, cleanName.length-1);
- }
- return cleanName;
- };
- $.Tag.tallyTags = function() {
- var totalTags = $.Storage.totalItems(localStorage.tags);
- return totalTags;
- };
- $.Task = function(id, name, tag) {
- this.name = name;
- this.complete = false;
- this.id = id;
- this.tag = tag;
- };
- $.Task.prototype.save = function() {
- var allTasks;
- if (!$.Storage.has('tasks')) {
- allTasks = {};
- this.id = 1;
- } else {
- allTasks = JSON.parse(localStorage.tasks);
- this.id = $.Storage.totalItems(localStorage.tasks) + 1;
- }
- allTasks[this.id] = this;
- localStorage.setItem('tasks', JSON.stringify(allTasks));
- return this;
- };
- $.Task.prototype.addToList = function() {
- var task = {}, indicator, tasks;
- task[this.id] = this;
- tasks = $.View.renderTask(task, true);
- $.find($.props.html.taskList).appendChild(tasks);
- $.find($.props.html.taskInput).value = '';
- indicator = $.find('today-tab').getElementsByTagName('em')[0];
- indicator.textContent = $.Storage.totalItems(localStorage.tasks);
- return this;
- };
- $.Task.prototype.markComplete = function() {
- var tasks;
- if (window.localStorage) {
- if (this.complete) {
- this.complete = false;
- } else {
- this.complete = true;
- }
- tasks = JSON.parse(localStorage.tasks);
- tasks[this.id] = this;
- try {
- localStorage.setItem('tasks', JSON.stringify(tasks));
- return true;
- } catch(ex) {
- return false;
- }
- }
- };
- $.Task.find = function(id) {
- var tasks, task;
- if (window.localStorage) {
- tasks = JSON.parse(localStorage.tasks);
- if (tasks[id]) {
- task = new $.Task(id, tasks[id].name, tasks[id].tag);
- task.complete = tasks[id].complete;
- }
- return task;
- }
- };
- $.Task.OrganizeTasks = function() {
- var completedTasks = [],
- unfinishedTasks = [],
- tasks;
- if ($.Storage.has('tasks')) {
- tasks = JSON.parse(localStorage.tasks);
- for (task in tasks) { // iterate through tasks
- if (tasks[task].complete) { // store completed tasks in new obj
- completedTasks.push(tasks[task]);
- } else {
- unfinishedTasks.push(tasks[task]);
- }
- }
- if (completedTasks.length > 0) {
- localStorage.archive = JSON.stringify($.Helpers.toObject(completedTasks));
- } else {
- localStorage.removeItem('archive');
- }
- if (unfinishedTasks.length > 0) {
- localStorage.tasks = JSON.stringify($.Helpers.toObject(unfinishedTasks));
- } else {
- localStorage.removeItem('tasks');
- }
- }
- };
- $.Task.TallyTasks = function(tasks) {
- var totalTasks = $.Storage.totalItems(tasks);
- return totalTasks;
- };
- $.Time = {
- isNewDay: function(lastLoginDate) {
- var now = new Date();
- if (!lastLoginDate) {return true;}
- if (typeof lastLoginDate == 'string') {
- lastLoginDate = new Date(lastLoginDate);
- }
- return now.getDate() !== lastLoginDate.getDate();
- },
- todaysDate: function() {
- var today = new Date(),
- d = today.getDay(),
- m = today.getMonth(),
- year = today.getFullYear();
- return $.props.days[d] + ', ' + $.props.months[m] + ' ' + today.getDate() + ' ' + year;
- },
- lastWorkday: function() {
- var workday = new Date(localStorage.previousWorkday),
- d = workday.getDay(),
- m = workday.getMonth(),
- year = workday.getFullYear();
- return $.props.days[d] + ', ' + $.props.months[m] + ' ' + workday.getDate() + ' ' + year;
- }
- };
- $.View = {
- navigation: {
- renderArchive: function(numOfTasks, isActive) {
- var li, a, text, em, lastWorkday;
- li = document.createElement('li');
- a = document.createElement('a');
- a.setAttribute('href', '#');
- a.setAttribute('id', $.props.nav.previousDayId);
- if (isActive) {
- a.setAttribute('class', 'active');
- }
- lastWorkday = new Date(localStorage.previousWorkday);
- text = document.createTextNode($.props.days[lastWorkday.getDay()] + 's ' +$.props.nav.lastWorkdayText);
- em = document.createElement('em');
- em.textContent = numOfTasks || 0;
- a.appendChild(text);
- a.appendChild(em);
- li.appendChild(a);
- $.props.nav.ul.appendChild(li);
- },
- renderTags: function(numOfTags, isActive) {
- var li, a, text, em;
- li = document.createElement('li');
- a = document.createElement('a');
- a.setAttribute('href', '#');
- a.setAttribute('id', $.props.nav.tagsId);
- if (isActive) {
- a.setAttribute('class', 'active');
- }
- text = document.createTextNode($.props.nav.tagsText);
- em = document.createElement('em');
- em.textContent = numOfTags;
- a.appendChild(text);
- a.appendChild(em);
- li.appendChild(a);
- $.props.nav.ul.appendChild(li);
- },
- renderToday: function(numOfTasks, isActive) {
- var li, a, text, em;
- li = document.createElement('li');
- a = document.createElement('a');
- a.setAttribute('href', '#');
- a.setAttribute('id', $.props.nav.todayId);
- if (isActive) {
- a.setAttribute('class', 'active');
- }
- text = document.createTextNode($.props.nav.todayText);
- em = document.createElement('em');
- em.textContent = numOfTasks;
- a.appendChild(text);
- a.appendChild(em);
- li.appendChild(a);
- $.props.nav.ul.appendChild(li);
- }
- },
- renderArchivePanel: function() {
- var div, h2, input, ul,
- tasksFrag = document.createDocumentFragment(),
- parentElem = document.getElementById($.props.html.tasksWrapper);
- div = document.createElement('div');
- div.setAttribute('id', $.props.html.archiveWrapper);
- h2 = document.createElement('h2');
- h2.setAttribute('id', $.props.html.dateHeadline);
- h2.textContent = 'Completed tasks from ' + $.Time.lastWorkday() ;
- ul = document.createElement('ul');
- ul.setAttribute('id', $.props.html.archiveList);
- div.appendChild(h2);
- div.appendChild(ul);
- tasksFrag.appendChild(div);
- if (parentElem.hasChildNodes()) {
- parentElem.textContent = '';
- }
- parentElem.appendChild(tasksFrag);
- },
- renderTagPanel: function() {
- var div, h2, input, ul,
- tasksFrag = document.createDocumentFragment(),
- parentElem = document.getElementById($.props.html.tasksWrapper);
- div = document.createElement('div');
- div.setAttribute('id', $.props.html.archiveWrapper);
- h2 = document.createElement('h2');
- h2.textContent = 'Tags for your tasks'
- div.appendChild(h2);
- tasksFrag.appendChild(div);
- if (parentElem.hasChildNodes()) {
- parentElem.textContent = '';
- }
- parentElem.appendChild(tasksFrag);
- },
- renderTodayPanel: function() {
- var div, h2, input, ul,
- tasksFrag = document.createDocumentFragment(),
- parentElem = document.getElementById($.props.html.tasksWrapper);
- div = document.createElement('div');
- div.setAttribute('id', $.props.html.todayWrapper);
- h2 = document.createElement('h2');
- h2.setAttribute('id', $.props.html.dateHeadline);
- h2.textContent = 'Tasks for ' + $.Time.todaysDate() ;
- input = document.createElement('input');
- input.setAttribute('id', $.props.html.taskInput);
- input.setAttribute('placeholder', 'What are you doing today?');
- input.setAttribute('size', '40');
- input.setAttribute('type', 'text');
- ul = document.createElement('ul');
- ul.setAttribute('id', $.props.html.taskList);
- div.appendChild(h2);
- div.appendChild(input);
- div.appendChild(ul);
- tasksFrag.appendChild(div);
- if (parentElem.hasChildNodes()) {
- parentElem.textContent = '';
- }
- parentElem.appendChild(tasksFrag);
- },
- renderTask: function(tasks, editable) {
- var li, checkbox, text, frag, tagSpan;
- frag = document.createDocumentFragment();
- if (typeof tasks !== 'object') {
- tasks = JSON.parse(tasks);
- }
- for (t in tasks) {
- task = tasks[t];
- li = document.createElement('li');
- text = document.createTextNode(task.name);
- if (editable) {
- checkbox = document.createElement('input');
- checkbox.setAttribute('type', 'checkbox');
- checkbox.setAttribute('id', t); // May need to refactor object/id
- if (task.complete) {
- li.className = 'complete';
- checkbox.setAttribute('checked', 'checked');
- }
- li.appendChild(checkbox);
- //li.setAttribute('contenteditable', '');
- }
- li.appendChild(text);
- if (task.tag) {
- li.setAttribute('class', 'cat-'+$.Tag.find(task.tag).id);
- tagSpan = document.createElement('span');
- tagSpan.textContent = task.tag;
- li.appendChild(tagSpan);
- }
- frag.appendChild(li);
- }
- return frag;
- },
- renderTasks: function(tasks, parentElementID, editable) {
- var storedTasks = localStorage[tasks],
- parentElem = $.find(parentElementID);
- var tasksHTML = this.renderTask(storedTasks, editable);
- parentElem.appendChild(tasksHTML);
- }
- };
- $.initApp = function(callback) {
- if (!localStorage.lastLogin) { // Set today as current day if it doesn't exist
- localStorage.lastLogin = new Date();
- }
- if ($.Time.isNewDay(localStorage.lastLogin)) { // Setup storage for new work day
- localStorage.previousWorkday = localStorage.lastLogin;
- localStorage.lastLogin = new Date();
- $.Task.OrganizeTasks();
- }
- $.View.renderTodayPanel();
- $.View.navigation.renderToday($.Task.TallyTasks(localStorage.tasks), true);
- if ($.Storage.has('tasks')) {
- $.View.renderTasks('tasks', $.props.html.taskList, true);
- }
- if ($.Storage.has('archive')) {
- $.View.navigation.renderArchive($.Task.TallyTasks(localStorage.archive), false);
- }
- if ($.Storage.has('tags')) {
- $.View.navigation.renderTags($.Tag.tallyTags(), false);
- }
- document.title = 'Memero - ' + $.Time.todaysDate() ;
- callback.call();
- };
- $.initApp(function() {
- window.document.addEventListener('keypress', function(e) {
- var task,
- taskName,
- tag,
- tagName,
- input = document.getElementById($.props.html.taskInput);
- if (e.target.id === $.props.html.taskInput) {
- if (e.keyCode == '13' && input.value !== '') {
- taskName = input.value;
- if (taskName.match($.Tag.exp)) { // Task is tagged
- tag = new $.Tag($.Tag.getTag(taskName));
- tag.save();
- taskName = $.Tag.trimTagFromTaskName(taskName);
- tagName = tag.name;
- }
- task = new $.Task(0, taskName, tagName);
- task.save().addToList();
- }
- }
- }, false);
- window.document.addEventListener('click', function(e) {
- if (e.target.getAttribute('type') == 'checkbox') {
- taskId = e.target.getAttribute('id');
- task = $.Task.find(taskId);
- if (task.markComplete()) {
- $.Helpers.changeClass(e.target.parentNode, $.props.html.completeClass);
- }
- }
- }, false);
- $.capture($.props.nav.previousDayId, 'click', function(elem) {
- if (elem.className !== 'active') {
- $.Helpers.changeClass([[elem, 'active'], [$.find($.props.nav.todayId), 'active'], [$.find($.props.nav.tagsId), 'active']]);
- // $.Helpers.changeClass();
- $.View.renderArchivePanel();
- $.View.renderTasks('archive', $.props.html.archiveList, false);
- }
- });
- $.capture($.props.nav.todayId, 'click', function(elem) {
- if (elem.className !== 'active') {
- $.Helpers.changeClass([[elem, 'active'], [$.find($.props.nav.previousDayId), 'active'], [$.find($.props.nav.tagsId), 'active']]);
- $.View.renderTodayPanel();
- $.View.renderTasks('tasks', $.props.html.taskList, true);
- }
- });
- $.capture($.props.nav.tagsId, 'click', function(elem) {
- if (elem.className !== 'active') {
- $.Helpers.changeClass([[elem, 'active'], [$.find($.props.nav.previousDayId), 'active'], [$.find($.props.nav.todayId), 'active']]);
- $.View.renderTagPanel();
- }
- });
- });
- })();
- </script>
- </body>
- </html>
Add Comment
Please, Sign In to add comment