// calendar - generate a HTML page with a calendar on it.
//
// Usage:
//
//
// .. x = calendar(URL);
// .. replace innerHTML of something with x
//
// URL must be a file ending in .calin, containing lines
// * comment
// month num Print calendar for the Nth month (1-12)
// year num Print calendar for a year other than current
// title restofline Page title
// head restofline Any number of these, precede calendar
// foot restofline Any number of these, follow calendar
// mm/dd/yy text Put "text" in the box for dd if it's mm in yy
// mm/dd text Put "text" in the box for dd if it's mm
// class mm/dd cls Assign class "cls" to the box for mm/dd
// every thursday[+1] [in Nov] text
// first thursday[+1] in Nov text
// .. second, third, fourth, fifth, last ..
// include filename Process filename as input (holidays etc)
// boxwidth nn
// boxheight nn
//
// output is
// -- a DIV (class "calendar") containing
// -- an H1 [set by "title" verb]
// -- a heading (class "head") [set by "head" verb]
// -- an H2 [containing "month year"]
// -- a table
// ---- a heading row of boxes (class "headbox") with day names
// ---- 4 to 6 rows of boxes (class "rowN colM")
// ------ unused boxes (class "unused")
// ------ used boxes (class "box")
// -------- day number (class "daynum")
// -------- text (class "boxcontent") [set by multiple verbs]
// -- a footer (class "foot") [set by "foot" verb]
//
// CSS selectors and example content
// -- .calendar {font-family: Arial,Helvetica,Sans-serif;}
// -- .calendar H1 {text-align: center;}
// -- .calendar H2 {text-align: center;}
// -- .calendar .head {font-size: 80%;}
// -- .calendar TABLE {border: 2px solid black; background: white; border-collapse: collapse;}
// -- .calendar TABLE tr {border: 1px solid black; vertical-align: top;}
// -- .calendar TABLE th {border: 2px solid black; background: white;}
// -- .calendar TABLE td {border: 1px solid black; background: white; width: 115px;}
// -- .calendar TABLE .headbox {background-color: pink; color: black;}
// -- .calendar TABLE .boxcontent {font-size: 70%;}
// -- .calendar TABLE .boxcontent .col1 {background-color: yellow;} /* show Sunday in yellow */
// -- .calendar TABLE .boxcontent .col7 {background-color: yellow;} /* show Saturday in yellow */
// -- .calendar TABLE .daynumber {font-family: monospace; font-weight: bold; font-size: 120%;}
// -- .calendar TABLE .unused {background: #cccccc;}
// -- .calendar .foot {font-size: 70%;}
//
// THVV 01/98 initial .. Perl version, not derived from my 1981 FORTRAN version or 1974 Multics PL/I version
// THVV 01/17/98 v2 .. fix up year handling
// THVV 04/04/02 v3 .. styles
// THVV 02/29/08 v3 .. center
// THVV 05/09/11 v4 .. bug fixes, move more formatting into CSS
// THVV 02/27/12 v5 .. bug fix for leap year
// THVV 05/01/12 v5 .. bug fix for "every wed monoplane"
// THVV 12/02/16 initial -- a pedestrian translation of the Perl version cal.cgi into Javascript, with few changes
//
// to do: validate the numbers in dates
// Copyright (c) Tom Van Vleck, 2016
/* Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// ----------------------------------------------------------------
// read in a whole file specified by URL
// URL should be relative, no http: or anything, because of same-origin security
// BUG: this writes a message to the console saying "syntax error" and/or "not well formed" (because the file is not XML) .. but it works anyway.
function readfile(u) {
var funval = "";
if (u.substring(u.length-6) == ".calin") { // this is so the calendar function cannot be used fo poke around in your files
//alert("reading "+u);
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
funval = xhr.responseText;
}
}
// fire the open
xhr.open("GET", u, false); // synchronous. this may be deprecated but these files are so tiny it makes no difference
xhr.send();
}
return funval;
} // readfile
// ----------------------------------------------------------------
// return a calendar formatted in HTML
function calendar(filename) {
//constants
var GGmoname = ["January","February","March","April","May","June","July","August","September","October","November","December"]; // future .. i18n
var GGdaysmo = [31,28,31,30,31,30,31,31,30,31,30,31,31];
// parameters
var unusedclass = "unused"; // light gray
var rightnow = new Date(); // new Date(year, month [, day, hours, minutes, seconds, ms])
// define a Javascript object for the calendar page
var calPage = {
year: rightnow.getFullYear(), // year for this page
month: rightnow.getMonth(), // month for this page
title: "", // title for this page, or blank
head: "", // heading text for this page, NL separated, or blank
foot: "", // footer text for this page, NL separated, or blank
boxheight: 4, // standard height for all boxes
boxwidth: 14, // standard width for all boxes
boxlines: [], // array, number of text lines in each day's box
boxtext: [], // array, text lines for the box,
separated
boxclass: [] // array, CSS class for this box, or blank
};
for (i=0; i <= 31; i++) { // initialize the per-box arrays
calPage.boxlines[i] = 0;
calPage.boxtext[i] = "";
calPage.boxclass[i] = "";
}
// switches and initial values
var output = ""; // calendar output
if (filename != "") {
procfile (filename, calPage);
}
// month and year may have been changed while reading the input.
var bom = new Date(calPage.year, calPage.month, 1, 0, 0, 0, 0); // begin of month
var mday = bom.getDate();
var wday = bom.getDay();
var lastday;
var dayno;
lastday = GGdaysmo[calPage.month];
if (((calPage.year%4) == 0) && calPage.month == 1) { // leap year
lastday++;
}
dayno = ((mday-wday+12) % 7)-5; // 1 if month begins on Sun .. -5 if Sat
output += "
Sunday | "; // future.. i18n output += "Monday | "; output += "Tuesday | "; output += "Wednesday | "; output += "Thursday | "; output += "Friday | "; output += "Saturday | "; output += "
---|---|---|---|---|---|---|
\n";
// put the day number in the first row
x1 = rjust_number(dayno, calPage.boxwidth); // pad to width
output += "" + x1 + "\n"; // force box width
// print box contents if any
if (rowpadded == 0 || calPage.boxtext[dayno] != "") {
output += "\n";
if (calPage.boxtext[dayno] == "") {
output += " "; } for (j=calPage.boxlines[dayno]; j | \n"; } dayno++; output += " | \n"; } // for col output += "