How to save time value in dynamically created li to input box with javascript - javascript

How to save a time value in dynamically created li to input box with javascript
I have a simple timer, that starts, stops, pauses, takes a time snap and resets the time snap.
The timesnap in generated and displayed in the webpage inside a li. It all works fine what I am struggling with is trying to click on a displayed time snap and have the value placed in an input box so I can later save a selected value to a database.
This is the script I am using to place the clicked on li item into the input box
var items = document.querySelectorAll("#list li");
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
document.getElementById("inptSnap").value = this.innerHTML;
};
}
This is the html
<div class="container">
<!-- Different App -->
<div class="timeDisplay">00:00:00</div>
<button id="begin">Start</button>
<button id="hold">Pause</button>
<button id="end">Stop</button>
<button id="timeSnap">Time Snap</button>
<button id="resetSnap">Reset Time Snap</button>
<ul id="list" class="laps"></ul>
<div>
<input type="text" id="inptSnap" />
</div>
</div>
This is the full timer script with the attempted select value onclick
var begin = document.getElementById("begin");
begin.addEventListener("click", start);
var end = document.getElementById("end");
end.addEventListener("click", stop);
var hold = document.getElementById("hold");
hold.addEventListener("click", pause);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", snap);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", pause);
var resetSnap = document.getElementById("resetSnap");
resetSnap.addEventListener("click", resetSnaps);
var ms = 0,
s = 0,
m = 0;
var timeCounter;
var displayEl = document.querySelector(".timeDisplay");
var lapsContainer = document.querySelector(".laps");
function start() {
if (!timeCounter) {
timeCounter = setInterval(run, 10);
}
}
function run() {
displayEl.textContent = displayTimeCount();
ms++;
if (ms == 100) {
ms = 0;
s++;
}
if (s == 60) {
s = 0;
m++;
}
}
function stop() {
stopTimer();
ms = 0;
s = 0;
m = 0;
displayEl.textContent = displayTimeCount();
}
function stopTimer() {
clearInterval(timeCounter);
timeCounter = false;
}
function pause() {
stopTimer();
}
function displayTimeCount() {
return (
(m < 10 ? "0" + m : m) +
":" +
(s < 10 ? "0" + s : s) +
":" +
(ms < 10 ? "0" + ms : ms)
);
}
function snap() {
if (timeCounter) {
var li = document.createElement("li");
li.innerText = displayTimeCount();
lapsContainer.appendChild(li);
}
}
function resetSnaps() {
lapsContainer.innerHTML = "";
}
// Script to put lap into input box
var items = document.querySelectorAll("#list li");
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
document.getElementById("inptSnap").value = this.innerHTML;
};
}
This is the CodePen Link
I would be very grateful for any pointers and advice, thanks

You can do somthing like that...
PS: I think that the ergonomics of your button is to be reviewed, I did a kind of revision.
const
btStartPause = document.querySelector('#container button:nth-of-type(1)')
, btStopClear = document.querySelector('#container button:nth-of-type(2)')
, btSnap = document.querySelector('#container button:nth-of-type(3)')
, snapList = document.querySelector('ol')
, inptSnap = document.querySelector('input#inptSnap')
, chrono = ((dZTime='#container time') =>
{
const
displZone = document.querySelector(dZTime)
, chronoZero = '00:00:00.000'
, one_Sec = 1000
//, one_Min = one_Sec * 60
//, one_Hrs = one_Min * 60
, n_Dgts = (n,t) => `${t}`.padStart(n,'0')
;
let startTime = null
, timeElapsed = 0
, pausedTime = 0
, reqRef = null
, reqPause = false
, stoped = false
;
displZone.textContent = chronoZero
function reqLoop(timeStamp) // timeStamp is float
{
startTime ??= timeStamp // Logical nullish assignment (??=)
if (stoped)
{
cancelAnimationFrame(reqRef)
return
}
if (reqPause)
{
pausedTime = (timeStamp - startTime) - timeElapsed;
}
else
{
timeElapsed = ((timeStamp - startTime) - pausedTime) | 0 // get integer part of float
let
Tms = timeElapsed % one_Sec
, tim = (timeElapsed - Tms) / one_Sec
, T_s = tim % 60
, T_m = 0
, T_h = 0
;
tim = (tim - T_s) / 60
T_m = tim % 60
T_h = (tim - T_m) / 60
displZone.textContent = `${n_Dgts(2,T_h)}:${n_Dgts(2,T_m)}:${n_Dgts(2,T_s)}.${n_Dgts(3,Tms)}`
}
requestAnimationFrame( reqLoop )
}
const jso =
{ dispSz: chronoZero.length
, getVal: ()=> displZone.textContent
, start() { reqRef = requestAnimationFrame(reqLoop) }
, pause(OnOff) { reqPause = OnOff }
, stop() { stoped = true }
, RaZ()
{
startTime = null
timeElapsed = 0
pausedTime = 0
reqRef = null
reqPause = false
stoped = false
displZone.textContent = chronoZero
}
}
Object.freeze(jso)
return jso
})()
;
btStartPause.onclick =_=>
{
if (btStartPause.classList.toggle('pause') )
{
btStopClear.disabled = false
if ( btStartPause.dataset.lib !== 'continue' )
{
btStartPause.dataset.lib = 'continue'
chrono.start()
}
else
chrono.pause(false)
}
else
{
btStopClear.disabled = true
btStopClear.classList.remove('clear')
chrono.pause(true)
}
}
btStopClear.onclick =_=>
{
if (btStopClear.classList.toggle('clear') )
{
btStartPause.disabled = true
btStartPause.dataset.lib = 'start'
btStartPause.classList.remove('pause')
chrono.stop()
}
else
{
btStartPause.disabled = false
btStopClear .disabled = true
chrono.RaZ()
}
}
btSnap.onclick =_=>
{
snapList
.appendChild( document.createElement('li'))
.innerHTML = chrono.getVal()
+ '<span title="delete"> ✖ </span>'
+ '<span title="copy"> &#x2398 </span>'
}
snapList.onclick =({target}) =>
{
if (!target.matches('li > span'))
{
inptSnap.value = target.closest('li').textContent.substring(0, chrono.dispSz)
inptSnap.focus()
return
}
if (target.matches('span[title=delete]'))
{
target.closest('li').remove()
}
if (target.matches('span[title=copy]'))
{
let origin = target.closest('li')
copySomething ( origin.textContent.substring(0, chrono.dispSz), origin )
}
}
async function copySomething(toCopy, el )
{
try
{
await navigator.clipboard.writeText(toCopy);
el.classList.add('copyOK')
setTimeout(() => { el.classList.remove('copyOK')}, 1200);
}
catch (err)
{
el.classList.add('copyBad')
setTimeout(() => { el.classList.remove('copyBad')}, 1200);
console.error('Failed to copy :/', err);
}
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
}
time {
display : block;
font-size : 1.4rem;
margin : .6rem 1rem;
letter-spacing : .2rem;
}
ol {
list-style : none;
font-size : 1.6rem;
padding : 0;
margin : 1.5rem;
width : 15rem;
list-style-type: decimal;
}
li {
border : 1px solid lightblue;
padding : .3rem .6rem;
position : relative;
cursor : pointer;
}
li::marker {
font-size : .9rem;
color : darkslategray;
}
li span {
float : right;
margin : 0 0 0 .3em;
font-size : 1.2rem;
color : darkslategray;
}
li span[title=delete]:hover {
color : crimson;
}
li span[title=copy]:hover {
background : white;
color : darkblue;
}
#container button {
min-width : 4.4rem;
text-transform : capitalize;
}
#container button:before {
content : attr(data-lib)
}
#container button.pause:before {
content : 'pause'
}
#container button.clear:before {
content : 'clear'
}
li:hover {
background : lightblue;
}
li.copyOK::after,
li.copyBad::after {
position : absolute;
display : block;
font-size : .8rem;
top : 1.2rem;
left : 11rem;
padding : .1rem .2rem;
}
li.copyOK::after {
content : 'copied';
background : lightgreen;
}
li.copyBad::after {
left : 1rem;
content : 'Failed to copy :/';
background : lightcoral;
}
<input type="text" id="inptSnap" >
<hr>
<div id="container">
<time datetime="00:00:00.000">00:00:00.000</time>
<button data-lib="start"><!-- start / continue / pause --></button>
<button data-lib="stop" disabled><!-- stop / clear --></button>
<button>snap</button>
</div>
<ol></ol>
for info :
Fastest way to cast a float to an int in javascript?

So I understand that you need a place value kind of thing.
var begin = document.getElementById("begin");
begin.addEventListener("click", start);
var end = document.getElementById("end");
end.addEventListener("click", stop);
var hold = document.getElementById("hold");
hold.addEventListener("click", pause);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", snap);
var timeSnap = document.getElementById("timeSnap");
timeSnap.addEventListener("click", pause);
var resetSnap = document.getElementById("resetSnap");
resetSnap.addEventListener("click", resetSnaps);
var ms = 0,
s = 0,
m = 0;
var timeCounter;
var displayEl = document.querySelector(".timeDisplay");
var lapsContainer = document.querySelector(".laps");
function start() {
if (!timeCounter) {
timeCounter = setInterval(run, 10);
}
}
function run() {
displayEl.textContent = displayTimeCount();
ms++;
if (ms == 100) {
ms = 0;
s++;
}
if (s == 60) {
s = 0;
m++;
}
}
function stop() {
stopTimer();
ms = 0;
s = 0;
m = 0;
displayEl.textContent = displayTimeCount();
}
function stopTimer() {
clearInterval(timeCounter);
timeCounter = false;
}
function pause() {
stopTimer();
}
function displayTimeCount() {
return (
(m < 10 ? "0" + m : m) +
":" +
(s < 10 ? "0" + s : s) +
":" +
(ms < 10 ? "0" + ms : ms)
);
}
function snap() {
if (timeCounter) {
var input = document.createElement("input");
input.value = displayTimeCount();
lapsContainer.appendChild(input);
}
}
function resetSnaps() {
lapsContainer.innerHTML = "";
}
// Script to put lap into input box
var items = document.querySelectorAll("#list li");
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
document.getElementById("inptSnap").value = this.innerHTML;
};
}
.timeDisplay {
font-size: 32px;
}
ul li {
list-style: none;
font-size: 32px;
}
.container {
width: 400px;
margin: auto;
}
<div class="container">
<!-- Different App -->
<div class="timeDisplay">00:00:00</div>
<button id="begin">Start</button>
<button id="hold">Pause</button>
<button id="end">Stop</button>
<button id="timeSnap">Time Snap</button>
<button id="resetSnap">Reset Time Snap</button>
<ul id="list" class="laps">
</ul>
<div>
<input type="text" id="inptSnap" />
</div>
</div>

Related

I am stuck fixing my issue here with an hp bar

So I am doing an hp bar using js, I make an hp bar with 3000/3000 hp, and I have an input where I can type my damage... But When ever I type 2999, it should be 1/3000 right, and the width of the current Hp bar is 0%, the problem is, when I do 2999 again, it remains 1/3000, and it should be 0/3000, I don't know why. Heres my code:
let damage = 0;
let width = 100;
let minWidth = 0;
let text = '';
let hp = document.getElementById('hp');
let hpText = document.getElementById('hpText');
let currentHp = 3000;
let maxHp = 3000;
hpText.innerText = currentHp + '/' + maxHp;
let setUp = () => {
damage = parseInt(document.getElementById('text').value);
text = document.getElementById('text').value;
if(text.length > 0){
currentHp -= damage;
}
if(currentHp <= 0) {
currentHp = 0;
}
minWidth = (currentHp / maxHp) * 100;
let interval = setInterval(() => {
if(!(width <= minWidth)) {
if(width <= 0) {
currentHp = 0;
hpText.innerText = currentHp + '/' + maxHp;
clearInterval(interval);
alert('ha')
return;
}
width--;
hp.style.width = width + '%';
hpText.innerText = currentHp + '/' + maxHp;
if(width <= minWidth) {
alert(minWidth + " " + width)
clearInterval(interval);
return;
}
}
}, 15);
}
Why make it simple when you can make it complicated? ;)
see also for styling : Custom styling progress bar in CSS
const hp =
{ bar: document.getElementById('hp-bar')
, txt: document.getElementById('hp-bar').nextElementSibling
, itv: null
}
hp.itv = setInterval(()=>
{
hp.bar.value += 10
hp.txt.textContent = `${hp.bar.value} / ${hp.bar.max}`
if ( hp.bar.value >= hp.bar.max) clearInterval( hp.itv )
},200)
progress {
--bar-color : #0c1c499d;
width : 20em;
height : .6em;
color : var(--bar-color);
transition : All 0.2s linear;
}
progress::-moz-progress-bar {
background-color: var(--bar-color);
}
progress ~ span {
display : inline-block;
width : 6.6em;
margin-left : 1em;
padding : .1em .5em;
text-align : right;
border : 1px solid cadetblue;
border-radius : .4em;
transform : translateY(.2em);
}
<progress id="hp-bar" min="0" max="3000" value=0></progress><span>0 / 3000</span>

How to automatically place "read more" when characters hit X amount

I'm currently using a nice bit of open source code which pulls Google reviews.
Issue is, if a review is very long... it makes my site look weird. I need to set a max amount of characters, but give the user the option to read the full review. I'm not sure if this should be done through jQuery, CSS or what... Looking for some guidance.
See my issue here:
My code is here:
jQuery(document).ready(function( $ ) {
$("#google-reviews").googlePlaces({
placeId: 'place ID' //Find placeID #: https://developers.google.com/places/place-id
, render: ['reviews']
, min_rating: 5
, max_rows:3
});
});
/* https://github.com/peledies/google-places */
(function($) {
$.googlePlaces = function(element, options) {
var defaults = {
placeId: 'place ID' // placeId provided by google api documentation
, render: ['reviews']
, min_rating: 0
, max_rows: 0
, rotateTime: false
};
var plugin = this;
plugin.settings = {}
var $element = $(element),
element = element;
plugin.init = function() {
plugin.settings = $.extend({}, defaults, options);
$element.html("<div id='map-plug'></div>"); // create a plug for google to load data into
initialize_place(function(place){
plugin.place_data = place;
// render specified sections
if(plugin.settings.render.indexOf('reviews') > -1){
renderReviews(plugin.place_data.reviews);
if(!!plugin.settings.rotateTime) {
initRotation();
}
}
});
}
var initialize_place = function(c){
var map = new google.maps.Map(document.getElementById('map-plug'));
var request = {
placeId: plugin.settings.placeId
};
var service = new google.maps.places.PlacesService(map);
service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
c(place);
}
});
}
var sort_by_date = function(ray) {
ray.sort(function(a, b){
var keyA = new Date(a.time),
keyB = new Date(b.time);
// Compare the 2 dates
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
return ray;
}
var filter_minimum_rating = function(reviews){
for (var i = reviews.length -1; i >= 0; i--) {
if(reviews[i].rating < plugin.settings.min_rating){
reviews.splice(i,1);
}
}
return reviews;
}
var renderReviews = function(reviews){
reviews = sort_by_date(reviews);
reviews = filter_minimum_rating(reviews);
var html = "";
var row_count = (plugin.settings.max_rows > 0)? plugin.settings.max_rows - 1 : reviews.length - 1;
// make sure the row_count is not greater than available records
row_count = (row_count > reviews.length-1)? reviews.length -1 : row_count;
for (var i = row_count; i >= 0; i--) {
var stars = renderStars(reviews[i].rating);
var date = convertTime(reviews[i].time);
html = html+"<div class='review-item'><div class='review-meta'><span class='review-author'>"+reviews[i].author_name+"</span><span class='review-sep'>, </span><span class='review-date'>"+date+"</span></div>"+stars+"<p class='review-text'>"+reviews[i].text+"</p></div>"
};
$element.append(html);
}
var initRotation = function() {
var $reviewEls = $element.children('.review-item');
var currentIdx = $reviewEls.length > 0 ? 0 : false;
$reviewEls.hide();
if(currentIdx !== false) {
$($reviewEls[currentIdx]).show();
setInterval(function(){
if(++currentIdx >= $reviewEls.length) {
currentIdx = 0;
}
$reviewEls.hide();
$($reviewEls[currentIdx]).fadeIn('slow');
}, plugin.settings.rotateTime);
}
}
var renderStars = function(rating){
var stars = "<div class='review-stars'><ul>";
// fill in gold stars
for (var i = 0; i < rating; i++) {
stars = stars+"<li><i class='star'></i></li>";
};
// fill in empty stars
if(rating < 5){
for (var i = 0; i < (5 - rating); i++) {
stars = stars+"<li><i class='star inactive'></i></li>";
};
}
stars = stars+"</ul></div>";
return stars;
}
var convertTime = function(UNIX_timestamp){
var a = new Date(UNIX_timestamp * 1000);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var time = months[a.getMonth()] + ' ' + a.getDate() + ', ' + a.getFullYear();
return time;
}
plugin.init();
}
$.fn.googlePlaces = function(options) {
return this.each(function() {
if (undefined == $(this).data('googlePlaces')) {
var plugin = new $.googlePlaces(this, options);
$(this).data('googlePlaces', plugin);
}
});
}
})(jQuery);
#map-plug {display:none;}
#google-reviews {
display:flex;
flex-wrap:wrap;
//display: grid;
//grid-template-columns: repeat( auto-fit, minmax(320px, 1fr));
}
.review-item {
margin:0 auto;
padding:1em;
flex: 1 1 20%;
}
#media ( max-width:1200px) {
.review-item { flex: 1 1 40%; }
}
#media ( max-width:450px) {
.review-item { flex: 1 1 90%; }
}
.review-meta, .review-stars {text-align:center; font-size:115%;}
.review-author { text-transform: capitalize; font-weight:bold; }
.review-date {opacity:.6; display:block;}
.review-text { line-height:1.55; text-align:left; max-width:32em; margin:auto;}
.review-stars ul {
display: inline-block;
list-style: none;
margin:0; padding:0;
}
.review-stars ul li {
float: left;
margin-right: 1px;
line-height:1;
}
.review-stars ul li i {
color: #E4B248;
font-size: 1.4em;
font-style:normal;
}
.review-stars ul li i.inactive { color: #c6c6c6;}
.star:after { content: "\2605"; }
<div id="google-reviews"></div>
The substr method will return the part of a string between the start index and a number of characters after it and will truncate your text.
Ex:
reviews[i].text.substr(0, 100 /* amount of characters */) + " read more..."

how to display counter value into the output to start a countdown

I'm building a counter and have some issue with. I have a counter field where increment and decrement happen (by default it's 5 minutes). When 'start' button is pressed the final counter's digit should be set as the timer in the output field.
here is my solution:
;(function(){
var output = document.querySelector('#output'),
btn = document.querySelector('button'),
min = 5,
sec = min * 60,
timer;
setCount(min);
function setCount(n){
var c = document.querySelector('#counter'),
increment = c.children[1].children[0],
decrement = c.children[1].children[2],
num = c.children[1].children[1];
increment.onclick = function(){
if(n >= 1) {num.textContent = ++n;}
};
decrement.onclick = function(){
if(n > 1) {num.textContent = --n;}
};
num.textContent = n;
}
function setTimer(){
var currentMin = Math.round((sec - 30) / 60),
currentSec = sec % 60;
if(currentMin >= 0 ) {currentMin = '0' + currentMin;}
if(currentSec <= 9 ) {currentSec = '0' + currentSec;}
if(sec !== 0){sec--;}
timer = setTimeout(setTimer,10); // 10 is for the speedy
output.textContent = currentMin + ':' + currentSec;
}
btn.addEventListener('click', setTimer, false);
})();
here is the link : JS Bin
TL;DR
if(n >= 1) {num.textContent = ++n; sec = n * 60;} // Line 15
...
if(n > 1) {num.textContent = --n; sec = n * 60; } // Line 19
Your timer is deriving it's start min value from the seconds, which is always equal to 5 * 60. You need to update the seconds every time that the + or - is clicked.
(function() {
var output = document.querySelector('#output');
var btn = document.querySelector('button');
var min = 5;
var sec = min * 60;
var timer;
var counter = document.querySelector('#counter ul');
var increment = counter.children[0];
var decrement = counter.children[2];
var number = counter.children[1];
number.textContent = min;
increment.onclick = function() {
min++;
number.textContent = min;
sec = min * 60;
};
decrement.onclick = function() {
min--;
if (min < 1) {
min = 1;
}
sec = min * 60;
number.textContent = min;
};
function setTimer() {
var currentMin = Math.round((sec - 30) / 60),
currentSec = sec % 60;
if (currentMin == 0 && currentSec == 0) {
output.textContent = '00:00';
return;
} else {
timer = setTimeout(setTimer, 10);
}
if (currentMin <= 9) {
currentMin = '0' + currentMin;
}
if (currentSec <= 0) {
currentSec = '0' + currentSec;
}
if (sec !== 0) {
sec--;
}
output.textContent = currentMin + ':' + currentSec;
console.log('currentMin: ' + currentMin);
}
btn.addEventListener('click', setTimer, false);
})();
#wrapper {
width: 300px;
border: 1px solid #f00;
text-align: center;
}
#output {
height: 40px;
line-height: 40px;
border-bottom: 1px solid #f00;
}
h4 {
margin: 10px 0;
}
ul {
margin: 0;
padding: 0;
}
li {
list-style: none;
width: 40px;
height: 40px;
line-height: 40px;
display: inline-block;
border: 1px solid #f00;
}
li:nth-child(odd) {
cursor: pointer;
}
button {
padding: 5px 15px;
margin: 10px 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="wrapper">
<div id="output"></div>
<div id="counter">
<h4>counter</h4>
<ul>
<li>+</li>
<li></li>
<li>-</li>
</ul>
</div>
<button id="start">start</button>
</div>
</body>
</html>

Count-up Timer required

I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!

javascript game ( 3 in line ) line check logic

i've been in a battle to sort this problem since yesterday and i fear that i've gotten tunnel vision.
The game:
first player to make a line of 3 of a kind (xxx or 000) wins.
http://jsfiddle.net/brunobliss/YANAW/
The catch:
Only the first horizontal line is working!!! I can make it all work using a lot of IFS but repeating the same code over and over again is often a good indicator that i'm doing somethin wrong
The problem:
bruno.checkWin(); will check if there's a line or not, the guy who presented me this game chalenge told me that it is possible to check the lines with a for loop and that i should use it instead of IFS. I can't solve this without IFS unfortunately...
<!doctype html>
<html>
<head>
<meta charset="iso-8859-1">
<title> </title>
<style>
#jogo {
border: #000 1px solid;
width: 150px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -75px;
margin-top: -75px;
}
#jogo div {
display: inline-block;
vertical-align: top;
width: 28px;
height: 28px;
padding: 10px;
font-size: 20px;
border: #000 1px solid;
border-collapse: collapse;
text-align: center;
}
#reset {
font-family: Verdana;
width: 153px;
height: 30px;
background-color: black;
color: white;
text-align: center;
cursor: pointer;
left: 50%;
top: 50%;
position: absolute;
margin-left: -76px;
margin-top: 100px;
}
</style>
<script> </script>
</head>
<body>
<div id="jogo"> </div>
<div id="reset"> RESET </div>
<script>
var ultimo = "0";
var reset = document.getElementById('reset');
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
var bruno = {
init: function () {
var jogo = document.getElementById('jogo');
for ( i = 0 ; i < 9 ; i++ ) {
var cell = document.createElement('div');
cell.onclick = function () {
// variavel publica dentro do obj?
ultimo = (ultimo == "x") ? 0 : "x";
this.innerHTML = ultimo;
bruno.checkWin();
};
jogo.appendChild(cell);
}
},
checkWin: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
// as diagonais nao verificar por loop
for ( i = 0 ; i < cell.length ; i=i+4 ) {
switch(i) {
case 0:
if (cell[0].innerHTML != '') {
bruno.checkFirst();
}
case 4:
if (cell[4].innerHTML != '') {
bruno.checkFirst();
}
case 8:
if (cell[8].innerHTML != '') {
bruno.checkFirst();
}
}
/*
} else
if (i == 4 && cell[4].innerHTML != '') {
bruno.checkCenter();
} else
if (i == 8 && cell[8].innerHTML != '') {
bruno.checkLast();
}*/
}
},
reset: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
for ( j = 0 ; j < cell.length ; j++ ) {
cell[j].innerHTML = "";
}
},
checkFirst: function () {
if (cell[0].innerHTML == cell[1].innerHTML && cell[1].innerHTML == cell[2].innerHTML) {
alert("linha horizontal");
return false;
} else
if (cell[0].innerHTML == cell[3].innerHTML && cell[3].innerHTML == cell[6].innerHTML) {
alert("linha vertical");
return false;
}
},
checkMiddle: function () {
// check vertical and horizontal lines from the center
},
checkLast: function () {
// check last horizontal and right edge vertical
}
};
window.onload = function () {
bruno.init();
};
reset.onclick = function () {
bruno.reset();
};
</script>
</body>
</html>
I came up with a more 'compact' version of your code. No switch statements. Have a look:
http://jsfiddle.net/YANAW/1/
Here's the code, for those who prefer to read it here. Important/updated functions are checkWin() and checkCells().
var bruno = {
init: function () {
var jogo = document.getElementById('jogo');
for ( i = 0 ; i < 9 ; i++ ) {
var cell = document.createElement('div');
cell.onclick = function () {
// variavel publica dentro do obj?
ultimo = (ultimo == "x") ? 0 : "x";
this.innerHTML = ultimo;
bruno.checkWin();
};
jogo.appendChild(cell);
}
},
checkWin: function () {
var jogo = document.getElementById('jogo');
var cells = jogo.getElementsByTagName('div');
// Scan through every cell
var numRows = 3;
var numColumns = 3;
for (var i = 0; i < cells.length; i++)
{
// Determine cell's position
var isHorizontalFirstCell = ((i % numColumns) === 0);
var isVerticalFirstCell = (i < numColumns);
var isTopLeftCorner = (i == 0);
var isTopRightCorner = (i == 2);
// Check for horizontal matches
if (isHorizontalFirstCell
&& bruno.checkCells(
cells, i,
(i + 3), 1))
{
alert('Horizontal');
}
// Check for vertical matches
if (isVerticalFirstCell
&& bruno.checkCells(
cells, i,
(i + 7), 3))
{
alert('Vertical');
}
// Check for diagonal matches
if (isTopLeftCorner
&& bruno.checkCells(
cells, i,
(i + 9), 4))
{
alert('Diagonal');
}
if (isTopRightCorner
&& bruno.checkCells(
cells, i,
(i + 5), 2))
{
alert('Diagonal');
}
}
},
reset: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
for ( j = 0 ; j < cell.length ; j++ ) {
cell[j].innerHTML = "";
}
},
checkCells: function(cells, index, limit, step) {
var sequenceChar = null;
for (var i = index; i < limit; i += step)
{
// Return false immediately if one
// of the cells in the sequence is empty
if (!cells[i].innerHTML)
return false;
// If this is the first cell we're checking,
// store the character(s) it holds.
if (sequenceChar === null)
sequenceChar = cells[i].innerHTML;
// Otherwise, confirm that this cell holds
// the same character(s) as the previous cell(s).
else if (cells[i].innerHTML !== sequenceChar)
return false;
}
// If we reached this point, the entire sequence
// of cells hold the same character(s).
return true;
}
};

Categories