reptile7's JavaScript blog
Wednesday, August 06, 2014
The Quote Parade, Part 3
Blog Entry #329

We're ready to move on to QuoteOfTheDay.html, the second New Array Text Pages script. Upon visiting the QuoteOfTheDay.html page daily during a given month, the QuoteOfTheDay.html script displays a sequence of quotes, one quote per day, via an i index that maps the quotes onto the dates of the month.

Recall that the CookieQuotes.html script used a buildArray( ) function

function buildArray( ) { var a = arguments; for (i = 0; i < a.length; i++) this[i] = a[i]; this.length = a.length; }

to array a series of 15 quotes; the QuoteOfTheDay.html script uses the same function to array a series of 31 quotes.

var quote = new buildArray( "Lottery: A tax on people who don't understand statistics.", "Smash forehead on keyboard to continue.", ...28 other quotes... "If one synchronized swimmer drowns, do the rest have to drown too?");

We now have a quote Object object with 0, 1, ... 30 numerical properties that are set respectively to the quote strings. Next, the QuoteOfTheDay.html script
(a) creates a currentDate Date object,
(b) gets currentDate's getDate( ) date,
(c) subtracts one from the date, and
(d) assigns the difference to an i variable.

currentDate = new Date( );
i = currentDate.getDate( ) - 1;

Subsequently i is moduloed by quote.length to give a display index for the quote we'll put on the page; the modulo remainder is assigned to i.

i = i % quote.length;

After the modulo statement a conditional compares quote.length and 31: if they're not equal then an alert( ) message to that effect pops up.

if (quote.length != 31) window.alert("Number of quotes is not exactly 31");

We finally plug i into quote[ ] and write the corresponding quote string to the page. The user sees the quote[0] quote on the first day of the month, the quote[1] quote on the second day, etc.


(We don't get to the quote[30] quote in months having fewer than 31 days; moreover, February misses out on the quote[29] quote and also the quote[28] quote if the current year is not a leap year.)

Changes to make

(1) Converting the var quote = new buildArray( ...Quote strings... ); instantiation to a dense array constructor or an array literal will allow us to throw out the buildArray( ) function.

(2) The i = i % quote.length; statement can also be sent packing if quote comprises ≥ 31 quotes; however, for a smaller number of quotes you'd need to hang onto it.

(3) Chuck the Number of quotes is not exactly 31 conditional: there's no point in bothering the user with this information if you're working with < 31 quotes.

(4) The quote[i] text is horizontally centered/bolded/enlarged via <center> and <h1> elements: lose this markup in favor of a styled <div> per the Formatting section of the previous post.

A demo

The JavaScript Source hosts a QuoteOfTheDay.html demo here.

Jenson checks in

I have recently discovered that Jenson maintains a Web site with a javascript/ directory that showcases the five New Array Text Pages scripts and four other related scripts. Apropos the present discussion, the javascript/index.html page provides links to
(1) a Quote of the Day (Month) script and
(2) a Quote of the Day (Year) script.
It's not clear if these scripts predate or postdate the Java Goodies QuoteOfTheDay.html script.

Month to month

The Quote of the Day (Month) script displays a different quote on each day of a given month and works with the same series of 31 quotes that the Java Goodies QuoteOfTheDay.html script does. The former defines a quote array à la the latter but follows the buildArray( ) instantiation with:

function quoteOut( ) { currentDate = new Date( ); return this[((currentDate.getDate( ) - 1) % quote.length)]; /* The this keyword references the quote object. */ }
quote.toString = quoteOut;

The quote object's toString( ) method is overridden with a quoteOut( ) function that gets the quote of the day as described earlier and returns it to the concluding document.write(quote); command, which calls the quoteOut( )/toString( ) function and prints out its return.

Jenson explains:
The script redefines the toString( ) method for the quote object to make the document.write( ) call easier to use.
But why would we write( ) a re-engineered quote to the page in the first place? The toString( ) method is supposed to return a string representing its calling object. If we are only interested in a particular quote[i] member, then we should output quote[i] per the Java Goodies QuoteOfTheDay.html script.

The year scale

The Quote of the Day (Year) script applies a quote array of 36 quotes to the dates of an entire year.
• The "Back Up My Hard Drive? How do I Put it in Reverse?" quote appears twice.
• The "What we have here is a failure to assimilate.<br>[Cool Hand Locutus]" quote does not appear in the Source Code at the bottom of the QuoteOfTheDayY.html page.

The quote[0] quote is displayed on 1 January; on the following days the remaining quote quotes are individually displayed in sequence until they run out with quote[35] on 5 February; on 6 February the quote sequence begins anew; and so on.

The script obtains the display index for a given date's quote by
(i) tallying the daysSoFarThisYear, the number of days of the year up to and including the present date,
(ii) subtracting one from the tally, and then
(iii) moduloing the difference by quote.length.

return this[(daysSoFarThisYear - 1) % quote.length];

The script obtains the daysSoFarThisYear by adding the current getDate( ) date to the daysBeforeThisMonth, the number of days of the year prior to the present month. The daysBeforeThisMonth for a given month is stored in a daysBeforeThisMonth buildArray( ) object.

var daysBeforeThisMonth = new buildArray(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335);
var currentDate = new Date( );
var daysSoFarThisYear = daysBeforeThisMonth[currentDate.getMonth( )] + currentDate.getDate( );

The daysBeforeThisMonth[0] value is for January dates, the daysBeforeThisMonth[1] value is for February dates, etc. The daysBeforeThisMonth[2] value, 60, indicates that the preceding February has 29 days; however, the script follows the daysSoFarThisYear determination with a conditional that increments daysSoFarThisYear if the current year is a leap year.

if ((currentDate.getMonth( ) >= 2) && ((currentDate.getYear( ) % 4) == 0)) daysSoFarThisYear++;

• The long-deprecated getYear( ) should of course be replaced by getFullYear( ).
• Years that are divisible by 100 but not by 400 are not in fact leap years, although 2100 is a long way off, eh?

The script wraps the currentDate/daysSoFarThisYear code in a quoteOut( ) function, assigns a quoteOut reference to quote.toString, and write( )s quote to the page.

function quoteOut( ) { /* Create a currentDate; get the daysSoFarThisYear and 'correct' it for a leap year if necessary; return the quote of the day. */ }
quote.toString = quoteOut;

Here's how I would revamp the QuoteOfTheDayY.html JavaScript:

var quote = [ ...Quote strings... ];

var currentDate = new Date( );
var currentMonth = currentDate.getMonth( )
var currentYear = currentDate.getFullYear( )

var monthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if ((currentYear % 4) || (!(currentYear % 100) && (currentYear % 400))) monthDays[1] = 28;

window.onload = function ( ) { var daysBeforeThisMonth = 0; for (i = 0; i < currentMonth; i++) daysBeforeThisMonth += monthDays[i]; var daysSoFarThisYear = daysBeforeThisMonth + currentDate.getDate( ); document.getElementById("quoteDiv").innerHTML = quote[(daysSoFarThisYear - 1) % quote.length]; }

The daysBeforeThisMonth Object has been replaced by a monthDays Array whose elements specify the number of days in each month. The monthDays[1] value is initially set to 29 and is decremented to 28 if the currentYear is not a leap year. The monthDays values are sequentially summed to give a daysBeforeThisMonth tally via a for loop in the window.onload function.

If you go to the trouble of lining up 366 quotes for this script, then the expression for the quote of the day can be simplified to quote[daysSoFarThisYear - 1].

We'll take up the third New Array Text Pages script, RandomLinks.html, in the next post.

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)