What I have is a html select list that is populated through jquery. Right now I have the change event so that when I change the option, the map refocuses on the POI. I'm trying to make it work so that when I click on the same option, the map treats it as a change event. Options don't support click events, and adding a click event on the select list doesn't work either, seeing as there would be 2 click events.
In summary, .change() doesn't trigger if you click the same option.
Is there a way to make this work, a modification to the option tag or another event I may not be aware of?
Thanks!
Try to do something like this:
$('select').on({
change: function(e) {
alert('change')
$(this).data('change', true);
},
click: function() {
if (!$(this).data('change')) {
$(this).trigger('change');
}
$(this).data('change', false);
}
});
http://jsfiddle.net/WFmpW/1/
So the idea is to trigger change event on click only if there were not previous option change. To do this we can set some flag like I did with data-change.
Correct answer:
I'll just edit this answer so I can accept this as the correct answer seeing as the idea is right but the implementation isn't. The correct way is to take out the .change event. Link to the correct code: http://jsfiddle.net/qcJwm/1/.
Code:
$('select').click(function () {
if ($(this).data('click')) {
doStuff();
$(this).data('click', false);
} else {
$(this).data('click', true);
}
});
var doStuff = function () {
alert('stuff');
}
You could add a first option with no value. On change you change the value of the first option to that of the selected option and perform your ´goto-code'.
Because you want to be able to change it again, you have to make the first option selected with $('item')[0].selectedIndex=0. This will not be noticable by the user, because it has the same value. Because of this, your user can change it again to the option they just selected, to fold it back
I had the very same problem, but also needed it to work on mobile, so I combined couple different solutions. Unfortunately I didn't find a way to do all this without triggering the target function multiple times, so I ended up limiting it with setTimeOut. :(
It's far from perfect, but works in my scenario:
<select id="select">
<option disabled selected>Pick one..</option>
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
<option value="4">four</option>
<option class="dummy" style="display:none">Pick one..</option>
</select>
And jQuery:
var canDo = true; //variable for settimeout
$('#select').on('focus',function(){
$(this).find("option.dummy").text($(this).find("option:selected").text());
$(this).find("option.dummy").prop("selected", true);
$(this).data('click', true);
});
$('#select').on('change blur',function(){
//blur is optional and offers solution to the case where user closes options
//in mobile ja taps away (if you then want to trigger the function). BUT, it
//also causes a bug: if user opens options and clicks the topmost option, which
//is the header bar showing currently selected option, options are hidden and
//function triggered - but the focus stays on the element, so when user clicks
//away, function is re-triggered.
var select = $(this);
var text = select.find("option:selected").text();
$('.dummy').attr('value',select.val()).text(text);
doYourThing($(select).val());
});
$('#select option').on('click',function(){ //note that we're checking clicks to option instead of select
if($(this).data('click')){
$(this).data('click', false);
doYourThing($(select).val());
}else{
$(this).data('click', true);
}
$(this).parent().blur();
});
function doYourThing(stuff){
if(canDo){
canDo = false;
alert('Selected '+stuff);
canDoTimeout = setTimeout(function(){
canDo = true;
}, 500);
}
}
jsFiddle: http://jsfiddle.net/nxabv0wk/3/
Related
My question is about what event is better to use with the select tag in the case where I want to detect which option of the select is selected in JavaScript.
Until now I've found two way to do it. The first one is to use the "change" eventListener, just like this :
selectList.addEventListener("change", function(){
console.log(selectList.options[selectList.selectedIndex].value);
});
But there is two problem with this method. Firstly, this event is not fired at the beginning, so it don't log the very first element, selected by default in the list. Secondly, when clicking on an item of the list, the event is fired two times, which means there is two identical lines in the console.
The second method I've tried is with the "click" event, just like that :
selectList.addEventListener("click", function(){
console.log(selectList.options[selectList.selectedIndex].value);
});
The problem here is obviously that the event is fired each time I click on the list, so the log is done at least two times if I want to change the selected item. Furthermore, the default selected item when the list "spawn" is not logged either, which is normal.
So how can I do to log the selected item only once, and make the default selected item logged too ?
Change event fires when the event.target (in this example, the select element), has lost focus (or blur). So whatever the user does after triggering a change event, will cause the event to actually fire, so you should get only one event per action as it should be. Take a look at this Snippet, the log plainly shows that you needn't be concerned about double event firing.
The first click 'wakes up the listener but it's lazy and has one eye open.
As long as the select has focus, then the listener is just waiting for unfocus. In order to be unfocus, you must focus on something else by clicking , etc.
Now that you are clicking the option, you have officially unfocased from the select thereby causing the change event to fire.
SNIPPET
selectList.addEventListener("change", function() {
console.log(selectList.options[selectList.selectedIndex].value);
event.stopPropagation
});
var ta = document.getElementById('ta');
ta.addEventListener('change', function(e) {
alert('HEY! Why are not focusing on me anymore?');
}, false);
ta.addEventListener('click', function(e) {
alert('Why are you poking me? that\'s annoying, STOP!');
}, false);
select {
margin-right: 50px;
}
ol {
margin-left: 70px;
margin-right: 50px;
}
#ta {
margin-right: 50px;
}
<select id='selectList'>
<option value="">---</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<textarea id="ta"></textarea>
<ol>
<li>Type something in the textarea.</li>
<li>Click anywhere within this window, except the textarea</li>
<li>Now reset this Snippet.</li>
<li>Type something again.</li>
<li>Now click the textarea.</li>
</ol>
<button id="btn">CLICK</button>
change event is invoked when option of the select-input is changed.
Create a new change-event using Eventconstructor and invoke dispatchEvent on the target element.
document.getElementById('mySelect').addEventListener("change", function() {
console.log(this.value);
});
var event = new Event('change');
document.getElementById('mySelect').dispatchEvent(event);
<select id="mySelect">
<option>Apple</option>
<option>Orange</option>
<option>Pineapple</option>
<option>Banana</option>
</select>
Select list already have an "onchange" event you can use:
selectList.onchange = function()
{
console.log(selectList.options[selectList.selectedIndex].value);
};
On page i have two with same options. If a select option it should be disabled in each select. Here is my demo: http://jsfiddle.net/bfmKw/8/
$("select").off('change').on('change', function () {
disableOptions();
});
function disableOptions() {
var $dropdowns = $('select');
$dropdowns.find('option').attr('disabled', false);
$.each($dropdowns, function (i, dropdown) {
var mark = $(dropdown).find('option:selected').attr('mark');
if (mark) {
$dropdowns.find('option[mark="' + mark + '"]:not(:selected)').attr('disabled', true);
}
});
}
But in firefox exist bug or feature. Steps for reproduction:
1) Open select box and choose option. Change event will rise and options will be disabled.
2) Open same select box, hover mouse on another option and click twice on diferent from select box place. Change event will be rised too.
If instead disabled set any another attribute all works fine. May be exist another way how can i disable options?
This wrong behavior appears after disabling selected option and only in firefox. Right disabling:
$dropdowns.find('option[mark="' + mark + '"]:not(:selected)').attr('disabled', true);
I want a user to be able to confirm a selection they make in a select control, or to rollback to the previous value if they cancel. The following works fine in Chrome/Safari, but no matter what I try, I can't get it to work in Firefox (on Mac).
HTML:
<select id='my-select'>
<option value="client">Client</option>
<option selected="selected" value="assistant">Assistant</option>
<option value="manager">Manager</option>
</select>
JS:
$('#my-select').focus(function() {
//Store old value
$(this).data('lastValue',$(this).val());
});
$('#my-select').change(function(e) {
var lastRole = $(this).data('lastValue');
var newRole = $(this).val();
if(confirm("Change user's role from "+lastRole+" to "+newRole+"?"))
{
// The control may remain in focus, so we update lastValue here:
$(this).data('lastValue',newRole);
// Do stuff
}
else {
$(this).val(lastRole);
}
});
Fiddle:
http://jsfiddle.net/yxzqY/13/
The issue can be demonstrated as follows:
Select 'Manager'
Click 'Cancel' (Selected value = 'Assistant')
Select 'Manager' again
Click 'Cancel' (Selected value = 'Assistant' in Chrome, Selected value = 'Manager' in FireFox)
I'm just stumped- no idea how to get this working in Firefox, or how to resolve the diff behavior across browsers.
Why do you need focus event? I think the problem with Firefox is that focus event fires also when you choose element from the dropdown menu before actual change event.
I think you do not need to overcomplicate your code. Try to change focus event to default initialization of data value. Something like this:
$('#my-select').each(function() {
$(this).data('lastValue', $(this).val());
});
And it should work fine.
DEMO: http://jsfiddle.net/yxzqY/17/
OK figured out a solution, if not the exact cause- The issue has something to do with how Firefox behaves when the control keeps focus through multiple selections- If you remove focus post-selection, it will behave properly.
The answer is to add $(this).blur(); at the end of the change handler.
http://jsfiddle.net/yxzqY/16/
$('#my-select').focus(function() {
//Store old value
$(this).data('lastValue',$(this).val());
});
$('#my-select').change(function(e) {
var lastRole = $(this).data('lastValue');
var newRole = $(this).val();
if(confirm("Change user's role from "+lastRole+" to "+newRole+"?"))
{
// Do stuff
}
else {
$(this).val(lastRole);
}
// IMPORTANT!: Firefox will not act properly without this:
$(this).blur();
});
Basically, I have drop down menu that looks like this:
<select>
<option>0</option>
<option selected="selected">1</option>
<option>2</option>
<option>3</option>
</select>
I am trying to write a function that is fired even when you select the same option, i.e. even if the drop-down is opened and re-select the selected option, I want it to execute the function.
If you mean selecting with the mouse, you can use mouseup. However, it will fire when the select box is being opened as well, so you'll need to keep track of the amount of times it was fired (even: select is being opened, odd: select is being closed): http://jsfiddle.net/T4yUm/2/.
$("select").mouseup(function() {
var open = $(this).data("isopen");
if(open) {
alert(1);
}
$(this).data("isopen", !open);
});
pimvdb's answer was a big help for me but I added a couple of extra bits to deal with keyboard activation and navigation away from the select:
$('select').mouseup(... as in pimvdb... )
.blur(function() {
$(this).data('isopen', false);
}).keyup(function(ev) {
if (ev.keyCode == 13)
alert(1);
});
The blur handler deals with navigating away from the select while the dropdown is open, the keyup handler deals with when you change the select's value with the keyboard. The behaviour is then that the user is only considered to have finally selected the value when they click return to navigate away. If you want a different behaviour with the keyboard that shouldn't be hard to do.
select isn't meant to be used this way — there are hacks you can use to get this kind of behavior in most cases, like tracking mouse and keyboard events on the select, but there’s no guarantee they’ll keep working, or work on every platform.
I would suggest either…
Resetting the select to its default value on change, and using some other text to indicate which one is “selected”, or
using a control other than select.
Can you describe the end goal a little more detail?
An alternative, use the .blur() event -- http://jsfiddle.net/VKZb2/4/
Pro
This will fire either way.
Con
It only fires once the control loses focus.
I ran into the same issue. I just added a click event to the option tags and change the value of the select:
$("#select option").mouseup(function() {
$(this).parent().val($(this).attr("value"));
// do something.
});
NOTE: This doesn't work on iPhone or iPad devices.
Try the below solution. It accounts for loss of focus via mouse click or Esc key.
// whether or not dropdown is opened
var open = false;
$("#selectElement").on("click", function() {
open = !open;
if (!open)
{
console.log("option has been selected/re-selected");
}
});
// update dropdown state upon loss of focus
$("#selectElement").on("blur", function() {
if(open){
open = !open;
}
});
// update dropdown state upon Esc key of focus
$(document).keyup(function(e) {
if (e.keyCode == 27) {
if(open){
open = !open;
}
}
});
I am having trouble finding out how to figure out if an HTML dropdown box has been set?
Ok, I understand how I can check the index once it has been activated and an item chosen. But, how do I determine that the box hasn't been touched and no item selected?
Thanks.
The select.options.selectedIndex will be -1 in that case.
I don't think there's a native method, but you can add an event listener to call a function when the select is changed:
function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
hasBeenTouched = false;
addEvent(selectEl, 'change', function() {
hasBeenTouched = true;
});
It sounds like you want to make sure a user has selected an option and not just submitted the form with the default option. This situation is commonly achieved by having a "label" option (sometimes blank to keep the size down) in your drop down box, that is selected by default, followed by validation checking to see if another option has been selected:
<select>
<option>-- Please choose an option -- </option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</select>
Using validation properly (both server-side and client-side), you're able to implement a solution that doesn't rely on Javascript to check if an option has been properly selected.
After the document is loaded (naively window.onload), manually set the drop-down list selectedIndex to -1 (as others have observed, the default is otherwise for the first item to be selected)
window.onload = function() {
document.getElementById('ddlId').selectedIndex = -1;
};
There's no way for the user to set the drop-down list to unselected through the browser interface, so you can be sure it is both unset and untouched by testing whether the selectedIndex is still -1 at any point after initially setting it yourself.