JavaScript Time Exception Message - javascript

I'm currently working on a script that displays the amount of time until a period ends or starts in my school. One of the data sets in the array needs to be excluded from being counted as a period.
{ start: minutes(11, 20), end: minutes(11, 46) },
I want to exclude this data because its not a full fledged period, its lunch, and im not sure how I should go about doing it. Any ideas? Also the message would need to be changed to the user instead of.
document.getElementById("result").innerHTML = "There are " + timeLeft + " minutes left until period " + (i+1) + " is over."
Any ideas?
body, html {
height: 100%;
}
body {
background-color: #a00000;
margin: 0; /* remove default margins added by browsers */
}
.wrapper {
display: flex;
height: 100%;
}
#result {
margin: auto;
padding: 25px;
font-weight: bold;
text-align: center;
color:black;
width: 250px;
border-radius: 10px;
background-color: white;
}
h1 {
font-weight: bold;
margin:auto;
font-size: 20px;
}
.lunch {
width: 95px;
background-color: #a00000;
color: white;
border: 1px solid black;
border-radius: 5px;
padding: 5px;
margin-top: 10px;
}
<html>
<head>
<meta charset="UTF-8">
<title>Marking Period Countdow</title>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body onload="myFunction(myTime, periods);">
<script>
//Get current date & midnight
var now = new Date();
var midnight = new Date();
midnight.setHours(0,0,0,0);
//Get number of minutes that passed since midnight:
var myTime = Math.floor((now.getTime() - midnight.getTime()) / 60000);
//For Testing Purposes.
// console.log(myTime + ' minutes passed since midnight.');
function minutes(hour, min) {
return hour * 60 + min;
}
//All the periods throughout my school day.
var periods = [
{ start: minutes( 7, 45), end: minutes( 8, 34) },
{ start: minutes( 8, 38), end: minutes( 9, 30) },
{ start: minutes( 9, 34), end: minutes(10, 23) },
{ start: minutes(10, 27), end: minutes(11, 16) },
{ start: minutes(11, 20), end: minutes(12, 09) },
{ start: minutes(12, 12), end: minutes(12, 38) },
{ start: minutes(12, 42), end: minutes(13, 31) },
{ start: minutes(13, 35), end: minutes(14, 25) },
];
function myFunction(myTime, periods) {
periods.every(function (period, i) {
if (myTime < period.start) {
if (i == 0) {
console.log('School has not started yet');
document.getElementById("result").innerHTML = "School has not started yet";
} else {
var timeLeft = period.start - myTime;
console.log("There are " + timeLeft + " minutes left until period " + (i+1) + " starts.");
document.getElementById("result").innerHTML = "There are " + timeLeft + " minutes left until period " + (i+1) + " starts.";
}
} else if (myTime < period.end) {
var timeLeft = period.end - myTime;
console.log("There are " + timeLeft + " minutes left until period " + (i+1) + " is over.");
document.getElementById("result").innerHTML = "There are " + timeLeft + " minutes left until period " + (i+1) + " is over.";
} else if (i == periods.length - 1) {
console.log('School has finished for today');
document.getElementById("result").innerHTML = "School has finished for today";
} else {
return true; // keep looking for the right period
}
});
}
</script>
<div class="wrapper">
<div id="result"></div>
</div>
</body>
</html>

If you want to make it more functional, you can create functions for your messages and then let the periods themselves define which messages they should display. Like the following.
//Get current date & midnight
var now = new Date();
var midnight = new Date();
midnight.setHours(0, 0, 0, 0);
//Get number of minutes that passed since midnight:
var myTime = Math.floor((now.getTime() - midnight.getTime()) / 60000);
function minutes(hour, min) {
return hour * 60 + min;
}
function defaultMessage(minutes, i) {
document.getElementById("result").innerHTML = "There are " + minutes + " minutes left until period " + (i + 1) + " is over.";
};
function lunchMessage(minutes, i) {
document.getElementById("result").innerHTML = "Lunch will end in " + minutes + " minutes";
};
//All the periods throughout my school day.
var periods = [{
start: minutes(7, 45),
end: minutes(8, 34),
message: defaultMessage
}, {
start: minutes(8, 38),
end: minutes(9, 30),
message: defaultMessage
}, {
start: minutes(9, 34),
end: minutes(10, 23),
message: defaultMessage
}, {
start: minutes(10, 27),
end: minutes(11, 16),
message: defaultMessage
}, {
start: minutes(11, 20),
end: minutes(12, 09),
message: defaultMessage
}, {
start: minutes(12, 12),
end: minutes(12, 38),
message: lunchMessage
}, {
start: minutes(12, 42),
end: minutes(13, 31),
message: defaultMessage
}, {
start: minutes(13, 35),
end: minutes(14, 25),
message: defaultMessage
}, ];
function myFunction(myTime, periods) {
periods.every(function(period, i) {
if (myTime < period.start) {
if (i == 0) {
document.getElementById("result").innerHTML = "School has not started yet";
} else {
var timeLeft = period.start - myTime;
document.getElementById("result").innerHTML = "There are " + timeLeft + " minutes left until period " + (i+1) + " starts.";
}
} else if (myTime < period.end) {
var timeLeft = period.end - myTime;
period.message(timeLeft, i);
} else if (i == periods.length - 1) {
document.getElementById("result").innerHTML = "School has finished for today";
} else {
return true; // keep looking for the right period
}
});
}
body,
html {
height: 100%;
}
body {
background-color: #a00000;
margin: 0;
/* remove default margins added by browsers */
}
.wrapper {
display: flex;
height: 100%;
}
#result {
margin: auto;
padding: 25px;
font-weight: bold;
text-align: center;
color: black;
width: 250px;
border-radius: 10px;
background-color: white;
}
h1 {
font-weight: bold;
margin: auto;
font-size: 20px;
}
.lunch {
width: 95px;
background-color: #a00000;
color: white;
border: 1px solid black;
border-radius: 5px;
padding: 5px;
margin-top: 10px;
}
<body onload="myFunction(myTime, periods);">
<div class="wrapper">
<div id="result"></div>
</div>
</body>

I can only image how many students will be wanting to know how much time they have left ;)
What I believe you're looking for with regards to the exclusion is:
if (myTime > periods[4].start && myTime < periods[4].end) {
console.log('Lunch period');
document.getElementById("result").innerHTML = "Lunch period";
}
Place that just before if (myTime < period.start), and turn that line to an else if.
Not sure where your lunch break is from your array structure, but replace 4 with the break :)

Related

How could I add some HTML/Text into a Javascript text output? I can only seem to either only do JS or only text, not both

I am currently trying to design a scrolling command prompt with JS and HTML. Unfortunately I cannot find a way to output text and a JavaScript variable on the same line. I feel like I have tried a million things.
var textarea = $('.term');
var speed = 50; //Writing speed in milliseconds
var text = 'TEST';
var java = '282828'
var i = 0;
runner();
function runner() {
textarea.append(text.charAt(i));
i++;
setTimeout(
function() {
if (i < text.length)
runner();
else {
textarea.append("<br>")
i = 0;
setTimeout(function() {feedbacker();}, 1000);
}
}, Math.floor(Math.random() * 220) + 50);
}
var count = 0;
var time = 5;
function feedbacker() {
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
if (time % 10 == 0) {
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
}
if (time == 3) {
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
}
window.scrollTo(0, document.body.scrollHeight);
i++;
time = Math.floor(Math.random() * 1000) + 1000;
count += time;
setTimeout(
function() {
if (i < output.length - 2)
feedbacker();
else {
textarea.append("<br>Initialising...<br>");
setTimeout(function() {$(".load").fadeOut(1000);}, 1000000);
}
},time);
}
var output = [
"Below is a vat test",
"number" (java),
"Hello",
(java),
"Above is a test",
"Initialising...",
""];
html,
body {
margin: 0 auto;
height: 100%;
}
pre {
padding: 0;
margin: 0;
}
.load {
margin: 0 auto;
min-height: 100%;
width: 100%;
background: black;
}
.term {
font-family: monospace;
color: #fff;
opacity: 0.8;
font-size: 2em;
overflow-y: auto;
overflow-x: hidden;
padding-top: 10px;
padding-left: 20px;
}
.term:after {
content: "_";
opacity: 1;
animation: cursor 1s infinite;
}
#keyframes cursor {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="load">
<pre class="term">dev:~$ </pre>
</div>
This outputs correctly but any time I try to add text it fails. For example:
"number" (java),
"number", (java),
"number (java)",
"number '(java)'",
I think this output may be broken because it's a textarea. I am not sure. I would love to learn and get this figured out. Much appreciated!
var output = [
"Below is a vat test",
"number" (java),
"Hello",
(java),
"Above is a test",
"Initialising...",
""];
"number" (java) and (java) are not the correct way to display Javascript Variables.
You use simply java, or use + to concatenate two strings together such as "number" + java. You could be fancier with Template literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals:
var output = [
"Below is a vat test",
`number ${java}`,
"Hello",
java,
"Above is a test",
"Initialising...",
""];
Just use concatenation (+) to append a JavaScript variable to static content.
var textarea = $('.term');
var speed = 50; //Writing speed in milliseconds
var text = 'TEST';
var java = '282828'
var i = 0;
runner();
function runner() {
textarea.append(text.charAt(i));
i++;
setTimeout(
function() {
if (i < text.length)
runner();
else {
textarea.append("<br>")
i = 0;
setTimeout(function() {feedbacker();}, 1000);
}
}, Math.floor(Math.random() * 220) + 50);
}
var count = 0;
var time = 5;
function feedbacker() {
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
if (time % 10 == 0) {
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
}
if (time == 3) {
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
i++;
textarea.append("[ " + count / 1000 + "] " + output[i] + "<br>");
}
window.scrollTo(0, document.body.scrollHeight);
i++;
time = Math.floor(Math.random() * 1000) + 1000;
count += time;
setTimeout(
function() {
if (i < output.length - 2)
feedbacker();
else {
textarea.append("<br>Initialising...<br>");
setTimeout(function() {$(".load").fadeOut(1000);}, 1000000);
}
},time);
}
var output = [
"Below is a vat test",
"number (" + java + ")",
"Hello",
"(" + java + ")",
"Above is a test",
"Initialising...",
""];
html,
body {
margin: 0 auto;
height: 100%;
}
pre {
padding: 0;
margin: 0;
}
.load {
margin: 0 auto;
min-height: 100%;
width: 100%;
background: black;
}
.term {
font-family: monospace;
color: #fff;
opacity: 0.8;
font-size: 2em;
overflow-y: auto;
overflow-x: hidden;
padding-top: 10px;
padding-left: 20px;
}
.term:after {
content: "_";
opacity: 1;
animation: cursor 1s infinite;
}
#keyframes cursor {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="load">
<pre class="term">dev:~$ </pre>
</div>

JavaScript Amount Of Time

I'm currently working on a project that will display the amount of time left in a certain time period based on the users current time. Here is the code.
var periods = [
[ '07:45' , '08:34' ],
[ '08:38' , '09:30' ],
[ '09:34' , '10:23' ],
[ '10:27' , '11:16' ],
[ '11:20' , '12:38' ],
[ '12:42' , '15:55' ],
[ '07:00' , ]
];
updateTimePeriods();
setInterval(updateTimePeriods, 1000); // Update every second
function updateTimePeriods() {
var listEl = document.getElementById('periods');
var now = new Date();
var count = periods.length;
listEl.innerHTML='';
for (var i = 0; i < count; i++) {
if(formatTimeRemaining(timeLeft(now, periods[i][1])).charAt(0)!='–') {
child=listEl.appendChild(document.createElement('LI'));
child.innerHTML = periods[i][0] + ' — ' + periods[i][1]
+ ' => Duration: ' + formatUTCTime(duration(periods[i][0], periods[i][1]))
+ ', Remaining: ' + formatTimeRemaining(timeLeft(now, periods[i][1]));
}
}
}
function duration(start, end) {
var startTime = parseTime(start);
var endTime = parseTime(end);
return endTime.getTime() - startTime.getTime();
}
function timeLeft(now, end) {
var nowTime = parseTime(formatTime(now));
var endTime = parseTime(end);
return endTime.getTime() - nowTime.getTime();
}
function parseTime(timeStr) {
var tokens = timeStr.split(':');
return new Date(1970, 0, 1, parseInt(tokens[0], 10), parseInt(tokens[1], 10));
}
function formatUTCTime(time) {
var date = new Date(time);
return padZero(date.getUTCHours()) + ':' + padZero(date.getUTCMinutes());
}
function formatTime(time) {
var date = new Date(time);
return padZero(date.getHours()) + ':' + padZero(date.getMinutes());
}
function formatTimeRemaining(time) {
var sign = '+';
if (time < 0) { time *= -1; sign = '–'; }
var date = new Date(time);
return sign + padZero(date.getUTCHours()) + ':' + padZero(date.getUTCMinutes()) + ':' + padZero(date.getUTCSeconds());
}
function padZero(n) { return ('00' + n).substr(-2); }
body {
background-color: #A00000;
background-size: cover;
margin: 0;
padding: 0;
}
.outer-box {
border: 3px solid black;
height: true;
width: 75%;
padding: 10px;
margin: 10px auto 10px auto;
border-radius: 10px;
background-color: white;
text-align:center;
}
#periods {
border-radius: 5px;
margin: 20px auto 20px auto;
padding: 5px;
font-weight: bold;
text-align: center;
list-style-type: none;
}
<div class="outer-box">
<ul id="periods"></ul>
</div>
My goal is only display to the user the amount of time left in the current time period instead of all of them. And if its in between a time period it shows the amount of time until the next one occurs. The issue is once all the times occur I need to tell him much time until the start of the next time which occurs on a different day. To elaborate, currently if all the time periods occur it displays a blank space because there is nothing to display and all the times are negative. I want to display the amount of time until the next days starting time.
You should break the for loop as you create the new LI element. This way it should only show the actual time period.
for (var i = 0; i < count; i++) {
if(formatTimeRemaining(timeLeft(now, periods[i][1])).charAt(0)!='–') {
child=listEl.appendChild(document.createElement('LI'));
child.innerHTML = periods[i][0] + ' — ' + periods[i][1]
+ ' => Duration: ' + formatUTCTime(duration(periods[i][0], periods[i][1]))
+ ', Remaining: ' + formatTimeRemaining(timeLeft(now, periods[i][1]));
break;
}
}

Remove Component When Negative

My goal is to display to the user ONLY the time left in there current period. Currently it displays all of the periods duration and time reaming, I only want to display one, which is the time frame they are currently in.
var periods = [
[ '07:45' , '08:34' ],
[ '08:38' , '09:30' ],
[ '09:34' , '10:23' ],
[ '10:27' , '11:16' ],
[ '11:20' , '12:38' ],
[ '12:42' , '13:31' ],
[ '13:35' , '14:25' ]
];
generatePeriods();
updateTimePeriods();
setTimeout(updateTimePeriods, 1000); // Update every second
function generatePeriods() {
var listEl = document.getElementById('periods');
periods.forEach(function(period) {
listEl.appendChild(document.createElement('LI'));
});
}
function updateTimePeriods() {
var now = new Date();
var children = document.getElementById('periods').childNodes;
var i = 0;
for (var i = 0; i < children.length; i++) {
var child = children[i];
child.innerHTML = periods[i][0] + ' — ' + periods[i][1]
+ ' => Duration: ' + formatUTCTime(duration(periods[i][0], periods[i][1]))
+ ', Remaining: ' + formatTimeRemaining(timeLeft(now, periods[i][1]));
}
}
function duration(start, end) {
var startTime = parseTime(start);
var endTime = parseTime(end);
return endTime.getTime() - startTime.getTime();
}
function timeLeft(now, end) {
var nowTime = parseTime(formatTime(now));
var endTime = parseTime(end);
return endTime.getTime() - nowTime.getTime();
}
function parseTime(timeStr) {
var tokens = timeStr.split(':');
return new Date(1970, 0, 1, parseInt(tokens[0], 10), parseInt(tokens[1], 10));
}
function formatUTCTime(time) {
var date = new Date(time);
return padZero(date.getUTCHours()) + ':' + padZero(date.getUTCMinutes());
}
function formatTime(time) {
var date = new Date(time);
return padZero(date.getHours()) + ':' + padZero(date.getMinutes());
}
function formatTimeRemaining(time) {
var sign = '+';
if (time < 0) { time *= -1; sign = '–'; }
var date = new Date(time);
return sign + padZero(date.getUTCHours()) + ':' + padZero(date.getUTCMinutes()) + ':' + padZero(date.getUTCSeconds());
}
function padZero(n) { return ('00' + n).substr(-2); }
body {
background-color: #A00000;
background-size: cover;
margin: 0;
padding: 0;
}
.outer-box {
border: 3px solid black;
height: true;
width: 75%;
padding: 10px;
margin: 10px auto 10px auto;
border-radius: 10px;
background-color: white;
text-align:center;
}
#periods {
border-radius: 5px;
margin: 20px auto 20px auto;
padding: 5px;
font-weight: bold;
text-align: center;
}
<div class="outer-box">
<div id="periods"></div>
</div>
You can check the time using the following snippet :
for (var i = 0; i < children.length; i++) {
var child = children[i];
var now = new Date();
var nowHour = now.getHours();
if(periods[i][0] > nowHour) {
child.innerHTML = periods[i][0] + ' — ' + periods[i][1]
+ ' => Duration: ' + formatUTCTime(duration(periods[i][0], periods[i][1]))
+ ', Remaining: ' + formatTimeRemaining(timeLeft(now, periods[i][1]));
}
}
First, i have slightly changed your HTML, li should be child of ul.
Then i've removed your generatePeriods() function.
If you don't want to show all periods (just positive) - you don't need empty li elements.
Then i slightly modified your updateTimePeriods() function:
function updateTimePeriods() {
var listEl = document.getElementById('periods');
var now = new Date();
var count = periods.length;
listEl.innerHTML='';
for (var i = 0; i < count; i++) {
if(formatTimeRemaining(timeLeft(now, periods[i][1])).charAt(0)!='–') { // check if negative
child=listEl.appendChild(document.createElement('LI'));
child.innerHTML = periods[i][0] + ' — ' + periods[i][1]
+ ' => Duration: ' + formatUTCTime(duration(periods[i][0], periods[i][1]))
+ ', Remaining: ' + formatTimeRemaining(timeLeft(now, periods[i][1]));
}
}
}
So, now it should work like this:
var periods = [
[ '07:45' , '08:34' ],
[ '08:38' , '09:30' ],
[ '09:34' , '10:23' ],
[ '10:27' , '11:16' ],
[ '11:20' , '12:38' ],
[ '12:42' , '15:55' ],
[ '13:35' , '15:56' ]
];
updateTimePeriods();
setInterval(updateTimePeriods, 1000); // Update every second
function updateTimePeriods() {
var listEl = document.getElementById('periods');
var now = new Date();
var count = periods.length;
listEl.innerHTML='';
for (var i = 0; i < count; i++) {
if(formatTimeRemaining(timeLeft(now, periods[i][1])).charAt(0)!='–') {
child=listEl.appendChild(document.createElement('LI'));
child.innerHTML = periods[i][0] + ' — ' + periods[i][1]
+ ' => Duration: ' + formatUTCTime(duration(periods[i][0], periods[i][1]))
+ ', Remaining: ' + formatTimeRemaining(timeLeft(now, periods[i][1]));
}
}
}
function duration(start, end) {
var startTime = parseTime(start);
var endTime = parseTime(end);
return endTime.getTime() - startTime.getTime();
}
function timeLeft(now, end) {
var nowTime = parseTime(formatTime(now));
var endTime = parseTime(end);
return endTime.getTime() - nowTime.getTime();
}
function parseTime(timeStr) {
var tokens = timeStr.split(':');
return new Date(1970, 0, 1, parseInt(tokens[0], 10), parseInt(tokens[1], 10));
}
function formatUTCTime(time) {
var date = new Date(time);
return padZero(date.getUTCHours()) + ':' + padZero(date.getUTCMinutes());
}
function formatTime(time) {
var date = new Date(time);
return padZero(date.getHours()) + ':' + padZero(date.getMinutes());
}
function formatTimeRemaining(time) {
var sign = '+';
if (time < 0) { time *= -1; sign = '–'; }
var date = new Date(time);
return sign + padZero(date.getUTCHours()) + ':' + padZero(date.getUTCMinutes()) + ':' + padZero(date.getUTCSeconds());
}
function padZero(n) { return ('00' + n).substr(-2); }
body {
background-color: #A00000;
background-size: cover;
margin: 0;
padding: 0;
}
.outer-box {
border: 3px solid black;
height: true;
width: 75%;
padding: 10px;
margin: 10px auto 10px auto;
border-radius: 10px;
background-color: white;
text-align:center;
}
#periods {
border-radius: 5px;
margin: 20px auto 20px auto;
padding: 5px;
font-weight: bold;
text-align: center;
}
<div class="outer-box">
<ul id="periods"></ul>
</div>
P.S. I've updated periods array because of testing.

XML only show <Candidate></Candidate> if votes > 0

I am trying to show <Candidate></Candidate> in Rutland County with only votes higher than 0. Right now it shows them all just in Rutland County.
https://jsfiddle.net/jeffd/yqbwaxts/3/
https://99centbeats.com/ResultsData.xml
So Far:
$(document).ready(function() {
$.ajax({
type: 'GET',
url: 'https://99centbeats.com/ResultsData.xml',
//url: 'https://vtelectionresults.sec.state.vt.us/rss/2713/ResultsData.xml',
crossDomain: true,
success: parseXml
});
});
function parseXml(xml) {
$(xml).find('Town').each(function() {
var county = $(this).find('County').text(); //change to county for 'County'
window.votes = $(this).find('Votes').text();
if (county == 'RUTLAND') { // change to 'RUTLAND' for Rutland County
if (votes !== '0'){
window.townname = $(this).find('TownName').text();
window.officename = $(this).find('OfficeName, Name, Votes');
var newItems = $.map(officename, function(i) {
$(i).filter('0')
return $(i).text();
});
newItems2 = ("" + newItems).replace(/,/g, " - ");
$(".marquee").append(' - <strong>' + townname + '</strong>' + ' - ' + newItems2);
}
}
});
$('.marquee').marquee({
duration: 5000 // Speed of the counter (Lower = Faster)
});
}
setTimeout(function() {
window.location.reload(1);
}, 300000); // Refresh Results Every 5 Minutes
It seems like you're going at this rather haphazardly, just grabbing elements and stringing them together. It's better to methodically get the offices within a town, then their candidates, then filter those candidates by votes, etc.
The following should work, though it seems that there's currently only one candidate in one Rutland town that has any votes:
//Must have Allow-Control-Allow-Origin chrome plugin installed to work
$(document).ready(function() {
$.ajax({
type: 'GET',
url: 'https://99centbeats.com/ResultsData.xml',
//url: 'https://vtelectionresults.sec.state.vt.us/rss/2713/ResultsData.xml',
crossDomain: true,
success: parseXml
});
});
function textForOffice(office) {
var candidates = $(office).find('Candidate').filter(function(i, el) {
return $(el).find('Votes').text() > 0;
});
if (candidates.length === 0) {
return '';
}
var officeName = $(office).find('OfficeName').text();
var candidateValues = candidates.toArray().map(function (el) {
return $(el).find('Name').text() + ' - ' + $(el).find('Votes').text();
});
return ' - ' + officeName + ' - ' + candidateValues.join(' - ');
}
function parseXml(xml) {
$(xml).find('Town').each(function() {
var town = $(this);
var county = town.find('County').text(); //change to county for 'County'
if (county == 'RUTLAND') { // change to 'RUTLAND' for Rutland County
var townname = town.find('TownName').text();
var offices = town.find('Office');
var textForOffices = offices.toArray().map(textForOffice);
$(".marquee").append(' - <strong>' + townname + '</strong>' + textForOffices.join(''));
}
});
$('.marquee').marquee({
duration: 5000 // Speed of the counter (Lower = Faster)
});
}
setTimeout(function() {
window.location.reload(1);
}, 300000); // Refresh Results Every 5 Minutes
.rssfeed {
background-color: black;
color: white;
bottom: 0;
font-family: Gotham, Helvetica Neue, Helvetica, Arial, " sans-serif";
height: 150px;
line-height: 150px;
font-size: 32px;
}
.marquee {
overflow: hidden;
width: 100%;
white-space: nowrap;
}
.description {
width: 100%;
height: 50px;
background: red;
color: white;
line-height: 50px;
text-align: center;
font-family: Gotham, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 24px;
}
<div class="description">Rutland City - Vote Count Per Ward</div>
<div class="rssfeed">
<div class="marquee"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.marquee/1.4.0/jquery.marquee.min.js"></script>

Selecting a clicked element based on its data attribute

I'm working on a personal trainer website that lets you choose the time of your training session. There are 6 times available: 5 mins, 10 mins, 15 mins, and so on. This is what I have so far.
I want to highlight the time that you've chosen. I've only tried to implement this for the top row of times, and when you click a time to highlight it the other ones don't get unhighlighted, but that is not why I'm asking this question. My problem is that when you click on a time, nothing happens. I've tried looking in the console and this is the error it throws:
What's wrong with my code?
$("body").append(
"<p class='text' id='CYTText'>Choose your session's time:</p>"
);
setUpCYT(350, 200, 0.8, 0.85);
function setUpCYT(littleXOffset, littleYOffset, littleScale, littleOpacity) {
for (i = 1; i < 4; i++) {
var timeSelectorElement = "[data='" + i + "']";
var timeSelectorName = "timeSelector"+i;
$("body").append(
"<p class='text' id='CYTTimerText' data='" + i + "' onclick='selectTime(" + timeSelectorElement + ")'>00:00</p>"
);
$("[data='" + i + "']").css({"left":littleXOffset * (i-2), "-webkit-transform":"scale(" + littleScale + ")", "opacity":littleOpacity});
timeSelectorName = new Timer(timeSelectorElement);
timeSelectorName.set(i*5,0);
}
for (i = 1; i < 4; i++) {
$("body").append(
"<p class='text' id='CYTTimerText' data='" + i+3 + "'>00:00</p>"
);
$("[data='" + i+3 + "']").css({"top":littleYOffset, "left":littleXOffset * (i-2), "-webkit-transform":"scale(" + littleScale + ")", "opacity":littleOpacity});
var timeSelectorElement = "[data='" + i+3 + "']";
var timeSelectorName = "timeSelector"+i+3;
timeSelectorName = new Timer(timeSelectorElement);
timeSelectorName.set((i+3)*5,0);
}
//select the middle
selectTime("[data='2']");
}
function selectTime(data) {
TweenLite.to($(data), 0.5, {
"-webkit-transform":"scale(1)",
"opacity":1
});
}
//timer function
function Timer (element) {
var minutes, seconds, finalTimeInSeconds, displayMinutes, displaySeconds, interval = 1000, self = this, timeLeftToNextSecond = 1000, running = false;
this.set = function(inputMinutes, inputSeconds) {
finalTimeInSeconds = inputMinutes * 60 + inputSeconds;
minutes = (Math.floor(finalTimeInSeconds / 60));
seconds = finalTimeInSeconds % 60;
this.print();
}
this.add = function(inputMinutes, inputSeconds) {
finalTimeInSeconds += inputMinutes * 60 + inputSeconds;
finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
minutes = (Math.floor(finalTimeInSeconds / 60));
seconds = finalTimeInSeconds % 60;
this.print();
}
this.subtract = function(inputMinutes, inputSeconds) {
finalTimeInSeconds -= inputMinutes * 60 + inputSeconds;
if(finalTimeInSeconds < 0) {nextTask()}
finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
minutes = (Math.floor(finalTimeInSeconds / 60));
seconds = finalTimeInSeconds % 60;
this.print();
}
this.reset = function() {
this.set(0,0);
}
this.print = function() {
displayMinutes = (minutes.toString().length == 1) ? "0" + minutes : minutes; //ternary operator: adds a zero to the beggining
displaySeconds = (seconds.toString().length == 1) ? "0" + seconds : seconds; //of the number if it has only one caracter.
$(element).text(displayMinutes + ":" + displaySeconds);
}
this.run = function() {
if (running == false) {
running = true;
var _f = function() {
secondStarted = new Date;
self.subtract(0, 1);
interval = 1000;
var theColorIs = $(element).css("color");
ac = setTimeout(_f,interval);
}
ac = setTimeout(_f, interval);
}
}
this.stop = function() {
if (running == true) {
running = false;
stopped = new Date;
interval = 1000 - (stopped - secondStarted);
clearTimeout(ac);
}
}
}
body{
background-color: #02BFC1;
overflow:hidden;
margin: 0;
}
#font-face {
font-family: 'Bebas Neue';
font-style: normal;
font-weight: normal;
src: local('Bebas Neue'), url('BebasNeue.woff') format('woff');
}
.text {
color: #F1F2F0;
font-family:Bebas Neue;
-webkit-user-select: none;
cursor: default;
text-shadow: 3px 3px 2px rgba(0,0,0,0.2);
}
#CYTText {
text-align:center;
height: 100px;
position: absolute;
margin: auto;
top: 0;
bottom: 290px;
right: 0;
left: 0;
font-size:50px;
}
#CYTTimerText {
text-align:center;
height: 100px;
position: absolute;
margin: auto;
top: 0;
bottom: 150px;
right: 0;
left: 0;
font-size:95px;
}
The syntax error is caused by the string that you're passing to append():
$("body").append(
"<p class='text' id='CYTTimerText' data='" + i +
"' onclick='selectTime(" + timeSelectorElement + ")'>00:00</p>"
);
Let's print an instance of this string and examine it:
<p class='text' id='CYTTimerText' data='1' onclick='selectTime([data='1'])'>00:00</p>
Observe that the onclick handler is a code fragment delimited by single quotes:
onclick='selectTime([data='
We can fix this by replacing the single quotes with escaped double quotes:
$("body").append(
"<p class='text' id='CYTTimerText' data='" + i +
"' onclick=\"selectTime(" + timeSelectorElement + ")\">00:00</p>"
);
However, now we have another problem. An instance of the string looks like this:
<p class='text' id='CYTTimerText' data='1' onclick="selectTime([data='1'])">00:00</p>
The code for onclick is selectTime([data='1']), which is syntactically incorrect. The intention is to pass the string "[data='1']" to selectTime.
The inline HTML already uses double quotes to delimit the onclick value. How do we put double quotes inside this value? We have to use " for each double quote:
$("body").append(
"<p class='text' id='CYTTimerText' data='" + i + "' onclick=\"selectTime("" + timeSelectorElement + "")\">00:00</p>"
);
Now an instance of the string looks like this:
<p class='text' id='CYTTimerText' data='1' onclick="selectTime("[data='1']")">00:00</p>
That looks strange, but it will be correct once it has been inserted into the document.
After making that change, the code sort of works. It's still not right because you have layout problems, but at least you can click on the 15:00 time and see that the onclick handler calls selectTime correctly.
By the way, there are better approaches than building that complicated string. You can simplify the inline handler to onclick="selectTime(this)", where this will have the value of the object that was clicked. An even better way to go about it would be to avoid inline handler definitions. Instead, build a paragraph object and make a new function that you assign as a click handler.
Regardless of how you implement the onclick handler, you're left with the problem of overlapping timer elements. Your timers are paragraphs that you've absolutely positioned next to one another. The paragraphs stretch as wide as possible. Thus, the first timer is obscured by subsequent timers.
You can get rid of the overlap by displaying the timers as inline-block elements. To restrict the width of the layout, put everything into a wrapper div. The following snippet demonstrates this approach.
window.onload = function () {
$('#wrapTimers').append(
"<p class='text' id='CYTText'>Choose your session duration:</p>"
);
setUpCYT(350, 200, 0.8, 0.85);
};
function setUpCYT(littleXOffset, littleYOffset, littleScale, littleOpacity) {
for (i = 1; i < 4; i++) {
var timeSelectorElement = "[data='" + i + "']";
var timeSelectorName = "timeSelector"+i;
var s = "<p class='text timerContainer' data='" + i +
"' onclick=\"selectTime(this)\">00:00</p>";
//"' onclick=\"selectTime("" + timeSelectorElement + "")\">00:00</p>";
$('#wrapTimers').append(s);
$("[data='" + i + "']").css({"left":littleXOffset * (i-2), "-webkit-transform":"scale(" + littleScale + ")", "opacity":littleOpacity});
timeSelectorName = new Timer(timeSelectorElement);
timeSelectorName.set(i*5,0);
}
for (i = 1; i < 4; i++) {
$('#wrapTimers').append(
"<p class='text timerContainer' data='" + i+3 + "'>00:00</p>"
);
$("[data='" + i+3 + "']").css({"top":littleYOffset, "left":littleXOffset * (i-2), "-webkit-transform":"scale(" + littleScale + ")", "opacity":littleOpacity});
var timeSelectorElement = "[data='" + i+3 + "']";
var timeSelectorName = "timeSelector"+i+3;
timeSelectorName = new Timer(timeSelectorElement);
timeSelectorName.set((i+3)*5,0);
}
//select the middle
selectTime("[data='2']");
}
function selectTime(selector) {
TweenLite.to($(selector), 0.5, {
"-webkit-transform":"scale(1)",
"opacity":1
});
}
//timer function
function Timer (element) {
var minutes, seconds, finalTimeInSeconds, displayMinutes, displaySeconds, interval = 1000, self = this, timeLeftToNextSecond = 1000, running = false;
this.set = function(inputMinutes, inputSeconds) {
finalTimeInSeconds = inputMinutes * 60 + inputSeconds;
minutes = (Math.floor(finalTimeInSeconds / 60));
seconds = finalTimeInSeconds % 60;
this.print();
}
this.add = function(inputMinutes, inputSeconds) {
finalTimeInSeconds += inputMinutes * 60 + inputSeconds;
finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
minutes = (Math.floor(finalTimeInSeconds / 60));
seconds = finalTimeInSeconds % 60;
this.print();
}
this.subtract = function(inputMinutes, inputSeconds) {
finalTimeInSeconds -= inputMinutes * 60 + inputSeconds;
if(finalTimeInSeconds < 0) {nextTask()}
finalTimeInSeconds = (finalTimeInSeconds < 0) ? 0 : finalTimeInSeconds;
minutes = (Math.floor(finalTimeInSeconds / 60));
seconds = finalTimeInSeconds % 60;
this.print();
}
this.reset = function() {
this.set(0,0);
}
this.print = function() {
displayMinutes = (minutes.toString().length == 1) ? "0" + minutes : minutes; //ternary operator: adds a zero to the beggining
displaySeconds = (seconds.toString().length == 1) ? "0" + seconds : seconds; //of the number if it has only one caracter.
$(element).text(displayMinutes + ":" + displaySeconds);
}
this.run = function() {
if (running == false) {
running = true;
var _f = function() {
secondStarted = new Date;
self.subtract(0, 1);
interval = 1000;
var theColorIs = $(element).css("color");
ac = setTimeout(_f,interval);
}
ac = setTimeout(_f, interval);
}
}
this.stop = function() {
if (running == true) {
running = false;
stopped = new Date;
interval = 1000 - (stopped - secondStarted);
clearTimeout(ac);
}
}
}
body {
background-color: #02BFC1;
overflow: hidden;
margin: 0;
}
#wrapTimers {
width: 800px;
margin: 40px auto;
text-align: center;
}
.text {
color: #F1F2F0;
font-family: Oswald, sans-serif;
-webkit-user-select: none;
cursor: default;
text-shadow: 3px 3px 2px rgba(0, 0, 0, 0.2);
}
#CYTText {
width: 800px;
margin: auto;
font-size: 50px;
}
.timerContainer {
text-align: center;
display: inline-block;
font-size: 95px;
margin: 0 10px;
}
<link rel="stylesheet" type="text/css"
href="https://fonts.googleapis.com/css?family=Oswald" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<div id="wrapTimers"></div>
There are a couple of simple issues. first off the string isn't being parsed correctly that is setting up the onclick
Closing quotes
It should look like this: onclick="selectTime("[data='2']")"
But it looks like this: onclick="selectTime([data=" 2'])'
Reference Error
There is also a scoping /reference error for the function selectTime the click is trying to call
Here is the full working example: http://jsfiddle.net/qLnLmgy6/2/
Hope that helps!

Categories

Resources