What I am trying to achieve is changing the way a player moves in a JQuery game.
Rather than a keypress I am trying to get the player to move if they click/mousedown on text, with id "left".
Original code is as follows.
if(jQuery.gameQuery.keyTracker[65]){ //this is left! (a)
var nextpos = parseInt($("#player").css("left"))-5;
if(nextpos > 0){
$("#player").css("left", ""+nextpos+"px");
}
}
My code is as follows, and when I play, it just continuously moves the player left without me pressing anything. It shouldn't move left until I click or mousedown on the "left" id text.
if ($('#left').mousedown){
var nextpos = parseInt($("#player").css("left"))-5;
if(nextpos > 0){
$("#player").css("left", ""+nextpos+"px");
}
}
This:
if ($('#left').mousedown){
will always be true. You're checking if $() has a mousedown property and it always will because all jQuery objects have a mousedown method. You probably want to bind a mousedown event handler:
$('#left').mousedown(function(e) {
//...
});
Related
I have found many similar questions and answers like mine. Unfortunatly, I have tried to adapt those answers to fit my problem but I cannot make it work. I am making a drawing pad application. The drawing pad is made of a container full of divs. I want the color to change only when mousedown and mouseover are both true. basically, I want to click and drag my drawing lines. Im probably way out to lunch here but I am at my whits end trying things.
let boxes = document.getElementsByClassName("grid-item");
let isClicked = false;
let isHover = false;
for (box of boxes) {
box.addEventListener("mousedown", () => isClicked = true);
}
for (box of boxes) {
box.addEventListener("mouseover", () => isHover = true);
}
function draw() {
if (isClicked == true && isHover == true) {
box.target.style.background_color = "black";
}
}
Instead of trying to manage and track global variables, you can use the event object passed. In my example, I have a function which can make the event target black, by changing the background color. I did use the style.backgroundColor because style.background-color is incorrect for js. If the mousedown event is triggered, you can safely assume the cursor is over the element. The mouseover event does not always make the target black. Instead, I check the event property .buttons which will be 1 if the left mousebutton is pressed, and 0 if not. This way, I can verify if it is clicked, then we just pass the event along to our make black function.
It is possible to solve this problem by tracking global variables, however you would need to be doing a lot of "state managing" which can quickly become messy and complex. You would need a mouseout function that turns the isHover off, as well as a mouseup function that turns the isClick off. You would probably need some debouncing in case the mouseout or mouseup event didn't trigger due to a right click or the cursor being in a different position. Then you would also need to track which element isHover and isClick which is redundant in this case because we can just check the event object from our mouseover event.
const boxes = [...document.getElementsByClassName("grid-item")];
const makeBlack = event => event.target.style.backgroundColor = "black";
function equip(box) {
box.addEventListener("mousedown", makeBlack);
box.addEventListener("mouseover", event => {
if (event.buttons == 1) makeBlack(event);
});
}
boxes.forEach(equip);
All,
I have a circle that I drag and drop from the upper div to the bottom div. Please see fiddle. After I click the circle in the bottom I then try to change the height with the input button. The input button is between the top and bottom div and uses incremental values of 5.
However, my event handler doesn't change the height value after incrementing from 5 to 10.
My goal is to allow changing of a height especially after I dropped a circle in the bottom and div and after selecting the circle to simulate activation.
Is there something wrong with how I'm trying to associate the event handler to the circle and the input button?
https://jsfiddle.net/mdevera/ff1bfpsd/
destinationContainer.addEventListener("click", change);
function change(event) {
activeShape = event.srcElement;
}
function changeHeight(event) {
//var height = (parseInt(activeShape.clientHeight, 10) + parseInt(event.target.value, 10)) + "px";
activeShape.style.height = event.target.value + "px";
}
The problem is that your click event listener for the #destination element only calls the change function when it is clicked. In other words, the change function isn't fired when you drag/drop the element since there aren't any click events fired. As a result, the activeShape variable defined in the change function doesn't point to an element since the change function is never called.
Another approach would be to select the last child element of the #destination element using the :last-child pseudo class. The last child is always the last element appended which means that you would always target the most recently dropped element when changing the height.
Updated Example
function changeHeight(event) {
var activeShape = destinationContainer.querySelector(':last-child');
if (activeShape !== null) {
activeShape.style.height = event.target.value + "px";
}
}
After reading your comment:
In addition to the changes above, it also seems like you are looking for the input event rather than the change event. The input event is fired fired synchronously when the value of the element is changed, whereas the change event is fired on blur (which is when focus is removed from that field).
Updated Example
var destinationContainer = document.querySelector("#destination");
var input = document.querySelector('#height-input');
input.addEventListener('input', function (event) {
var activeShape = destinationContainer.querySelector(':last-child');
if (activeShape !== null) {
activeShape.style.height = event.target.value + "px";
}
});
It looks unusual, but you should move out of input after changes made or use keys up/down to "catch up" input changes. In general it's some kind of onblur needed. In modern browser oninput event is preferable one for such cases.
onchange - only after focus out
oninput - the same as onchange but do not need blur focus
onpropertychange -
Just change onchange in your HTML to oninput and your problem will be resolved.
I'm trying to make a simple plugin to be able to make a div draggable. Of course a div can have a content inside (typically a form) and it should be dragged with it.
Here is a prototype: http://jsfiddle.net/Xcb8d/539/
The problem is that the texbox inside this div never gets focus, so I cannot type in it:
<div id="draggable-element">Drag me!
<form>
<input type="text" style="width:50px;"/>
<button>ok</button><br><br>
<input type="checkbox">check it</input>
</form>
</div>
As you can see, this does not happen to other elements on the form. Checkbox can be regularily used, as well as the button.
In addition, I would like only the grey coloured area to be draggable, and not the inner elements. On this example, you can place the mouse cursor fully inside the textbox and start the drag of the whole parent div.
the onmousedown handler on the draggable element return false and there by stopping event propagation, allowing it will make the input focus-able and the dragging still works. (at least on chromium)
document.getElementById('draggable-element').onmousedown = function (e) {
// memorize the offset to keep is constant during drag!
x_offset = e.clientX - x_elem;
y_offset = e.clientY - y_elem;
_drag_init(this);
return true;
};
In your onmousedown handler you end with a return false. This prevents the click event from happening when you click on the input, and thus it never gets focus. What I think you are looking for is this:
// Bind the functions...
document.getElementById('draggable-element').onmousedown = function (e) {
if (e.id == 'draggable-element') {
// memorize the offset to keep is constant during drag!
x_offset = e.clientX - x_elem;
y_offset = e.clientY - y_elem;
_drag_init(this);
return false;
}
};
paradoxix's answer was correct in stating that the return falseon the mousedown event is preventing the propagation of all other events.
On any element listening to the mousedown event you won't have any problems, because the event happens for them first, and only after for the box itself. But the input listens to the focusevent, which never happens due to the return false in the box's event.
The solution is to prevent onmousedown from bubbling from the child elements into the box, like so:
var nodes = document.getElementById('draggable-element').childNodes;
for(var i=0; i<nodes.length; i++) {
nodes[i].onmousedown = function(e) {
e.stopPropagation();
}
}
Working fiddle: http://jsfiddle.net/Xcb8d/546/
I am implementing drag'n'drop functionality on the page. The idea is that user can start dragging image from special place and drop it (release left mouse button) inside textarea, where special tag insertion will occur.
I have no issues with the dragging itself, the problem I got is that I can't determine position of the mouse inside textarea. I know x and y positions from mouseup event and I definetely know the mouse pointer is inside textarea, but can't determine at which position do I need to insert the required tag. Since the focus is not inside the textarea, selectionStart and selectionEnd properties are 0. Also, it is worth noticing that I prevent default behavior by returning false in mousemove handler - otherwise default behavior will put the image itself inside the textarea (which is extremely bad for base64 images).
Below is the code I currently have.
window.onPreviewItemMouseDown = function (e) {
var curTarget = $(e.currentTarget);
var container = curTarget.parent();
window.draggingImage = funcToGetId();
$(document).on("mousemove", window.onPreviewItemDragged);
$(document).on("mouseup", window.onPreviewItemDropped);
};
window.onPreviewItemDragged = function (e) {
return false;
};
window.onPreviewItemDropped = function (e) {
var target = $(e.target);
$(document).off("mousemove");
$(document).off("mouseup");
if (target[0].id === ID_TEXTAREA_TEXT) {
// here I need to get mouse pointer position inside the text somehow
}
return false;
};
Any help is appreciated.
In your case it would be easier to use native ondragstart event instead of a complex mousedown-move-up implementation, and manipulate the data to drop. Something like this:
document.getElementById('img').addEventListener('dragstart', function (e) {
e.dataTransfer.setData("text", '[img]' + this.id + '[/img]');
});
A live demo at jsFiddle. Or a delegated version. Notice that you can also delegate to the "special place" element, which might make the page running a little bit faster.
I want to cancel an HTML5 drag operation based on some condition. I have tried to search this but found nothing useful. It seems that there is no way to cancel an HTML5 drag and drop using JavaScript. returning false in the dragstart doesn't seem to do anything. Any ideas?
You can cancel it by calling event.preventDefault() in the event handler.
For example this should work:
<p id="p1" draggable="true" ondragstart="dragstart_handler(event);">This element is draggable.</p>
<script>
var enableDragDrop = true;
function dragstart_handler(ev) {
if (!enableDragDrop) {
ev.preventDefault();
}
console.log("dragStart");
}
</script>
I think you need to do something tricky to make it work, for I do not know how to stop a drag from js, but you can fake a drag with mousedown,mousedown,mouseup and a isDragging flag
some code look like:
var isDragging = false
var fakeDraggingElement
var currentDragging
$('#item').mousedown(function(e){
e.preventDefault()
isDragging = true
currentDragging = this
//change your cursor and make it loos like dragging
$('#parent').css({cursor: 'move'})
//fake dragging element
fakeDraggingElement = $(this).clone().css({
opacity:0.5,
position:'absolute',
top:e.pageY+offsetY, //parent offset
left:e.pageX+offsetX,//parent offset
}).appendTo(parent)
}).mousemove(function(e){
if(!isDragging){
return
}
fakeDraggingElement.css({
top:e.pageY+offsetY, //parent offset
left:e.pageX+offsetX,//parent offset
})
}).mousedown(function(e){
if(!isDragging){
return
}
cancleDrag()
//your old drop
ondrop(currentDragging,e.target)
})
function cancleDrag(){
isDragging = false
$(currentDragging).remove()
currentDragging = undefined
}
EDIT:
got it. Its a bit roundabout, but works. Take advantage of the fact that the drag event is a cancellable mouse event, and cancelling it stops all further drag actions. Create a drag event on your condition and call preventDefault(). The following cancels it after 3 seconds:
setTimeout(function(){document.getElementById("drag").ondrag = function(e){
e.preventDefault();
this.ondrag = null;
return false;
};},3000);
Note first that I clear all ondrag events after it is cancelled, which you may need to adjust if you need other ondrag events, and second that this truly cancels all parts of the drag, so you don't get an ondragend event after, as shown in this jsfiddle:
http://jsfiddle.net/MaxPRafferty/aCkbR/
Source: HTML5 Spec: http://www.w3.org/html/wg/drafts/html/master/editing.html#dndevents