diff --git a/README.md b/README.md index 0fdb47c..6cba2da 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,11 @@ Here are some features to look forward to in a future version: ## How to install? -ClassTime is a web-based app that can be saved to your phone's home screen or bookmarked in your browser for easy access. +ClassClock is a web-based app that can be saved to your phone's home screen or bookmarked in your browser for easy access. ### iOS -1. Navigate to https://classclock.app in Safari (not tested on other browsers) +1. Navigate to ClassClock in Safari (not tested on other browsers) 2. Click the "Share" or "Action" button (it looks like a square with an arrow pointing up out of the top) 3. Click "Add to Home Screen" on the bottom row (you might have to scroll sideways to see it) 4. Click "Done" in the top corner of the screen to add it to your home screen. @@ -45,7 +45,7 @@ ClassTime is a web-based app that can be saved to your phone's home screen or bo ### Android -1. Navigate to https://classclock.app (instructions for Google Chrome) +1. Navigate to ClassClock (instructions for Google Chrome) 2. Click the "Overflow" button on the top right of your screen (it looks like three vertical dots) 3. Click "Add to Home Screen" button in the menu (it's about 2/3 of the way down) 4. Click "Add" in the dialog box that pops up to add it to your home screen. diff --git a/_layouts/default.html b/_layouts/default.html index 516529b..56c89ee 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -1,5 +1,14 @@ + + + + @@ -17,22 +26,9 @@ - {{ content }} +

+
+ {{ content }} +
- - - - diff --git a/classtime.js b/classtime.js index 3a6458d..8d02a6a 100644 --- a/classtime.js +++ b/classtime.js @@ -1,197 +1,147 @@ -var currentDay = 0; -var currentHours = 0; -var currentMinutes = 0; -var currentSeconds = 0; +let DAY_OFF_FLAG = "day off" +let OUTSIDE_SCHOOL_HOURS_FLAG = "outside school hours" +let SCHOOL_IN_CLASS_OUT_FLAG = "school is in session, but class is not" +let CLASS_IN_SESSION_FLAG = "class is in session" + +let FLASH_SUCCESS = "SUCCESS" +let FLASH_INFO = "INFO" +let FLASH_WARN = "WARNING" +let FLASH_DANGER = "DANGER" + var currentDate; var currentClassPeriodIndex = -1; //nextClassPeriodIndex var currentScheduleIndex = -1; - +var selectedSchoolIndex = 0; var use24HourTime = getLocalStorageBoolean("use24HourTime", false); -var data = { - fullName: "", - shortName: "", - //order is as is on the school website, although it doesnt matter. - schedules: [ +var schools = [ { - name: "Mon/Fri (Regular)", - days: [1, 5], - classes: [ - { - name: "1st Period", - startTime: {hours: 8, minutes:25}, - endTime: {hours: 9, minutes:55} - }, - { - name: "TSCT", - startTime: {hours: 9, minutes:55}, - endTime: {hours: 10, minutes:10} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 10, minutes:10}, - endTime: {hours: 10, minutes:15} - }, - { - name: "2nd Period", - startTime: {hours: 10, minutes:15}, - endTime: {hours: 11, minutes:45} - }, - { - name: "Lunch", - startTime: {hours: 11, minutes:45}, - endTime: {hours: 12, minutes:20} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 12, minutes:20}, - endTime: {hours: 12, minutes:25} - }, - { - name: "3rd Period", - startTime: {hours: 12, minutes:25}, - endTime: {hours: 13, minutes:55} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 13, minutes:55}, - endTime: {hours: 14, minutes:00} - }, - { - name: "4th Period", - startTime: {hours: 14, minutes:00}, - endTime: {hours: 15, minutes:30} - } - ] - }, - { - name: "Tues/Wed (Support Seminar)", - days: [2, 3], - classes: [ - { - name: "1st Period", - startTime: {hours: 8, minutes:25}, - endTime: {hours: 9, minutes:47} - }, - { - name: "TSCT", - startTime: {hours: 9, minutes:47}, - endTime: {hours: 9, minutes:57} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 9, minutes:57}, - endTime: {hours: 10, minutes:02} - }, - { - name: "Support Seminar", - startTime: {hours: 10, minutes:02}, - endTime: {hours: 10, minutes:34} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 10, minutes:34}, - endTime: {hours: 10, minutes:39} - }, - { - name: "2nd Period", - startTime: {hours: 10, minutes:39}, - endTime: {hours: 12, minutes:01} - }, - { - name: "Lunch", - startTime: {hours: 12, minutes:01}, - endTime: {hours: 12, minutes:36} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 12, minutes:36}, - endTime: {hours: 12, minutes:41} - }, - { - name: "3rd Period", - startTime: {hours: 12, minutes:41}, - endTime: {hours: 14, minutes:03} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 14, minutes:03}, - endTime: {hours: 14, minutes:8} - }, - { - name: "4th Period", - startTime: {hours: 14, minutes:8}, - endTime: {hours: 15, minutes:30} - } - ], - }, - { - name: "Thursday (Early Release)", - days: [4], - classes: [ - { - name: "1st Period", - startTime: {hours: 8, minutes:25}, - endTime: {hours: 9, minutes:50} - }, - { - name: "TSCT", - startTime: {hours: 9, minutes:50}, - endTime: {hours: 10, minutes:00} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 10, minutes:00}, - endTime: {hours: 10, minutes:05} - }, - { - name: "2nd Period", - startTime: {hours: 10, minutes:05}, - endTime: {hours: 11, minutes:30} - }, - { - name: "Lunch", - startTime: {hours: 11, minutes:30}, - endTime: {hours: 12, minutes:05} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 12, minutes:05}, - endTime: {hours: 12, minutes:10} - }, - { - name: "3rd Period", - startTime: {hours: 12, minutes:10}, - endTime: {hours: 13, minutes:35} - }, - { - name: "Passing Period", - showInFullSchedule: false, - startTime: {hours: 13, minutes:35}, - endTime: {hours: 13, minutes:40} - }, - { - name: "4th Period", - startTime: {hours: 13, minutes:40}, - endTime: {hours: 15, minutes:05} - } - ] - } - ] -}; + fullName: "Lake Oswego High School", + shortName: "LOHS", + passingPeriodName: "Passing Period", //the name to use for time gaps in the schedule between classes + //order is as is on the school website, although it doesnt matter. + timeZone: 'America/Los_Angeles', + schedules: [ + { + name: "Mon/Fri (Regular)", + days: [1, 5], + classes: [ + { + name: "1st Period", + startTime: {hours: 8, minutes:25}, + endTime: {hours: 9, minutes:55} + }, + { + name: "TSCT", + startTime: {hours: 9, minutes:55}, + endTime: {hours: 10, minutes:10} + }, + { + name: "2nd Period", + startTime: {hours: 10, minutes:15}, + endTime: {hours: 11, minutes:45} + }, + { + name: "Lunch", + startTime: {hours: 11, minutes:45}, + endTime: {hours: 12, minutes:20} + }, + { + name: "3rd Period", + startTime: {hours: 12, minutes:25}, + endTime: {hours: 13, minutes:55} + }, + { + name: "4th Period", + startTime: {hours: 14, minutes:00}, + endTime: {hours: 15, minutes:30} + } + ] + }, + { + name: "Tues/Wed (Support Seminar)", + days: [2, 3], + classes: [ + { + name: "1st Period", + startTime: {hours: 8, minutes:25}, + endTime: {hours: 9, minutes:47} + }, + { + name: "TSCT", + startTime: {hours: 9, minutes:47}, + endTime: {hours: 9, minutes:57} + }, + { + name: "Support Seminar", + startTime: {hours: 10, minutes:02}, + endTime: {hours: 10, minutes:34} + }, + { + name: "2nd Period", + startTime: {hours: 10, minutes:39}, + endTime: {hours: 12, minutes:01} + }, + { + name: "Lunch", + startTime: {hours: 12, minutes:01}, + endTime: {hours: 12, minutes:36} + }, + { + name: "3rd Period", + startTime: {hours: 12, minutes:41}, + endTime: {hours: 14, minutes:03} + }, + { + name: "4th Period", + startTime: {hours: 14, minutes:8}, + endTime: {hours: 15, minutes:30} + } + ], + }, + { + name: "Thursday (Early Release)", + days: [4], + classes: [ + { + name: "1st Period", + startTime: {hours: 8, minutes:25}, + endTime: {hours: 9, minutes:50} + }, + { + name: "TSCT", + startTime: {hours: 9, minutes:50}, + endTime: {hours: 10, minutes:00} + }, + { + name: "2nd Period", + startTime: {hours: 10, minutes:05}, + endTime: {hours: 11, minutes:30} + }, + { + name: "Lunch", + startTime: {hours: 11, minutes:30}, + endTime: {hours: 12, minutes:05} + }, + { + name: "3rd Period", + startTime: {hours: 12, minutes:10}, + endTime: {hours: 13, minutes:35} + }, + { + name: "4th Period", + startTime: {hours: 13, minutes:40}, + endTime: {hours: 15, minutes:05} + } + ] + } + ] + } +]; /** * The standard run loop for updating the time and other time-related information on the site. @@ -199,11 +149,19 @@ var data = { */ function update() { updateTime(); - if (scheduleExists()) { + document.getElementById('time').innerHTML = getCurrentTimeString(); + document.getElementById('date').innerHTML = getCurrentDateString(); + + + if (typeof selectedSchoolIndex !== 'undefined') { updateVariables() updateText(); - setTimeout(update, 500); + document.getElementById("scheduleInfo").style.visibility = "visible"; + } else { + document.getElementById("scheduleInfo").style.visibility = "hidden"; } + + setTimeout(update, 500); } /** @@ -212,50 +170,90 @@ function update() { function updateVariables() { currentScheduleIndex = getCurrentScheduleIndex(); currentClassPeriodIndex = getCurrentClassPeriodIndex(); - //document.getElementById('currentClass').innerHTML = data.schedule[selectedSchedule][currentClassPeriodIndex].name; } /** * Updates labels on the homepage */ function updateText() { - document.getElementById('time').innerHTML = getCurrentTimeString(); - document.getElementById('date').innerHTML = getCurrentDateString(); - document.getElementById("schedule").innerHTML = getSummaryString(); - - if (!isNoSchoolDay()) { - if(!classIsInSession() && !isNoSchoolDay() && !checkGivenTimeIsBeforeCurrentTime(data.schedules[currentScheduleIndex].classes[0].startTime)) { - - document.getElementById("countdownLabel").innerHTML = "School starts in: " - document.getElementById('timeToEndOfClass').innerHTML = getTimeToStartOfSchoolString(); + if (getCurrentTimeState() !== DAY_OFF_FLAG ) { + document.getElementById("schedule").innerHTML = "You are viewing the " + getCurrentScheduleName() + " schedule" + document.getElementById("selectedSchoolDisplay").innerHTML = "from " + schools[selectedSchoolIndex].fullName + "."; + + document.getElementById("viewScheduleLink").style.display = "block"; + } + + + switch (getCurrentTimeState()) { + case DAY_OFF_FLAG: + document.getElementById("schedule").innerHTML = "There's no class today!" + document.getElementById("viewScheduleLink").style.display = "none"; + + let labels = document.getElementsByClassName("label") + for (let i = 0; i < labels.length; i++ ) { + labels[i].style.display = "none"; + } + + + break; + + case OUTSIDE_SCHOOL_HOURS_FLAG: + + if(compareTimes(getCurrentTimeObject(), schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[0].startTime) == -1) { + document.getElementById("countdownLabel").innerHTML = "School starts in: " + document.getElementById('timeToEndOfClass').innerHTML = getTimeToStartOfSchoolString(); + } else { + document.getElementById('timeToEndOfClass').innerHTML = "No Class"; + } + + document.getElementById("nextClass").innerHTML = getClassName(currentClassPeriodIndex+1) + document.getElementById("currentClass").innerHTML = getClassName(currentClassPeriodIndex) + + break; + + case SCHOOL_IN_CLASS_OUT_FLAG: - } else { + + document.getElementById("nextClass").innerHTML = getClassName(getMostRecentlyStartedClassIndex()+1) + document.getElementById("currentClass").innerHTML = schools[selectedSchoolIndex].passingPeriodName + document.getElementById('timeToEndOfClass').innerHTML = getTimeStringFromObject(getTimeTo(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[getMostRecentlyStartedClassIndex()+1].startTime)); + break; + + case CLASS_IN_SESSION_FLAG: document.getElementById("countdownLabel").innerHTML = "...which ends in: "; - document.getElementById('timeToEndOfClass').innerHTML = getTimeToEndOfCurrentClassString(); - } - - document.getElementById("nextClass").innerHTML = getClassName(currentClassPeriodIndex+1) - document.getElementById("currentClass").innerHTML = getClassName(currentClassPeriodIndex) - //document.getElementById('sentence').innerHTML = getSummaryString() + document.getElementById('timeToEndOfClass').innerHTML = getTimeStringFromObject(getTimeTo(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[getCurrentClassPeriodIndex()].endTime)); - labels = document.getElementsByClassName("label") + document.getElementById("nextClass").innerHTML = getClassName(currentClassPeriodIndex+1) + document.getElementById("currentClass").innerHTML = getClassName(currentClassPeriodIndex) + break; - for (var i = 0; i < labels.length; i++) { - labels[i].style.display = "block"; - } + default: - document.getElementById("viewScheduleLink").style.display = "block"; + + } + +} + + +/** + * @returns a flag that represents the current chunk of time categorically + */ +function getCurrentTimeState() { + + //there is no schedule that applies today + if (getCurrentScheduleIndex() <= -1) { return DAY_OFF_FLAG } + + //it is a school day but it is not school hours + else if (!schoolIsInSession()) { return OUTSIDE_SCHOOL_HOURS_FLAG } - } else { - labels = document.getElementsByClassName("label") + //the current time lies between the start of the first schedules class and the end of the last + else if (schoolIsInSession() && !classIsInSession()) { return SCHOOL_IN_CLASS_OUT_FLAG } + + //the current time lies within a scheduled class period + else if (classIsInSession()) { return CLASS_IN_SESSION_FLAG } - for (var i = 0; i < labels.length; i++) { - labels[i].style.display = "none"; - } - document.getElementById("viewScheduleLink").style.display = "none"; - } } /** @@ -263,7 +261,7 @@ function updateText() { */ function getCurrentScheduleName() { if (!isNoSchoolDay()) { - return data.schedules[currentScheduleIndex].name + return schools[selectedSchoolIndex].schedules[currentScheduleIndex].name } else { return "No School"} } @@ -277,6 +275,20 @@ function classIsInSession() { //might later want to add a check to make sure that currentClassPeriodIndex is not greater than the number of classes in the schedule for today } +/** + * this function checks to see if the current time is between the start of the first scheduled class and the end of the last scheduled class. This indicates that school is currently in session + * + * @returns a boolean representing if school is in session + */ +function schoolIsInSession() { + + return checkTimeRange( + getCurrentTimeObject(), + schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[0].startTime, + schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes.length-1].endTime + ) == 0 +} + /** * this function checks to see if the currentScheduleIndex is valid (greater than -1), indicating that there is a schedule for the day * @@ -289,58 +301,37 @@ function isNoSchoolDay() { /** - * Checks if the schedule exists - * @returns boolean describing if the schedule exists + * This function updates the variables that keep track of the current time and date */ -function scheduleExists() { - return typeof data !== 'undefined' -} - -function getSummaryString() { - if (isNoSchoolDay()) { - return "There's no class today!" +function updateTime() { + if (typeof selectedSchoolIndex !== 'undefined') { + currentDate = moment().tz(schools[selectedSchoolIndex].timeZone); } else { - return "You are viewing the " + getCurrentScheduleName() + " schedule." + currentDate = moment() } - //other options - //"it is currently ##:##:##. (period) ends in ##:##" } - - -/** - * This function updates the variables that keep track of the current time and date - */ -function updateTime() { - currentDate = new Date(); - - currentDay = currentDate.getDay(); // Sunday - Saturday : 0 - 6 - - currentHours = currentDate.getHours(); - currentMinutes = currentDate.getMinutes(); - currentSeconds = currentDate.getSeconds(); +function getCurrentTimeObject() { + return {hours: currentDate.hour(), minutes: currentDate.minute(), seconds: currentDate.second()} } - - + /** - * * @returns the current time as a formatted string */ -function getCurrentTimeString() { return currentDate.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: !use24HourTime }) } +function getCurrentTimeString() { return use24HourTime ? currentDate.format("h:mm:ss a") : currentDate.format("H:mm:ss") } /** - * * @returns the current date as a formatted string */ function getCurrentDateString() { -return "on " + currentDate.toLocaleString('en-US', { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' }) + "" + return "on " + currentDate.format("ddd, MMM Do, YYYY") + "" } /** * this function determines the index of the class period that is currently going on (if any) * - * @returns an index for looking up the current class period, or -1 if there is no school today + * @returns an index for looking up the current class period, or -1 if there is no class happening right now */ function getCurrentClassPeriodIndex() { if (isNoSchoolDay()) { @@ -349,15 +340,51 @@ function getCurrentClassPeriodIndex() { } //using for over forEach() because we are breaking out of the loop early - for (let i = 0; i < data.schedules[currentScheduleIndex].classes.length; i++) { - if (checkStartTime(data.schedules[currentScheduleIndex].classes[i]) && checkEndTime(data.schedules[currentScheduleIndex].classes[i])) { + for (let i = 0; i < schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes.length; i++) { + if (checkClassTime(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i]) == 0) { return i break;//not sure if this is necessary so I included it anyway } } - return -1 + return -1 //no match found, there is no class currently in session +} + + + +/** + * @returns the index of the class that started most recently + */ +function getMostRecentlyStartedClassIndex() { + + if (isNoSchoolDay()) { + //return immediately if there is no school today + return -1 + } + + + //using for over forEach() because we are breaking out of the loop early + for (let i = 0; i < schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes.length; i++) { + let classPeriodStatus = checkClassTime(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i]) + let nextClassPeriodStatus; + if (i+1 < schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes.length) { + nextClassPeriodStatus = checkClassTime(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i+1]) + } + + if (classPeriodStatus == -1) { + //class hasnt started, do nothing + } else if (classPeriodStatus == 0 ){ + //class is currently in session, return index + return i + } else if (classPeriodStatus == 1 && (typeof nextClassPeriodStatus !== "undefined" && nextClassPeriodStatus == -1)) { + //class has passed and next class hasnt started (indicating a passing period) + //return the class index + return i + } + } + } + /** * this function determines the index of the schedule that applies to today (if any) * @@ -365,8 +392,8 @@ function getCurrentClassPeriodIndex() { */ function getCurrentScheduleIndex() { //using for over forEach() because we are breaking out of the loop early - for (let i = 0; i < data.schedules.length; i++) { - if (data.schedules[i].days.includes(currentDay)) { + for (let i = 0; i < schools[selectedSchoolIndex].schedules.length; i++) { + if (schools[selectedSchoolIndex].schedules[i].days.includes(currentDate.day())) { return i } } @@ -374,35 +401,65 @@ function getCurrentScheduleIndex() { return -1 } + /** - * this function checks to see if the given time occurred before the current time, used for checking whether the current time falls within a scheduled class period + * Compares the hours and minutes of two times, aassuming all times occoured on the same day * - * @param {*} givenTime - * @returns true if the given time occurred before the current time, false otherwise + * @param {*} time1 + * @param {*} time2 + * @returns -1 if time1 is before time2, 0 if they are the same, 1 if time1 is after time2 */ -function checkGivenTimeIsBeforeCurrentTime( givenTime ) { - if (givenTime.hours < currentHours || (givenTime.hours == currentHours && givenTime.minutes <= currentMinutes)) { - //hours match and given minutes are before or the same as current minutes - return true - } else { return false } +function compareTimes( timeObject1, timeObject2 ) { + + let time1 = sanitizeTimeObject(timeObject1) + let time2 = sanitizeTimeObject(timeObject2) + + + let hoursDiff = time1.hours - time2.hours; + let minutesDiff = time1.minutes - time2.minutes; + let secondsDiff = time1.seconds - time2.seconds; + + if (hoursDiff < 0) {return -1} + else if (hoursDiff > 0) {return 1} + + //hours are the same if execution reaches here + + if (minutesDiff < 0) {return -1} + else if (minutesDiff > 0) {return 1} + + //hours and minutes are the same if execution reaches here + + if (secondsDiff < 0) {return -1} + else if (secondsDiff > 0) {return 1} + + //hours, minutes, and seconds are the same if execution reaches here + return 0 } /** - * checks that the time a class was scheduled to start has already passed (i.e. the class has started) - * - * @param {*} classPeriod the object representing the class period to be checked - * @returns true if the start time of the class has already passed, false otherwise + * This function checks if the current time is between the two given times + * This is useful for checking which class period you are currently in or for checking if school is in session. + * + * @param {*} checkTime the time that the check results are returned for + * @param {*} startTime the start time of the range to check + * @param {*} endTimethe the end time of the range to check + * + * @returns -1 if checkTime is before range, 0 if checkTime is within range, 1 if checkTime is after range */ -function checkStartTime(classPeriod) { return checkGivenTimeIsBeforeCurrentTime(classPeriod.startTime)} +function checkTimeRange(checkTime, startTime, endTime) { -/** - * checks that the time a class was scheduled to end has not already passed (i.e. the class has not yet ended) - * - * @param {*} classPeriod the object representing the class period to be checked - * @returns true if the end time of the class has not already passed, false otherwise - */ -function checkEndTime(classPeriod) { return !checkGivenTimeIsBeforeCurrentTime(classPeriod.endTime)} + let startCheck = compareTimes(checkTime, startTime) + let endCheck = compareTimes(checkTime, endTime) + + if (startCheck == -1) { return -1 } + else if ( startCheck >= 0 && endCheck <= 0) { return 0 } + else { return 1 } + +} +function checkClassTime(classPeriod) { + return checkTimeRange(getCurrentTimeObject(), classPeriod.startTime, classPeriod.endTime) +} /** * this function gets the absolute value of the difference between the given time and the current time @@ -410,14 +467,42 @@ function checkEndTime(classPeriod) { return !checkGivenTimeIsBeforeCurrentTime(c * @param {*} time the time that you want to calculate the delta to from the current time * @returns the absolute value of the difference between the given time and the current time as an object */ -function getTimeDelta(time) { - var currentTime = new Date(2000, 0, 1, currentHours, currentMinutes, currentSeconds); - var givenTime = new Date(2000, 0, 1, time.hours, time.minutes, 0); +function getTimeDelta(timeObject1, timeObject2) { + var time1 = new Date(2000, 0, 1, timeObject1.hours, timeObject1.minutes, timeObject1.seconds); + var time2 = new Date(2000, 0, 1, timeObject2.hours, timeObject2.minutes, timeObject2.seconds); //order doesnt matter - return convertMillisecondsToTime(Math.abs(givenTime - currentTime)); + return convertMillisecondsToTime(Math.abs(time1 - time2)); } + +/** + * this function returns a new time object that has been checked for inconsistencies + * such as omitted or invalid values and corrected + * + * @param {*} timeObject the timeObject to validate + * @returns a new, validated time object + */ +function sanitizeTimeObject(timeObject) { + + //this prevents the original object from being modified + var newTimeObject = timeObject; + + if (newTimeObject.hours == undefined ) { newTimeObject.hours = 0; } + if (newTimeObject.minutes == undefined ) { newTimeObject.minutes = 0; } + if (newTimeObject.seconds == undefined ) { newTimeObject.seconds = 0; } + // if (timeObject.milliseconds == undefined ) { timeObject.milliseconds = 0; } + + //timeObjects are always in 24-hour time + newTimeObject.hours = newTimeObject.hours % 24; + newTimeObject.minutes = newTimeObject.minutes % 60; + newTimeObject.seconds = newTimeObject.seconds % 60; + // timeObject.milliseconds = timeObject.milliseconds % 1000; + + return newTimeObject; +} + + /** * converts a given number of milliseconds into a time object. Used for calculating the time between now and the end of the current class * @@ -439,44 +524,29 @@ function convertMillisecondsToTime(milliseconds) { return time } -/** - * - * @returns the time to the end of the current class as a string - */ -function getTimeToEndOfCurrentClassString() { - if (classIsInSession()) { - return getTimeStringFromObject(getTimeDelta(data.schedules[currentScheduleIndex].classes[currentClassPeriodIndex].endTime)); - } else { - return "No Class" - } -} - /** * This fucntion is used for calculating how long until school starts * @returns the time to the start of school as a string */ function getTimeToStartOfSchoolString() { - if (!classIsInSession() && !isNoSchoolDay() && !checkGivenTimeIsBeforeCurrentTime(data.schedules[currentScheduleIndex].classes[0].startTime)) { - return getTimeStringFromObject(getTimeDelta(data.schedules[currentScheduleIndex].classes[0].startTime)); + if (!classIsInSession() && !isNoSchoolDay() && compareTimes(getCurrentTimeObject(), schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[0].startTime) == -1) { + return getTimeStringFromObject(getTimeTo(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[0].startTime)); } else { return "No Class" } } + /** - * this is a an unused method that was written for a feature that never got implemented and, as of this point in time, identical to @function getTimeToEndOfCurrentClassString() + * A shortcut function that inserts the current time into getTimeDelta() for convenience * - * @returns the time to the start of the next class as a string + * @param {*} timeObject + * @returns */ -function getTimeToStartOfNextClassString() { - if (classIsInSession() && currentClassPeriodIndex+1 < data.schedule[selectedSchedule].classes.length ) { - return getTimeStringFromObject(getTimeDelta(data.schedules[currentScheduleIndex].classes[currentClassPeriodIndex+1].startTime)); - } else { - return "No More Classes" - } +function getTimeTo(timeObject) { + return getTimeDelta(getCurrentTimeObject(), timeObject) } - /** * converts a time object into a string * @@ -499,8 +569,10 @@ function getTimeStringFromObject(timeObject, includeSeconds=true) { * @returns returns the class name for the given index or "No Class" if there is no class in session */ function getClassName(index) { - if (!isNoSchoolDay() && index >= 0 && index < data.schedules[currentScheduleIndex].classes.length) { - return data.schedules[currentScheduleIndex].classes[index].name.toString() + var classes = schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes; + + if (index >= 0 && index < classes.length) { + return classes[index].name.toString() } else { return "No Class" } @@ -519,19 +591,19 @@ function populateScheduleTable() { //tbl.setAttribute('border', '1'); var tbdy = document.createElement('tbody'); - for (var i = 0; i < data.schedules[currentScheduleIndex].classes.length; i++) { - if (data.schedules[currentScheduleIndex].classes[i].showInFullSchedule != false) { + for (var i = 0; i < schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes.length; i++) { + if (schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i].showInFullSchedule != false) { var tr = document.createElement('tr'); //for (var j = 0; j < 3; j++) { var td = document.createElement('td'); - td.innerHTML = data.schedules[currentScheduleIndex].classes[i].name; + td.innerHTML = schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i].name; td.style.fontWeight = "bold"; //td.appendChild(document.createTextNode(data.schedules[currentScheduleIndex].classes[i].name)) tr.appendChild(td) var td = document.createElement('td'); - td.innerHTML = getFormattedTimeStringFromObject(data.schedules[currentScheduleIndex].classes[i].startTime) + " - " + getFormattedTimeStringFromObject(data.schedules[currentScheduleIndex].classes[i].endTime) + td.innerHTML = getFormattedTimeStringFromObject(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i].startTime) + " - " + getFormattedTimeStringFromObject(schools[selectedSchoolIndex].schedules[currentScheduleIndex].classes[i].endTime) //td.appendChild(document.createTextNode(data.schedules[currentScheduleIndex].classes[i].name)) tr.appendChild(td); @@ -566,7 +638,7 @@ function getFormattedTimeStringFromObject(timeObject) { } /** - * Gets a value from HTML5 localStorage + * Gets a boolean value from HTML5 localStorage * * @param {*} key the key which the value is stored under * @param {boolean} [unsetDefault=false] the value to return if there was no item at that key. Default: false @@ -582,6 +654,62 @@ function getLocalStorageBoolean(key, unsetDefault=false) { } } +/** + * Gets a Number from HTML5 LocalStorage + * + * @param {*} key the key which the Number is stored under + * @returns the Number stored at the key if it exists, otherwise undefined. + */ +function getLocalStorageIndex(key) { + if (localStorage.getItem(key) !== null) { + return (Number(localStorage.getItem(key))) + } else { + return undefined; + } +} + +/** + * Causes a message to be displayed to the user. + * This is useful for displaying error or succcess messages or otherwise warning users about something that may impact their use of classclock + * + * @param {*} message the text of the message to display to the user + * @param {*} [type=FLASH_INFO] the flag of the style to use when displaying the message. Default: INFO + * @param {number} [timeout=5000] the mumber of milliseconds to wait before the message disappears again. Anything less than 1 will disable the timeout + */ +function flashMessage(message, type = FLASH_INFO, timeout = 5000) { + flash = document.getElementById("flash") + + flash.innerHTML = message; + // flash.style.visibility = "visible"; + flash.style.display = "normal"; + + switch (type) { + case FLASH_SUCCESS: + flash.className = "success"; + break; + + case FLASH_WARN: + flash.className = "warning"; + break; + + case FLASH_DANGER: + flash.className = "danger"; + break; + + default: //FLASH_INFO + flash.className = "info"; + } + // maybe animate down or fade in + + if (timeout > 0) { + setTimeout( function remove() { + // flash.style.visibility = "hidden"; + flash.style.display = "none"; + }, timeout) + } + +} + var a=document.getElementsByTagName("a"); for(var i=0;i

It is currently:

-

+
-

You are currently in:

-

+

+

+ View Schedule -

...which ends in:

-

+

You are currently in:

+

-

Your next class period is:

-

+

...which ends in:

+

- +

Your next class period is:

+

-View Schedule + + + + +
- - \ No newline at end of file + + \ No newline at end of file diff --git a/schedule.html b/schedule.html index 6fdb5aa..69e9c3e 100644 --- a/schedule.html +++ b/schedule.html @@ -16,8 +16,8 @@

diff --git a/settings.html b/settings.html index e7a6eba..cf85291 100644 --- a/settings.html +++ b/settings.html @@ -6,17 +6,18 @@
- - + + Settings are automatically saved
-

Settings are automatically saved

View on GitHub - Submit Feedback
+ Come chat on Slack!

Idea by: Dan Kumprey
Created by: Adrian Edwards and diff --git a/style.css b/style.css index 124fe4b..a8ea495 100644 --- a/style.css +++ b/style.css @@ -27,6 +27,16 @@ body { font-family: 'Source Sans Pro', Arial, Helvetica, sans-serif; color: white; font-size: 20px; + display: flex; + flex-direction: column; +} + +div#page { + flex: 1; + width: 100%; + height: 100%; + padding: 0; + margin: 0; } .time { @@ -52,10 +62,11 @@ body { .navButton { font-size: 32px; - position: absolute; + /* position: absolute; top: 0; - left: 0; - padding: 2px; + left: 0; */ + padding-right: 4px; + /* padding-bottom: 2px; */ border-bottom-right-radius: 10px; color: white; } @@ -81,6 +92,70 @@ h1.bigger { font-size: 3em; } +section#credits { + margin-top: 20vh +} + section#credits > a { margin: 5px; +} + +section#options > * { + display: block; + margin-top: 2vw; +} + +#flash { + /* flex: 1; */ + display:none; + margin: 0 auto; + display: block; + text-align: center; + width: 100vw; + /* border-bottom-right-radius: .5rem; + border-bottom-left-radius: .5rem; */ + border-bottom: 1px solid rgba(0, 0, 0, 0.5); +} + +#flash a { + font-weight: 700; + text-decoration: none; + +} +#flash a:hover { + text-decoration: underline; +} + +#flash.success { + background-color: #d4edda; /* copied from bootstrap */ + color: #155724; +} + +#flash.info { + color: #0c5460; /* copied from bootstrap */ + background-color: #a7d6f5; +} + +#flash.info a { + color: #002752; +} + +#flash.warning { + background-color: #faf0ce; + color: #856404; +} + +#flash.danger { + background-color: #f38c95; + color: #721c24; /* copied from bootstrap */ + +} + +.alert-link { + font-weight: 700; +} + +.verticalFlex { + display: flex; + flex-direction: column; } \ No newline at end of file