Force mouse click - javascript

Ok, I know that is a rookie question but is there any way to force a mouse click? To be more specific, say I want to trigger mouse click on random time and I don't know in which element the mouse would rest that time.

You can install a root level event handler on the document object to track the mouse position so you can know where the mouse is at any given time. You can create events in the browser using the code described in this post: Is it possible to trigger a link's (or any element's) click event through JavaScript? which gets its info from this article: http://jehiah.cz/a/firing-javascript-events-properly
Usually, creating raw events is not the most efficient way to solve a problem (unless you're doing some sort of automated tester). Usually it's better to just call the function you want directly or modify the DOM object directly rather than try to cause that change with an event.

No, this is not possible exactly the way you describe.
You can listen to mouseenter for everything and always update a reference to whatever was hovered last.

You can track elements with mouseover/mouseout and trigger their click handlers at any time

Related

Is there any way to dynamically pause all eventListeners of an element?

I'm making the step-by-step-filled form-like page now (hope it was grammatically correct ☺ ).
The main idea here is quite simple: while step one isn't done, step two is unavailable.
I need it to be truly unavailable, not just CSS-hidden (like opacity: 0; or visibility: hidden;).
So, here is the question: in JavaScript is there any way to dynamically pause (and unpause later) all eventListeners of some element?
P.S.: Event is for example onwheel || onmousewheel.
Here is the image (sorry for cyrillic):
(It's about scoresheet-typing.)
You see the <input type="range"> element here. Mouse scrolling on it will change it's value.
The first step of a form isn't done yet; so the second one have to be unavailable, and mouse scrolling on input range element should not work.
But this time I managed to it with opacity: .3;.
So all works fine, but the picture is kinda translucent, that's all.
It is bad.
It shouldn't react on mouse wheel at all (just usual page-scrolling).
And opacity must be full (opacity: 1;).
So, we return to the initial question.
There is no way in JavaScript to even list all event listeners for an element, so to stop them is an even taller order.
In short, the answer to your question is: there's no general way to pause all event listeners.
However, there are some things you may try that could help achieve your intent.
Plan A - HTML / CSS + a little JS: If your intent is simply to prevent the events from reaching the unactivated step, you may try a hack: create a transparent "blocker" element of the exact same dimensions. When you "disable" your step, "enable" your blocker to be right on top of it - probably using absolute positioning, e.g.
// Disable step 2
step2.style.opacity = '0.3'; // could also be a CSS class toggle, or an JS animation
step2_blocker.style.display = 'block'; // make your blocker show up on top of step2
You may use HTML+CSS to create the blocker, provided you know the position/dimensions. If not, you can use JS to create the blocker at run-time after computing step2's position/dimensions.
Plan B - JS only: If for some reason, you can't change HTML or CSS and you need a JS-only solution that doesn't alter the DOM, or if you are truly trying to solve the generic problem of "How can I pause event listeners?", then you probably only have one solution - keep track of your listeners. Essentially, you will be building your own event-binding/tracking library. The API consists of on(), off(), pause(), resume().
on(HTMLElement, eventType, callback): you should push the listener callback into a registry - an array of listener objects, where listener objects contain HTMLElement and its corresponding eventType and event listener callback.
off(HTMLElement, eventType, callback): remove listener object from registry.
pause(HTMLElement, eventType, callback): find listener object from registry and set it to paused state, i.e. stop the actual listener.
resume(HTMLElement, eventType, callback): find listener object from registry and rebind the element to the event listener.
Of course, the API can be made to be flexible/smart enough to accept different number of parameters (simulate function overloading), so that pause(elem) can pause all events on the element, and pause(elem, 'click') can pause all click events on that element.
Then, rather than use addEventListener() in your code, always remember to use on() in the library you created. You may have to refactor all your event binding and listener code.
This plan is slightly elaborate, but is probably the only way to keep track of event listeners. I have done this before, so I know this really works.
P/S: You may try to take a look at the source of some popular libraries out there to see how they keep track of events. I don't think any of them has any kind of support for pause() and resume() (yet), so it'd only be for some code inspiration.
In the context of a problem, I may just addEventListener after correct passing the step one, of course.
It is not the answer though.
You can set the disabled attribute of the inputs to true initially. Then as each input is filled in and/or validated, you can set the disabled attribute of the next one to false, to make it available.
Edit: given the update to the question, this answer doesn't seem to work. Setting disabled on an <input type="range"> does not seem to prevent wheel events from firing, at least in chrome.

What's the most efficient way to handle displaying a dialog/modal in JavaScript?

[UPDATE:] here is a link to test (if you don't want to clone the repo) http://jsfiddle.net/integralist/g9EPu/
I've got a lot of dialogs/modals that need to be displayed when mousing over certain links in a web app.
Table of content (tl;dr)
How I used to do handle it
How I've tried it recently
Which is better?
What about mouseenter/leave?
How I used to do handle it
The way I usually do this is to use event delegation.
So I add one event handler to a container and then check for the relevant element to become the target and then display the relevant dialog.
I normally have one dialog which I change the content for and re-position (saves having lots of different HTML mark-up).
If the mouseover event (for the link) gets triggered then I display the dialog.
If the mouseout event (for the link) gets triggered then I hide the dialog.
If I mouseout of the link which triggered the event handler then I normally need to set a timer to delay hiding the dialog (just long enough) so I can then mouseover the dialog which itself clears the timer set by the mouseout of the link.
I then have a mouseout event bound to the dialog so I can then hide the dialog when the user rolls their mouse off the dialog.
There are two problems I've encountered at this stage, the first happens practically all the time and the other is an edge case I noticed recently which prompted me to try and find a better solution...
The dialog has 'x' number of child elements and rolling the mouse over a child element causes the mouseout event for the dialog to be triggered hence I need to put in checks to see if the element has a parent which is the dialog itself and if so then don't try to hide the dialog.
When using this technique on a <table> element I've found that when the mouse moves too quickly the mouseout/over events don't get triggered.
How I've tried it recently
For example code see: https://github.com/Integralist/Mouse-Over-Out-Script (you should be able to just clone the repo and run the index.html file locally to see what's happening)
But to give a brief explanation...
We bind a mousemove event to the document.documentElement element (but you could do it on the document.body if you wanted) and then we store the x/y co-ordinates of the mouse position. We provide public API access to a 'check' method which lets us know if the position of the mouse is over the element we've provided to 'check' (we measure the elements dimensions and add those onto its x/y co-ordinates).
In the above repo we have a calendar which shows a dialog whenever a particular date has an event on. We're storing all <td>'s that have an event and we set-up a timer for each of those <td>'s (this is because we need to keep calling the 'check' method to see if that <td> has the mouse over it).
So potentially there could be 31+ (because we're showing the first few days of the following month) opportunities for a dialog to be shown and so 31+ timers set!
This example repo works now, where as the first version where I was using event delegation wasn't.
Which is better?
I'm worried about performance on the mousemove version because it can potentially use a lot of timers (depending on how many dialogs you need in a single page). In my calendar example above there is up to 31+ timers that could be running!
What about mouseenter/leave?
I know these events exist and if all browsers supported it then I could safely use the first version and not have to check for child elements causing erroneous mouseout/over events to be triggered. But regardless I don't believe this would have fixed the example with the event calendar where moving the mouse too quickly was meaning the mouseout/over events for the <td>'s weren't being triggered by the browser. Either way, I know you can polyfill this as jQuery provides mouseenter/leave events but looking through their code I couldn't get that to work for my script (as I don't use jQuery or any other general purpose library - ps, and I don't wish to, so please do not suggest that as an option).
Many thanks for any help/advice or guidance someone can provide me.
The dialog has 'x' number of child elements and rolling the mouse over a child element causes the mouseout event for the dialog to be triggered hence I need to put in checks to see if the element has a parent which is the dialog itself and if so then dont try to hide the dialog.
To solve this: in your event code, simply use the function "isAncestor" (see below)
/*
* element = the "target" in your mouseout event handler
* other = the node you really want to check if you're over
*/
isAncestor: function(element, other)
{
while ( element && element != other ) element = element.parentNode;
return ( element != null && element != undefined );
}
So in your mouseout code for your element (let's call it "itemElement"), you'd check it like:
//We're really mousing out, close dialog
if ( !isAncestor( mouseOutEvent.target, itemElement ) )
{
...do something ...
}

Javascript drag and drop.... the receiving object?

Ive written some code so that i can drag an object, but eventually i wish to place this on a particular object and then call some functions.
How do i add a listener to the destination object, when i dont know which actual object will be dropped onto it?
In simple way you must attach some function on mousemove. This function must get round all dom elements and find your element. But it is DOM, and it so long. You must cache elemetns position and it will be fine.
i highly recommend using jquery ui draggable and droppable. no need to re-invent the wheel for this!
http://jqueryui.com/demos/draggable/
http://jqueryui.com/demos/droppable/
There are a couple ways that I've handled this in the past. They both depend on the cursor being outside the element you're dragging.
First, you could define a mouseup event handler on the document level, and determine which element was the target of the event. That element will be the element that your draggable item was dropped on to, and you can handle the event from there.
Second, you could define a mouseup event handler for each droppable area. This allows easier customization of the handler.
Keep in mind that both of these solutions rely on the cursor being outside the element you're dragging. Otherwise, the target of the event will always be the element you're dragging.
Do you simply want to have a 'drop' event on DOM elements but think you need to care what is being dropped onto them?
My initial approach to similar issues started with the 'drop', not the drag, but found that the 'ondrop' event is not very portable, implying I should use a framework like jQuery instead. See:
See here for a jQuery UI framework approach with demo:
http://jqueryui.com/demos/droppable/
See here for a less framework oriented approach with some disscusion on the topic:
http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/

How can I reliably track mouse enter and leave events?

Various experiments I've carried out indicate that there is no foolproof way of responding to a 'mouseleave' event using jQuery. Two actions appear to not trigger any relevant event:
Moving the pointer away from an element very quickly
Moving the pointer off the element via some browser chrome (or out the the window entirely)
The second is by no means a show-stopper, but the first is a big problem. Is there a solution? Tracking document.mousemove and continually checking whether the cursor is over the target element?
i usually use hoverintent instead of hover to solve problems like this.

which HTML element lost focus?

in javascript, when I receive a focus event, how can I work out which element has lost focus? I'm trying to avoid having to put an onblur event handler on all elements within my web page.
#pbrodka: the target/srcElement property would refer to the element with focus for onfocus events
offhand I can't see a way to get this short of onblur, or if the set of objects you care about all have focus methods you could store a reference to that object instead. It's also possible event bubbling could get you out of jail
this all feels like a bit of a code smell though - perhaps you need to describe the problem in more detail
Difficult this. You cannot use event delegation to find out which control last produced a blur as focus/blur do not bubble up. There have been some attempts to 'fix' this but they are buggy and not resiliant cross browser.
Could I ask you why do you need this information as maybe there is an alternative solution.
Unfortunately, the onblur event doesn't bubble, otherwise you could have handled it at the window level to always know when an element lost focus.
As things are, I do believe it will be hard to do without, as you say, adding an onblur event handler to all elements (a truly nasty solution ;-).
It is possible to delegate the focus and blur events, if you follow PPK's advice, here:
http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
The most simple solution is to write a function that walks all forms and then all elements within the form and installs an onblur handler for each (which will probably call some global function). This handler will get an event and this event will contain the info you seek.
This way, you just have to call this method once in body.onload and it will work no matter how complex your document is.
The only drawback is that you will need to call it if you dynamically add forms to your current document. In this case, you must make sure not to install the handler again (or you will get spurious duplicate events).

Categories