I'm attempting to create something that makes a button only work once. In order to do so, I created an if loop. In that if loop, I put it to a function called myFunction and then set a variable, button, to 0 (the if loop only runs if button is =2. It will not run in the first place. What am I doing wrong?
I've already attempted to recreate the variable(saying var button once out of the loop and then saying it again within).
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var button = 2;
var x = 0
function ins() {
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
x = getRndInteger(0, window.innerWidth)
alert(x);
}
function button() {
if (button === 2) {
alert("k")
myFunction();
button = 0;
} else {}
}
function myFunction() {
var para = document.createElement("SPAN");
para.style.position = "absolute";
x = getRndInteger(0, (window.innerWidth - 60))
para.style.left = x + "px"
var p = getRndInteger(0, (window.innerHeight - 60))
para.style.top = p + "px"
para.style.display = "inline-block;"
para.style.height = "50px"
para.style.width = "50px"
para.style.backgroundColor = "red"
para.style.borderRadius = "50px"
para.style.border = "1px solid black"
para.style.animation = "1s a linear"
para.id = "a"
para.onclick = myFunction
document.getElementById("myDIV").appendChild(para);
}
#keyframes a {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
button {
background-color: #010417;
border-radius: 10px;
border: 4px solid white;
color: white;
padding: 10px 26px;
font-size: 20px;
}
<div id="myDIV"></div>
<center>
<button id="button" onClick="button();">Start</button>
</center>
EDIT: Ignore the delete function, doesn't mean anything
The issue with this code is that your event handler function, and the flag (that changes value between 2 and 0) are both named 'button'. Javascript is a relatively accommodating language, so this kind of dual declaration might not throw error right away, but it will obviously cause unexpected behaviour.
Looking at your code:
var button = 2;
function button() {
if (button === 2) {
alert("k")
myFunction();
button = 0;
} else {}
}
In this case (depending on the JS engine), button either refers to the function or the number. If it's the number, then type error will be thrown when button is clicked. Since the code will try to call the number like a function.
If it's a function, then the button === 2 comparison will always be false, and the (empty) else block will get executed. Either way you wouldn't get the expected behavior. You can simply change the variable name to something else, and it should work.
Please note that, as someone pointed out in comments, you should prefer adding disabled attribute to the button over this logic. Unless the aim is to do something other than blocking multiple clicks of the button.
Related
I have 9 boxes in my html.
There is a value, id called 'lifepoint'.
There is a mouse-click function: click once & decrease one life point. This code is completed.
function decrementlife() {
var element = document.getElementById('lifepoint');
var value = element.innerHTML;
--value;
console.log(value);
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) { alert("Game Over!")};
}
Also, there is a css style, called 'crackbox'.
.crackbox {
position: relative;
background: linear-gradient(0deg, black, rgb(120, 120, 120));
width: 12vh;
height: 12vh;
border-radius: 30%;
margin: 5px;
}
I want to change all box class from 'box' to 'crackbox' if life point is zero. Therefore, all box style can be 'crackbox'.
The below code is fail...
$(document).ready(function () {
$(".box").each(function() {
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) {
".box".toggleClass('crackbox')
};
})
});
Instead of using document ready, call another function from decrement life if the value turns 0. I am writing the code for your help.
function decrementlife() {
var element = document.getElementById('lifepoint');
var value = element.innerHTML;
--value;
console.log(value);
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) { changeClass(); alert("Game Over!")};
}
function changeClass(){
$('.box').addClass('crackbox').removeClass('box');
}
Hope, it helps!!
The simplest way would be to use querySelectorAll and loop through the elements:
for(let i = 0, list = document.querySelectorAll(".box"); i < list.length; i++)
{
list[i].classList.toggle('crackbox');
}
Or shorter ES6 version:
[...document.querySelectorAll(".box")].forEach(el => el.classList.toggle('crackbox'))
Hi I want to store a number when its value is 0
var count = 3;
var count2 = "0";
var count3;
var btn = document.getElementById("btn");
btn.onclick = function() {
count--;
btn.style.transform = "scale(2)";
setTimeout(function() {
btn.style.transform = "scale(1)";
}, 0005);
if(count === 0) {
/* I want to store the result here in manner that even when the page reload the number remains the same ( 0 in that case ) */
var zero = localStorage.getItem(count);
count3 = parseInt(count2);
localStorage.setItem( count , count3 );
}
}
#btn {
width : 300px;
height : 300px;
border : solid 2px red;
border-radius : 50%;
transition : .1s;
}
<button id="btn">Click me</button>
But I don't need to affect count3 to count since count is already set at 0 :( but I can't affect numbers ? I think there's only string in the 'key' for localStorage.
How I can do that ?
The key for localstorage is to only use String. You can define a function to parse the key to any.... When the page reload, loacalStorage can't be cleared. So you can do it like var key = parse(localStorage.getitem(count)) in your defined function.
localStorage.setItem( count , count3 )
This is wrong. You should write
localStorage.setItem( "where" , value );
So instead of setting the item in the key equal to the variable count, you should set the value in key "count", which is a string. Otherwise, every time you change the integer count, you store the new value (count3) in a new place.
When you then reload the page, the integer count is then trying to fetch the stored information in key 3.
Also, count === 0 could as well be written as count == 0 so it doesn't check if count is an integer first, and instead accepts strings (and boolean, undefined and null).
EDIT: added snippet as example. I refactored the code so it's more readable, commented out localStorage so you can run the snippet on Stack Overflow, and I assumed that count can't get lower than 0.
As a bonus, I removed count2 and count3 while changing the setTimeout from 0.005 (5ms is minimum anyway) to 50ms (half of 0.1s that is in the transition).
var storedCount = getStoredCount();
const GOT_PREVIOUS_VALUE = storedCount != null;
var count = (GOT_PREVIOUS_VALUE) ? storedCount : 3;
var btn = document.getElementById("btn");
btn.onclick = changeCount;
function changeCount() {
if (count > 0) {
count--;
scaleButton();
storeCount();
console.log({count})
}
}
function scaleButton() {
btn.style.transform = "scale(2)";
setTimeout(function() {
btn.style.transform = "scale(1)";
}, 50);
}
function getStoredCount() {
return localStorage.getItem('count') ;
}
function storeCount() {
localStorage.setItem('count', count);
}
#btn {
width: 300px;
height: 300px;
border: solid 2px red;
border-radius: 50%;
transition: .1s;
}
<button id="btn">Click me</button>
Code:
window.onload = function() {
var a = document.getElementById("q");
var b = 1;
function tri() {
a.style.width = "100px";
b++
if (b == 3) {
b--
}
return b;
}
function un() {
a.style.width = "40px"
if (b == 2) {
b--
}
};
if (b == 1) {
a.addEventListener("click", tri);
};
if (b == 2) {
a.addEventListener("click", un)
};
};
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
I don't know why but my code is not working. Is it possible to add two event listeners in one element? If yes, then please explain how. I tried a lot, but it's not working.
Your code is only adding one listener to the DIV. It's testing the value of b when the page is loaded, and adds the tri function as a listener. It never performs the addEventListener code again when the value of b changes.
You can add multiple event listeners to an element, but there's no need to do that in this case. Just write one event listener that checks a variable. To alternate the action, the function simply inverts the value of the variable.
window.onload = function() {
var a = document.getElementById("q");
var small = true; // Is the DIV small or big?
function change() {
if (small) { // If it's small, make it big
a.style.width = "100px";
} else { // Otherwise, make it small
a.style.width = "40px";
}
small = !small; // invert the value of the variable
}
a.addEventListener("click", change)
};
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
your program is stuck on the first function. you enter as 1, and you get stuck on three. I debugged your program into a tragic story. I call it lost to 3. click on the square for the tragedy to unfold.
var square = document.getElementById("q");
var b = 0;
function triun() {
if (b === 0) {
square.style.width = "100px";
b=1;
}
else if (b === 1) {
square.style.width = "40px"
b=0;
};
}
square.addEventListener("click", triun)
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
window.onload = function() {
var a = document.getElementById("q");
var b = 1;
function tri() {
console.log('I want to be 1 but I am fleeting, forever to be two, click once more for my story'+ b +'unfold')
a.style.width = "100px";
b++;
console.log(b,' wowe is me, am I 2 or am I 3. All I know, is I will be a tragedy of the click handler that will always fire before the comming of the un')
if (b == 3) {
b--
console.log('I am lost to enter as 3, never will I ever be that 1, lost in time to that fading binary dream I once was but am now', b);
}
return b;
}
function un() {
console.log(b)
a.style.width = "40px"
if (b == 2) {
b--
}
};
if (b == 1) {
console.log('I am that first "if", that very first time you dared to dream, what might have been had "un" been here',b )
a.addEventListener("click", tri);
};
if (b == 2) {
console.log('I am that poor un, I will never be, because 2 will never visit me ');
a.addEventListener("click", un)
};
};
#q {
width: 40px;
height: 40px;
background-color: blue;
}
<div id="q"></div>
I've got a simple number input with a min="1" and max="12" value set, this is used as an hour selector. I'd like it to cycle through the hours, so when you get to 12 and press the "up" arrow, it goes back to 1 and vice-versa as well.
Right now I have this mostly working:
var inputTimer = null;
function cycle(element) {
if (element.attributes.max && element.attributes.min) {
var prevVal = element.value;
inputTimer = setTimeout(function() {
if (prevVal === element.attributes.max.value) {
element.value = element.attributes.min.value;
} else if (prevVal === element.attributes.min.value) {
element.value = element.attributes.max.value;
}
}, 50);
}
}
$("input[type='number']")
.on("mousedown", function(e) {
//this event happens before the `input` event!
cycle(this);
}).on('keydown', function(e) {
//up & down arrow keys
//this event happens before the `input` event!
if (e.keyCode === 38 || e.keyCode === 40) {
cycle(this);
}
}).on('input', function(e) {
//this event happens whenever the value changes
clearTimeout(inputTimer);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" min="1" max="12" value="12" />
Working DEMO
The issue I have is that I can't find a way to detect if the arrow spinners in the input have been clicked, or just the input as a whole has been clicked. Right now it has an issue where it changes the value when you click anywhere in the field when the value is currently at 1 or 12
Is there a way to detect if the click event occurs on the spinners/arrows within the text field?
You have to handle the input event, like this:
$('[type=number]').on('input',function(){
this.value %= 12 ;
if( this.value < 1 )
this.value -= -12 ;
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type=number>
I searched a lot and it seems there is no way to natively detect that. That makes this one a very important question because I think this should be added to new versions of HTML.
There are many possible workarouds. They all fail on the problem the it's impossible to know, in which direction is value going. I decided to use mouse position information to detect, whether is user increasing or decreasing a value. It works, but does not properly handle the situation, when user holds the button.
var inputTimer = null;
function cycle(event) {
var value = this.value;
// Value deep within bonds -> no action
if(value>this.min && value<this.max) {
return;
}
// Check coordinate of the mouse
var x,y;
//This is the current screen rectangle of input
var rect = this.getBoundingClientRect();
var width = rect.right - rect.left;
var height = rect.bottom-rect.top;
//Recalculate mouse offsets to relative offsets
x = event.clientX - rect.left;
y = event.clientY - rect.top;
// Now let's say that we expect the click only in the last 80%
// of the input
if(x/width<0.8) {
console.log("Not click on arrows.", x, width);
return;
}
// Check "clicked button" by checking how high on input was clicked
var percentHeight = y/height;
// Top arrow was clicked
if(percentHeight<0.5 && value==this.max) {
this.value = this.min;
event.preventDefault();
return false;
}
// Bottom arrow was clicked
if(percentHeight>0.5 && value==this.min) {
this.value = this.max;
event.preventDefault();
return false;
}
}
var input = document.getElementById("number");
input.addEventListener("mousedown", cycle);
<input id="number" type="number" min="1" max="12" value="12" />
A method you could try is by using the Attributes of the element to track what the previous value is. This isn't, of course, actually tracking which button got hit but it's the closest I've been able to get.
JS:
$(document).ready(function() {
function Init(){
var test = document.getElementById('test');
test.setAttribute('prev', 0);
}
Init()
$('#test').on('input', function() {
var test = document.getElementById('test')
var d = test.value - test.getAttribute('prev');
console.log(d);
test.setAttribute('prev', test.value);
});
});
HTML:
<input type="number" id="test">
Then all you would have is logic that says if d(irection) is positive, they clicked up. If negative, they clicked down. If it's 0 then they didn't click a button.
Working Fiddle
I think this is what you really want.
<input type="time" value="01:00" step="600"/>
There is currently no native way to capture the arrow input events separate from the input box events. Everything using number input seems to be kinda hacky for this purpose.
Next best option is something like http://jdewit.github.io/bootstrap-timepicker/
This doesn't work for your specific situation where you have a maximum and want it to wrap, but it might be helpful for others who want to process the field value based on changes via arrows, such as for setting .toFixed(2) to a currency value like I needed:
document.getElementById('el').setAttribute('data-last',document.getElementById('el').value);
document.getElementById('el').addEventListener('keyup', function(){
this.setAttribute('data-last',this.value);
});
document.getElementById('el').addEventListener('click', function(){
if(this.value>this.getAttribute('data-last')) console.log('up clicked');
if(this.value<this.getAttribute('data-last')) console.log('down clicked');
});
This is my code written in JQuery , this one can implement auto-increment ( + & - ) long-press spin buttons .
$.fn.spinInput = function (options) {
var settings = $.extend({
maximum: 1000,
minimum: 0,
value: 1,
onChange: null
}, options);
return this.each(function (index, item) {
var min = $(item).find('>*:first-child').first();
var max = $(item).find('>*:last-child').first();
var v_span = $(item).find('>*:nth-child(2)').find('span');
var v_input = $(item).find('>*:nth-child(2)').find('input');
var value = settings.value;
$(v_input).val(value);
$(v_span).text(value);
async function increment() {
value = Number.parseInt($(v_input).val());
if ((value - 1) > settings.maximum) return;
value++;
$(v_input).val(value);
$(v_span).text(value);
if (settings.onChange) settings.onChange(value);
}
async function desincrement() {
value = Number.parseInt($(v_input).val());
if ((value - 1) < settings.minimum) return;
value--
$(v_input).val(value);
$(v_span).text(value);
if (settings.onChange) settings.onChange(value);
}
var pressTimer;
function actionHandler(btn, fct, time = 100, ...args) {
function longHandler() {
pressTimer = window.setTimeout(function () {
fct(...args);
clearTimeout(pressTimer);
longHandler()
}, time);
}
$(btn).mouseup(function () {
clearTimeout(pressTimer);
}).mousedown(function () {
longHandler();
});
$(btn).click(function () {
fct(...args);
});
}
actionHandler(min, desincrement, 100);
actionHandler(max, increment, 100)
})
}
$('body').ready(function () {
$('.spin-input').spinInput({ value: 1, minimum: 1 });
});
:root {
--primary-dark-color: #F3283C;
--primary-light-color: #FF6978;
--success-dark-color: #32A071;
--sucess-light-color: #06E775;
--alert-light-color: #a42a23;
--alert-dark-color: #7a1f1a;
--secondary-dark-color: #666666;
--secondary-light-color: #A6A6A6;
--gold-dark-color: #FFA500;
--gold-light-color: #FFBD00;
--default-dark-color: #1E2C31;
--default-light-color: #E5E5E5;
}
.fx-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.fx-colum {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.fx-colum.nowrap,
.fx-row.nowrap {
flex-wrap: nowrap;
}
.fx-row.fx-fill>*,
.fx-colum.fx-fill>* {
flex-grow: 1;
}
.spin-input {
border: 1px solid var(--secondary-light-color);
}
.spin-input>div:first-child {
cursor: pointer;
border-right: 1px solid var(--secondary-light-color);
}
.spin-input>div:first-child:active {
transform: translate3d(1px, 0px, 1px)
}
.spin-input>div:last-child {
flex: none;
border-left: 1px solid var(--secondary-light-color);
cursor: pointer;
}
.spin-input>div:last-child:active {
transform: translate3d(1px, 0px, 1px)
}
.icon {
font-weight: bold;
text-align: center;
vertical-align: middle;
padding: 12px;
font-size: 28px;
}
.icon.primary,
.icon.primary .ci {
color: var(--primary-dark-color);
}
.icon.reactive:hover .ci {
color: var(--primary-light-color);
}
.hidden {
display: none;
}
<script src="https://releases.jquery.com/git/jquery-3.x-git.min.js"></script>
<div class="spin-input nowrap fx-row fx-fill" >
<div class="icon reactive">
<span class="ci ci-minus">-</span>
</div>
<div class="icon">
<span>0</span>
<input type="text" class="hidden" value="0">
</div>
<div class="icon reactive">
<span class="ci ci-plus">+</span>
</div>
</div>
There is my jQuery plugin , I hope that can help you .
So I am not sure there is anyway to determine what is being clicked, be it field input or little arrows, but I was able to get it working like this.
Fiddle: http://jsfiddle.net/nusjua9s/4/
JS:
(function($) {
var methods = {
cycle: function() {
if (this.attributes.max && this.attributes.min) {
var val = this.value;
var min = parseInt(this.attributes.min.value, 10);
var max = parseInt(this.attributes.max.value, 10);
if (val === this.attributes.max.value) {
this.value = min + 1;
} else if (val === this.attributes.min.value) {
this.value = max - 1;
} else if (!(val > min && val < max)) {
// Handle values being typed in that are out of range
this.value = $(this).attr('data-default');
}
}
}
};
$.fn.circularRange = function() {
return this.each(function() {
if (this.attributes.max && this.attributes.min) {
var $this = $(this);
var defaultVal = this.value;
var min = parseInt(this.attributes.min.value, 10);
var max = parseInt(this.attributes.max.value, 10);
$this.attr('min', min - 1);
$this.attr('max', max + 1);
$this.attr('data-default', defaultVal);
$this.on("change", methods.cycle);
}
});
};
})(jQuery);
$("input[type='number']").circularRange();
HTML:
<input type="number" min="1" max="12" value="12" />
So I am not sure why I keep thinking about this and it still doesn't solve what you are seeing with the flash of out of range numbers which I don't see. But now its not confusing to setup the html ranges at least. You can set the range you want without thinking and just initialize the type="number" fields.
Try with $('input[type="number"]').change(function() {}); ? No result ?
I have one main "Div" on which after clicking it gets split into n X n matrix. On every click inside it with a random colour div. Until here it's fine, now I want to create a click function on that random colourful div which currently is on any where inside the whole main "div"..
$(window).load(function() {
var no = 1,
$m = $(".main_div"),
size = 200;
$m.live('click', function() {
no++;
var n = no * no,
i, _size;
$m.empty();
for (i = 0; i < n; i++)
$m.append($('<div title=' + i + '/>'));
_size = size / no;
$m.find('> div').css({
width: _size,
height: _size
});
var colors = ["#FFFFFF", "#CC00CC", "#CC6699", "#0099CC", "#FF99FF"];
var rand = Math.floor(Math.random() * colors.length),
randomTotalbox = Math.floor(Math.random() * $('.main_div div').length);
$m.find("div:eq(" + randomTotalbox + ")").css("background-color", colors[rand]);
var rand = Math.floor(Math.random() * colors.length);
});
});
.main_div {
width: 200px;
height: 200px;
background-color: #9F0;
}
.main_div > div {
float: left;
box-shadow: 0 0 1px #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main_div" id="demo">
</div>
Here is a fiddle...Code
so you are saying that the clickable div is added to the DOM whenever you click(for example on a button )
that means that those divs were not there in the beginning so you can use
the Babak Naffas answer and also the .delegate method
example
$('body').delegate('.main_div > div','click',function(){
// here goes your instructions
});
for more details you can check:
jQuery: difference between .click() AND .on("click")
If you're asking for an event to be triggered when the NxN <div>s that make up the matrix are clicked, you could try
$(".main_div > div").on('click', function (evt) { ... } );
This will attach the function (the 2nd parameter) to the click event of the <div> from the matrix just like the CSS class you have with the same selector.