How can I fire a event when a key is pressed down - javascript

I have tried the code before, but when I hold down W it repeats the code, but I want to so if I hold it down, it will only execute the code one.
window.addEventListener("keydown", checkKeyPressW, false);
var player = document.getElementById("player");
var leftMarginCounter = 0;
var bottomMarginCounter = 0;
var leftMarginCounterToString = "";
function checkKeyPressA_D(keyPressed) {
if(keyPressed.keyCode == "97") {
if(player.style.marginLeft != "0px") {
leftMarginCounter = leftMarginCounter - 1;
leftMarginCounterToString = leftMarginCounter.toString();
leftMarginCounterToString = leftMarginCounterToString + "px";
player.style.marginLeft = leftMarginCounterToString;
}
}
else if(keyPressed.keyCode == "100") {
if(player.style.marginLeft != "1316px") {
leftMarginCounter = leftMarginCounter + 1;
leftMarginCounterToString = leftMarginCounter.toString();
leftMarginCounterToString = leftMarginCounterToString + "px";
player.style.marginLeft = leftMarginCounterToString;
}
}
};
function checkKeyPressW(keyPressedW) {
if(keyPressedW.keyCode == "87") {
console.log("Pressed w");
}
}

JS demo: https://jsfiddle.net/utnqeLmf/1/
Code:
window.addEventListener("keydown", checkKeyPressW, {
once : true
});
From the docs
once A Boolean indicating that the listener should be invoked at most
once after being added. If true, the listener would be automatically
removed when invoked.
EDIT
If you want to avoid continuous key consoling when having the key pressed then change the event to keyup
window.addEventListener("keyup", checkKeyPressW);

There is a property called repeat that returns true if the key is being held down
document.addEventListener('keydown', (event) => {
if(event.repeat) {
// key is being held down
} else {
// key is being pressed
}
});

Related

Memory game with javascript

I have a small problem that could ruin the game. Once you click a card you need to search for the other card with the same picture right? but the problem is you can also double click and it will think you found the other card. Anyone know how o solf this problem?
const cards = document.querySelectorAll(".cards .card");
cards.forEach((card) => {
card.addEventListener("click", () => {
card.classList.add("clicked");
if (counter === 0) {
firstSelection = card.getAttribute("meme");
counter++;
} else {
secondSelection = card.getAttribute("meme");
counter = 0;
if (firstSelection === secondSelection) {
const correctCards = document.querySelectorAll(".card[meme='" + firstSelection + "']");
score.innerHTML = parseInt(score.innerHTML) + 1
if (score.innerHTML >= 8)
correctCards[0].classList.add("checked");
correctCards[0].classList.remove("clicked");
correctCards[1].classList.add("checked");
correctCards[1].classList.remove("clicked");
} else {
const incorrectCards = document.querySelectorAll(".card.clicked");
incorrectCards[0].classList.add("red");
incorrectCards[1].classList.add("red");
setTimeout(() => {
incorrectCards[0].classList.remove("red");
incorrectCards[0].classList.remove("clicked");
incorrectCards[1].classList.remove("red");
incorrectCards[1].classList.remove("clicked");
}, 600);
}
}
});
});
You can set 2 global vars firstClickedCard and secondClickedCard, and on click, assign the card element (event.currentTarget) to these variables. Then on second click, check if (secondClickedCard === firstClickedCard) before any of your other logic, and reject the click event if this is true.
This should verify if the actual clicked element (not just the meme attribute) are the same or not.
Note: this is untested, and would be easier to verify if your question included a minimal, reproducible example.
const cards = document.querySelectorAll(".cards .card");
var firstClickedCard;
var secondClickedCard;
cards.forEach((card) => {
card.addEventListener("click", (e) => {
card.classList.add("clicked");
if (counter === 0) {
firstClickedCard = e.currentTarget;
firstSelection = card.getAttribute("meme");
counter++;
} else {
secondClickedCard = e.currentTarget;
// reject this click
if (secondClickedCard === firstClickedCard) {
secondClickedCard = null;
return false;
}
secondSelection = card.getAttribute("meme");
counter = 0;
if (firstSelection === secondSelection) {
const correctCards = document.querySelectorAll(".card[meme='" + firstSelection + "']");
score.innerHTML = parseInt(score.innerHTML) + 1
if (score.innerHTML >= 8)
correctCards[0].classList.add("checked");
correctCards[0].classList.remove("clicked");
correctCards[1].classList.add("checked");
correctCards[1].classList.remove("clicked");
} else {
const incorrectCards = document.querySelectorAll(".card.clicked");
incorrectCards[0].classList.add("red");
incorrectCards[1].classList.add("red");
setTimeout(() => {
incorrectCards[0].classList.remove("red");
incorrectCards[0].classList.remove("clicked");
incorrectCards[1].classList.remove("red");
incorrectCards[1].classList.remove("clicked");
}, 600);
}
}
});
});
Although there is a double click event (dblclick), it is not supported by all browsers. The way around this is to test for double clicks within your click event handlers and use a timer function (to see if two clicks happened within a select amount of time). I use 300ms for the timer, but you may have to play around with that a bit.
const cards = document.querySelectorAll(".cards .card");
let clickCount = 0;
cards.forEach((card) => {
card.addEventListener("click", () => {
clickCount ++;
if (clickCount == 1) {
clickTimer = setTimeout(() => {
clickCount = 0;
//single click functionality here
card.classList.add("clicked");
if (counter === 0) {
firstSelection = card.getAttribute("meme");
counter++;
} else {
secondSelection = card.getAttribute("meme");
counter = 0;
if (firstSelection === secondSelection) {
const correctCards = document.querySelectorAll(".card[meme='" + firstSelection + "']");
score.innerHTML = parseInt(score.innerHTML) + 1
if (score.innerHTML >= 8)
correctCards[0].classList.add("checked");
correctCards[0].classList.remove("clicked");
correctCards[1].classList.add("checked");
correctCards[1].classList.remove("clicked");
} else {
const incorrectCards = document.querySelectorAll(".card.clicked");
incorrectCards[0].classList.add("red");
incorrectCards[1].classList.add("red");
setTimeout(() => {
incorrectCards[0].classList.remove("red");
incorrectCards[0].classList.remove("clicked");
incorrectCards[1].classList.remove("red");
incorrectCards[1].classList.remove("clicked");
}, 600);
}
}
}, 300);
} else if (clickCount == 2) {
clearTimeout(clickTimer);
clickCount = 0;
console.log("This was a double click!");
}
});
});

How to check if a function has been called before executing another function everytime

I have a onMouseDownEssence() and onMouseUpEssence() function for an HTML element, how to check if onMouseDownEssence() is called every time before calling onMouseUpEssence() to ensure I get the correct mouse down position?
Here is mousedown function:
var mouseDownIndex = -1;
function onMouseDownEssence(downIndex, e, className) {
dragTarget = e.target;
holdStarter = new Date().valueOf();
mouseDownIndex = downIndex;
}
Here is mouseup function:
function onMouseUpEssence(upIndex, e, className) {
var el = e.target;
var holdActive = (new Date().valueOf() - holdStarter) > holdDelay;
if (holdActive) {
var thisUpTargetIndex = el.getAttribute("name");
if (lastUpTargetIndex != null && thisUpTargetIndex != lastUpTargetIndex) {
// console.log("double drag done");
el.removeAttribute(dbl);
lastUpTargetIndex = null;
var selectedText = clickDragAutoExpand(mouseDownIndex, upIndex,
className);
} else {
// console.log("drag done");
var selectedText = clickDragAutoExpand(mouseDownIndex, upIndex,
className);
}
holdActive = false;
} else if (el.getAttribute(dbl) == null) {
el.setAttribute(dbl, 1);
setTimeout(
function() {
if (el.getAttribute(dbl) == 1 && !dragTarget) {
if (e.button === 0) {
// console.log("single clicked ");
el.removeAttribute(dbl);
var selectedText = clickAutoExpand(upIndex,
className);
}
} else {
if (el.getAttribute(dbl) != null)
lastUpTargetIndex = el.getAttribute("name");
}
}, dblDelay);
} else {
// console.log("double clicked");
el.removeAttribute(dbl);
var selectedText = clickAutoExpand(upIndex, className);
}
dragTarget = null;
}
My approach would be to keep a track of whether mouseDownEssence() was called. And if not, call it before proceeding further. This approach would work somewhat as below. It would work differently for asynchronous functions but mouseDownEssence() seems to be a synchronous function.
let isMouseDownEssenceCalled = false;
function mouseDownEssence() {
isMouseDownEssenceCalled = true;
...
}
function mouseUpEssence() {
if (!isMouseDownEssenceCalled) {
mouseDownEssence()
}
...
isMouseDownEssenceCalled = false;
}

generating a number of divs at a time in jQuery

I'm trying to make a game with jquery where bullets are appended using a function. So far bullets are generating whenever I press spacebar but I want to generate bullets like 3-5 stacks. 3-5 bullets will be generated and then a short break then again 3-5 bullets will be generated and the process continues. Bullets are appended as div element. Here are the codes,
function generateBullet() {
var Player = $('#player');
var PlayerLeft = Player.offset().left;
var PlayerTop = Player.offset().top - 50;
var appendingValue = "<div class='bulletID' style=' position: absolute; left: 250px; top: 250px;'></div>";
var appendSize = $('.bulletID').size();
if (appendSize >= 3) {
$('#content').delay(5000).append(appendingValue);
} else {
$('#content').append(appendingValue);
}
}
function animateBullet() {
var bulletID = $('.bulletID');
bulletID.each(function () {
var nowTop = $(this).offset().top;
$(this).css("top", nowTop - 25);
});
}
var keys = {}
$(document).keydown(function (e) {
keys[e.keyCode] = true;
});
$(document).keyup(function (e) {
delete keys[e.keyCode];
});
function shoot() {
var Player = $('#player');
for (var direction in keys) {
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 32) {
generateBullet();
}
}
}
JSFIDDLE DEMO : http://jsfiddle.net/ygz5wo7r/1/
I'm not getting any more idea how to do this. Your help will be really appreciated. TnQ.
Try this
I added
return false;
after
if (appendSize >= 3) {
...
and
parseInt($(this).css("top"))< 0 && $(this).remove();
to animateBullet()
to remove the bullets when they leave the screen
you can count how many bullets you fired each chain, and block the gun if chain reaches 3-5 bullets. and then using a timeout you can unblock the gun. that way you have control over the interval between bullet chains:
Fixed Fiddle
var bullets_chain = 0;
var block_gun = false;
function generateBullet() {
if (block_gun == false) {
var Player = $('#player');
var PlayerLeft = Player.offset().left;
var PlayerTop = Player.offset().top - 50;
var appendingValue = "<div class='bulletID' style=' position: absolute; left: 250px; top: 250px;'></div>";
bullets_chain++;
if (bullets_chain >= 5) {
block_gun = true;
bullets_chain = 0;
setTimeout(function () {
block_gun = false;
}, 500);
}
$('#content').append(appendingValue);
}
}
function animateBullet() {
var bulletID = $('.bulletID');
bulletID.each(function () {
var nowTop = $(this).offset().top;
if (nowTop < 0) {
$(this).remove();
} else {
$(this).css("top", nowTop - 25);
}
});
}
var keys = {}
$(document).keydown(function (e) {
if (block_gun == false) {
keys[e.keyCode] = true;
}
});
$(document).keyup(function (e) {
delete keys[e.keyCode];
});
function shoot() {
var Player = $('#player');
for (var direction in keys) {
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 32) {
generateBullet();
}
}
}
$(document).ready(function () {
setInterval(shoot, 50);
setInterval(animateBullet, 100);
});

override global variable and return in another function javascript

How do I get currentQuestion is updated in createQuestion()
each time that the button is clicked, currentQuestion will updating *1, but in the createQuestion() function, the value of currentQuestion is still 0.
var currenQuestion = 0;
function nxtQuestion() {
var button = document.getElementById('nextQuestion');
document.getElementById('genralCulture').addEventListener('click', function (event) {
if (event.target == button) {
currenQuestion += 1;
//createQuestion();
event.preventDefault();
}
}, false);
}
function createQuestion() {
var question = document.getElementById('theQuestion');
if (currenQuestion < allQuestions.length) {
nxtQuestion();
question.innerHTML = allQuestions[currenQuestion].question;
} else {
question.innerHTML = "Your score is "
}
}
In others words, when I click in the button, the question is not updating, but event handlers works properly
Try this
var currenQuestion = 0;
function nxtQuestion() {
var button = document.getElementById('nextQuestion');
document.getElementById('genralCulture').addEventListener('click', function (event) {
if (event.target == button) {
currenQuestion += 1;
//createQuestion();
event.preventDefault();
}
}, false);
}
function createQuestion() {
currenQuestion += 1;
var question = document.getElementById('theQuestion');
if (currenQuestion < allQuestions.length) {
nxtQuestion();
question.innerHTML = allQuestions[currenQuestion].question;
} else {
question.innerHTML = "Your score is "
}
}

Splitting HTML page into different sections using sliding panel dividers? How is it done?

I'm wanting to divide a web page up into different sections as shown here. I'm trying to figure it out what this technique is called and an efficient way to implement it?
The page is divided up into different sections giving the user the flexiblity to expand and contract the different sections using panel handles.
I'm assuming these aren't regular frames (which I'd like to avoid using anyways).
Does anybody know of a tutorial or good example out there besides the one on jsfiddle?
the idea is quite simple.
you break up the screen with some elements, it does not really matter which (say divs) with a given height.
then attach a onclick event to the handle that starts the drag. what the onclick does is attach a mousemove event to the body which will resize the elements.
here is something i wrote a while back (before my jquery days), i'm sure it could be written much better, and you might find a plugin for this, i don't know of one:
function WidenHandle(widenedELement, handleElement, ondblClick, startWidth, withCoverDiv, onDrop)
{
this.Handle = handleElement;
this.IsClosed = false;
this.Element = widenedELement;
this.LastX = 0;
this.LastY = 0;
this.AttachedDragFunction = null;
this.AttachedDropFunction = null;
this.StartWidth = startWidth ? startWidth : 300;
this.CoverDiv;
this.OnDrop = onDrop;
this.IsDragging = false;
if (withCoverDiv)
{
var coverDiv = document.createElement("div");
coverDiv.style.width = "2000px";
coverDiv.style.height = "2000px";
coverDiv.style.display = "none";
coverDiv.style.position = "fixed";
coverDiv.style.zIndex = "1000";
// coverDiv.style.backgroundColor = "red";
// coverDiv.style.opacity = "0.3";
coverDiv.style.top = '0px';
this.CoverDiv = coverDiv;
document.body.appendChild(coverDiv);
}
if (this.Handle.addEventListener)
{
this.Handle.addEventListener("mousedown", function(element)
{
return function(event)
{
element.StartDragging(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "";
if (event.preventDefault)
event.preventDefault();
}
} (this), true);
this.Handle.addEventListener("dblclick", function(element)
{
return function(event)
{
element.Close(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "none";
ondblClick(element);
}
} (this), true);
}
else
{
this.Handle.attachEvent("onmousedown", function(element)
{
return function(event)
{
element.StartDragging(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "";
if (event.preventDefault)
event.preventDefault();
}
} (this));
this.Handle.attachEvent("ondblclick", function(element)
{
return function(event)
{
element.Close(event);
if (element.CoverDiv)
element.CoverDiv.style.display = "none";
ondblClick(element);
}
} (this), true);
}
}
WidenHandle.prototype.StartDragging = function(event)
{
this.IsDragging = true;
if (this.CoverDiv)
this.CoverDiv.style.display = "none";
this.ClearAttachedEvents();
this.LastX = this.GetX(event);
// ** attach mouse move and mouse up events to document ** //
this.AttachedDragFunction = function(element)
{
return function(event)
{
element.OnDragging(event);
}
} (this);
this.AttachedDropFunction = function(element)
{
return function(event)
{
element.OnDropping(event);
}
} (this);
if (window.attachEvent) // ie
{
document.attachEvent('onmousemove', this.AttachedDragFunction);
document.attachEvent('onmouseup', this.AttachedDropFunction);
}
else // ff
{
document.onmousemove = this.AttachedDragFunction;
document.onmouseup = this.AttachedDropFunction;
}
}
// ** for repositioning popup while dragging ** //
WidenHandle.prototype.OnDragging = function(event)
{
clearHtmlSelection();
this.WidenCell(event);
}
// ** for release popup movement when dropping ** //
WidenHandle.prototype.OnDropping = function(event)
{
this.IsDragging = false;
if (this.CoverDiv)
this.CoverDiv.style.display = "none";
this.ClearAttachedEvents();
if (this.OnDrop)
this.OnDrop();
}
WidenHandle.prototype.ClearAttachedEvents = function()
{
// ** detach events from document ** //
if (window.attachEvent) // ie
{
document.detachEvent('onmousemove', this.AttachedDragFunction);
document.detachEvent('onmouseup', this.AttachedDropFunction);
}
else // ff
{
document.onmousemove = null;
document.onmouseup = null;
}
}
WidenHandle.prototype.GetX = function(event)
{
// ** return x position of mouse ** //
var posx = 0;
if (!event) event = window.event;
if (event.pageX)
{
posx = event.pageX;
}
else if (event.clientX)
{
posx = event.clientX;
}
return posx;
}
WidenHandle.prototype.WidenCell = function(event)
{
if (!this.Element.style.width)
this.Element.style.width = this.Element.offsetWidth - 9 + "px";
var width = parseInt(this.Element.style.width) + (this.GetX(event) - this.LastX);
if (width > 13)
this.Element.style.width = width + "px";
// ** remember last mouse position ** //
this.LastX = this.GetX(event);
}
WidenHandle.prototype.Close = function(event)
{
var width = parseInt(this.Element.style.width);
if (width < 30)
{
this.IsClosed = false;
this.Element.style.width = "";
return;
// width = this.StartWidth;
}
else
{
width = 14;
this.IsClosed = true;
}
this.Element.style.width = width + "px";
}
function clearHtmlSelection()
{
var sel;
if (document.selection && document.selection.empty)
{
document.selection.empty();
}
else if (window.getSelection)
{
sel = window.getSelection();
if (sel && sel.removeAllRanges) sel.removeAllRanges();
}
}

Categories

Resources