I'm trying to make an element move backward on the X axis when the user presses "a". However, I don't know how to make it move farther every time the users presses that key :(. I'm new to JS
document.addEventListener("keypress", function (e) {
let moveBy = 20;
if (e.key === "a") {
moveBy++;
element.style.webkitTransform = `translateX(-${moveBy}px)`;
}
}
Thank you!
Define moveBy outside of function and increment every keypress
const element = document.querySelector('div');
let moveBy = 20;
document.addEventListener("keypress", function (e) {
if (e.key === "a") {
moveBy++;
element.style.webkitTransform = `translateX(-${moveBy}px)`;
moveBy+=20
}
})
div {
width: 200px;
height: 200px;
background: red;
}
<div></div>
Related
I am wondering how I can make my code repeat, actually how the square can move next 10px. When I press "d" key, the square mooves, but when i click on it again, nothing happens. It's because I set the position to 10px, but I cant figure out new naw how to do it.
My code:
let body = document.querySelector("body")
body.addEventListener("keypress", function(event){
console.log(event.key)
if(event.key == "d"){
console.log("something")
let cube = document.getElementById("cube")
cube.style.left = "10px"
}
})
Any tips? Thank you.
let body = document.querySelector("body")
body.addEventListener("keypress", function(event){
console.log(event.key)
if(event.key == "d"){
console.log("something")
let cube = document.getElementById("cube");
const left = cube.style.left || 0;
cube.style.left = `${parseInt(left) + 10}px`;
}
})
#cube {
width: 10px;
height: 10px;
position: absolute;
top: 10px;
left: 0;
background:red;
}
<div id="cube">
</div>
If cube.style.left = "10px" works as expected for the first click, so it set left property to 10px. In this case, you need to add 10px to current Xpx. Hope this code help you
if(event.key == "d"){
console.log("something")
let cube = document.getElementById("cube")
cube.style.left = `${(parseInt(cube.style.left) + 10) || 0}px`
}
The thing is, you don't move the box by 10px to the left everytime you press d but you apply it once. To apply it multiple times you should use a variable that you keep increasing by every button press.
PS: You don't need to use querySelector('body') as you can simply address it with body directly:
let left_multiplier = 0;
document.body.addEventListener("keypress", function(event){
console.log(event.key);
if(event.key == "d"){
left_multiplier++;
let cube = document.getElementById("cube")
cube.style.left = `${left_multiplier * 10}px`;
}
})
You can add a variable and store what the current offset position is
Everytime you press "D" you add 10 to the variable.
let leftOffset = 0;
let body = document.querySelector("body")
body.addEventListener("keypress", function(event) {
if(event.key == "d") {
let cube = document.getElementById("cube")
leftOffset += 10;
cube.style.left = `${leftOffset}px`;
}
})
Jsfiddle demo
Try this:
let body = document.querySelector("body")
let value = 0
body.addEventListener("keypress", function(event){
if(event.key == "d"){
let cube = document.getElementById("cube")
value += 10
cube.style.marginLeft = value + 10 + 'px'
}
})
When you put cube.style.left = "10px" you are fixing a value to the style.
But when you do:
value += 10
cube.style.marginLeft = value + 10 + 'px'
You are dynamically updating the style in each key event
Can you recommend a JS library that actually provides edge swipe functionality when working with bare-bones HTML & CSS?
I've searched all over and haven't found a source of truth for that problem.
I've seen lots and lots of libraries enabling swipe gestures but not edge swipe.
My last attempt was using Hammer.js which I've tried implementing as:
var swipe = new Hammer(document);
// detect swipe and call to a function
swipe.on('swiperight swipeleft', function (e) {
e.preventDefault();
var endPoint = e.pointers[0].pageX;
var distance = e.distance;
var origin = endPoint - distance;
//swipe right to open nav
if (origin <= 15 && e.type == 'swiperight') {
// open main menu
$('#navigation-menu').animate({
left: '0'
});
} else {
// close/hide menu(s)
$('#navigation-menu').animate({
left: '-100%'
});
}
});
Further, if not using any library, how can I implement a mobile edge swipe to show and hide content, (in my case it'd be a navigation menu) with vanilla JS?
At this point I'm open to either solution/direction.
Here is a solution, you can set thresholdStart, End, Milliseconds. You may want to tidy up the code, and port it for touch events (I used mouse events for testing in my browser more easily).
Use:
swipeEdgeFromLeft function and swipeEdgeFromRight function.
var div = document.body;
var mouse = {
isDown: false,
inLeft: false,
inRight: false,
downTimestamp: null
};
var width, thresholdStart, thresholdEnd, thresholdMilliseconds;
function resize(){
width = window.innerWidth;
thresholdStart = 0.1*width;//within 10% of screen width
thresholdEnd = 0.13*width;//beyond 13% of screen width
thresholdMilliseconds = 500;//must be done in 500 milliseconds
}
document.addEventListener("resize", resize, false);
resize();//initialize
div.addEventListener('mousedown'/*'touchstart'*/, function(e){
var x = e./*touches[0].*/pageX;
mouse.isDown = true;
mouse.downTimestamp = performance.now();
if(x < thresholdStart){
mouse.inLeft = true;
} else if(x > width-thresholdStart){
mouse.inRight = true;
}
});
div.addEventListener('mousemove'/*'touchmove'*/, function(e){
var x = e./*touches[0].*/pageX;
if(mouse.inLeft && x > thresholdEnd){
mouse.inLeft = false;
if(performance.now() - mouse.downTimestamp < thresholdMilliseconds){
swipeEdgeFromLeft();
}
} else if(mouse.inRight && x < width-thresholdEnd){
mouse.inRight = false;
if(performance.now() - mouse.downTimestamp < thresholdMilliseconds){
swipeEdgeFromRight();
}
}
});
div.addEventListener('mouseup'/*'touchend'*/, function(e){
//var x = e./*changedTouches[0].*/pageX;
mouse.isDown = false;
mouse.inLeft = false;
mouse.inRight = false;
mouse.downTimestamp = null;
});
function swipeEdgeFromLeft(){
console.log("edge swipe from left");
}
function swipeEdgeFromRight(){
console.log("edge swipe from right");
}
body {
max-width: 100vw;
height: 100vh;
}
.bar {
height: 100vh;
background-color: rgba(0,0,0,0.4);
position: fixed;
pointer-events: none;
}
#left-inner-threshold {
width: calc(0.1 * 100vw);
left: 0;
}
#right-inner-threshold {
width: calc(0.1 * 100vw);
right: 0;
}
#left-outer-threshold {
width: calc(0.13 * 100vw);
left: 0;
}
#right-outer-threshold {
width: calc(0.13 * 100vw);
right: 0;
}
<div id="left-inner-threshold" class="bar"></div>
<div id="left-outer-threshold" class="bar"></div>
<div id="right-inner-threshold" class="bar"></div>
<div id="right-outer-threshold" class="bar"></div>
Here's a solution to your existing code using Hammer.js v2.0.8
The explanation for how to achieve the edge swipe can be found here answered by #jovinbm.
$(document).ready(function () {
const swipe = new Hammer(document);
function getStartPosition(e) {
const delta_x = e.deltaX;
const delta_y = e.deltaY;
const final_x = e.srcEvent.pageX || e.srcEvent.screenX || 0;
const final_y = e.srcEvent.pageY || e.srcEvent.screenY || 0;
return {
x: final_x - delta_x,
y: final_y - delta_y
}
};
swipe.on('swiperight swipeleft', function (e) {
e.preventDefault();
const { x } = getStartPosition(e);
console.log(x);
//swipe right to open nav /* note the condition here */
if (e.type == 'swiperight' && x >= 0 && x <= 50) {
// open menu
$('#navigation').animate({
left: '0'
});
//swiping left should slide out nav and/or sub-nav
} else {
// close/hide menu
$('#navigation, #task-menu').animate({
left: '-100%'
});
}
});
});
Here's a pen showing it in action:
For swipes, only the final pointerup event is included as the srcEvent in the event object passed to your handler (see http://hammerjs.github.io/api/). The initial pointerdown event that carries the details of the initial position of where the swipe event started is not provided in the hammer event object. Fortunately, you can use the srcEvent in the event object to get the starting position of the event initial pointerdown event.
const getStartPosition = (e) => {
const delta_x = e.deltaX;
const delta_y = e.deltaY;
const final_x = e.srcEvent.pageX || e.srcEvent.screenX || 0;
const final_y = e.srcEvent.pageY || e.srcEvent.screenY || 0;
return {
x: final_x - delta_x,
y: final_y - delta_y
};
};
const handleSwipe = (e) => {
const {x} = getStartPosition(e);
if (x >= 0 && x <= 50) {
// handle swipe from left edge e.t.c
}
else {
// handle other case
}
};
The srcEvent is just a normal javascript event that inherits properties from UIEvent hence the pageX/pageY api above. This will probably not work in other browsers since some of them are not standardized
Im making a simple Tetris game. So far I have a Tetris piece that rotates when the space bar is clicked.
The next step for me is to move the objects left and right using the arrow keys. From looking at other Stack Questions I found that this was possible by changing the margins.
var angle = 0;
var obj = document.getElementById('image')
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '32') {
rotate();
}
else if (e.keyCode == '37') {
moveLeft();
}
else if (e.keyCode == '39') {
moveRight();
}
}
function rotate() {
angle = angle + 90;
console.log(angle)
obj.className = "image" + angle;
console.log(obj.className)
if (angle == 360) {
angle = 0;
}
}
function moveLeft() {
obj.style.left = parseInt(obj.style.left) - 5 + 'px';
}
function moveRight() {
obj.style.left = parseInt(obj.style.left) + 5 + 'px';
}
For some reason this isn't working for me.
I've also re-created my code in a JSFiddle using a banana instead of a Tetris piece.
The problem is not with your Javascript, but with your styles. You need to absolutely position your image (banana in this case), and set an initial "left" value. The position: absolute; can be set either in the HTML or CSS, but the left: 0; must be set in the HTML style attribute. Here is an updated jsfiddle with the changes.
<div style="width: 250px;
height: 100px;
background-color: Green;
border-style: solid;
border-color: Black;"></div>
With the code above, I create a green box with a black outline. Fiddle.
Below, I have a Javascript function myFunction().
function myFunction() {
window.alert("Hello world!");
}
How do I get this function to run when the user uses his middle mouse button twice in a row with his mouse in the green box (as quickly as how someone double-clicks with his left mouse button)?
Plain JavaScript 1:
Cross browser support
var div = document.getElementsByTagName("div")[0];
var count = 0;
var timeout;
div.onmouseup = function(e){ // thanks RobG, it should be `mouseup`
if(e.which == 2){
count++;
if(!timeout){
timeout = setTimeout(function(){
timeout = undefined;
check();
}, 250);
}
}else{
count = 0;
}
};
function check(){
if(count >= 2){
alert('y');
}
count = 0;
}
DEMO
With jQuery:
Not working in Firefox 27.0 - use "Plain JS 1"
$("div").dblclick(function(e){
if(e.which == 2)
alert('y');
})
DEMO
Plain JavaScript 2:
Doesn't work in Safari 7/FireFox 27.0 - use "Plain JS 1"
var div = document.getElementsByTagName("div")[0];
div.ondblclick = function (e) {
if(e.button == 1) alert('y');
};
DEMO
Start simple. Add a click handler to you div like this:
<div style="width: 250px;
height: 100px;
background-color: Green;
border-style: solid;
border-color: Black;" onclick="myFunction();"></div>
Get that working, then search for how to modify the click event to use other buttons
Here is a function version of Gaurang's answer, however I can't get it to work reliably on Mac OS (nor is Gaurang's answer reliable). Anyway, it might be useful.
// Listener to add
function foo(e) {
console.log(this.id + ':' + e.button);
}
// Main function
var addNonPrimaryDblclick = (function() {
var timeout = null,
count = 0,
delay = 250;
// If timeout expires, reset everything
function checkTimeout() {
if (timeout) {
clearTimeout(timeout);
timeout = null;
count = 0;
}
}
return function(element, listener, newDelay) {
if (typeof newDelay != 'undefined') delay = newDelay;
// Add isDoubleClick as listener
element.addEventListener('mouseup', isDoubleClick, false);
function isDoubleClick(e) {
// A bit of debug
console.log('button: ' + e.button + ' which: ' + e.which);
e.preventDefault();
// 2 is the secondary button, equivalent to 3 in "which" scheme
if (e.button == 2) {
count++;
if (timeout) {
// If this is second click within delay, reset everything
// and call listener
if (count == 2) {
clearTimeout(timeout);
timeout = null;
count = 0;
// Set element to "this" in the listener and pass event
listener.call(element, e);
return;
}
// If no timeout setup, doso
} else {
timeout = setTimeout(checkTimeout, delay);
}
}
}
}
}());
// Example use - set long delay for testing
addNonPrimaryDblclick(document.getElementById('d0'), foo, 1000);
I'm fairly new to JavaScript, so any help would be awesome!
I created this small block of code that let's me grab a div and drag it around. I assign the "dragme" id to the div and all is fine and dandy. The problem is that if I replace that div from my html and put an img element instead (obviously assigning the "dragme" id to the img), things don't work as expected.
When I click to drag the img, it actually moves for about 3 or 4 pixels then it freezes until I lift the mouse button (mouseup).
Is there some property or characteristic that would prevent the img element from acting the same way as the div does?
var isClicked = false;
var startClientX = 0;
var startClientY = 0;
var startLeft = 0;
var startTop = 0;
window.addEventListener("load", addListeners, true);
function addListeners()
{
document.getElementById("dragme").addEventListener("mousedown", mouseIsDown, false);
document.getElementById("dragme").addEventListener("mouseup", mouseIsUp, false);
window.addEventListener("mousemove", moveImage, false);
function mouseIsDown(e)
{
if (isClicked == false)
{
isClicked = true;
startClientX = e.clientX;
startClientY = e.clientY;
startLeft = document.getElementById("dragme").offsetLeft;
startTop = document.getElementById("dragme").offsetTop;
}
}
function mouseIsUp()
{
if (isClicked == true)
{
isClicked = false;
}
}
function moveImage(e)
{
if (isClicked == true)
{
imageLeftDif = e.clientX - startClientX;
imageTopDif = e.clientY - startClientY;
var newLeftPos = (startLeft + imageLeftDif) + "px";
var newTopPos = (startTop + imageTopDif) + "px";
document.getElementById("dragme").style.left = newLeftPos;
document.getElementById("dragme").style.top = newTopPos;
}
}
}
This fixed the problem (answer provided as a comment by syazdani):
I'd venture to say that the built in browser drag and drop for images
is kicking in. Try e.preventDefault and return false in the mousedown
handler. – syazdani Dec 2 '12 at 17:26