Related
This is really straight forward but I'm still fairly new to JavaScript and just found JSFiddle. I'm trying to find the element with the getElementById() to disable and enable a button. What am I missing?
<form name="frm" >
<div id="chkObj">
<input type="checkbox" name="setChkBx" onclick="basicList.modifyAndEnableButton(this)"></input>
</div>
<div id="Hello">
<input type="button" name="btn" value="Hello"></input>
</div>
</form>
This is a list that I am using to add checkboxes because there is going to be more than one:
var basicList = {
'items': {},
'modifyAndEnableButton': function(obj1) {
var element = document.getElementsByName("btn");
if (obj1.checked == true && element.getAttribute('disabled') == false) {
element.getAttribute('disabled') = true;
this.addRecord(obj2);
} else if (element.getAttribute('disabled') == true) {
if (hasItems == false) {
element.getAttribute('disabled') = false;
}
}
}
};
http://jsfiddle.net/Arandolph0/E9zvc/3/
All browsers support this (see example here):
mySelectedElement.onclick = function(e){
//your handler here
}
However, sometimes you want to add a handler (and not change the same one), and more generally when available you should use addEventListener (needs shim for IE8-)
mySelectedElement.addEventListener("click",function(e){
//your handler here
},false);
Here is a working example:
var button = document.getElementById("myButton");
button.addEventListener("click",function(e){
button.disabled = "true";
},false);
And html:
<button id='myButton'>Hello</button>
(fiddle)
Here are some useful resources:
addEventListener on mdn
The click event in the DOM specification
Click example in the MDN JavaScript tutorial
Benjamin's answer covers quite everything. However you need a delegation model to handle events on elements that were added dynamically then
document.addEventListener("click", function (e) {
if (e.target.id == "abc") {
alert("Clicked");
}
});
For IE7/IE8
document.attachEvent('onclick', function (e) {
if (window.event.srcElement == "abc") {
alert("Clicked");
}
});
You have a Error here
btnRush should be Rushbtn
This is a example of cross browser event's I just made (not tested) )
var addEvent = function( element, type, callback, bubble ) { // 1
if(document.addEventListener) { // 2
return element.addEventListener( type, callback, bubble || false ); // 3
}
return element.attachEvent('on' + type, callback ); // 4
};
var onEvent = function( element, type, callback, bubble) { // 1
if(document.addEventListener) { // 2
document.addEventListener( type, function( event ){ // 3
if(event.target === element || event.target.id === element) { // 5
callback.apply(event.target, [event]); // 6
}
}, bubble || false);
} else {
document.attachEvent( 'on' + type, function( event ){ // 4
if(event.srcElement === element || event.srcElement.id === element) { // 5
callback.apply(event.target, [event]); // 6
}
});
}
};
Steps
Create a function that accepts 4 values ( self explaining )
Check if the browser supports addEventListener
Add event on the element
else add event on the element for older IE
Check that the (clicked) element is = to the passed element
call the callback function pass the element as this and pass the event
The onEvent is used for event delegation.
The addEvent is for your standard event.
here's how you can use them
The first 2 are for dynamically added elements
onEvent('rushBtn', 'click', function(){
alert('click')
});
var rush = document.getElementById('rushBtn');
onEvent(rush, 'click', function(){
alert('click');
});
// Standard Event
addEvent(rush, 'click', function(){
alert('click');
});
Event Delegation is this basically.
Add a click event to the document so the event will fire whenever & wherever then you check the element that was clicked on to see if it matches the element you need. this way it will always work.
Demo
I've made an editable implementation which behaviour is:
dblclick on element makes it editable:
an input is created
element contents emptied
input appended to element
attach keydown event handler to input, to disable edition when user presses Enter
idem with blur event
It works fine in decents browsers, but it breaks on IE8.
there are two problems:
input.focus() will call the blur event handler (wtf??)
keystrokes won't generate events intercepted by keydown handler, so my handler to validate when enter is hit don't work
I checked clicks events on the input and they are fine
The thing is it still works if I run the sample in a minimalist sample, but in my application, it won't.
what could prevent those keydown events from being fired / catch ?
here's the implementation:
widget.Editable = function( el, options ) {
this.element = $(el).addClass('editable');
this.value = this.element.text();
var _that = this;
this.element.dblclick( function(e) {
_that.enableEdition();
} );
};
widget.Editable.prototype = {
disableEdition: function( save, e ) {
this.value = this.input.val();
this.input.remove();
this.element.text( this.value ).removeClass('dragDisable');
this.editionEnabled = false;
this.onupdate( e, this.value, this.element );
},
/**
* enables the field for edition. Its contents will be placed in an input. Then
* a hit on "enter" key will save the field.
* #method enableEdition
*/
enableEdition: function() {
if (this.editionEnabled) return;
var _that = this;
this.value = this.element.text();
this.input = $( document.createElement('input') ).attr({
type:'text',
value:this.value
});
this.element
.empty().append( this.input )
.addClass('dragDisable'); //We must disable drag in order to not prevent selection
this.input.keydown( function(e) {
IScope.log('keydown editable:', e );
switch ( e.keyCode ) {
case 13:
_that.disableEdition( true );
break;
default:
break;
}
} );
this.input.click( function() {
console.log('input clicked');
});
//if ( !YAHOO.env.ua.ie )
// this.input.blur( function( e ) {
// IScope.log( "editable blurred", e );
// _that.disableEdition( true );
// });
//this.input.focus();
this.editionEnabled = true;
}
};
On mouseUp or touchEnd I want to get the reference of the element on which that event happened.
Demo
In this example, you need to click on one element, drag mouse and released over another element. When the mouse is released, that element's background will change to red. My code works correctly for mouse events, but not on touch devices.
When the touchStart is on one element and the finger is released over another element, I'm getting only the reference to the first element.
What I need to change to make the touch events work exactly like the mouse events?
var isMouseDown = false;
var panel1 = document.getElementById( 'panel1' );
var panel2 = document.getElementById( 'panel2' );
panel1.onmousedown = onDocumentMouseDown;
panel1.onmouseup = onDocumentMouseUp;
panel1.onmousemove = onDocumentMouseMove;
panel1.addEventListener( 'touchstart', onDocumentTouchStart, false );
panel1.addEventListener( 'touchmove', onDocumentTouchMove, false );
panel1.addEventListener( 'touchend', onDocumentTouchEnd, false );
panel2.onmousedown = onDocumentMouseDown;
panel2.onmouseup = onDocumentMouseUp;
panel2.onmousemove = onDocumentMouseMove;
panel2.addEventListener( 'touchstart', onDocumentTouchStart, false );
panel2.addEventListener( 'touchmove', onDocumentTouchMove, false );
panel2.addEventListener( 'touchend', onDocumentTouchEnd, false );
function onDocumentMouseDown(event) {
event.preventDefault();
panel1.style.background="#2E442E";
panel2.style.background="#5D855C";
}
function onDocumentMouseUp(event) {
event.preventDefault();
this.style.background="#ff0000";
}
function onDocumentMouseMove( event ) {
}
function onDocumentTouchStart( event ) {
event.preventDefault();
panel1.style.background="#2E442E";
panel2.style.background="#5D855C";
}
function onDocumentTouchMove( event ) {
}
function onDocumentTouchEnd( event ) {
event.preventDefault();
this.style.background="#ff0000";
}
This was a fun question to tackle. Thanks for that.
Here's what I have done. I have modified your touchmove handler as such:
function onDocumentTouchMove(event) {
onDocumentTouchMove.x = event.changedTouches[event.changedTouches.length - 1].clientX;
onDocumentTouchMove.y = event.changedTouches[event.changedTouches.length - 1].clientY;
}
In this handler I'm saving the last co-ordinate that the user moved to. In all probability, this is the point at which the user took his finger, nose, knuckle, stylus, etc off the touch surface. These co-ordinates I then use in the handler for touchend to find the element that surrounds them.
function onDocumentTouchEnd(event) {
event.preventDefault();
var elem = document.elementFromPoint(onDocumentTouchMove.x, onDocumentTouchMove.y);
elem.style.background = "#ff0000";
}
I have utilized the document.elementFromPoint(mdn link) for this purpose. It is one of those golden yet fairly unknown methods provided to us by the CSSOM spec.
Here's the fiddle.
From what it seems, this is intended behavior for touch events. However, I have a workaround!
I haven't tested this extensively, but it seems to work on mobile Safari for at least touchStart and touchEnd events.
Basically what we are going to do is capture all touch events on the document as they are in capture-phase (see http://www.w3.org/TR/DOM-Level-3-Events/). The handler for these events will find the DOM element at this location and re-send the event with the "correct" target.
It seems that the position of touchEnd events is not well defined, so I had to query the changedEvents array to get the last-touched position. I am not sure if this works as-is for touchMove events et al.
function rerouteTouch (evt) {
if (evt.passthrough) { // Ignore if already rerouted
return;
}
evt.stopPropagation();
var newevt = document.createEvent('TouchEvent');
newevt.initTouchEvent (
evt.type,
evt.bubbles,
evt.cancelable,
evt.view,
evt.detail,
evt.screenX,
evt.screenY,
evt.clientX,
evt.clientY,
evt.ctrlKey,
evt.altKey,
evt.shiftKey,
evt.metaKey,
evt.touches,
evt.targetTouches,
evt.changedTouches,
evt.scale,
evt.rotation);
newevt.passthrough = true; // Only reroute once
var target;
var x = (evt.type === 'touchend') ? evt.changedTouches[0].pageX : evt.pageX;
var y = (evt.type === 'touchend') ? evt.changedTouches[0].pageY : evt.pageY;
if (document !== (target = document.elementFromPoint(x, y))) {
target.dispatchEvent(newevt);
}
}
document.addEventListener( 'touchstart', rerouteTouch, true); // Third arg is true to indicate capture-phase
document.addEventListener( 'touchend', rerouteTouch, true);
...
// Your event handlers here
Here's a jsfiddle which works as expected on mobile safari for me: http://jsfiddle.net/DREer/12/
Perhaps if you can include jQuery into your program you can do something like this:
$('#itemId').on('touchEnd',function(){ this.trigger('mouseUp') });
I'm not sure if jQuery out of the box supports this events, but you can always try jQuery movil, hope it helped
Is there any event generated by continuous mouse click i.e., not releasing the mouse button 1? If no, please let me know.
The mousedown event is triggered when the mouse button is pressed down. If you are looking for an event that fires repeatedly, while the button is held down, you are out of luck, but you can use the mousedown event to repeatedly perform an action, and stop when the mouseup event is triggered.
For example, you could use the setInterval function to repeatedly call a function while the mouse button is down, and then use clearInterval to stop when the mouse button is released. Here is an example (using jQuery):
var interval;
$("#elementToClick").mousedown(function() {
interval = setInterval(performWhileMouseDown, 100);
}).mouseup(function() {
clearInterval(interval);
});
function performWhileMouseDown() {
$("#output").append("<p>Mouse down</p>");
}
You can see this running in this example fiddle.
There is a JQuery plugin: LongClick
Longclick is press & hold mouse button "long click" special event for jQuery 1.4.x.
The event is triggered when the mouse button stays pressed for a (configurable) number of seconds, while the pointer is stationery.
Yes, you can do this using onmousemove= movefunction(event) :
What I did to solve this is the following:
First, create a onmousedown() event that sets a global variable to 1 when triggered.
Second, create a onmouseup() event that sets that global variable to 0 when triggered.
Then, use the onmousemove() event to trigger in the div where I want the mouse down behavior to occur but only if the global variable we set earlier is set to 1.
example on how to use onmousemove(): http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmousemove
Done.
There is not such event.
What you might implement to achieve this is a function that evaluates the time elapsed between the (first) mouse click ond the following mouse release.
Given a predefined range you can estabilish how long should the button be clicked before being considered valid in your logic.
According to the spec,
A click is defined as a mousedown and
mouseup over the same screen location.
The sequence of these events is:
mousedown, mouseup, click
So no, there isn't a "continuous click", because a click is a descrete event resulting from a sequence of actions.
What you probably want to do, is receive mousedown, set a timer, and if neither mouseup or mousemove occur within some time, invoke some behaviour.
There's a function I've been using to determine if an object is being dragged (if for some reason you cannot use the regular on drag event). Can't be certain that $(':focus')[0] === undefined will work for every situation, but it can be customized.
// this function will set up a mouse drag event and also check if something is being dragged
function customOnDrag(selector) {
var dragInProgress = false;
let mouseDrag = false;
let mouseDown = false;
$(selector).on('mousedown', function(event) {
mouseDrag = false;
mouseDown = true;
interval = setInterval(checkIfDraggingAnObject, 20, event); // set to check every 20 ms
}
).on('mousemove', function(event) {
if ( mouseDown ){
mouseDrag = true;
}
}
).on('mouseup', function(event) {
checkIfDraggingAnObject(event);
clearInterval(interval);
mouseDrag = false;
mouseDown = false;
}
);
// function to check if an object is being dregged:
function checkIfDraggingAnObject(event){
if ( event.type === 'mousedown' ){
if ( $(':focus')[0] === undefined || mouseDrag === false ){
// not dragging an object
dragInProgress = false;
}else{
// dragging an object
dragInProgress = true;
console.log('dragging: ');
console.log($(':focus')); // the object being dragged
};
}else if ( event.type === 'mouseup' ) {
if ( dragInProgress ){
// dropped the object
console.log('dropped: ');
console.log($(':focus')); // the dropped object
dragInProgress = false;
}else if ( mouseDrag ) {
// dragged the mouse, but no object
console.log('did not drag an object');
}else{
// did not drag the mouse
console.log('did not drag the mouse');
}
}
}
}
import java.awt.Robot;
import java.awt.event.*;
public class App {
private static final int key = InputEvent.BUTTON1_DOWN_MASK;
public static void main(String[] args) {
System.out.println("Hello, World!");
Robot robot;
while (1==1) {
try {
robot = new Robot();
robot.mousePress(key);
robot.mouseRelease(key);
// robot.mouseMove(x, y);// x,y are cordinates
// Simulate a mouse click
robot.mousePress(key);
robot.mouseRelease(key);
Thread.sleep(3000);
// Simulate a key board press
// robot.keyPress(KeyEvent.VK_A);
// robot.keyRelease(KeyEvent.VK_A);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Is there a way to detect if a mouse button is currently down in JavaScript?
I know about the "mousedown" event, but that's not what I need. Some time AFTER the mouse button is pressed, I want to be able to detect if it is still pressed down.
Is this possible?
Regarding Pax' solution: it doesn't work if user clicks more than one button intentionally or accidentally. Don't ask me how I know :-(.
The correct code should be like that:
var mouseDown = 0;
document.body.onmousedown = function() {
++mouseDown;
}
document.body.onmouseup = function() {
--mouseDown;
}
With the test like this:
if(mouseDown){
// crikey! isn't she a beauty?
}
If you want to know what button is pressed, be prepared to make mouseDown an array of counters and count them separately for separate buttons:
// let's pretend that a mouse doesn't have more than 9 buttons
var mouseDown = [0, 0, 0, 0, 0, 0, 0, 0, 0],
mouseDownCount = 0;
document.body.onmousedown = function(evt) {
++mouseDown[evt.button];
++mouseDownCount;
}
document.body.onmouseup = function(evt) {
--mouseDown[evt.button];
--mouseDownCount;
}
Now you can check what buttons were pressed exactly:
if(mouseDownCount){
// alright, let's lift the little bugger up!
for(var i = 0; i < mouseDown.length; ++i){
if(mouseDown[i]){
// we found it right there!
}
}
}
Now be warned that the code above would work only for standard-compliant browsers that pass you a button number starting from 0 and up. IE uses a bit mask of currently pressed buttons:
0 for "nothing is pressed"
1 for left
2 for right
4 for middle
and any combination of above, e.g., 5 for left + middle
So adjust your code accordingly! I leave it as an exercise.
And remember: IE uses a global event object called … "event".
Incidentally IE has a feature useful in your case: when other browsers send "button" only for mouse button events (onclick, onmousedown, and onmouseup), IE sends it with onmousemove too. So you can start listening for onmousemove when you need to know the button state, and check for evt.button as soon as you got it — now you know what mouse buttons were pressed:
// for IE only!
document.body.onmousemove = function(){
if(event.button){
// aha! we caught a feisty little sheila!
}
};
Of course you get nothing if she plays dead and not moving.
Relevant links:
MouseEvent's button (DOM 2)
MSDN's button
Update #1: I don't know why I carried over the document.body-style of code. It will be better to attach event handlers directly to the document.
This is an old question, and the answers here seem to mostly advocate for using mousedown and mouseup to keep track of whether a button is pressed. But as others have pointed out, mouseup will only fire when performed within the browser, which can lead to losing track of the button state.
However, MouseEvent (now) indicates which buttons are currently pushed:
For all modern browsers (including Safari v11.1+ [v11.3+ on iOS]), use MouseEvent.buttons
For Safari < 11.1 (11.3 on iOS), use MouseEvent.which (buttons will be undefined for Safari) Note: which uses different numbers from buttons for Right and Middle clicks.
When registered on document, mousemove will fire immediately as soon as the cursor reenters the browser, so if the user releases outside then the state will be updated as soon as they mouse back inside.
A simple implementation might look like:
var primaryMouseButtonDown = false;
function setPrimaryButtonState(e) {
var flags = e.buttons !== undefined ? e.buttons : e.which;
primaryMouseButtonDown = (flags & 1) === 1;
}
document.addEventListener("mousedown", setPrimaryButtonState);
document.addEventListener("mousemove", setPrimaryButtonState);
document.addEventListener("mouseup", setPrimaryButtonState);
That code tracks the state of the primary mouse button (typically the left), ignoring the state of other mouse buttons.
If more complicated scenarios are required (different buttons/multiple buttons/control keys), check out the MouseEvent docs.
I think the best approach to this is to keep your own record of the mouse button state, as follows:
var mouseDown = 0;
document.body.onmousedown = function() {
mouseDown = 1;
}
document.body.onmouseup = function() {
mouseDown = 0;
}
and then, later in your code:
if (mouseDown == 1) {
// the mouse is down, do what you have to do.
}
the solution isn't good.
one could "mousedown" on the document, then "mouseup" outside the browser, and on this case the browser would still be thinking the mouse is down.
the only good solution is using IE.event object.
I know this is an old post, but I thought the tracking of mouse button using mouse up/down felt a bit clunky, so I found an alternative that may appeal to some.
<style>
div.myDiv:active {
cursor: default;
}
</style>
<script>
function handleMove( div ) {
var style = getComputedStyle( div );
if (style.getPropertyValue('cursor') == 'default')
{
// You're down and moving here!
}
}
</script>
<div class='myDiv' onmousemove='handleMove(this);'>Click and drag me!</div>
The :active selector handles the mouse click much better than mouse up/down, you just need a way of reading that state in the onmousemove event. For that I needed to cheat and relied on the fact that the default cursor is "auto" and I just change it to "default", which is what auto selects by default.
You can use anything in the object that is returned by getComputedStyle that you can use as a flag without upsetting the look of your page e.g. border-color.
I would have liked to set my own user defined style in the :active section, but I couldn't get that to work. It would be better if it's possible.
If you're working within a complex page with existing mouse event handlers, I'd recommend handling the event on capture (instead of bubble). To do this, just set the 3rd parameter of addEventListener to true.
Additionally, you may want to check for event.which to ensure you're handling actual user interaction and not mouse events, e.g. elem.dispatchEvent(new Event('mousedown')).
var isMouseDown = false;
document.addEventListener('mousedown', function(event) {
if ( event.which ) isMouseDown = true;
}, true);
document.addEventListener('mouseup', function(event) {
if ( event.which ) isMouseDown = false;
}, true);
Add the handler to document (or window) instead of document.body is important b/c it ensures that mouseup events outside of the window are still recorded.
The following snippet will attempt to execute the "doStuff" function 2 seconds after the mouseDown event occurs in document.body. If the user lifts up the button, the mouseUp event will occur and cancel the delayed execution.
I'd advise using some method for cross-browser event attachment - setting the mousedown and mouseup properties explicitly was done to simplify the example.
function doStuff() {
// does something when mouse is down in body for longer than 2 seconds
}
var mousedownTimeout;
document.body.onmousedown = function() {
mousedownTimeout = window.setTimeout(doStuff, 2000);
}
document.body.onmouseup = function() {
window.clearTimeout(mousedownTimeout);
}
In case someone else runs into this, you can use .matches with the :active selector:
function mouseDown() {
return document.body.matches(":active");
}
Using the MouseEvent api, to check the pressed button, if any:
// Mouse buttons
document.addEventListener('mousedown', e => console.log(e.buttons))
// Keyboard keys
document.addEventListener('keydown', e => console.log(e.key))
Return:
A number representing one or more buttons. For more than one button
pressed simultaneously, the values are combined (e.g., 3 is primary +
secondary).
0 : No button or un-initialized
1 : Primary button (usually the left button)
2 : Secondary button (usually the right button)
4 : Auxilary button (usually the mouse wheel button or middle button)
8 : 4th button (typically the "Browser Back" button)
16 : 5th button (typically the "Browser Forward" button)
You can combine #Pax and my answers to also get the duration that the mouse has been down for:
var mousedownTimeout,
mousedown = 0;
document.body.onmousedown = function() {
mousedown = 0;
window.clearInterval(mousedownTimeout);
mousedownTimeout = window.setInterval(function() { mousedown += 200 }, 200);
}
document.body.onmouseup = function() {
mousedown = 0;
window.clearInterval(mousedownTimeout);
}
Then later:
if (mousedown >= 2000) {
// do something if the mousebutton has been down for at least 2 seconds
}
You need to handle the MouseDown and MouseUp and set some flag or something to track it "later down the road"... :(
Short and sweet
I'm not sure why none of the previous answers worked for me, but I came up with this solution during a eureka moment. It not only works, but it is also most elegant:
Add to body tag:
onmouseup="down=0;" onmousedown="down=1;"
Then test and execute myfunction() if down equals 1:
onmousemove="if (down==1) myfunction();"
Using jQuery, the following solution handles even the "drag off the page then release case".
$(document).mousedown(function(e) {
mouseDown = true;
}).mouseup(function(e) {
mouseDown = false;
}).mouseleave(function(e) {
mouseDown = false;
});
I don't know how it handles multiple mouse buttons.
If there were a way to start the click outside the window, then bring the mouse into the window, then this would probably not work properly there either.
As said #Jack, when mouseup happens outside of browser window, we are not aware of it...
This code (almost) worked for me:
window.addEventListener('mouseup', mouseUpHandler, false);
window.addEventListener('mousedown', mouseDownHandler, false);
Unfortunately, I won't get the mouseup event in one of those cases:
user simultaneously presses a keyboard key and a mouse button, releases mouse button outside of browser window then releases key.
user presses two mouse buttons simultaneously, releases one mouse button then the other one, both outside of browser window.
var mousedown = 0;
$(function(){
document.onmousedown = function(e){
mousedown = mousedown | getWindowStyleButton(e);
e = e || window.event;
console.log("Button: " + e.button + " Which: " + e.which + " MouseDown: " + mousedown);
}
document.onmouseup = function(e){
mousedown = mousedown ^ getWindowStyleButton(e);
e = e || window.event;
console.log("Button: " + e.button + " Which: " + e.which + " MouseDown: " + mousedown);
}
document.oncontextmenu = function(e){
// to suppress oncontextmenu because it blocks
// a mouseup when two buttons are pressed and
// the right-mouse button is released before
// the other button.
return false;
}
});
function getWindowStyleButton(e){
var button = 0;
if (e) {
if (e.button === 0) button = 1;
else if (e.button === 1) button = 4;
else if (e.button === 2) button = 2;
}else if (window.event){
button = window.event.button;
}
return button;
}
this cross-browser version works fine for me.
Below jQuery example, when mouse is over $('.element'), color is changing depending on which mouse button is pressed.
var clicableArea = {
init: function () {
var self = this;
('.element').mouseover(function (e) {
self.handlemouseClick(e, $(this));
}).mousedown(function (e) {
self.handlemouseClick(e, $(this));
});
},
handlemouseClick: function (e, element) {
if (e.buttons === 1) {//left button
element.css('background', '#f00');
}
if (e.buttons === 2) { //right buttom
element.css('background', 'none');
}
}
};
$(document).ready(function () {
clicableArea.init();
});
Well, you can't check if it's down after the event, but you can check if it's Up... If it's up.. it means that no longer is down :P lol
So the user presses the button down (onMouseDown event) ... and after that, you check if is up (onMouseUp). While it's not up, you can do what you need.