Update: I tried a suggestion by #newmount however, if I call fireEvent('blur') then the focus of the trigger isn't fired by any keyboard action. (It resumes once there is a mouse click)
To be honest the triggerfield doesn't fire blur in a certain situation.
From within the focus event if I have a reference to another field and do field.focus() the blur of the current field doesn't fire. What's worse is it fires later if I click anywhere else.
Below is code and steps to reproduce:
Ext.onReady(function() {
Ext.define('Ext.ux.CustomTrigger', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.customtrigger',
labelStyle: 'white-space: nowrap',
initComponent : function() {
this.on("focus", function() {
console.log("Trigger focused");
//the problem point.
//I do some processing here and then
//in some case I do the following:
Ext.getCmp('some_field').focus();
//when this is called the BLUR of this trigger field isn't fired.
});
this.on("blur", function() {
console.log("Trigger blurred");
});
this.callParent();
}
});
//end of onReady
});
Here is a live fiddle : http://jsfiddle.net/sq37s/
To Reproduce:
Click into the first name field
Hit tab, it will jump into the trigger and then jump into the mid init field.
The console at this point will not show a Trigger blurred
Now click anywhere in the panel and you'll see Trigger blurred.
This behavior is causing some very unexpected issues in our application, this is something so trivial we based assumptions on the fact that something like this will work.
I would love:
Any suggestions to work around this, perhaps pure javascript
Any hope of getting the extjs guys to fix this?
When the focus gets changed programmatically, the event may not get fired (think events gets fired only on user-action). One workaround is to fire that event programmatically while changing focus
this.on("focus", function(e) {
console.log("Trigger focused");
if (someConditionToChangeFocus){
e.fireEvent('blur'); //Fires the blur event
Ext.getCmp('some_field').focus();
}
});
[Edit]
Another approach is to use FocusManager's beforecomponentfocus event, fiddle here: https://fiddle.sencha.com/#fiddle/3mq
Related
I need to show my pop-up when the mouse leaves the <body>, this identifies an exit intention.
So when my clients are typing their emails, the popup just appears at the exact moment their pointer is over the suggestion and it should not have happened. But it happens because this part is not in the DOM, so it triggers the mouse leave
however, this event is triggered when the mouse is over a native input suggestion on browsers (I tested on Firefox and Chrome).
So, any ideas how can I skip this fake trigger?
document.body.onmouseleave = function(e) {
console.log("mouse leave was trigged")
}
Take a look what is happen:
I've encountered the same issue, solved it by looking at what exactly triggered the mouseleave event. So if it was not an input field from your form, you could proceed and show your popup
$('body').on('mouseleave', function (e) {
if ('INPUT' !== e.target.nodeName) {
// do your stuff
}
});
i have:
<input type="text" />
and
$('input').blur(function(){
alert('stay focused!');
});
I want to prevent the blur function running when I'm "blurring" by clicking on an anchor element.
I.E. if i tab to another input, click somewhere on the page etc i want the blur to fire, but if i click a link, I don't want it to fire.
Is this easily achievable, or do i need to hack about with delegates and semaphores?
Thanks
I had to solve this problem myself today, too. I found that the mousedown event fires before the blur event, so all you need to do is set a variable that indicates that a mousedown event occurred first, and then manage your blur event appropriately if so.
var mousedownHappened = false;
$('input').blur(function() {
if(mousedownHappened) // cancel the blur event
{
alert('stay focused!');
$('input').focus();
mousedownHappened = false;
}
else // blur event is okay
{
// Do stuff...
}
});
$('a').mousedown(function() {
mousedownHappened = true;
});
Hope this helps you!!
If you want to keep the cursor at its position in a contenteditable element, simply:
$('button').mousedown(function(){return false;});
Delay the blur a bit. If the viewer clicks a link to another page, the page should change before this code gets a chance to run:
$('input').blur(function(){
setTimeout(function() {alert('stay focused!');}, 1000);
});
You can experiment with what delay value for the timeout seems appropriate.
You can get this behavior by calling preventDefault() in the mousedown event of the control being clicked (that would otherwise take focus). For example:
btn.addEventListener('mousedown', function (event) {
event.preventDefault()
})
btn.addEventListener('click', function(ev) {
input.value += '#'
input.setSelectionRange(ta.value.length, ta.value.length)
})
See live example here.
Some clarification that was too long to put in a comment.
The click event represents both pressing the mouse button down, AND releasing it on a particular element.
The blur event fires when an element loses focus, and an element can lose focus when the user "clicks" off of the element. But notice the behavior. An element gets blurred as soon as you press your mouse DOWN. You don't have to release.
That is the reason why blur gets fired before click.
A solution, depending on your circumstances, is to call preventDefault on mousedown and touchstart events. These events always (I can't find concrete documentation on this, but articles/SO posts/testing seem to confirm this) fire before blur.
This is the basis of Jens Jensen's answer.
I'm trying to add a class to my body tag when I focus on an input, textarea, or CKeditor instance. And remove the class when I blur from any of these. The problem is that when I blur from a CKeditor instance and immediately focus on an input or textarea, the focus event happens before the blur event does. There is a significant delay when blurring from a CKeditor instance. I've tried using delay() and setTimeout() in addition to many other things and I can't get it to work. Since it's blurring after I focus, the focus event is adding the class to the body and then the blur event is removing the class.
I'm doing this because I need to reposition the header and hide the footer when the user is on a mobile device the keyboard displays. Below is the code I current have. Does anyone have any ideas on how I can get around this? Thanks!
if ($("html").hasClass("touch")) {
// Set focus and blur listeners for all editors to be created.
CKEDITOR.on( 'instanceReady', function() {
var editor = txtEditor.get_instance();
editor.on('focus', function(e) {
$("body").addClass(fix);
});
editor.on('blur', function(e) {
$("body").removeClass(fix);
});
});
$("input").on("focus", function(e) {
$("body").addClass(fix);
})
.on("blur", function(e) {
$("body").removeClass(fix);
});
}
The delay is caused by the focus manager. It waits 200ms for the next editor UI component to receive focus. It has to do wait, because in various cases and depending on browsers focus may be moved from one component (e.g. editable element) to another component (toolbar, elements path, dialog) with a significant delay. I know from my own experience that it can even exceed 100ms. If it wasn't waiting the editor#blur and editor#focus events would be fired many times when working within editor.
In your case, the input element should behave like editor's UI component. If it gets focus the same should happen as when editor gets focus and vice versa. I think that the easiest solution is to register it as editor's UI component:
CKEDITOR.on('instanceReady', function() {
var editor = txtEditor.get_instance();
editor.focusManager.add(new CKEDITOR.dom.element(inputEl));
editor.on('focus', function(e) {
$("body").addClass(fix);
});
editor.on('blur', function(e) {
$("body").removeClass(fix);
});
});
Thanks for your feedback, but I got it. I was able to place an editor.focusManager.forceBlur() statement in the focus statement of my input fields. That way the blur from any previous ckeditors is immediate. Thanks again though!
Jesse
I'm working on a mobile site and struggling with events firing when I don't want them to.
For the sake of simplicity, it's written something like this (in jQuery):
el.on('touchend', function(ev) {
ev.preventDefault();
// fire an ajax call
};
However, sometimes a user would hit the item when scrolling the page, causing the ajax request to fire (thus changing the page state).
I couldn't think of a way around it (ev.stopPropagation() didn't work) , so I decided watch for dragstart and dragend events.
el.on('dragstart', function() {
el.off('touchend');
});
el.on('dragend', function(ev) {
ev.stopPropagation(); // <-- seems to do nothing
// add back the event above (the function is set to a var)
});
If I alert inside the touchend callback, I get confirmation that the touchend event did in fact fire after I stopped dragging.
Does anyone have any idea how to prevent any other events from firing? I'm hoping I'm just being blind and missing something obvious.
You can't stop an event from firing, you can only prevent the default behavior for that event from happening.
If you're worried about the state of your page changing before the touchend event fires, you should just change your function to check for and then account for the state change.
I think in a case like this you should use event.stopImmediatePropagation();
for arcane reasons I need to be able to cancel the click event via the mousedown event.
Briefly; I am creating a context menu in the mousedown event, however, when the user clicks on the page the context menu should disappear.
I am not able to use the mousedown event over the click in that scenario as I want the user to be able to click links inside the menu ( a full click would never travel to the <a> based menu elements ).
If it is any help, jQuery can be applied.
I would like to either be able to prevent the click event from happening from within the initial mousedown, or be able to pass information to the click event (via originalEvent or otherwise).
TIA
Seems to be impossible, neither FF nor Opera didnt cancel upcoming click when prevented in mousedown and/or mouseup (as side note: click is dispatched after mouseup if certain conditions met). testcase: http://jsfiddle.net/ksaeU/
I have just had the exact same problem. I fixed my context menu by closing it on mousedown and eating the mousedown event on the menu so that I can still receive clicks on the menu, like so:
$(document).one('mousedown.ct', null, function() { cmenu.hide(); return false; });
cmenu.bind('mousedown', function(e) { e.stopImmediatePropagation(); });
And in the hide() function I unbind the mousedown.ct again, in case it was closed due to a click on an item.
Hey, I think this is what you are trying to do with your code. If not, I apologize, I may have misunderstood the question. I used jQuery to get it done: http://jsfiddle.net/jackrugile/KArRD/
$('a').bind({
mousedown: function(){
// Do stuff
},
click: function(e){
e.preventDefault();
}
});