I'd like to detect if a drop down is expanded or not. I don't want to use extra event handlers for click/mouseover etc because the drop-downs are dynamic and for other reasons I can't use something like jQuery live. Basically I'd like something that can given an arbitrary select element (no other attached event handlers, classes, etc), can give a true/false answer on whether it is expanded or not.
For my specific application, I am handling mouse wheel events, but don't want to handle them when a drop down is open (which would override the browser default functionality). However, I still want to handle the mouse wheel events when the mouse has hovered over the select, but has not opened it.
I looked into this before, for similar reasons. I could never find a solution other than trying to track it manually which really doesn't work. There are several ways to open/close a select (drop down) such as Alt+Dn Arrow. An open select will close if the user clicks on something outside the browser. Trying to keep track of the state of the select is an exercise in futility. Unless someone else comes along with something I missed on my hunt, you'll have to code around it as elegantly as you can.
How about when it's got focus, even if it isn't expanded? You specifically ask for expanded because you don't want to override default browser behaviour, but the browser behaviour should be to scroll through the items when the item is focussed, even if it isn't expanded, so I would say you'd be better off detecting focus.
If you're okay with that, then you can certainly easily detect when a field has focus and when it loses it, by using the JQuery focus() and blur() methods, or focusin() and focusout().
http://api.jquery.com/focus/ and http://api.jquery.com/blur/
http://api.jquery.com/focusin/ and http://api.jquery.com/focusout/
Hope that helps.
Maybe you could do something like this:
$('#dropdown').live('click', function(){
//bind mousewheel here
});
$('#dropdown').live('change', function(){
//unbind mousewheel here
})
Related
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.
})
}
Lets imagine we have this sample code:
<input type="text" onblur="blurHandler()" />
<div class="results">
<ul>
<li>sampleText</li>
</ul>
</div>
Lets say you have currently focus on your input tag, and you hover to the "a" tag and click it. The browser will handle the onblur event first.
The task of the blur event is that it should hide the results div, but you still want to be able to click the link in the results div before that happens.
In blurHandler, use setTimeout() to delay hiding your div.
function blurHandler() {
setTimeout(function () {
//close the div
}, 100);
//do whatever else needs to be done
}
jsFiddle Demo
Another option would be to play with the mouseenter/mouseleave events on the link, and use a common flag between the event handlers so that they know about each other.
And one more: you can hide the div with a short animation, so it is actually still there when the click happens. Something like this:
$('.results').hide(1000);
jsFiddle Demo
Note: you should take a look at advanced event handling, inline event handlers can really mess up your HTML quickly. Separation of concerns helps others and your future self. If you use jQuery (seeing the tags under your question), you should use jQuery's event handling methods, which use the advanced model already.
I agree with Marcell's comment, though perhaps more from a usability perspective.
Assigning a timeout (as suggested by bažmegakapa) means you're choosing an arbitrary time limit that may or may not fire before the user has processed what they are supposed to do before that time limit is over. Unless your UI somehow makes it clear that they must react within a given time frame, this is likely to lead to frustrated users.
Even taking for granted that the users have had time to process the directions on screen, there's also transition time between moving from keyboard to mouse (or touch, where it's even worse as you have to deal with the UI shifting to hide the soft-keyboard), which means there's even more variance between different users' and their ability to follow the directions before the time limit you've chosen is over.
Just something to think about, in regard to how your interactivity is set up.
I have a system with a fast-changing set of items that may appear as options in select boxes. I could update the options themselves directly each time the data changes, but I'd rather simply fill in the options at the point where the user is about to see them. E.g. when it's about to open. Is there an event for this?
I suppose I could use the 'click' or 'mousedown' event, but what about navigating via the keyboard? There may be other cases too (perhaps)
BTW, I know how to add options to a select, the 'opening' event is really what I'm after.
Thanks,
Ben
You've got two choices: click() and focus() there are no others.
Use focus() and not click() because the click event does not give enough time to populate the drop down with new values which causes quirky behavior. Also the click event will only capture mouse clicks, with the focus() you get both mouse and keyboard focus events and also it gives ample time for the drop down to get populated with new data. Here is a fiddle with some simple experiments, try each function one at a time to see the difference.
If you're doing something like this, a select drop down probably isnt going to be the UI element of choice.
I would recommend changing to a jQuery UI Autocomplete widget; then you can simply serve items based on the query the user entered.
In addition, you can attach to the keyup event (or the focus event), and show a set of items at that point (as if the 'drop down' was clicked on) http://jqueryui.com/demos/autocomplete/#maxheight
I've read up on questions pertaining to detecting the state of a select menu, whether it's visible, open, or closed and the quick answer is that it's not universal and depends on what you're trying to do. My situation isn't covered by any of these answers 100%.
I need to determine when the select menu is closed, which currently works by storing a variable onblur; however, the select element does not lose focus on the first click off, but rather the second click off. Is there an event I can detect which occurs on the first click off? or make the select lose focus on the first click off rather than the second click off? Looking for pure JavaScript answers, no jQuery.
Here's some sample code demonstrating this: http://jsfiddle.net/BhnH9/1/
You can use a general click listener on the document (or some other suitable ancestor of the select) and see if the select element matches the document.activeElement. If so, then it has focus either because it just got it or an option has been selected.
However, there are other ways of selecting options than clicks, such as keyboard navigation. A click listener will not help you there.
Recently there was a comment on this thread, so I decided to take another look at the issue. I don't recall quite what the original circumstances were, but I do know that I needed the select drop down to lose focus after selected an item. So lo and behold, my jQuery solution... what with me saying it had to not be jQuery :) It's been a long time, I've switched jobs, and don't know why that was a requirement.
$('select').bind('change', function(e) {
$(this).trigger('blur');
});
$('select').bind('blur', function(e) {
alert('select lost focus');
});
Here's a JSFiddle: http://jsfiddle.net/7tUse/
I have a page with an input box, and a function that processes the value of this input box and produces piece of text. I want this text to always be up to date in relation to the contents of the input box, so I've attached a couple of event handlers to it with jQuery to catch any changes:
$('#input').bind('keyup cut paste', function(){...});
This works well in most cases. Whenever the user modifies the contents using the keyboard in any way, or right-clicks to use the cut or paste functions, the text is updated immediately. However, there are two events I still haven't figured out how catch, if it's even possible to do so:
When the user selects a of text and drags it do a different position in the input box
When the user uses the Delete action in the right-click context menu
Both of these can of course be detected by binding the change event, but the problem with that approach is that it doesn't fire until the input box loses focus. The whole point of these bindings is to have the text update in real-time as the value of the input box changes, so change is no good.
English is my second language so I could simply be bad at wording my Google searches, but so far they've turned up nothing. I haven't found any solutions to this after digging through a couple of related Stack Overflow pages either, so I'm asking here. Is there an event binding for this that I don't know of? If not, is there a different approach I could take? Or is this simply not possible with plain JavaScript?
In non-IE browsers, you can handle the input event.
In IE, you can handle the propertychange event.
Demo (works in all browsers)
It's possible this SO question (and related jsfiddle) might answer your question.
(On the linked jsfiddle, put text in the top box to test)
In other words, bind to mouseup and mousedown, etc.
If you can't find a combination of events that cover all cases, you may want to use setInterval(function() {... }, period). You could play around with the period to see how well this works.