How would i replace internally triggered events of medium-editor with my custom ones or simply change internally designed behaviour?
In this hierarchy
<div>
<textarea class='editable'></textarea>
</div>
I bind a click handler to the div and do e.stopPropagation() and e.preventDefault().
I also try adding after the instantiating of medium-editor.
var editor = new MediumEditor('.editable')
.subscribe("editableClick", function(e){
e.preventDefault();
});
Every way i try textarea gets focused and cursor starts to blink.
For example intial click event adds an element to the dom with a class .medium-editor-element should i dive to source to modify this behaviour?
Or maybe i would like it to work with not a click but a double click.
Anyone familiar with the internal workings of medium-editor?
After trial and error and the help of dev tools i found the way to do what i want.
But i think this question is still answerable because i did it by modifying the source of medium-editor.
So, in medium-editor.js in line 2725 there is setupListener function.
There are 3 main events attached there to case 'externalInteraction': 2731th line.
mousedown,click,focus.
Starting from 2959th line there are the attached handlers for those events.
handleBodyClick,handleBodyFocus,handleBodyMousedown
The mousedown is important for my case because it is the first one that fires and should be prevented and accepted in different cases.
In the end i added a dblclick and handleBodyDblClick to source then put some logic in handleBodyMousedown to prevent the default behaviour of mousedown event in some cases.
Anyway, from the source as i can understand there are no override methods or hooks to modify medium-editor internal events.
It would be nice to have that feature.
Or if i am wrong i would like to know if there is a better way to do all these.
Related
I need to change behavior of jQuery library (date range picker), it have code like this:
box.find('.month').off("change").change(function(evt) {
dateChanged($(this));
});
box.find('.year').off("change").change(function(evt) {
dateChanged($(this));
});
Those are two select elements. It don't return false and functions inside handler don't access the event. But for some reason my events that use delegation doesn't work. They are ignored.
$picker.on('change', 'select', function() {
console.log('CHANGE');
});
The console log is not executing, but if I remove previous lines from the library, my event delegation code works fine.
NOTE: $picker is object in my code that is parent of box element. But I also have event added on $(document) that is also not working.
First time I see something like this. Adding event directly to element, prevents event propagation. Can someone explain what is happening here? Is this documented anywhere?
This happens in Firefox and Chrome.
If someone need simple example, I can create one. But thought that this is self explanatory.
EDIT: I've created a simple reproduction and it works fine. I have complex application with a lot of files (R Shiny Application), but I don't see any change events in dev tools. Are there any way of making the event not propagate? Maybe using event capturing. What should I search for in order to find the code that is preventing the events from propagating?
while testing my JavaScript I have the following problem:
$('#idOfMyElement').click();
is executed. But I want to verfiy with my test, that is is not executed, because it has the following CSS:
<span style="cursor: not-allowed; pointer-events: none;" id="idOfMyElement"></span>
I debugged it and it is sure, that when the .click() is executed, it has DEFINITELY the mentioned CSS-attributes. In my normal program it works (means that the click doesn´t work), but in my test the click works, even if it shouldn´t.
I have no clou, what might be the problem.
Thanks for your help!
Looks like in your test you are triggering the event programmatically by using $('#idOfMyElement').click();; in that case it is not bound by the CSS mouse rules, and thus the click handlers will get executed.
You need to check the mouse pointer rules before triggering the click event in your test suite.
Prevent the default click event using jQuery:
$('#idOfMyElement').on('click', function(e) {
e.preventDefault(); });
* UPDATE *
Now that I know what you're trying to do, I highly recommend using javascript over CSS for this because CSS does not work the way you're trying to use it – Javascript does. Instead of using CSS attributes, use Javascript variables.
When you want the element to be clickable,
$('#idOfMyElement').prop('disabled', false);
When it should be unclickable,
$('#idOfMyElement').prop('disabled', true);
The browser takes care of the cursor without needing CSS, and click events should react appropriately. Hope that was helpful!
Pointer events only respond correctly to a real pointer event. If you trigger click() function it fires in all times that you make it. Just add a condition reading if pointer events is active or replace it by a disabled attribute
I'm looking into custom events in JavaScript.
According to MDN, using the CustomEvent constructor, there is an option to make the event "bubble up" (false by default):
https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#CustomEventInit
Example:
// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) });
// create and dispatch the event
var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}});
obj.dispatchEvent(event);
I tested it on jsfiddle:
http://jsfiddle.net/ppx4gcxe/
And the bubble up functionality seems to work. But I'd like my custom event to "trickle down", that is to trigger even listeners on child elements; the opposite of bubbling up.
I vaguely remember some default browser events "trickling down". This was supposedly one of these points of contention in the early browser days.
Anyway, is there any way to get this functionality on my custom events? Any relatively easy and straightforward way, of course. I don't really want to write a function to traverse all child elements and manually trigger any listeners on them. I hope there's another way.
The behavior you're looking for is called event capturing (the opposite of event bubbling). You can enable event capturing by passing in true as the third argument to addEventListener.
See: http://jsfiddle.net/zs1a6ywo/
NOTE: event capturing is not supported in IE 8 or below.
For more information, see: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener
I've written an html5 application which is supposed to work on mobile devices. 90% of the time it works fine however in certain devices (mostly androids 4.0+) the click events fire twice.
I know why that happens, I'm using iScroll 4 to simulate native scrolling and it handles the events that happen inside the scroll.(line 533 dispatches the event if you're interested) Most of the time it works fine but in certain devices both the iScroll dispatched event and the original onClick event attached to the element are fired, so the click happens twice. I can't find a pattern on which devices this happen so I'm looking for alternatives to prevent double clicks.
I already came up with an ugly fix that solves the problem. I've wrapped all the clicks in a "handleClick" method, that is not allowed to run more often than 200ms. That became really tough to maintain. If I have dynamically generated content it becomes a huge mess and it gets worse when I try to pass objects as parameters.
var preventClick = false;
function handleClick(myFunction){
if (preventClick)
return;
setTimeout(function(){preventClick = true;},200);
myFunction.call():
}
function myFunction(){
...
}
<div onclick='handleClick(myfunction)'> click me </div>
I've been trying to find a way to intercept all click events in the whole page, and there somehow work out if the event should be fired or not. Is it possible to do something like that?
Set myFunction on click but before it's called, trigger handleClick()? I'm playing with custom events at the moment, it's looking promising but I'd like to not have to change every event in the whole application.
<div onclick='myfunction()'> click me </div>
You can do that with the following ( i wouldn't recommend it though):
$('body').on('click', function(event){
event.preventDefault();
// your code to handle the clicks
});
This will prevent the default functionality of clicks in your browser, if you want to know the target of the click just use event.target.
Refer to this answer for an idea on how to add a click check before the preventDefault();
I don't like events on attributes, but that's just me.
Thinking jquery: $(selector).click(function(){ <your handler code> } you could do something like:
$(selector).click(function(event){
handleClick(window[$(this).attr("onclick")]);
};
of course, there wouldn't be any parameters...
I was recently in a discussion with a work colleague about some differences in our coding practices, where I raised an issue about his excessive use of the two above mentioned methods in his event handlers. Specifically, they all look like this...
$('span.whatever').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
/* do things */
});
He has made the claim that this is a good practice with no foreseeable blowback, and will improve cross-platform support while reducing unexpected issues down the road.
My question to you guys: If he's right, why hasn't the jQuery team implemented this behavior globally applied to all event handlers? In effect, my assumption is that he's wrong simply because the methods are available for independent use, but who knows... Your insight is much appreciated.
--
Update: I did a simple speed test, and there is a little drag caused by these two function, but nothing terribly noticeable. Still, among other things, a good reason to be deliberate in their use I think.
$('span.whatever').on('click', function(e) {
var start = new Date();
for (i = 0; i < 999999; i++) {
e.preventDefault();
e.stopPropagation();
}
console.log( new Date() - start );
});
The above logged ~9.5 seconds as is, and ~2.5 seconds when I took the function calls out of the loop.
I don't do the same thing as your colleague (pushing the 2 calls on EVERY event handler), but I do have the same practice of using these calls explicitely rather than a "return false;", and I believe that has made my life easier.
When I started with Jquery, I figured if I need to both stop propagation, and prevent default, I should just "return false", which I kind of did all over the place.
$('a.whatever').on('click', function(e) {
do_stuff();
return false;
});
But there was 2 problems I enventually encountered:
if do_stuff() has any critical error causing an exception, "return false;" will never be reached!!! The error will eventually be "nicely" swallowed by jquery; your event will bubble, and let the browser execute the default action. If you are in a single page app and a link was clicked, for all you know the page navigated away, and the entire app state went down the toilet (I've been there before).
I was too lenient with my return false: in many cases, I just needed a preventdefault(). "return false" was killing event bubbling and sometimes hindered my ability to perform another action higher up the dom hierarchy (or made some other plugin/libs I was using not work properly)
So I now prefer to be explicit. I litterally never use "return false;" any more. If I have an event handler that must either not propagate or not execute default, I deliberatly put that in my function FIRST, before any processing code. Whatever happens during event handling should NOT affect the fact that I do NOT want the default action to run, and/or event to not bubble.
And yes, that being said, I am also mindful of using just one of the 2 when required (or none at all in some cases). I do not just add both preventDefault() and stopPropagation() for no reason. Everywhere I manipulate an event in a handler, it is part of a conscious case-by-case decision.
It would be a problem if the element is part of a menu and the click event was supposed to bubble out and tell the menu to close itself too.
Or if a menu was open elsewhere and clicking outside the menu was supposed to bubble up to the body where an event handler would close the menu. But the element having stopped the bubble, prevents the menu from closing.
<div id="wrapper">
<div id="header">header
<div id="footer">footer
<div id="content">click this!!!</div>
</div>
</div>
</div>
$("#wrapper div").click(function(){
console.log( $(this) )
});
Please try clicked to div and show console...
And now added
$("#wrapper div").click(function(e){
e.stopPropagation()
})