How do i find the new focus item with jquery? - javascript

I have a pop up dialog that lets you write text and does stuff when you click a button. My code is below
This function works, i find the new object by looking at e.originalEvent.explicitOriginalTarget. However now i notice if i press tab this function will be called but e.originalEvent.explicitOriginalTarget will give me the same current object instead of the new object. So my dialog doesnt close if a user presses tab to leave. How do i find the correct new dom item?
$('#Area').focusout(function (e) {
if ($(e.originalEvent.explicitOriginalTarget).closest('#Area').size() == 0)
$('#Area').hide();
});

event.relatedTarget worked for me. It will give the other DOM element, within the event, if there is one.
An example would be, if you had 2 buttons controlling the same function, and didn't want their code to be executed if they were clicked consecutively. You could attach a focusout event handler and check for an ID, or a class name.
$(".buttons").on("focusout", function (event) {
if($(event.relatedTarget).prop("class").indexOf("buttons") === -1) {
//code to execute
}
});
Perhaps a better example would be the issue I had.
I created a custom drop down list, that has a button beside it. The drop down list can be opened and closed by either clicking on the list, or the button. It can also be closed be losing focus to either object.
This becomes a problem in the following scenario.
1) user opens drop down list by clicking the list object.
2) user closes drop down list by clicking the button.
What happens is the list opens, but when the user goes to close the list, the list loses focus, which closes it, but since they are clicking on the button, it opens back up. The focusout causes the two objects to cancel each other out, in this type of scenario.
By writing the focusout event, I can now set it to only trigger when the relatedTarget doesn't have the same class as the target that called the event.
$(".listControl").on("focusout", function (event) {
if($(event.relatedTarget).prop("class").indexOf("listControl") === -1) {
//Close the drop down list
}
});
http://api.jquery.com/event.relatedTarget/

Check out this question/answer How to select an element that has focus on it with jQuery
I think the reason why you don't get anything with $("*:focus"); in Firebug console is when you click the console, the element loses focus.
And if you want to tackle it with events, the opposite of focus() is blur().
Edit
Maybe you can even try a different approach. If your only concern is watching for tab key, you can use .keypress() event and watch for tab keycode which is 9.

Related

Input type color click event fails if called within contextmenu event

This is pretty tricky, so I'll try to explain it well.
I have a web app where I want to allow my users to change background color of some divs. To do so I'd like to use a color picker interface, and I want to use contextmenu event on target divs to open it, as they already have another behaviour attached to click event.
So the idea is to have an input type color hidden in the screen, attach its click event to contextmenu event on target divs and change background color of target divs on input type color change event.
The funny thing is that when I try to chain events, color picker doesn't open if its click event is called from within contextmenu event handler, but it does if called from within click event.
Using jQuery for code simplicity and clearness:
//this works perfectly, color picker opens
$("#myTargetDiv").on("click", function() {
$("#inputTypeColor").trigger("click");
});
//this fails miserably
$("#myTargetDiv").on("contextmenu", function() {
$("#inputTypeColor").trigger("click");
return false;
});
The most weird fact is that, if I use a third element to pass the event, say, for example that I call to an intermediate input type text which passes the call from myTargetDiv to inputTypeControl, the click event in the intermediate element fires (even when called from within contextmenu event handler) while the event in the input type color doesn't fire.
But if you click directly on the intermediate input type text the color picker opens!
//If you right click on myTargetDiv "firing!" appears on console, but color picker doesn't opens
$("#myTargetDiv").on("contextmenu", function() {
$("#intermediateElement").trigger("click");
return false;
});
//If you click on intermediateElement, however, the color picker opens!!!
$("#intermediateElement")on("click", function() {
console.log("firing!");
$("#inputTypeColor").trigger("click");
});
I've reproduced this behaviour in Firefox and Chrome, and I'm not very sure if it's an expected feature, a bug in browsers input type color implementation or a problem with event handling from jQuery (I haven't tried launching the events myself yet).
https://jsfiddle.net/bardobrave/0z6ev4rd/1 If you click on "FIRE!" the color picker opens, but if you right click on it the color picker doesn't opens despite if you click on input type text it does.
Anyone can give some insight on the matter?
So to execute your own contextual menu, you may want to bind to the following:
$("#firestarter").on("contextmenu", function(e) {
// Execute your menu with Color Picker Option
return false;
});
This could be something simple like a List wrapped in a div, or more complex like JQuery UI Menu.
<div id="menu">
<ul>
<li class="menuItem" id="menuOption-1" data-action="color" data-rel="#myColor">Select Color</li>
<li class="menuItem" id="menuOption-2" data-action="reset">Reset to Default</li>
</ul>
</div>
Now the user has something to click on, which can be carried over:
$("#menu li.menuItem").on("click", function(){
switch($(this).data("action")){
case "color":
$("#menu").hide();
var target = $(this).data("rel");
$(target).trigger("click");
break;
case "reset":
$("#menu").hide();
// Do something else
break;
default:
$("#menu").hide();
}
});
I have not found all the details on the HTML5 input type='color'. This is a good start: https://www.w3.org/TR/html5/forms.html#color-state-%28type=color%29 I suspect that since the Color Picker dialog is generated by the browser itself as well as a Contextual Menu, I am guessing it's a security or control feature that is preventing it being triggered by a Right-Click type of event.
Ok, I've found a way to fix the functionality.
To trigger color picker opening through a div context menu event.
As this event cannot call the input type color click event (for reason unknown), a feasible solution is to add a hidden div which pops on mouse position when context menu event is called on target div.
This hidden div poses as a context menu and can include a message: "click to open color picker" or something like that.
Then, you attach color input click event to this hidden div click event.
Coming from another click event, the color picker opens correctly, you've forced your user to make one click more than desired (one right click to open the fake context menu and another one to open de color picker), but functionality works in the end and it's quite consistent with the effect seeked.
The real question still applies:
Why input type color click event fires when called from within any other click event handler but fails if called from within context menu event handler?
Some DOM events require user interaction to be fired programmatically,, i.e. you can trigger a click programmatically only in the process of handling some other click or keyup etc.

how to run a jquery function on dropdown selection [duplicate]

This question already has answers here:
Fire event each time a DropDownList item is selected with jQuery
(10 answers)
Is there an onSelect event or equivalent for HTML <select>?
(37 answers)
Closed 8 years ago.
I have a simple dropdown named Filtername. I want to run a function when a value is selected from the list. I have already tried below
$('#FilterName').change(function() {
code1;
code2;
}
The problem is that it works only when selected value gets changed. I want to run the function even if the user selects the same value again from the dropdown. So I need to run the function when the value is selected. I tried .select/.submit functions but they didn't work. Please help.....
From my answer on Fire event each time a DropDownList item is selected with jQuery:
A lot of the current solutions will break in a lot of situations. Any solution that relies on checking the click count twice will be very fickle.
Some scenarios to consider:
If you click on, then off, then back on, it will count both clicks and fire.
In firefox, you can open the menu with a single mouse click and drag to the chosen option without ever lifting up your mouse.
If you use any combination of keyboard strokes you are likely to get the click counter out of sync or miss the change event altogether.
You can open the dropdown with Alt+↕ (or the Spacebar in Chrome and Opera).
When the dropdown has focus, any of the arrow keys will change the selection
When the dropdown menu is open, clicking Tab or Enter will make a selection
Here's a more comprehensive extension:
The most robust way to see if an option was selected is to use the change event, which you can handle with jQuery's .change() handler.
The only remaining thing to do is determine if the original element was selected again.
This has been asked a lot (one, two, three) without a great answer in any situation.
The simplest thing to do would be to check to see if there was a click or keyup event on the option:selected element BUT Chrome, IE, and safari don't seem to support events on option elements, even though they are in the w3c recommendation
Inside the Select element seems to be a black box. If you listen to events on it, you can't even tell on which element the event occurred or whether the list was open or not.
The next best thing then, seems to handle the blur event. This will indicate that the user has focused on the dropdown (perhaps seen the list, perhaps not) and made a decision that they would like to stick with the original value. To continue handling changes right away we'll still subscribe to the change event. And to ensure we don't double count, we'll set a flag if the change event was raised so we don't fire back twice:
Code:
(function ($) {
$.fn.selected = function (fn) {
return this.each(function () {
$(this).focus(function () {
this.dataChanged = false;
}).change(function () {
this.dataChanged = true;
fn(this);
}).blur(function (e) {
if (!this.dataChanged) {
fn(this);
}
});
});
};
})(jQuery);
Then call like this:
$("#dropdownid").selected(function (e) {
alert('You selected ' + $(e).val());
});
Updated example in jsFiddle

Focusing a Bootstrap button for keyboard enter

I have a Bootstrap 3.0 button on a web page. The button is not part of a form. When this page renders, I would like for the button to be clicked if the user hits return on the keyboard. I have a Marionette event listener set up to handle the click event.
Here is my button:
<button class="btn btn-primary js-new pull-right">New facility</button>
How do I do this?
I have tried several things - including what I thought was the obvious solution: executing $(".js-new").first().focus(). This does not work.
If I understand correctly, you'd like to trigger the click handler for a certain button when "return" is hit. If that's the case, this ought to work; $(".js-new").first().click();, assuming your selector is correct.
You can check whether or not your selector is finding an element by using either alert or console.log to display the length of the selector: console.log($(".js-new").length);.
Once you have verified that you have found the correct element, you can trigger whatever click handler(s) are bound to the element by simply calling the .click() function; if no arguments are passed to it, it executes whatever triggers are already on the element.
--
Edit: if you'd simply like to trigger the click handler when enter is pressed, you could bind an event to the return key:
$(document).keypress(function(e) {
if(e.which === 13) {
// enter has been pressed, execute a click on .js-new:
$(".js-new").first().click();
}
});

Problems with mouseleave/focusout event handlers and user selecting from autocomplete list

I have bound the jQuery event handler mouseover to an element with the below code:
jQuery(document).ready(function(){
jQuery('#buyout_field').mouseleave(function() {
alert('Hi!');
});
});
This works great, but then I noticed that if the user selects a value from those dropdown auto-complete menus the browser shows you of your past data you have entered that the mouseleave event fires too early for my liking. Yes, it fires at the right time (when their mouse leaves the element); however I need the function to fire only after the user has entered data into the field.
I then added the focusout handler to cover more bases with:
jQuery('#buyout_field').focusout(function() {
alert('Hi!');
});
However it's still possible the user may select a value from the dropdown list AND not click outside the text field.
Do I have any other options here at firing the function or do I have to resort to perhaps using setTimeout() to allow the user time to select something from the autocomplete list and THEN fire the function OR should I just disable autocomplete?
Fiddle: http://jsfiddle.net/wbsDy/

DOM problem with click initiating a focusout event on a different input

I have an <input type=text> with focusout event handler
I have a <button> with click event handler
Focusout checks whether format in input box is correct. It does so by testing input value against a regular expression. If it fails it displays a message (a div fades-in and -out after some time) and refocuses my input by calling
window.setTimout(function() { $(this).focus(); }, 10);
since I can't refocus in focusout event handler. focusout event can't be cancelled either. Just FYI.
Click collects data from input elements and sends it using Ajax.
The problem
When user TABs their way through the form everything is fine. When a certain input box failes formatting check it gets refocused immediately after user presses TAB.
But when user doesn't use TAB but instead clicks on each individual input field everything works fine until they click the button. focusout fires and sets time-out for refocusing. Since time-out is so short focusing happens afterwards and then click event fires and issues an Ajax request.
Question
I have implemented my formatting check as an independent jQuery plugin that I want to keep that way. It uses .live() to attach focusout on all input fields with a particular attribute where format regular expression is defined.
Data submission is also generic and I don't want to make it dependant on formatting plugin. They should both stay independent.
How can I prevent click event from executing without making these two plugins dependant?
Example code I'm fiddling with
After some searching I've seen that all major browser support document.activeElement but I can't make it work in Chrome. FF and IE both report this being the active element, but Chrome always says it's BODY that is active even though click fired on the button element.
Check this code http://jsfiddle.net/Anp4b/1/ and click on the button. Test with Chrome and some other browser and see the difference.
You could use a flag...
Live demo: http://jsfiddle.net/Anp4b/4/
So your question is:
How can I prevent click event from executing without making these two plugins dependent?
Well, you obviously cannot prevent the click event. If the user wants to click the button, he will, and the click event will trigger. There's nothing you can do about that.
So the answer to the above question is: You cannot.
Based on the current conditions, you have to - inside the click handler - retrieve the validation result, and based on that result, decide if form submission should or should not occur.
JS Code:
$("#Name").focusout(function(){
var that = this;
valid = this.value.length ? true : false;
!valid && window.setTimeout(function() {
$(that).focus();
}, 0);
});
$("#Confirm").click(function(e) {
if ( !valid ) { return false; }
e.preventDefault();
alert('AJAX-TIME :)');
});
HTML Code:
<input type="text" id="Name">
<button id="Confirm">OK</button>
Is there are reason you use .focusout instead of .blur?
Using a flag is a good idea, but I would rather use a class on the element. By using classes to determine the state you can also style it accordingly. Here's my example based on your fiddle.
Another solution that hopefully gives the result you are looking for.
1) Create a named click handler:
var clickHandler = function(e){ /** submit form or whatever you want to do**/ };
$("button").click(clickHandler);
2) Add the following to the focusout event when it's failing validation:
$("button").unbind("click", clickHandler).one("click", function(){ button.click(clickHandler); return false;});
You can find an example of this here.

Categories