diff --git a/index.css b/index.css index 3b85ee67..550d3982 100644 --- a/index.css +++ b/index.css @@ -1,27 +1,95 @@ +/* VARIABLES */ + +:root { + + --shadow-color: #111111CC; + +} + +/* BASIC STYLING */ + +html, body { height: 100%; } body { - color: white; - font-family: "Roboto Light"; + + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; + + margin: 0; + + background-size: cover; + background-position: 50%; + + font-family: 'Roboto', sans-serif; + color: white; + } -h1 { - font-size: 150px; -} -h2 { - font-size: 100px; -} -h3 { - font-size: 25px; +/* BACKGROUND CLASSES */ + +.mountain { background-image: url('images/1.jpeg'); } +.sunrise { background-image: url('images/2.jpeg'); } +.butterfly { background-image: url('images/3.jpeg'); } +.leaves { background-image: url('images/4.jpeg'); } + +/* TEXT SHADOW */ + +.greeting, +time, +.quote { + + filter: drop-shadow(var(--shadow-shift) var(--shadow-shift) 0 var(--shadow-color)); + } +/* Greeting */ + +.greeting { + + --shadow-shift: 0.2rem; + + font-size: 3.25rem; -html { - overflow: scroll; - overflow-x: hidden; } -::-webkit-scrollbar { - width: 0px; - background: transparent; /* https://stackoverflow.com/questions/16670931/ */ + +/* Time */ + +time { + + --shadow-shift: 0.4rem; + + font-size: 12rem; + } -::-webkit-scrollbar-thumb { - background: #FF0000; -} \ No newline at end of file + +/* Quote */ + +.quote { + + --shadow-shift: 0.125rem; + + width: 37.5%; + max-width: 37.5rem; /* 600px on desktop */ + + font-size: 1.5rem; + text-align: center; + +} + +/* quote text */ + +.quote blockquote { + + margin: 0 0 0.25rem 0; + + line-height: 1.125; + +} + +.quote blockquote::before { content: '“'; margin-right: 0.25ch; } +.quote blockquote::after { content: '”'; margin-left: 0.25ch; } + +/* quote author */ + +.quote cite { font-size: 83.33%; } diff --git a/index.html b/index.html index 1777ed77..dfdbd17e 100644 --- a/index.html +++ b/index.html @@ -1,24 +1,34 @@ - - - - New Tab - - - -
-



-

-
-

-

-
-

-









-

-
-

- - + + + + + + + New Tab + + + + + + + + +
+ + + +
+ +
+ + + +
+ + + + + diff --git a/index.js b/index.js index 5a3bbff8..0bdc68d7 100644 --- a/index.js +++ b/index.js @@ -1,31 +1,210 @@ -var day = new Date(); -var hr = day.getHours(); -if (hr < 12) { -document.getElementById("greetingmsg").innerHTML = "Good Morning"; -} else -if ((hr == 12 || hr == 13 || hr == 14 || hr == 15 || hr == 16)){ -document.getElementById("greetingmsg").innerHTML = "Good Afternoon"; -} else -if (hr >= 17) { -document.getElementById("greetingmsg").innerHTML = "Good Evening"; -} +// start a separate function for each of the things that we need to do -var num = Math.ceil( Math.random() * 5 ); -document.body.background = 'images/'+num+'.jpeg'; //https://stackoverflow.com/a/15231912 -document.body.style.backgroundRepeat = "repeat"; +// function construction is part of making the code clearer... +// ...i.e., easier to read and to debug -var quotes = ['"Time goes on. So whatever you’re going to do, do it. Do it now. Don’t wait." - Robert De Niro']; -var length = quotes.length; -var rand = Math.round(Math.random()*(length - 1)); -document.getElementById("quotemsg").innerHTML = quotes[rand]; +// the clearer the code, the easier it would be: +// 1. for the author to return to its development later, +// 2. for coders unfamiliar with it to understand it... +// 2.1. ...and help improve it, -setInterval(function() { - var currentTime = new Date ( ); - var currentHours = currentTime.getHours ( ); - var currentMinutes = currentTime.getMinutes ( ); - var currentSeconds = currentTime.getSeconds ( ); - currentMinutes = ( currentMinutes < 10 ? "0" : "" ) + currentMinutes; - currentSeconds = ( currentSeconds < 10 ? "0" : "" ) + currentSeconds; - var currentTimeString = currentHours + ":" + currentMinutes + " "; - document.getElementById("timemsg").innerHTML = currentTimeString; -}, 100); +// the clearer the code, the better it is perceived... +// ...which encourages others in open-source environment... +// ...to maintain, improve and copy it + +// further reading: +// https://eloquentjavascript.net/05_higher_order.html + +function setDaytimeMessage () { + + // skip the foreplay and get straight to hours... + // ...since we don't need the Date() anywhere else in the function + + let currentHour = new Date().getHours(), + + getDaytime = () => { + + // if it's morning... + + if (currentHour < 12) { return 'morning' } + + // ...if it's evening... + + else if (currentHour >= 18) { return 'evening' } + + // ...and in all other cases... + // ...which happens to be afternoon + + else { return 'afternoon' }; + + // no need to make code more specific than it needs to be + // if you can get the desired result without writing more... + // ...don't write more + + }; + + // ideally, one would want to have similar styles of comparison... + // ...within the same `if-else` structure (< and >, or, <= and >=)... + // ...but it makes more sense that way + + // separate function for setting an element's `innerHTML` + // uses template literals and ${}-extrapolation + + // further reading: + // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals + setHTMLContent(".greeting", `Good ${getDaytime()}`); + +}; + +function setRandomBackground () { + + let backgroundClasses = [ + + 'mountain', + 'sunrise', + 'butterfly', + 'leaves' + + ], + currentBackgroundClass = pickFromArray(backgroundClasses); + + // adds a class from backgroundClasses to + + // using classes to define element attributes is often safer... + // ...than setting the attributes straight to element's `style` + + document.body.classList.add(currentBackgroundClass); + +}; + +function setRandomQuote () { + + // each quote is an object within the array + + // `text` and `author` go into different elements... + // ...each of which has its own styling + + // also, semantic separation is important for clarity of code + + // big-enough objects — such as each of the quotes — may be... + // ...separated by a new line each for clarity + + let quotes = [ + + { text: 'Time goes on. So whatever you’re going to do, do it. Do it now. Don’t wait.', author: 'Robert De Niro' } + + ], + quote = pickFromArray(quotes); + + setHTMLContent('blockquote', quote.text); + setHTMLContent('cite', quote.author); + + // little treats of visual alignment, for code beauty's sake + +}; + + + +function setTime () { + + // we need to save Date() here because we use... + // ...the same moment of time down the line + + let date = new Date(), + + // instead of performing separate operations for formatting... + // we store the time unit values already formatted + + time = [ + + formatTimeUnit(date.getHours()), + formatTimeUnit(date.getMinutes()), + formatTimeUnit(date.getSeconds()) + + ]; + + // joins all of the array elements into a string... + // ...using the ':' separator + + // i.e. [16, 32, 03] -> "16:32:03" + + setHTMLContent('time', time.join(':')); + +}; + +function init () { + + // initialize everything + + // init() gets executed only when the page is fully loaded... + // ...which is good practice when dealing with page elements + + // init() serves as a container for all the functions that we require... + // ...to work at the start of the page + + setDaytimeMessage(); + setRandomBackground(); + setRandomQuote(); + setTime(); + + // set interval to update time every second + + // if you don't use milliseconds, updating more often... + // is wasting CPU resources + + let timeInterval = setInterval(setTime, 1000); + + // ideally, one would want to update only the time unit changed... + // ...i.e., only seconds if 16:02:32 became 16:02:33 + + // this would use even less resources for the same result... + // ...which is always the goal + +}; + +// initialize on page load through a listener... +// ...which tracks a particular event and executes... +// ...the set function when the event happens + +// 'DOMContentLoaded' is the event of 'all HTML has loaded' + +// it allows to safely search for and modify HTML nodes + +// if a node is searched for while the page hasn't loaded yet... +// ...you will not get the same result and may encounter an error... +// ...which will halt your code execution + +document.addEventListener('DOMContentLoaded', init); + +// UTILITY FUNCTIONS + +// since JavaScript defines variables lazily [1], one can... +// ...semantically separate current and utility functions [2] + +// here, utility functions are put to the bottom so they don't pollute... +// ...the workflow — i.e., the part of the code that does most of the work + +// [1] lazily means it may already use variables and functions... +// ...defined later in the code + +// [2] utility functions are those that help write better code... +// ...either by making it more concise, more expressive or both + +// formatTimeUnit() is the kind of a pure utility functions + +// its purpose is to perform a single action on a single object + +// it makes the code look more concise while performing... +// ...with the same effectiveness + +function formatTimeUnit (unit) { return unit < 10 ? '0' + unit : unit }; + +// setHTMLContent is the kind of function is referred to as a 'wrapper' + +// its purpose is to make code look better aesthetically... +// ...while performing the same function as... +// ...its straightfoward-yet-ugly equivalent native function + +function setHTMLContent (selector, content) { return document.querySelector(selector) .innerHTML = content }; + +function pickFromArray(array) { return array[Math.floor(Math.random() * (array.length - 1))] };