Controlling Events for Nested React Elements - javascript

In an effort to add favoriting to a application menu, I'm working on getting onMouseEnter events to fire only on the element that is currently hovered. The problem is that due to these items being nested, onMouseEnter will fire on both the child element and the onMouseEnter of the parent element will also fire.
Ie:
HTML Nesting
The ideal behavior would be this:
Ideal Behavior
But the actual behavior is this:
Actual Behavior
I have already tried stopPropogation, but the problem is that there is a separate event listener on each of the menu items (both the L1 and the L2 have their own on mouse enter listeners). As such, capturing the event at the L2 level doesn't stop the event from firing at the L1 level.
Does anyone know of a way to only trigger the L2 event? Ideally, we wanted to be able to keep hover state specific to each item (ie don't have to have pass handlers for "setIsChildElementHovered"), but open to any ideas people have.

Did you try to add the event only on the child element ? If you have some snippets code might to answer your question. thanks :)

Related

Stopping event propagation - salesforce1

I have a Javascript mobile app that had an initial problem of touch down resulting in refreshing of the page. To counteract that, I added a ontouchmove attribute on my div tag where in the javascript I stop propagation (event.stopPropagation())
Context of the screen :
Asks a simple question, with 4 radio button options, and 2 buttons. The two buttons are being cut off after I've stopping the propagation. Confused how the bubbling of parent tags are impacting my buttons being cutoff.
Share the code so that everyone can better understand the problem.
From your statement above I could infer that some event which was vital for your screen has also stopped because of your stopPropagation call.
stop propagation should be the last resort, rather you can add your event to a specific component or add class to all components for which you need to listen to the event so as to avoid bubbling on the whole screen.

How can I make 'clickable' elements have selectable text on iOS touch devices?

I have an element (a div) that has a number of javascript touch and mouse handlers on it. Apparently, this means the element is 'clickable', and it seems you are not able to select text on clickable elements on the iPad.
Is there any way around this? The event handlers are necessary for this to work right, but I'd also like users to be able to select and copy the text.
One solution is to make the div contenteditable=true. The event handlers still work, and I'm able to long-press to bring up the selector. But this would create its own set of problems and I'd like to avoid contenteditable if I can.
After some tinkering, I've found a workaround solution: Put the mouse and click handlers on the window instead of the element. Then, check the event target in the handler to see if the element of interest is what was clicked.
Not ideal, but it seems to work. I'm able to long-press and create a selection on an iPad.

What's the difference between 'mouseup' and 'click' events?

Using jQuery, I often like to use mousedown and mouseup events in conjunction for pushable buttons.
However, in every case I've used the mouseup event, binding the click event instead seemed to produce identical results.
Is there any substantial difference between the two methods below?
// Method 1
$('.myButton').bind('click', callback);
// Method 2
$('.myButton').bind('mouseup', callback);
Please note I'm seeking a technical explanation on the differences between using both methods. This has no relation to the question that has been flagged as a dupe: Differentiate click vs mousedown/mouseup
With a mouseup event, you can click somewhere else on the screen, hold down the click button, and move the pointer to your mouseup element, and then release the mouse pointer.
A click event requires the mousedown and mouseup event to happen on that element.
The normal expectation is that a click requires both the mousedown and mouseup event, so I'd recommend the click event.
From the possible duplicate, it appears that mouseup and mousedown events can also be caused by mouse buttons other than the left click button. Which is very different from what a generic user would expect.
My understanding is that "click" hides lots of complexities (such as making sure that mousedown/up occur on the same element, cancelling with ESC/right click). Using "click" over "mousedown/up" should be preferred.
One scenario where "click" does not seem to work when app updates content very often in such a way that underlying DOM elements get replaced. In this case "click" will not be triggered and it might result in poor customer experience.
I think Mouse Down and Mouse Up events give you further control over the click event. It divides the click event into two more events so that more details can be coded for each event. Click event restricts the mouse click and force you to code both the events in the same function.
You can understand this restriction if you ever try to make your own dragging behavior.
Dragging needs a mouse-down event to start a drag behavior. You cannot do it with click event. And since you need a separate mouse-down event. The requirement of a separate mouse-up event becomes obvious.
Once the dragging starts ( you have not yet release the mouse button) you need the object to change position as per the cursor position. This too needs to be coded only in mouse-down event.
However you can use click event too if we could change the way how people drag the objects. For example click-1 starts the drag and click-2 stops the drag and puts the object on another position. But there are two problems I see:
It does not look natural. As in the real world we are in habit of
pressing the object and dragging it.
It can be process intensive to move heavy graphics just by clicking and mouse-move.
I would like to add to the other answers that click event works on touch-enabled devices while mouseup / mousedown do not (obviously because there's no "mouse")
Note that there's a 300ms delay on touch devices with the click event.
The biggest difference that affects the way I code is: the click event on an a HTML tag is responsible for changing the URL. In contrast, the mousedown and mouseup events will not acheive this

Force mouse click

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

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 ...
}

Categories