Count down timer on button click - button

So I created a count down timer that starts when the person clicks on the button. the countdown timer works but the issue i an running into are two things:
if a person click on the button a second time it speeds up the timers
If a person click on the button after the timer finish it starts to show a negative number.
I am still learning Java and cannot figure this one out.
<button
style="
background:#f1b005;
margin-bottom: 25px;
border:0px;
color: White;
text-align: center;
text-decoration: none;
display: inline-block;
height:50px;
width:125px;
border-radius: 5px;
align:center;
cursor: pointer;"
onclick="onTimer()">
120 Sec Rest
</button>
<div
style="60px;
font-size:30px;
text-align:center;
color:#f1b005;"
id="mycounter">
</div>
<script>
i = 120;
function onTimer() {
document.getElementById('mycounter').innerHTML = i;
i--;
if (i < 0) {
alert('Times Up! Lets Get It!');
clearInerval(i);
}
else {
setTimeout(onTimer, 1000);
}
}
</script>

You have multiple mistakes.
You wrote clearInerval(i) instead of clearInterval(i).
You put the definition of i outside the function - so it's set once, and every time it's clicked, it does the function but does not reset i.
It speeds down because you are doing i--, which makes the value of i one lower.
The major problem is that you set i outside the function.
Try this:
<script>
function onTimer() {
i = 120;
document.getElementById('mycounter').innerHTML = i;
i--;
if (i < 0) {
alert('Times Up! Lets Get It!');
clearInterval(i);
}
else {
setTimeout(onTimer, 1000);
}
}
</script>
Look here for an example of nicer code, just change i++ to i-- to make it count down instead of up in this example: Javascript Second Counter

Related

CodeMirror Line-Break doesn't add line number - Angular

I'm using code mirror from ngx-codemirror. I want to split the line when it fits to the width of the parent. I have found some solutions to split the like using,
lineWrapping: true
and in styles
.CodeMirror-wrap pre {
word-break: break-word;
}
Using this I was able to split the line but I need to show the line number too.
The line number is not shown for the line that was just split.
This is the stackblitz link to my issue : code-mirror-line-break-issue
Screenshot :
Please help me with this.
This is not feasible using Code Mirror options, as this is something that is a bit counter intuitive that is rarely (ever?) wanted.
Like I said in my comment, say 2 persons discussing on a phone/web chat about a piece of code/json. They will not see the same thing when one mentions a line number to the other if they have different windows/screen sizes
Solution
As a hack, you can create your own elements representing line numbers and place them over the default line numbers.
Here is the stackblitz demo
Note: This a a very basic example. If you change code mirror settings (font size, gutters,...), you might need to tweak the css or do more calculation based on these settings.
component.html
<div class='codeMirrorContainer'>
<ngx-codemirror
#codeMirror
[options]="codeMirrorOptions"
[(ngModel)]="codeObj"
></ngx-codemirror>
<ul class='lineContainer' [style.top.px]="-topPosition">
<li [style.width.px]='lineWidth' *ngFor="let line of lines">{{line}}</li>
</ul>
</div>
component.css
li
{
height: 19px;
list-style: none;
}
.codeMirrorContainer
{
position:relative;
overflow: hidden;
}
.lineContainer
{
position:absolute;
top:0;
left:0;
margin: 0;
padding: 5px 0 0 0;
text-align: center;
}
::ng-deep .CodeMirror-linenumber
{
visibility: hidden; /* Hides default line numbers */
}
component.ts
export class AppComponent
{
#ViewChild('codeMirror') codeMirrorCmpt: CodemirrorComponent;
private lineHeight: number;
public lineWidth;
public topPosition: number;
public lines = [];
codeMirrorOptions: any = ....;
codeObj :any = ...;
constructor(private cdr: ChangeDetectorRef)
{
}
ngAfterViewInit()
{
this.codeMirrorCmpt.codeMirror.on('refresh', () => this.refreshLines());
this.codeMirrorCmpt.codeMirror.on('scroll', () => this.refreshLines());
setTimeout(() => this.refreshLines(), 500)
}
refreshLines()
{
let editor = this.codeMirrorCmpt.codeMirror;
let height = editor.doc.height;
this.lineHeight = editor.display.cachedTextHeight ? editor.display.cachedTextHeight : this.lineHeight;
if (!this.lineHeight)
{
return;
}
let nbLines = Math.round(height / this.lineHeight);
this.lines = Array(nbLines).fill(0).map((v, idx) => idx + 1);
this.lineWidth = editor.display.lineNumWidth;
this.topPosition = document.querySelector('.CodeMirror-scroll').scrollTop;
this.cdr.detectChanges();
}
}

How to finish an animation even if its rule is removed?

I'm writing code that makes it so that when an element is given a class, it flashes briefly. To do this, I've created an animation from its "highlighted" appearance to its "unhighlighted" appearance, which is applied when the element is given the .highlight class.
The trouble is that the .highlight class is usually only applied for a very short moment - it's removed well before the animation finishes. The result of this is that the element will use its "unhighlighted" appearance immediately once the class is removed. But my goal is that it will finish the animation, gradually transitioning to the unhighlighted appearance, even though the class that applies that animation was removed.
Below is some code that represents the situation I'm dealing with. Try clicking the button once, then click it again before the animation has finished; note that the animation is cancelled and the "unhighlighted" appearance is immediately used.
#foo {
background: blue;
color: white;
}
#keyframes unhighlight {
from {
background: red;
}
to {
background: blue;
}
}
#foo.highlight {
animation-duration: 5s;
animation-name: unhighlight;
}
<p id="foo">
Hello!
</p>
<button onclick="document.getElementById('foo').classList.toggle('highlight')">
Click
</button>
Since in practice I'm writing in the context of React, I'd prefer to avoid involving JavaScript in the solution here (e.g. only removing the .highlight class once it's detected that the animation has finished) - it would be difficult to incorporate into my existing code (really).
You can remove .highlight class using timer. I understand you have not added JavaScript tag but you are already using JavaScript to add and remove class.
See the Snippet below:
var timer = 0;
var stopAnimation = false;
var animationTimer = 5;
function playStopAnimation(){
console.log(document.getElementById("foo").classList.contains("highlight"));
if(document.getElementById("foo").classList.contains("highlight")){
if(timer != animationTimer){
stopAnimation = true;
}else{
document.getElementById('foo').classList.toggle('highlight');
stopAnimation = false;
timer = 0;
console.log("Highlight removed");
}
}else{
document.getElementById('foo').classList.toggle('highlight');
stopAnimationFn(animationTimer);
}
}
const stopAnimationFn = (n)=>{
for (let i = 1; i <= n; i++) {
setTimeout(() =>{
console.log(i);
timer = i;
if(stopAnimation && timer==animationTimer){
document.getElementById('foo').classList.toggle('highlight');
stopAnimation = false;
timer = 0;
console.log("Highlight removed");
}
}, i * 1000)
}
}
function timerSet(i) {
setTimeout(function(){
timer=i;
console.log(timer);
},1000);
}
#foo {
background: blue;
color: white;
}
#keyframes unhighlight {
from {
background: red;
padding-left:0;
}
to {
background: blue;
padding-left:500px;
}
}
#foo.highlight {
animation-duration: 5s;
animation-name: unhighlight;
}
<p id="foo">
Hello!
</p>
<button onclick="playStopAnimation()">
Click
</button>

transition for translateY(0) working, but not translateY(-50px)

I'm having some trouble with a transition on a transform. I'm making a tic-tac-toe game like in the freecodecamp front-end challenges: https://codepen.io/freeCodeCamp/full/KzXQgy.
I've been able to create most layout things no problem, but am having an issue with my transition on a div that shows which players' turn it is after hitting the reset button. Right now I'm just working on two player mode, so I click two players, then X or O, and then the tic-tac-toe board shows up and a div transform: translateY(-50px) to indicate whether it's Player 1 or Player 2's turn (based on a random number variable I set up). The first time through the div transition's perfectly. Then I hit the Reset All div and it takes me back to the beginning to choose how many players again. And the div transitions the transform: translateY(0) perfectly back to it's starting position. Where I'm struggling is, now when I cycle through the options again, if it's Player 1 or Player 2's turn again, the transition never happens and the div just transforms -50px up with the translateY.
I've tried everything I could think of, JS setting up the transition, resetting the transition, moving the transition to be on different classes, adding and removing a class that only has a transition on it. Can't figure it out, but the weird thing is, whenever I hit the "Reset All", the transform transitions back to 0px normally. Here's my codepen: https://codepen.io/rorschach1234/pen/dZMaJg?editors=0111. I know it's still very rough, but just can't figure out this transition problem. Really appreciate any help. Thanks everyone!
My relevant Html:
<div class="container">
<div class="turns">
<div class="turns__left turns__box"></div>
<div class="turns__right turns__box"></div>
</div>
</div>
My relevant CSS:
.turns {
width: 100%;
display: flex;
position: absolute;
justify-content: space-around;
top: 0;
left: 0;
z-index: -1;
&__box {
width: 40%;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 1.3em;
font-family: sans-serif;
transition: transform 1s .3s ease;
}
&__left {
background-color: $color-turn-left;
//transition: transform 1s .3s ease;
}
&__right {
background-color: $color-turn-right;
//transition: transform 1s .3s ease;
}
}
My Javascript:
let numOfPlayers = document.querySelectorAll(".player .choices h2");
let playerScreen = document.querySelector(".player");
let markerScreen = document.querySelector(".markers");
let singlePlayer = true;
let backBtn = document.querySelector(".markers__back");
let gameScreen = document.querySelector(".game");
let playerOne; let playerTwo; let activePlayer;
let turnBoxes = document.querySelectorAll(".turns__box");
let resetBtn = document.querySelector(".scoreboard__reset");
game();
function game() {
playerModeSelection();
markerSelection();
}
function boardChange(active, inactive) {
inactive.style.opacity = "0";
inactive.style.zIndex = "0";
active.style.opacity = "1";
active.style.zIndex = "1";
}
//One or Two player Selection & transition to Marker Selector
function playerModeSelection() {
for (let i = 0; i < numOfPlayers.length; i++) {
numOfPlayers[i].addEventListener("click", function() {
if(i === 1) {
singlePlayer = false;
}
boardChange(markerScreen, playerScreen);
})
}
}
function markerSelection() {
//Back Button Functionality
backBtn.addEventListener("click", function() {
boardChange(playerScreen, markerScreen);
})
//Listen for choice of X or O
for (let i = 0; i < markers.length; i ++) {
markers[i].addEventListener("click", function() {
boardChange(gameScreen, markerScreen);
if (i === 1) {
playerArr = ["O", "X"];
}
//Starts Two Player Game; Here begin is the function that calls transition
if(!singlePlayer) {
twoPlayerMode();
}
})
}
}
function twoPlayerMode() {
activePlayer = Math.floor(Math.random() * 2);
turnBoxes[activePlayer].textContent = "Go Player " + (activePlayer + 1) + "!";
turnBoxes[activePlayer].style.transform = "translateY(-50px)";
resetBtn.addEventListener("click", function() {
boardChange(playerScreen, gameScreen);
turnBoxes[activePlayer].style.transform = "translateY(0px)";
})
}

Make toggle behave like input controls i.e. to respond to space bar key down and keyboard tab action

We have toggle controls as in the below link
https://www.w3schools.com/howto/howto_css_switch.asp
While these take input on mouse click, they don't change state on space key down and when keyboard tab is used these are not highlighted/selected.
How can these be made behave like any regular input control?
I would look for solution in html/css which could be easily applied to any such controls.
Update:
As mentioned in the answer, checkboxes change state on press of spacebar and not enter key.
I found the answer. First add a tab index to the element, so it can be focused. Then you can add this jQuery code.
$('.switch').on('keydown', function(e) {
if(e.keyCode == 13) {
if($(this).children("input").attr('checked')) {
$(this).children("input").attr('checked', false);
} else {
$(this).children("input").attr('checked', true);
}
}
});
I edited the code W3Schools site to add this code. You can view it at https://www.w3schools.com/code/tryit.asp?filename=FHPJRINMFQOH.
Good Luck!! Hope this helps!!
This can be done with css. Since we have to guess how your html and css is structured, i can only provide you something you can work with.
And by the way you change checkbox state with spacebar, not with enter key
label { margin-right: 1rem }
span {
display: inline-block;
width: 2rem;
height: 2rem;
background: rebeccapurple
}
input:focus + label span {
outline: 1px solid red
}
input:checked + label span {
background: red
}
/* https://css-tricks.com/places-its-tempting-to-use-display-none-but-dont/ */
.visuallyhidden {
position: absolute;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px; width: 1px;
margin: -1px; padding: 0; border: 0;
}
<input id="check" class="visuallyhidden" type="checkbox">
<label for="check"><span></span></label>
<input id="box" class="visuallyhidden" type="checkbox">
<label for="box"><span></span></label>
This can done using jquery
Since the toggle button is a simple checkbox we can access them using the keypress function
$(document).ready(function(){
$('#mycheckbox').keypress(function(event) {
var keycode = (event.keyCode ? event.keyCode : event.which);
if (keycode == 13) {
clickCheckBox(this);
}
event.stopPropagation();
});
});
function clickCheckBox(box){
var $box = $(box);
$box.prop('checked',!$box.prop('checked'));
}
find the fiddle here

numbered grid jquery mobile css

I'd like to create a numbered grid.The user puts in the number and the grid is generated. I'd like to do it in CSS, HTML or Jquery Mobile. This is for an ipad project. I'm not sure how to approach the problem. I would like the following result:
As it stands now, I have a div that repeats a grid image across the page. I have to regenerate an image for each background. i.e.: user wants a 40X60 feet area, I will have to generate a 40X60 image. (100px=5 feet on the grid) I'd much rather have the user input two numbers and have the grid and numbers auto generated.
<div style="background-image:url(/images/linegrid100.png);
width:980px;height:700px;
border:1px solid black;padding:10px;">
I've looked at a serious number of grid generators. I've thought about using a table rather than an image. Would that be better? How do I approach the math for the number generation? Seems like this should all be pretty straight forward, but I can't find much information. (Googled for a couple of days now) These kinds of grids are done all of the time in graphics programs and CAD programs.
Any help would be appreciated.
TIA -Rachel
OK. Here is the result of your code. It is running :-) but not as expected. I've been working with the code all day. It is making more sense now, but I'm still lost with the loops and math. Any ideas? So nice to have help and this is fun. Thanks again -R
The code that seems to impact things is :
w = parseInt($square.css('width'), 10) + 2; //the width of each square + 2 pixels for the borders;
If I leave it just as you have it:
If I change the 10 to 100:
Let's assume you have the following form where users enter the two numbers:
<form>
<input type="text" id="x">
<input type="text" id="y">
</form>
Then you can use jQuery to generate your grid as follows:
var x = parseInt($('#x').val(), 10),
y = parseInt($('#y').val(), 10);
grid(x, y);
function grid(x, y) {
var i = -1,
j = -1,
step = 5, //assuming that each grid unit = 5
$grid = $('<div>', {'id':'grid'}),
$square = $('<div>', {'class':'square'}),
$label,
w = parseInt($square.css('width'), 10) + 2; //the width of each square + 2 pixels for the borders;
$grid.width(w * x);
while(++i < x) {
while(++j < y) {
if(j === 0) {
$label = $('<span>', {'class':'label'});
$label.css('top', j * w).css('left', i * w).html(i * step);
}
if(i === 0 && j > 0) {
$label = $('<span>', {'class':'label'});
$label.css('top', j * w).css('left', i * w).html(j * step);
}
$grid.append($square.clone(), $label);
}
j = -1;
}
$('body').append($grid);
}
CSS:
#grid { overflow: hidden; border-left: 1px solid #000; border-top: 1px solid #000; position: relative; }
div.square { width: 50px; height: 50px; float: left; border-bottom: 1px dotted #000; border-right: 1px dotted #000; }
span.label { position: absolute; background: #fff; font-weight: bold; z-index: 10; }
Let's say here's our overlay (dialog box):
<div>
<input type="text" id="x">
<input type="text" id="y">
<button id="build-grid" type="button">Build grid</button>
</div>
Then, you attach an onclick event to the build-grid button. So, when the button is clicked, we read the x and y values and build the grid.
$('#build-grid').on('click', function(e){
e.preventDefault();
var x = parseInt($('#x').val(), 10), //get our values from the input fields
y = parseInt($('#y').val(), 10);
grid(x, y); // build the grid
});

Resources