# HG changeset patch # User paulo # Date 1466227457 25200 # Node ID 256b8df1c6869d8ab56c7c477c576ae84930f1dc # Parent ff0878207f0e838582a6a94330e8fa058def0962 add life_calendar diff -r ff0878207f0e -r 256b8df1c686 life_calendar/happy.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/life_calendar/happy.js Fri Jun 17 22:24:17 2016 -0700 @@ -0,0 +1,134 @@ +/*global $*/ +(function happyJS($) { + function trim(el) { + return (''.trim) ? el.val().trim() : $.trim(el.val()); + } + $.fn.isHappy = function isHappy(config) { + var fields = [], item; + var pauseMessages = false; + + function isFunction(obj) { + return !!(obj && obj.constructor && obj.call && obj.apply); + } + function defaultError(error) { //Default error template + var msgErrorClass = config.classes && config.classes.message || 'unhappyMessage'; + return $('' + error.message + ''); + } + function getError(error) { //Generate error html from either config or default + if (isFunction(config.errorTemplate)) { + return config.errorTemplate(error); + } + return defaultError(error); + } + function handleSubmit() { + var i, l; + var errors = false; + for (i = 0, l = fields.length; i < l; i += 1) { + if (!fields[i].testValid(true)) { + errors = true; + } + } + if (errors) { + if (isFunction(config.unHappy)) config.unHappy(); + return false; + } else if (config.testMode) { + if (isFunction(config.happy)) return config.happy(); + if (window.console) console.warn('would have submitted'); + return false; + } + if (isFunction(config.happy)) return config.happy(); + } + function handleMouseUp() { + pauseMessages = false; + } + function handleMouseDown() { + pauseMessages = true; + $(window).bind('mouseup', handleMouseUp); + } + function processField(opts, selector) { + var field = $(selector); + var error = { + message: opts.message || '', + id: selector.slice(1) + '_unhappy' + }; + var errorEl = $(error.id).length > 0 ? $(error.id) : getError(error); + var handleBlur = function handleBlur() { + if (!pauseMessages) { + field.testValid(); + } else { + $(window).bind('mouseup', field.testValid.bind(this)); + } + }; + + fields.push(field); + field.testValid = function testValid(submit) { + var val, gotFunc, temp; + var el = $(this); + var errorTarget = (opts.errorTarget && $(opts.errorTarget)) || el; + var error = false; + var required = !!el.get(0).attributes.getNamedItem('required') || opts.required; + var password = (field.attr('type') === 'password'); + var arg = isFunction(opts.arg) ? opts.arg() : opts.arg; + var fieldErrorClass = config.classes && config.classes.field || 'unhappy'; + + // handle control groups (checkboxes, radio) + if (el.length > 1) { + val = []; + el.each(function(i,obj) { + val.push($(obj).val()); + }); + val = val.join(','); + } else { + // clean it or trim it + if (isFunction(opts.clean)) { + val = opts.clean(el.val()); + } else if (!password && typeof opts.trim === 'undefined' || opts.trim) { + val = trim(el); + } else { + val = el.val(); + } + + // write it back to the field + el.val(val); + } + + // get the value + gotFunc = ((val.length > 0 || required === 'sometimes') && isFunction(opts.test)); + + // check if we've got an error on our hands + if (submit === true && required === true && val.length === 0) { + error = true; + } else if (gotFunc) { + error = !opts.test(val, arg); + } + + if (error) { + errorTarget.addClass(fieldErrorClass).after(errorEl); + return false; + } else { + temp = errorEl.get(0); + // this is for zepto + if (temp.parentNode) { + temp.parentNode.removeChild(temp); + } + errorTarget.removeClass(fieldErrorClass); + return true; + } + }; + field.bind(opts.when || config.when || 'blur', handleBlur); + } + + for (item in config.fields) { + processField(config.fields[item], item); + } + + $(config.submitButton || this).bind('mousedown', handleMouseDown); + + if (config.submitButton) { + $(config.submitButton).click(handleSubmit); + } else { + this.bind('submit', handleSubmit); + } + return this; + }; +})(this.jQuery || this.Zepto); diff -r ff0878207f0e -r 256b8df1c686 life_calendar/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/life_calendar/index.html Fri Jun 17 22:24:17 2016 -0700 @@ -0,0 +1,386 @@ + + + + Life Calendar + + + + + + + + +
+

Life Calendar

+

+ A minimalist life calendar. Shows the number of weeks you've lived and the number of weeks you + have left. +

+
+

+ +

+

+ +

+

+ +

+
+ +
+ + diff -r ff0878207f0e -r 256b8df1c686 life_calendar/tooltip.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/life_calendar/tooltip.js Fri Jun 17 22:24:17 2016 -0700 @@ -0,0 +1,58 @@ +// Based on http://matthias-schuetz.js.org/tooltip.js/ + +var _tt_options = { + tooltipId: "tooltip", + offsetDefault: 15 +}; + +function getTooltipElm() { + return document.querySelector("#" + _tt_options.tooltipId); +} + +function adjustTooltip(evt, tooltipElm, title, text) { + var offset = _tt_options.offsetDefault; + var scrollY = window.scrollY || window.pageYOffset; + var scrollX = window.scrollX || window.pageXOffset; + var tooltipTop = evt.pageY + offset; + var tooltipLeft = evt.pageX + offset; + + tooltipTop = (tooltipTop - scrollY + tooltipElm.offsetHeight + 20 >= window.innerHeight ? (tooltipTop - tooltipElm.offsetHeight - 20) : tooltipTop); + tooltipLeft = (tooltipLeft - scrollX + tooltipElm.offsetWidth + 20 >= window.innerWidth ? (tooltipLeft - tooltipElm.offsetWidth - 20) : tooltipLeft); + + tooltipElm.style.top = tooltipTop + "px"; + tooltipElm.style.left = tooltipLeft + "px"; + + setTooltipText(tooltipElm, title, text); +} + +function removeTooltip() { + document.querySelector("body").removeChild(getTooltipElm()); +} + +function createTooltip(evt, title, text) { + var tooltipElm = getTooltipElm(); + + if (!tooltipElm) { + tooltipElm = document.createElement("div"); + tooltipElm.appendChild(document.createElement("h1")); + tooltipElm.appendChild(document.createElement("h2")); + + tooltipElm.style.position = "absolute"; + tooltipElm.setAttribute("id", _tt_options.tooltipId); + + document.querySelector("body").appendChild(tooltipElm); + } + + adjustTooltip(evt, tooltipElm, title, text); +} + +function setTooltipText(tooltipElm, title, text) { + var eTitle = tooltipElm.children[0]; + var eText = tooltipElm.children[1]; + if (eTitle && title) { + eTitle.textContent = title; + } + if (eText && text) { + eText.textContent = text; + } +}