I have a Material UI Switch Component where I would like to detect click events on and be able, in certain circumstances, to prevent the change event from firing.
What would be the best way to do this?
I've used event.preventDefault to prevent events from bubbling up to parent component event listeners before, but in this case I have two events on the same Component/element and I want one to fire before the other and potentially prevent the other from firing.
Here's a codePen of what I've tried.
I've got it to work. Rather than have two events on the same element/component and try to orchestrate their order, I realized that its better to just have a click listener and let that call the change event for the Switch if the conditions are met. Here is a codepen with the solution.
The <Switch /> component only has an onClick event which opens a Dialog to detect whether to enact the change event. Much easier.
Related
Dispatching an event means firing it. the following code will fire the click event of the button 2 times.
let event = new Event("click");
elem.dispatchEvent(event);
elem.dispatchEvent(event);
<button id="elem" onclick="alert('Click!');">Autoclick</button>
Javascript has classes that are listening to the user events (click, hover a button, press a key). That classes are the event dispatchers. What does "dispatch a event" means?
The event dispatchers manage the event in order to "understand" which action has made the user and react with the behaviour that the developer coded.
Javascript has some event dispatcher classes defined by default, but some libraries like JQuery let you create custom events.
To understand a custom event, you can think this example: You are programming a clock class that you will use in the future. You code all the methods to make the clock work. Further, you declare a new event that triggers when a second passes. Let's call it "timestep".
Now imagine you use that class in two different programs. You can implement a different behaviour in both programs by inserting code in the "timestep" event.
In this example, I created a custom event that fires when the user moves one handle. It's behaviour consist in modify the label to the time the handle is on. Check it here:
http://ytcropper.com/crop/hsceS7udV4g
Recently, I have been integrating Material Design Lite into my React web application. For the most part, everything has worked out just fine, but currently I am having some issues with React's event handling, which doesn't seem to play nice with some MDL components.
In particular, I have a DOM element with an onClick handler, which works perfectly fine, until a MDL Tooltip is added, which causes the onClick to no longer fire. I've tried pretty much every variation possible (put the tooltip somewhere else in the DOM, attach the onClick handler to a container div which has the tooltip as a child, etc), and I just can't seem to get it to work.
Here's a JSBin that demonstrates the issue (I've also included an example that uses jQuery to bind a click handler to the element after the component mounts, which actually DOES work):
http://jsbin.com/sewimi/3/edit?js,output
I have some theories as to why this isn't working, but I don't know enough about either React or MDL to verify any of them.
I believe it has something to do with the way React handles events, and for some reason, MDL seems to be clashing with it. From the documentation:
React doesn't actually attach event handlers to the nodes themselves.
When React starts up, it starts listening for all events at the top
level using a single event listener. When a component is mounted or
unmounted, the event handlers are simply added or removed from an
internal mapping. When an event occurs, React knows how to dispatch it
using this mapping. When there are no event handlers left in the
mapping, React's event handlers are simple no-ops
This makes it seem like MDL might be messing with React's internal mapping of events, which causes my click on the element to become a no-op. But again, this is just a complete guess.
Does anyone have any ideas about this? I would prefer not to have to manually bind an event listener in componentDidMount for each of my components that use MDL Tooltips (like I did in the example JSBin I provided), but that's the solution I'm going with for now.
Also, since I was not sure if this was an MDL specific bug, I opted to post this question here instead of on their issues page. If anyone thinks I should post it there as well, let me know, and I can do that.
Thanks!
I faced this same issue too. I was trying to capture event clicks on a mdl-menu__item. And you are right in that React's synthetic event system is clashing.
What happens is that if an event happens inside your React component, your component will be the last to hear of the event. My work around was circumvent reacts event and use a react component which helps to attach native events react-native-listener.
<NativeListener onClickCapture={this.onListClick}>
<li className='mdl-menu__item' >
{...}
</li>
</NativeListener>
// This will be called by the native event system not react,
// this is in order to catch mdl-menu events and stop the menu from closing
// allowing multiple fields to be clicked
onListClick(field, event) {
event.stopImmediatePropagation();
// console.log('click');
}
My solution was for the mdl-menu but I'm sure it applies to the tooltip too.
A little late but
componentHandler.upgradeAllRegistered();
gets dynamically loaded elements working.
Note: that if you move the target element via CSS position the tooltip does not render to the new position automagically, you will need to id it and position it too.
I am using backbone and Marionette for my Application.I want to create my own event like If div innerHTML clears the event should be trigger.
html code :
<div id="firstDiv"></div>
While div clearing time, I want to unbind the view events.In my Application,we have Main button to go main page.This button common in every screen,So I written a code for this button,once use click on this button div clears and main page will be render,the problem was still the previous view events are listening.So How can I clear the previous View events.
can anyone help me.
Thanks.
You can't really do that, to the best of my knowledge. You can listen to events triggered by the browser (click, focus, etc.), and you can also listen or trigger events on Backbone/Marionette instances.
What you'd like to do is trigger an event on a specific DOM change, which you can't do. Instead, when you clear that div, you should trigger an event yourself and have your code listen for that event.
It is correct to say that you should be thinking about how you can capture this within the view logic, rather than listening to a DOM change.
That said, if you do think that listening to the DOM is the best approach, then this could be a good use case for a Mutation Observer. Explaining how is a little above and beyond, but there is a lot of good information on the MDN Dev page
If you are using Marionette, you should not worry about the previous view events. It automatically handles the Garbage Collections and unbinds the previous events. You have to make the application in such a style that when you render a View in a Region, it will bind the events to that, and when you click on button "Main" you should handle route to get the new View/stored View to be shown in that same region. So the old view will be removed automatically and the events will be also removed. Marionette is best at that part.
And if you have custom events using jQuery I suggest
Use Marionette View's events
OR
Use $(element).off("event").on("event", function(){});
In short
Is there a way in which, when listening to a native event, I can detect if the event was somehow used by CKEditor before it propagated to my listener, or prevent it from propagating at all?
Use case
I'm listening to the keyup event using jQuery, to detect when escape is pressed. When it is, the user is prompted if they want to discard changes, and the CKEditor instance is destroyed and its element removed from the DOM.
$('body').on('keyup', function(e){
if(e.which==27){
CKEDITOR.instances.myDiv.destroy();
$('#myDiv').remove();
}
});
The problem here is that CKEditor allows the user to interact with certain UI elements using the escape key. For instance to close a dialog window or drop-down list.
So my event should only execute its code if CKEditor did not already use the event to close a UI element of its own.
Attempt
I tried to listen to the dialogShow and dialogHide events to detect if a dialog window is open, and my action should thus be ignored. This didn't work for two reasons:
CKEditor handles the event first, so by the time the event propagates to my listener, no dialog windows are open and my code is executed.
Even if it would work, it wouldn't for drop-down lists as they do not trigger the dialog* events.
Ideas
I don't know enough about the workings of CKEditor to come up with a solution, but I think I'm looking for something along the lines of:
A setting in CKEditor to prevent event propagation: CKEDITOR.instances[0].noEventPropagation = true
An indication in the original event object: if(event.CKEditorWasHere){/*do nothing*/}
A plugin providing functionality that I can use.
Worst case scenario: A setTimeout in the dialogHide event which I'll use to suppress my own events for a short time.
So
Maybe I'm completely overlooking something. This seems to me like a common problem which should have a simple solution.
Thanks for your time.
I have a scheduler control, and some divs which can be dragged into the Scheduler which are two separate controls, now I have a problem, I succeeded to make the drag and drop event, when I drop I created an alert to get the coordinates where the drop was made see img below:
Now what I need to do is simulate a click event so when the user makes a drop an automatic click event is triggered (to trigger the add new event function of the scheduler)... anyone has any idea of how to achieve this?
Now what I need to do is simulate a click event so when the user makes a drop an automatic click event is triggered (to trigger the add new event function of the scheduler)... anyone has any idea of how to achieve this?
Don't try to simulate the click; instead, have both the click event and the drop event call a central, reusable function. While there are legitimate reasons you might want to simulate a click event, normally that's not how you solve this sort of problem.
Define the handler externally. Instead of ... ('click', function(event){}) do var handler = function(event){}; ... ('click', handler) and then you can easily do handler.call(this,event);.
A Pub/Sub system of any sort would handle this in a more loosely coupled way. For jQuery there is a really tiny but good one at https://gist.github.com/661855
If you're using any other framework you're likely to find others to suit you.