diff life_calendar/index.html @ 81:256b8df1c686

add life_calendar
author paulo
date Fri, 17 Jun 2016 22:24:17 -0700
parents
children a0fdf2cf1d53
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/life_calendar/index.html	Fri Jun 17 22:24:17 2016 -0700
     1.3 @@ -0,0 +1,386 @@
     1.4 +<html>
     1.5 +    <head>
     1.6 +        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     1.7 +        <title>Life Calendar</title>
     1.8 +        <style type="text/css">
     1.9 +            body {
    1.10 +                padding: 0;
    1.11 +                margin: 0;
    1.12 +                position: relative;
    1.13 +                font-family: sans-serif;
    1.14 +                background-size: cover;
    1.15 +            }
    1.16 +
    1.17 +            a, a:visited {
    1.18 +                color: #70BCF9;
    1.19 +            }
    1.20 +
    1.21 +            table {
    1.22 +                width: 100%;
    1.23 +                height: 100%;
    1.24 +            }
    1.25 +
    1.26 +            table, td {
    1.27 +                border: 1px solid;
    1.28 +                border-collapse: collapse;
    1.29 +                padding: 0;
    1.30 +                margin: 0;
    1.31 +            }
    1.32 +
    1.33 +            div#welcome {
    1.34 +                display: none;
    1.35 +
    1.36 +                width: 50vw;
    1.37 +                margin: 8vh auto 0;
    1.38 +            }
    1.39 +
    1.40 +            div#welcome h1 {
    1.41 +                text-align: center;
    1.42 +                text-transform: uppercase;
    1.43 +                font-family: serif;
    1.44 +                font-size: 4em;
    1.45 +            }
    1.46 +            div#welcome form {
    1.47 +                border: 1px solid #999999;
    1.48 +                padding: 10px 20px;
    1.49 +            }
    1.50 +
    1.51 +            div#welcome .settings {
    1.52 +                margin-left: 5px;
    1.53 +                padding: 5px;
    1.54 +            }
    1.55 +
    1.56 +            div#welcome div#footer {
    1.57 +                color: #a6a6a6;
    1.58 +                padding-top: 50px;
    1.59 +                text-align: center;
    1.60 +            }
    1.61 +
    1.62 +            #settingsForm span.unhappyMessage {
    1.63 +                font-size: 0.8em;
    1.64 +                padding-left: 10px;
    1.65 +            }
    1.66 +
    1.67 +            div#tooltip {
    1.68 +                background-color: #5070D0;
    1.69 +                padding: 0.5em;
    1.70 +            }
    1.71 +
    1.72 +            div#tooltip h1 {
    1.73 +                color: #DFDFDF;
    1.74 +                font-size: 1.25em;
    1.75 +                margin: 1px;
    1.76 +            }
    1.77 +
    1.78 +            div#tooltip h2 {
    1.79 +                color: #AAAAAA;
    1.80 +                font-size: 0.75em;
    1.81 +                font-weight: normal;
    1.82 +                margin: 1px;
    1.83 +            }
    1.84 +
    1.85 +            td {
    1.86 +                border-color: #FFFFFF;
    1.87 +            }
    1.88 +
    1.89 +            table {
    1.90 +                border-color: #FFFFFF;
    1.91 +            }
    1.92 +
    1.93 +            tr.previous td {
    1.94 +                background-color: #BBBBBB;
    1.95 +            }
    1.96 +
    1.97 +            tr.current td.partial {
    1.98 +                background-color: #CCDDCC;
    1.99 +            }
   1.100 +
   1.101 +            tr.current td.today {
   1.102 +                background-color: #DDDDCC;
   1.103 +            }
   1.104 +
   1.105 +            tr.current td.future {
   1.106 +                background-color: #DDCCCC;
   1.107 +            }
   1.108 +
   1.109 +            tr.future {
   1.110 +                background-color: #DDDDDD;
   1.111 +            }
   1.112 +
   1.113 +        </style>
   1.114 +        <script src="jquery-2.1.3.min.js"></script>
   1.115 +        <script src="happy.js"></script>
   1.116 +        <script src="tooltip.js"></script>
   1.117 +
   1.118 +        <script type="text/javascript">
   1.119 +            var nWeeks = 52;
   1.120 +            var nMsPerDay = 3600 * 24 * 1000;
   1.121 +            var nMsPerWeek = 7 * nMsPerDay;
   1.122 +            var QSParams;
   1.123 +
   1.124 +            var birthday;
   1.125 +            var birthdayString;
   1.126 +            var birthdayDate;
   1.127 +
   1.128 +            var lifespan;
   1.129 +
   1.130 +            var age;
   1.131 +            var ageYears;
   1.132 +            var remainder;
   1.133 +
   1.134 +            var previousYears;
   1.135 +            var futureYears;
   1.136 +            var remainderWeeks;
   1.137 +            var restOfYearWeeks;
   1.138 +
   1.139 +            function validateBirthday(birthday) {
   1.140 +                var birthdayPattern = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
   1.141 +                return birthdayPattern.test( $("#birthday").val());
   1.142 +            }
   1.143 +
   1.144 +            function validateLifespan(lifespan) {
   1.145 +                var lifespanPattern = /^[0-9]{1,3}$/;
   1.146 +                return lifespanPattern.test( $("#lifespan").val());
   1.147 +            }
   1.148 +
   1.149 +            // Read a page's GET URL variables and return them as an associative array.
   1.150 +            // From http://jquery-howto.blogspot.ca/2009/09/get-url-parameters-values-with-jquery.html
   1.151 +            function getQSParams()
   1.152 +            {
   1.153 +                var vars = [], hash;
   1.154 +                var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
   1.155 +                for(var i = 0; i < hashes.length; i++)
   1.156 +                {
   1.157 +                    hash = hashes[i].split('=');
   1.158 +                    vars.push(hash[0]);
   1.159 +                    vars[hash[0]] = hash[1];
   1.160 +                }
   1.161 +                return vars;
   1.162 +            }
   1.163 +
   1.164 +            function isLeapYear(year) {
   1.165 +                var d = new Date(year, 1, 28);
   1.166 +                d.setDate(d.getDate() + 1);
   1.167 +                return d.getMonth() == 1;
   1.168 +            }
   1.169 +
   1.170 +            function getAge(date) {
   1.171 +                var d = new Date(date), now = new Date();
   1.172 +                var years = now.getFullYear() - d.getFullYear();
   1.173 +                d.setFullYear(d.getFullYear() + years);
   1.174 +                if (d > now) {
   1.175 +                    years--;
   1.176 +                    d.setFullYear(d.getFullYear() - 1);
   1.177 +                }
   1.178 +                var days = (now.getTime() - d.getTime()) / nMsPerDay;
   1.179 +                return years + days / (isLeapYear(now.getFullYear()) ? 366 : 365);
   1.180 +            }
   1.181 +
   1.182 +            function getCalendar(d, week, year) {
   1.183 +                var c = new Date(d);
   1.184 +                c.setFullYear(d.getFullYear() + year);
   1.185 +                c.setTime(c.getTime() + (week * nMsPerWeek)); 
   1.186 +                return c;
   1.187 +            }
   1.188 +
   1.189 +            function getWeekYearCal(e, week) {
   1.190 +                var yearParent = e.parentNode;
   1.191 +                var calParent = yearParent.parentNode;
   1.192 +                var year;
   1.193 +                for (year = 0; year < calParent.childNodes.length; year++) {
   1.194 +                    if (calParent.childNodes[year] === yearParent) {
   1.195 +                        break;
   1.196 +                    }
   1.197 +                }
   1.198 +                var cal = getCalendar(birthdayDate, week, year);
   1.199 +                return {
   1.200 +                    week: week,
   1.201 +                    year: year,
   1.202 +                    cal: cal,
   1.203 +                }
   1.204 +            }
   1.205 +
   1.206 +            function loop(x, f) {
   1.207 +                for (var i = 0; i < x; f(i++));
   1.208 +            }
   1.209 +
   1.210 +            function mapLoop(x, f) {
   1.211 +                var ret = [];
   1.212 +                for (var i = 0; i < x; i++) {
   1.213 +                  ret.push(f(i));
   1.214 +                }
   1.215 +                return ret;
   1.216 +            }
   1.217 +
   1.218 +            function cycleColors(e) {
   1.219 +                var colors = [
   1.220 +                    undefined,
   1.221 +                    "black",
   1.222 +                    "red",
   1.223 +                    "green",
   1.224 +                    "blue",
   1.225 +                    "white",
   1.226 +                ];
   1.227 +
   1.228 +                var i = 0;
   1.229 +                for (; i < colors.length, colors[i] != e._fill_color; i++);
   1.230 +                e._fill_color = colors[(i + 1) % colors.length];
   1.231 +                if (e._fill_color != undefined) {
   1.232 +                    e.setAttribute("style", "background-color: " + e._fill_color);
   1.233 +                } else {
   1.234 +                    e.setAttribute("style", undefined);
   1.235 +                }
   1.236 +            }
   1.237 +
   1.238 +            function _createElement(tagName, className) {
   1.239 +                var e = document.createElement(tagName);
   1.240 +                if (className) {
   1.241 +                    e.className = className;
   1.242 +                }
   1.243 +                return e;
   1.244 +            }
   1.245 +
   1.246 +            function weekElem(className) {
   1.247 +                return _createElement("td", className);
   1.248 +            }
   1.249 +
   1.250 +            function yearElem(className) {
   1.251 +                return _createElement("tr", className);
   1.252 +            }
   1.253 +
   1.254 +            function yearWeekElems() {
   1.255 +                return mapLoop(nWeeks, function(i) {
   1.256 +                    var e = weekElem();
   1.257 +                    addWeekMouseEvents(e, i);
   1.258 +                    return e;
   1.259 +                });
   1.260 +            }
   1.261 +
   1.262 +            function addWeekMouseEvents(e, i) {
   1.263 +                e.addEventListener("mouseover", function(evt) {
   1.264 +                    var wyc = getWeekYearCal(e, i);
   1.265 +                    var calYear = wyc.cal.getFullYear();
   1.266 +                    var calMonth = wyc.cal.getMonth() + 1;
   1.267 +                    var calDay = wyc.cal.getDate();
   1.268 +                    createTooltip(evt, calYear + '-' + calMonth + '-' + calDay, "(Week: " + wyc.week + ", Year: " + wyc.year + ")");
   1.269 +                });
   1.270 +                e.addEventListener("click", function() {
   1.271 +                    cycleColors(e);
   1.272 +                });
   1.273 +            }
   1.274 +
   1.275 +            $( document ).ready(function() {
   1.276 +                $( "#settingsForm" ).isHappy({
   1.277 +                    fields: {
   1.278 +                        '#birthday': {
   1.279 +                            required: true,
   1.280 +                            test: validateBirthday,
   1.281 +                            message: 'Please enter your birthday (like YYYY-MM-DD).'
   1.282 +                        },
   1.283 +                        '#lifespan': {
   1.284 +                            required: true,
   1.285 +                            test: validateLifespan,
   1.286 +                            message: 'Please enter your expected lifespan (like 90)'
   1.287 +                        }
   1.288 +                    }
   1.289 +                });
   1.290 +
   1.291 +                QSParams = getQSParams();
   1.292 +
   1.293 +                if(!("birthday" in QSParams) | !("lifespan" in QSParams)) {
   1.294 +                    // Show the form
   1.295 +                    $("#welcome").css("display", "block");
   1.296 +
   1.297 +                    // Give the first field focus
   1.298 +                    $("#birthday").focus();
   1.299 +                    return;
   1.300 +                }
   1.301 +
   1.302 +                $("body").append( '<table id="calendar"></table>' );
   1.303 +
   1.304 +                birthday = QSParams["birthday"];
   1.305 +                birthdayString = birthday + "T00:00:00";
   1.306 +                birthdayDate = new Date(birthdayString);
   1.307 +
   1.308 +                lifespan = QSParams["lifespan"];
   1.309 +
   1.310 +                age = getAge(birthdayDate);
   1.311 +                ageYears = Math.floor(age);
   1.312 +                remainder = age - ageYears;
   1.313 +
   1.314 +                previousYears = (ageYears).toFixed(0);
   1.315 +
   1.316 +                if( lifespan > ageYears) {
   1.317 +                    futureYears = lifespan - ageYears - 1;
   1.318 +                    remainderWeeks = Math.floor(remainder * nWeeks);
   1.319 +                    restOfYearWeeks = Math.ceil(nWeeks - remainderWeeks) - 1;
   1.320 +                } else {
   1.321 +                    futureYears = 0;
   1.322 +                    remainderWeeks = nWeeks;
   1.323 +                    restOfYearWeeks = 0;
   1.324 +                }
   1.325 +
   1.326 +                // Fill in lived years
   1.327 +                loop(previousYears, function() {
   1.328 +                    var tr = yearElem("previous");
   1.329 +                    $(tr).append(yearWeekElems());
   1.330 +                    $("#calendar").append(tr);
   1.331 +                })
   1.332 +
   1.333 +                // Fill in the current birth-year (the number of weeks elapsed since the most recent birthday.)
   1.334 +                var current_tr = yearElem("current");
   1.335 +                loop(remainderWeeks, function(i) {
   1.336 +                    var e = weekElem("partial");
   1.337 +                    addWeekMouseEvents(e, i);
   1.338 +                    $(current_tr).append(e);
   1.339 +                })
   1.340 +                var e = weekElem("today");
   1.341 +                addWeekMouseEvents(e, remainderWeeks);
   1.342 +                $(current_tr).append(e);
   1.343 +                loop(restOfYearWeeks, function(i) {
   1.344 +                    var e = weekElem("future");
   1.345 +                    addWeekMouseEvents(e, remainderWeeks + 1 + i);
   1.346 +                    $(current_tr).append(e);
   1.347 +                })
   1.348 +                $("#calendar").append(current_tr);
   1.349 +
   1.350 +                // Fill in future years
   1.351 +                loop(futureYears, function() {
   1.352 +                    var tr = yearElem("future");
   1.353 +                    $(tr).append(yearWeekElems());
   1.354 +                    $("#calendar").append(tr);
   1.355 +                })
   1.356 +            });
   1.357 +        </script>
   1.358 +    </head>
   1.359 +    <body>
   1.360 +        <div id="welcome">
   1.361 +            <h1>Life Calendar</h1>
   1.362 +            <p>
   1.363 +                A minimalist life calendar. Shows the number of weeks you've lived and the number of weeks you
   1.364 +                have left.
   1.365 +            </p>
   1.366 +            <form method="get" action="" id="settingsForm">
   1.367 +                <p>
   1.368 +                    <label for="birthday">Birthday:
   1.369 +                        <input class="settings" id="birthday" name="birthday" placeholder="1985-01-01"/>
   1.370 +                    </label>
   1.371 +                </p>
   1.372 +                <p>
   1.373 +                    <label for="lifespan">Life expectancy:
   1.374 +                        <input class="settings" id="lifespan" name="lifespan" placeholder="90"/>
   1.375 +                    </label>
   1.376 +                </p>
   1.377 +                <p>
   1.378 +                    <input type="submit" id="submit" value="Show calendar" />
   1.379 +                </p>
   1.380 +            </form>
   1.381 +            <div id="footer">
   1.382 +                <p>
   1.383 +                    Based on <a href="http://waitbutwhy.com/2014/05/life-weeks.html">Your Life in Weeks</a>
   1.384 +                    and <a href="http://count.life">count.life</a>.
   1.385 +                </p>
   1.386 +            </div>
   1.387 +        </div>
   1.388 +    </body>
   1.389 +</html>