Dragging div elements and then switching places with another element - javascript

So I'm trying to program a bejeweled like game in javascript but instead of clicking a jewel then clicking another jewel to make them switch positions, I want to the player to click on a jewel then drag to another jewel to make them switch places. In the code I use the variable orb as jewels.
function makeOrb(orb, x, y) {
orb.className = "orb";
var bejeweledarea = document.getElementById("bejeweledarea");
bejeweledarea.appendChild(orb);
var random = Math.round(Math.random() * (colors.length - 1));
orb.style.backgroundColor = colors[random];
orb.style.position = "absolute";
orb.style.top = y + "px";
orb.style.left = x + "px";
orb.onmousedown = activate;
if (activeSwitching) {
orb.onmouseover = switchOrbs(activeOrb, orb);
}
}
function activate() {
activeSwitching = true;
activeOrb = this;
}
function switchOrbs(orb, otherOrb) {
var oldTop = orb.style.top;
var oldLeft = orb.style.left;
orb.style.top = otherOrb.style.top;
orb.style.left = otherOrb.style.left;
otherOrb.style.top = oldTop;
otherOrb.style.left = oldLeft;
}
My could will register the activeSwitching as true but for some reason the mouseover event doesn't ever work.

You are now adding a onmouseover event to the orb that has just been clicked. I assume you want all the other orbs to have an onmouseover event that calls switchOrbs, right? Because you want to switch the orbs when the activated is hovered over an other orb.
You could add that mouseover event to all the orbs. In that function you then check if activeSwitching = true. If so, you perform the routine to switch. Otherwise you stop, since there is no activated orb and the program needs to wait for a orb.onmousedown / activate() call.
Edit: outline for the code
$(".orbs").on("mouseover", function() {
// `this` is the orb that is being hovered
if( currentActiveOrb != null ) {
switch(this, currentActiveOrb);
}
}).on("mousedown", function() {
// `this` is the orb that is being clicked
currentActiveOrb = this;
}).on("mouseup", function() {
currentActiveOrb = null;
});
function switch(hovered, active) {
// Code to switch the orbs.
}

Related

Element.scrollIntoView(); Not working in Chrome and Edge, Works in Firefox?

Let me preface by saying I am relatively green in respect to JavaScript. However, I am trying to create a JavaScript function that will listen for a wheel event, determine the direction of the scroll and scroll the next part of the page into view. Similar to a swipe gesture. I have it working in Firefox as intended, user scrolls down the page moves down, up the page moves up. However, in Chrome and Edge, the element.scrollIntoView() function seems to be called, but nothing happens.
I am using Blazor with JSInterop to get the page to scroll.
Here is the gist of the file:
// scrolldetection.js //
window.scrolldetection {
scrollSetup: function (elementId) {
autoscroller(elementId);
}
}
function autoscroller(elementId) {
// Set up vars
var idList = document.getElementById(elementId).children.id;
var idListIndex = // Gets current index based on current location on page
var curDirection;
document.addEventListener("wheel", function () {
var currentPos = window.scrollY;
if (!curDirection) {
// Check for what direction user scrolls
idListIndex = // Function that determines new index
scrollScreen(idList, idListIndex);
}
var timerId = setTimeout(function () {
curDirection = undefined;
clearTimeout(timerId);
}, 700);
}
}
function scrollScreen(idList, curIndex) {
console.log("list index: " + curIndex);
element = document.getElementById(idList[curIndex]);
console.log(element.id);
element.scrollIntoView({ behavior: 'smooth' });
}
I have another function that calls scrollIntoView() on the same elements, via a button press. Works just fine.
Here is that function:
// anchorlink.js // This one works as intended //
window.anchorlink = {
scrollIntoView: function (elementId) {
var elem = document.getElementById(elementId);
if (elem) {
elem.scrollIntoView({ behavior: 'smooth' });
}
}
}
The console.log() calls within the scrollScreen() function show up properly in the console in each browser. Leading me to believe that element.scrollIntoView() is being called, but something is going wrong to make it not function appropriately. If there is any other information you need, I will be happy to provide, thanks.
After working on this some more, I decided the concept I was using wasn't as user friendly as I had hoped.
I decided to let the user scroll freely along the page and when they stop scrolling, then determine the closest DOM element and scroll to it. Works on Edge, Chrome and Firefox.
window.contentcenter = {
contentCenter: function (elementId) {
var centeringFunction = debounce(function () { autocenter(elementId) }, 200);
document.addEventListener("scroll", centeringFunction);
}
}
function autocenter(elementId) {
var currentElement = detectCurrentElement(elementId);
currentElement.scrollIntoView({ behavior: "smooth" });
}
function detectCurrentElement(elementId) {
var element = document.getElementById(elementId);
var currentPos = window.scrollY;
var contentIdList = getContentIdList(elementId);
var currentElement = closestContent(currentPos, element, contentIdList);
return currentElement;
}
function closestContent(pos, element, contentIdList) {
var contentId = Math.round(pos / (element.offsetHeight / contentIdList.length));
var currentElement = document.getElementById(contentIdList[contentId]);
return currentElement;
}
function getContentIdList(elementId) {
var idList = []
var childElements = document.getElementById(elementId).children;
for (var i = 0; i < childElements.length; i++) {
idList.push(childElements[i].id);
}
return idList;
}
function debounce(func, timeout) {
var timer;
return function () {
var context = this, args = arguments;
var later = function () {
timer = null;
func.apply(context, args);
};
clearTimeout(timer);
timer = setTimeout(later, timeout)
};
}

how to make cocos creator touch listener

I started to learn cocos a few days ago and I don't really understand how to use the eventListener, I tried to copy the example code in their documentation website and make it so that instead of moving with the WASD keys you'll move by touching the screen, I tried to add it to the code but it didn't work... this is my code
cc.Class({
extends: cc.Component,
properties: {
// foo: {
// // ATTRIBUTES:
// default: null, // The default value will be used only
when the component attaching
// // to a node for the first time
// type: cc.SpriteFrame, // optional, default is typeof default
// serializable: true, // optional, default is true
// },
// bar: {
// get () {
// return this._bar;
// },
// set (value) {
// this._bar = value;
// }
// },
},
// Player.js
//...
properties: {
// main character's jump height
jumpHeight: 0,
// main character's jump duration
jumpDuration: 0,
// maximal movement speed
maxMoveSpeed: 0,
// acceleration
accel: 0,
},
//...
setJumpAction: function jump() {
// jump up
var jumpUp = cc.moveBy(this.jumpDuration, cc.p(0,
this.jumpHeight)).easing(cc.easeCubicActionOut());
// jump down
var jumpDown = cc.moveBy(this.jumpDuration, cc.p(0, -
this.jumpHeight)).easing(cc.easeCubicActionIn());
// repeat
return cc.sequence(jumpUp, jumpDown);
},
setInputControl: function () {
var self = this;
// add keyboard event listener
// When there is a key being pressed down, judge if it's the
designated directional button and set up acceleration in the corresponding
direction
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function
(event) {
switch (event.keyCode) {
case cc.KEY.a:
self.accLeft = true;
break;
case cc.KEY.d:
self.accRight = true;
break;
case cc.KEY.w:
self.accUp = true;
break;
}
});
// when releasing the button, stop acceleration in this direction
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, function (event) {
switch (event.keyCode) {
case cc.KEY.a:
self.accLeft = false;
break;
case cc.KEY.d:
self.accRight = false;
break;
case cc.KEY.w:
self.accUp = false;
break;
}
});
},
setTouchControl: function () {
//Create a "one by one" touch event listener (processes one touch at a time)
var listener1 = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
// When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it.
swallowTouches: true,
//onTouchBegan event callback function
onTouchBegan: function (touch, event) {
var x = touch.getLocationX();
var y = touch.getLocationY();
},
//Trigger when moving touch
onTouchMoved: function (touch, event) {
//Move the position of current button sprite
var x = touch.getLocationX();
var y = touch.getLocationY();
},
//Process the touch end event
onTouchEnded: function (touch, event) {
var x = touch.getLocationX();
var y = touch.getLocationY();
}
});
cc.systemEvent.addListener(listener1, this.node);
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, function (event) {
switch (event.keyCode) {
case cc.KEY.a:
self.accLeft = false;
break;
case cc.KEY.d:
self.accRight = false;
break;
case cc.KEY.w:
self.accUp = false;
break;
}
});
},
// Player.js
onLoad: function () {
// initialize jump action
this.jumpAction = this.setJumpAction();
this.node.runAction(this.jumpAction);
// switch of acceleration direction
this.accLeft = false;
this.accRight = false;
this.accUp = false;
// current horizontal speed of main character
this.xSpeed = 0;
this.ySpeed = 0;
// initialize keyboard input listener
this.setInputControl();
this.setTouchControl();
},
// LIFE-CYCLE CALLBACKS:
// onLoad () {},
start() {
},
// update (dt) {},
// Player.js
update: function (dt) {
// update speed of each frame according to the current acceleration direction
if (this.accLeft) {
this.xSpeed -= this.accel * dt;
} else if (this.accRight) {
this.xSpeed += this.accel * dt;
}
// restrict the movement speed of the main character to the maximum movement speed
if (Math.abs(this.xSpeed) > this.maxMoveSpeed) {
// if speed reaches its limit, use the max speed with current direction
this.xSpeed = this.maxMoveSpeed * this.xSpeed / Math.abs(this.xSpeed);
}
// update the position of the main character according to the current speed
this.node.x = this.x;
},
});
I tried to use the function setTouchControl for my porpuses but I don't even know if it's good and if so how to use it in code...
ok, I found the answer... here:
properties: {
},
onLoad () {
this.node.on('touchstart', function(){
}, this.node);
this.node.on('touchmove', function (event) {
var delta = event.touch.getDelta();
this.x += delta.x;
this.y += delta.y;
}, this.node);
this.node.on('touchend', function () {
}, this.node);
},

While mousedown JS

I'm trying to run a function while mousedown but for the life of me I can't get it to work while holding down but everything works by just clicking. I'm trying to change color of countries on a map as I hold down.
Here's my code:
var int;
var mouseStillDown = false;
function mousedown(geography)
{ console.log('mousedown '+mousedownID);
mouseStillDown = true;
int = setInterval( performWhileMouseDown(geography), 100);
}
function mouseup()
{
clearInterval(int);
mouseStillDown = false;
}
function mouseout()
{
clearInterval(int);
}
function performWhileMouseDown(geography)
{
if (!mouseStillDown)
{console.log('error');}
if (mouseStillDown) {
if(data[geography.id])
{
data[geography.id] ++;
}else
{
data[geography.id] = 1;
}
var m = {};
m[geography.id] = color(data[geography.id]);
map.updateChoropleth(m);
}
/* if (mouseStillDown)
{ setInterval(performWhileMouseDown(geography), 100); }*/
}
You could try to use mousemove instead, mousedown will only fire once.
var mouseDown = false;
window.addEventListener('mousedown', function() { mouseDown = true })
window.addEventListener('mouseup', function() { mouseDown = false })
window.addEventListener('mousemove', function() {
if (!mouseDown) {
return;
}
// perform while mouse is moving
})
here's what worked for me
var timeout ;
function mouseDown(geography){
timeout = setInterval( function(){
if(data[geography.id]){
data[geography.id] ++;
}else{
data[geography.id] = 1;
}
var m = {};
m[geography.id] = color(data[geography.id]);
map.updateChoropleth(m);}, 100);
return false;
}
function mouseUp(geography){
clearInterval(timeout);
return false;
}
The two conditions for your event are that the code executes every time there is an update in mouse position AND the mouse button is pressed.
Addressing the first part can be done with the 'mousemove' event, which fires when the mouse is moved over the element.
The second filter can be solved, by checking the mouse event, on if the button is pressed. If not, we don't execute the following code.
window.addEventListener('mousemove', function() { // Attach listener
if (event.buttons == 0) // Check event for button
return; // Button not pressed, exit
// perform while mouse is moving
})

Tap event firing X times a second in jquery

I'm trying to make touch controls for a little game I'm writting with the help of jquery. But i just can't figure out how to write a function that basicly does the same thing that happens when you keep a key pressed.
Could you please help me?
PS. its not originaly my code source
jQuery.fn.mousehold = function(timeout, f) {
if (timeout && typeof timeout == 'function') {
f = timeout;
timeout = 100;
}
if (f && typeof f == 'function') {
var timer = 0;
var fireStep = 0;
return this.each(function() {
jQuery(this).mousedown(function() {
fireStep = 1;
var ctr = 0;
var t = this;
timer = setInterval(function() {
ctr++;
f.call(t, ctr);
fireStep = 2;
}, timeout);
})
clearMousehold = function() {
clearInterval(timer);
if (fireStep == 1) f.call(this, 1);
fireStep = 0;
}
jQuery(this).mouseout(clearMousehold);
jQuery(this).mouseup(clearMousehold);
})
}
}
$.fn.extend({
disableSelection: function() {
this.each(function() {
this.onselectstart = function() {
return false;
};
this.unselectable = "on";
$(this).css('-moz-user-select', 'none');
$(this).css('-webkit-user-select', 'none');
});
}
});
Well the question is, how often do you want to check for a change in user input. You are quite limited when it comes to the resolution of a timer in JS. Although be aware that everything is running in sequence and thus events are queued and potentially sum up. This is especially true for setInterval() as it rigorously queues new events, even when previously triggered events were not yet processed.
Something like this works:
var pressed; // flag for continous press between mousedown and timer-events
var duration; // number of times the timer fired for a continous mousedown
var timeout; // reference to timer-event used to reset the timer on mouseup
$(document).mousedown = function(){
pressed = true;
handleMousedown(false);
}
function handleMousedown(continued){
if(pressed){ // if still pressed
if(continued){ // and fired by the timer
duration++;
// measure time, use duration
// do anything
}
timeout = setTimeout('handleMousedown(true)', 100); // wait for another 100ms then repeat
}
}
$(document).mouseup = function() {
// do sth on mouseup
pressed = false; // reset flag for continous mousedown
clearTimeout(timeout); // abandon the timer
}
$(document).mouseout = function() { // $(document).mouseenter = function(){
// do sth on mouse leave or mouse entering again according to how your game should behave
pressed = false; // reset flag for continous mousedown
clearTimeout(timeout); // abandon the timer
}

jQuery debug functionlity in a "class" file

im creating a simple game and, I need some direction for debuging some data.
i have a div in my HTML file, that I want him to show some data that change when some variables get change by the user actions.
for exmple i got var xPosition, I want to send the data to a div in the HTML, so i can see the current state of xPosition.
i realy dont have any idea where to start creating this functionlity.
my questions:
is it possible to create event inside this class and register some
element to him that will show all the changing data?
do i have to use a some a timer for that sort of thing?
this is the "class":
(function ($) {
$.Player = function (element) {
this.element = (element instanceof $) ? element : $(element);
this.movmentSpeed = 10;
this.size = $(element).width();
this.xPos = 0;
this.yPos = 0;
};
$.Player.prototype = {
//register events
InitEvents: function () {
var that = this;
$(document).keydown(function (e) {
var key = e.which;
if (key == 39) {
that.moveRight(400);
} else if (key == 37) {
that.moveLeft();
}
});
this.element.css({
left: this.xPos
});
},
//movment functions
moveRight: function (worldWidth) {
if ((this.xPos + this.size) <= worldWidth) {
this.xPos += this.movmentSpeed;
this.element.css("left", '+=' + this.movmentSpeed);
}
},
moveLeft: function () {
if (this.xPos > 0) {
this.xPos -= this.movmentSpeed;
this.element.css("left", '-=' + this.movmentSpeed);
}
}
};
} (jQuery));
here the HTML:
<div id="player">
<div id="debugData"> <div>
<script>
var player = new $.Player($("#player"));
player.InitEvents();
</script>
(sorry for my english)
jsFiddle Demo
I'd say having an internal function inside the Class would help. Maybe even having a setting where you turn the logging on by doing player.logging = true;, and having it default to false;
In your prototype just add a public prototype variable for logging = false, and our prototype function log().
The internal function you could use could be something as simple as:
logging : false, // our default
log : function (str) {
if (this.logging) {
$('#debugData').html(str);
}
},
This way you could leave your log(this.xPos); (or whatever you want to log) within your code, and by removing the player.logging = true; when you instantiate your class, they won't show up, till you put that code back in.

Categories