I am using plain JavaScript (no JQuery etc.) to display a semi-modal dialog, which contains a small FORM
The way that I have things set up at the moment, the same handler will show a different dialog if the user clicks on a different part of the page, but if the user clicks on an INPUT field in my dialog, the click propogates/bubbles through to the handler, and the INPUT loses focus - the only way to type into it is to TAB into it, which is not exactly ideal!
Any suggestions on how to avoid this?
You can attach a click handler to your dialog's main element, and stop propagation at that point:
theDialogMainElement.addEventListener("click", function(e) {
e.stopPropagation();
}, false);
That way, clicking within the dialog doesn't propagate to the click handler on your page that's interfering.
If you need to support old versions of IE (IE8 and earlier) that don't have addEventListener and stopPropagation, see this other answer for a cross-browser event hookup function (which supplies stopPropagation as well).
You can call a .focus() on the specific input element you are referring to.
http://www.w3schools.com/jsref/met_html_focus.asp
Related
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.
IE fires the change event on a select menu when using the arrows to navigate the menu. This is not the case in non-IE browsers. Non-IE browsers only fire the event when clicking on the option, or pressing enter after navigating to the item with the arrows. Is there a way program around this? I need the event to not fire when navigating with the keys.
I would add my own change event listener and handle things that way if I could. Without knowing all of the details it's hard to say but I'd look there first because the event cannot be cancelled. Outside of that approach, IE is going to fire the event when the value changes so not much you can do about that. Here is a link to the change/onchange in IE. It actually says this in the doc.
To invoke this event, do one of the following:
Choose a different option in a select object using mouse or keyboard navigation.
Alter text in the text area and then navigate out of the object.
It stinks but one of those you have to account for when using a select field.
The solution that worked for my situation was the following.
bind to the blur event instead of the change event.
This introduced another issue, where when I initially load the page the select fires a change event, and I need the code in my blur binding to take effect. Binding to change and having it trigger blur caused massive recursion. The solution was to create an init function that ran at startup.
initData : function(){
var t = this,
formSelects = 'select';
jQuery.each(formSelects, function(){
// do my code here that normally happens in blur.
})
}
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
I'm using jQuery to alter things when a user enters text into an input. This works fine with .keydown() or .change() when typing.
I'm unable to capture an event when the user selects from the browser stored inputs for that field. This is the dropdown that appears when typing or on click when the element already has focus and the browser has previously entered items for this input.
Anyone know what event I can use to capture the population of the input by the browser from a stored list of previous inputs when the user clicks on one or uses the keyboard?
EDIT: As requested an example would be https://launchpad.37signals.com/highrise/signin (the Username and password, not openID). This hides the label for pasting, selecting from previous inputs or typing. I want to emulate this.
Thanks,
Denis
There's not one event triggered. As you said, it depends on how the user is using it : keyboard or mouse.
If I can remember well, keyboard approach triggers nothing. You should bind on the blur() event.
The mouseup should work for the mouse approach.
But whatever since you can bind several event at once thanks to
$("#id").bind("blur mouseup", function(){
alert("bound !");
});
The change event will fire as well, but when the element looses focus.. (like it normally does)
You would have the same issue even without the browser cache, if someone use the right-mouse-click -> paste of something they had in the clipboard ...
What about mouseup event? did you try it on the input?
I'm trying my hand at jQuery Address http://www.asual.com/jquery/address/
On a click event I set $.address.value(mypath);
This fires off the $.address.change() event.
When I click a link I want the behavior to be slightly different than when this event is fired by clicking the back/forward button or with a bookmark or link.
Is there a way to distinguish between the two events. I've looked at the event object passed to $.address.change() and they seem to be identical in both situations.
I think I found the answer. There are two other events, $.address.internalChange(fn) and $.address.externalChange(fn). externalChange event is for the forward/back buttons and links. That is what I needed.