I am making a website that takes a bunch of dining hall information and puts it all together in a neater (and hopefully more mobile friendly) form.
Here is the link: https://googledrive.com/host/0By7Z_HHj2VhnWmlhbWl4aF8xdFU/nuEats.html
It's a little incomplete at the moment, but what it does is the bar up top shows you how much a "meal" is worth at a university convenience store (there is an arrow that is usually there, but it is current gone because it is 2:21 AM, which is after closing time).
Also, there are links to dining halls and their menus. My first question is: I don't know a lot about HTML and CSS best practices.
I have tried to keep everything nice and neat, but I was wondering if someone could just browse through my code and see
- Is the code efficient
- Is the code clear and concise?
The second point is especially important to me because I don't want anything to be ambiguous or hard to understand in my code, since I inevitably will have to pass it down.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>nuEats</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css"/>
<!-- User-fed CSS -->
<link rel="stylesheet" href="nuEats.css" type="text/css">
<!-- Bootstrap responsive CSS -->
<link rel="stylesheet" href="css/bootstrap-theme.min.css" type="text/css"/>
</head>
<body onload="onCreate()">
<!-- Navigation Bar -->
<div class="navbar navbar-inverse navbar-static-top">
<div class="navbar-inner">
<div class="container">
<a class="navbar-brand" href="#">nuEats</a>
</div>
</div>
</div>
<!-- Clock -->
<div class="container">
<div id="clock"></div>
</div>
<!-- Equivalency Meal Exchange Rate Timeline -->
<div class="container">
<div id="rate-bars-label">Equivalency Meal Exchange Rate:</div>
<div class="rate-bars-container" id="rate-bars-container"></div>
<div id="arrow"><img src="arrow.png"></div>
</div>
<!-- Info Panels for Each Dining Hall -->
<div class="container">
<div class="panel-group" id="accordion">
<!-- 1835 Hinman -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
1835 Hinman
<a href="https://m-nucuisine.sodexomyway.com/images/Hinman3_tcm238-12915.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div id="hinman" class="panel-body">
<!-- This is where body text goes -->
</div>
</div>
</div>
<!-- Allison -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Allison
<a href="https://m-nucuisine.sodexomyway.com/images/Allison3_tcm238-9944.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
</div>
<!-- Elder -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Elder
<a href="https://m-nucuisine.sodexomyway.com/images/Elder3_tcm238-12911.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
</div>
<!-- Plex East -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Plex East
<a href="https://m-nucuisine.sodexomyway.com/images/Foster_East3_tcm238-12913.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
</div>
<!-- Plex West -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Plex West
<a href="https://m-nucuisine.sodexomyway.com/images/Foster_West3_tcm238-12914.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
</div>
<!-- Sargent -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Sargent
<a href="https://m-nucuisine.sodexomyway.com/images/Sargent3_tcm238-12910.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
</div>
<!-- Willard -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
Willard
<a href="https://m-nucuisine.sodexomyway.com/images/Willard3_tcm238-12912.htm">
<div class="menu">Menu</div>
</a>
</h4>
</div>
</div>
</div>
</div>
</body>
<!-- Bootstrap Core Javascript -->
<script src="jquery-1.10.1.min.js"></script> <!-- Change this back to the link when you publish!!! -->
<script src="js/bootstrap.js"></script>
<!-- User Javascript -->
<script src="nuEats.js" type="text/javascript"></script>
<html>
CSS
#clock {
font-size: 1em;
}
/* Control the label FONT above the timeline bars */
#rate-bars-label {
margin-top: 5px;
margin-bottom: 20px;
font-size: 1em;
font-weight: bold;
}
/* Format each equivalency-rate bar as a group */
.rate-bars {
height: 1em;
float: left;
}
/* Set each bar's color individually; add more CSS if you add more time blocks */
/* LIGHT GREEN */
#block0 {
background-color: #40d351;
}
/* MEDIUM GREEN */
#block1 {
background-color: #2e973a;
}
/* DARK GREEN */
#block2 {
background-color: #216C2A;
}
/* MEDIUM GREEN */
#block3 {
background-color: #2e973a;
}
/* Control the FONT surrounding the timeline bars */
.timeText {
margin-top: -1.5em;
margin-left: 5px; /* Some space makes it look better */
font-size: 0.75em;
font-weight: bold;
}
.timeText-right {
margin-top: -3.0em;
font-size: 0.75em;
font-weight: bold;
float: right;
}
.priceText {
margin-left: 5px;
color: white;
font-size: 0.75em;
}
/* Formatting concerning the "Menu" button */
.menu {
font-weight: bold;
float: right;
}
.menu:hover {
text-decoration: underline;
}
JavaScript
function onCreate() {
// Consider this to be the "main" function of sorts
document.getElementById("clock").innerHTML = createClock(); // Create a clock
setInterval(function() { document.getElementById("clock").innerHTML = createClock(); }, 500); // Update it every half-second
// Dynamically create equivalency-rate bars from array data
// Time Equivalency Rate
var EqRates = [ [7, 30, "5.00"],
[10, 45, "7.00"],
[16, 45, "9.00"],
[19, 30, "7.00"],
[26, 00, "N/A" ] ]; // 2:00 AM, the NEXT day!
createEqRateBars(EqRates);
// Set the position of an arrow pointing to the correct time block
setArrowPosition(EqRates);
setInterval(function() { setArrowPosition(EqRates); }, 1000); // Update it every second
$(window).resize(function() { setArrowPosition(EqRates); }); // Update it upon window resize
}
/*
* Create a clock, with special formatting
*/
function createClock() {
// Date format is "Sunday, January 1st, 12:00:00 AM"
var today = new Date();
var day = returnDay(today.getDay()); // Convert day integer to string (i.e. Monday, Tuesday, Wednesday...)
var o = returnMonth(today.getMonth()); // Convert month integer to string (i.e. January, February, March...)
var d = formatDate(today.getDate()); // Add suffix to date (i.e. 1st, 2nd, 4th...)
var h = today.getHours();
var m = formatTime(today.getMinutes()); // If minutes or seconds is single digit, add zero before
var s = formatTime(today.getSeconds());
var AMPM = getAMPM(h);
h = h % 12;
// Controls the final output of the clock's text
return (day).bold() + ", " + o + " " + d + ", " + h + ":" + m + ":" + s + " " + AMPM;
}
// A series of helper functions
function returnDay(day) { return ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][day]; }
function returnMonth(month) { return ["January","February","March","April","May","June","July","August","September","October","November","December"][month]; }
function formatDate(date) {
digit = date % 10;
if (digit == 1) {
return date + "st";
} else if (digit == 2) {
return date + "nd";
} else if (digit == 3) {
return date + "rd";
} else {
return date + "th";
}
}
// Add zeros before numbers where necessary
function formatTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
// Given an hour, determine if it is AM or PM
function getAMPM(hour) {
return ["AM","PM"][(((hour % 24) >= 12) & 1)];
}
/*
* Procedurally create equivalency rate exchange bars
*/
function createEqRateBars(EqRates) {
// EqRates is a "3-dimensional" array of time slots and corresponding equivalency rates
var rows = EqRates.length;
var columns = EqRates[0].length;
// Use the total length of all blocks to figure out what proportion each individual block takes up
var startMin = timeInMin(EqRates[0][0], EqRates[0][1]); // Converts hours and minutes to just minutes for easy math
var endMin = timeInMin(EqRates[rows - 1][0], EqRates[rows - 1][1]);
var totalMin = endMin - startMin;
// For each time block, create a div that represents that block graphically as a horizontal bar
for (var i = 0; i < rows - 1; i++) {
// Set up variables that specify the horizontal bar's name and width, then add it
var name = "block" + i;
var blockMin = timeInMin(EqRates[i + 1][0], EqRates[i + 1][1]) - timeInMin(EqRates[i][0], EqRates[i][1]);
var blockWidth = (blockMin / totalMin) * 100 + "%";
jQuery('<div/>', {
id: name,
class: "rate-bars",
css: {
width: blockWidth,
}
}).appendTo('#rate-bars-container');
// Format time information, then display it ABOVE the bar
var hour = EqRates[i][0] % 12; // 12-hour time
var minute = formatTime(EqRates[i][1]); // Add '0' before minute if minute < 10
var AMPM = getAMPM(EqRates[i][0]); // Is it AM or PM?
jQuery('<div/>', {
class: 'timeText',
text: hour + ":" + minute + " " + AMPM
}).appendTo("#" + name);
// Pull price information, then display it ON the bar
var price = EqRates[i][2];
jQuery('<div/>', {
class: 'priceText',
text: '$' + price
}).appendTo("#" + name);
}
// Do something special to pull closing time and put it ABOVE the bar and flush right
var hour = EqRates[rows-1][0] % 12; // 12-hour time
var minute = formatTime(EqRates[rows-1][1]); // Add '0' before minute if minute < 10
var AMPM = getAMPM(EqRates[rows - 1][0]); // Is it AM or PM?
jQuery('<div/>', {
class: 'timeText-right',
text: hour + ":" + minute + " " + AMPM
}).appendTo("#" + name); // Just to keep thing simple, we'll make it a subclass of the last horizontal bar
}
/*
* Set arrow location depending on equivalency meal value
*/
function setArrowPosition(EqRates) {
// EqRates is a "3-dimensional" array of time slots and corresponding equivalency rates
var rows = EqRates.length;
// Get some time information
var today = new Date();
var currentMin = dateInMin(today); // Current time in minutes from midnight
var openMin = timeInMin(EqRates[0][0], EqRates[0][1]); // 7:30 AM - same format
var closeMin = timeInMin(EqRates[rows - 1][0], EqRates[rows - 1][1]); // 2:00 AM the NEXT DAY - same format
var DAY_IN_MINUTES = 24*60; // Will be useful later on for subtracting
// If it is after 7:30 AM OR before 2:00 AM on the SAME DAY, show the arrow, otherwise hide it
if (currentMin >= openMin || currentMin < closeMin - DAY_IN_MINUTES) {
/* Place the "current time" arrow as such:
* 1) Subtract currentMin by openMin so the arrow is at 0(%) displacement at 7:30 AM
* 2) Divide by (closeMin - openMin), the minutes from open to close time, so that at close time, the arrow is at 100(%) displacement
* 3) There is 5px of offset from the width of the arrow, convert that to a (%) and subtract it
* 4) Multiply by 100 so we have an actual percent
* 5) Set this absolute number to the left-margin shift
*/
var timelinePercent = [(currentMin - openMin)/(closeMin - openMin) - (5/$("#rate-bars-container").width())] * 100;
$("#arrow").css("margin-left", timelinePercent + "%");
} else {
$("#arrow").hide();
}
}
// Easy ways to return times as minutes
function dateInMin(dateObject) {
return dateObject.getHours() * 60 + dateObject.getMinutes();
}
function timeInMin(hours, minutes) {
return hours * 60 + minutes;
}
Furthermore, I want to have the bar for each dining hall glow green or red depending on whether or not the dining hall is open and show what kind of meal (breakfast, lunch, dinner, etc.) it is currently serving. I plan to pull this information from a tab-delimited table in a text file. Can anyone recommend a best/better way to do this? I was thinking either Javascript or PHP, but I don't really like PHP, both because I don't know it yet and because I believe it will spaghettify my code.