I have a span nested within several divs (nothing else special about the DOM) and on mousedown I'm running e.preventDefault() in order to prevent text selection from happening. I don't want to stop the span element from being focused on because I want to allow subsequent keydown events on it. I'm guessing the best way to do this would be to manually trigger events that I want from the list of default events that I'm preventing (though I'm open to other thoughts).
My question is, when I run e.preventDefault(), what things would naturally trigger? Or in other words, what things am I preventing?
Related
In Chrome (85) and FF (80), clicking on a tabbable element gives it focus. Of course, one can focus by tabbing to the element too, and the focus events that come from either seem to be identical (view dump in browser console: the focus event is quite big):
document.getElementById('main').addEventListener('focus', console.log)
focus here
This becomes problematic for the following: I'm implementing a double-click behavior, where one must select an item with one click, then click again to follow it. I'd also like users to be able to use tab + enter or tab + single-click to follow through.
While I'd strongly prefer to use the default browser behavior to do most of the work, given all I'm adding is one extra click, this seems to be impossible to do without listening for keystrokes. This is because if indeed the two above events are indistinguishable, then one can't tell the difference between:
a tab followed immediately by click, and
a single click that generates both a focus and click event.
Event order can't be trusted, and unfortunately FF has focus first before click anyways.
Is there something in the focus or click events that I'm overlooking that I could use to check where that event is coming from?
I have an app im building with phonegap.
I'm listening for touchstart/ touchend events to make it responsive.
Sometimes, the event listener for the touchend will fire, but then, for e.g, an input will focus afterwards as the click event is fired 300ms later.
an example is, i have a menu sidebar. each sidebar list item listens to the touchend event. on receiving the event, the sidebar closes and the relevant page is shown. however, if the relevant page contains a form element that is where the user had clicked for the sidebar list item, the form element will get focused.
what is the best way to stop this across the entire app? it happens in various scenarios which vary with different phones.
Ive tried things like stopPropagation etc but these only work ina few cases, and i need to have a generic cross-app solution rather than adding in for each function, if possible.
something like:
$('body').on('touchend', function(){
//stop any further touchends/ clicks from firing
//apart from the 1 i do want
})
You could try 'touchcancel' instead of 'touchend', see if it works :) good luck.
your app goes to fast ;)
EASY WAY:
just put a setTimeout(gotopage(),100)
on every button/menu action
HARD WAY:
If you really don't want to put a setTimeout, you should take a look to how bubbling works, problem is here
TIP:
Anyway to avoid the 300ms you should use the Fastclick of FTLABS :
https://github.com/ftlabs/fastclick
and the use click event, it will do the job for you (you will still have to use setimeout trick)
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.
There is a lot of material/posts on ghost clicks and I'm trying to understand it better. So the way I understand it, the reason for ghost clicks is the click event being dispatched ~300ms after the touch event. jQuery Mobile suggests to not use their vclick event whenever there is any chance of changing the content underneath the finger position.
My first question would be: Does that mean ghost clicks will only fire if the element targeted by click is different from the one originally touched? So, say, I write a database entry when a button is touched – nothing else. Is there a chance of ghost clicking or not?
If this is the case, wouldn't that mean that I can prevent ghost clicks altogether if I simply use only tap events and no click events whatsoever?
My last question would be if I can simply tell the browser to not use the 300ms delay when using PhoneGap (which would instantly solve the problem), but I'd just guess that I can't do that as it's probably hard-coded into the browser.
The click event is delayed by 300 ms to detect things like double tap or fat finger mistakes.
Yes, wherever possible you should use the touch events instead.
Yes, there are many ways to enable fast clicks by doing a bit of JS. For instance:
https://developers.google.com/mobile/articles/fast_buttons
https://forum.jquery.com/topic/how-to-remove-the-300ms-delay-when-clicking-on-a-link-in-jquery-mobile
http://labs.ft.com/2011/08/fastclick-native-like-tapping-for-touch-apps/
You don't have to live with the 300ms delay.
If everything on your page that can be clicked has the appropriate vclick jQuery event handlers installed, then one easy way of stopping ghost clicks is create a touchend event handler on the body and call preventDefault from it:
$(document.body).on('touchend', null, function(e) {
e.preventDefault();
});
Note that this will disable regular clicks from touches, so any conventional links or form inputs you have will stop working unless you add vclick handlers to them.
This question is related to Javascript event handling and flow control, but it is one step beyond. The question that remains unanswered is: when an event is fired and control is returned to the browser, could the browser decide to handle other events first (fired by other scripts or user action) (A), or will it always handle my event directly (B)?
The question is important, because in case (B) you can rely on the fact that nothing has been changed between firing the event and the event handler, while (A) gives no guarantees whatsoever.
My first guess is (B), how else could stopPropagation() and preventDefault() work? But giving it a second thought, it is no hard evidence.
A real-life example of this problem. I am modifying a rich text editor (hallo), and I want it to have these specs:
clicking on an editable text (#txt) will activate the editor, and clicking outside #txt will deactivate it. hallo uses blur and focus events on #txt to achieve this.
Activating the editor opens a toolbar, mousedown on the toolbar (but not on a button) will set a flag that prevents the blur event on #txt to deactivate the editor. The toolbar will return focus to #text.
mousedown on a toolbar button should also prevent deactivating the editor, but it should first wait till the click event, perform its action and then return focus to #txt. Some actions are immediate (bold or italic), while others need extra user input (selecting from a dropdown).
Some of these buttons open a dialog.
...And I want all these elements (editor, toolbar, dialog) to be modular
and easily extendable.
Now in most cases when you close a dialog you want the focus to return to #txt. But in the case where a dialog is opened and you click somewhere else on the page, the editor will close and call the toolbar, including the dialog to close as well. If in this case the dialog would return focus to the editor, it would activate the editor again.
As far as I understand now, the event handling order is at least deterministic. It is not possible that some event gets a delay while others are processed earlier. This is what is meant by 'synchronous'. The exception is of course events like loading a file.
From the perspective of a program component, say the dialog, the situation can be quite unpredictable. It can bind a handler to the open event, and then call dialog("open"), but anything can happen between the call and the handler, if only because the editor has an event handler on the same event.
So my conclusion is 1) yes it is predictable but 2) it needs a sophisticated architecture to implement this.
In general the event model is synchronous and reentrant, meaning that if an event handler causes another event - the second event will be executed synchronously and only after completion will the first event continue executing.
This seems to be what you're trying to describe, in which case (B) is guaranteed.
Relevant source: http://www.w3.org/TR/DOM-Level-3-Events/#event-flow