jQuery prevent change for select - javascript

I want to prevent a select box from being changed if a certain condition applies. Doing this doesn't seem to work:
$('#my_select').bind('change', function(ev) {
if(my_condition)
{
ev.preventDefault();
return false;
}
});
I'm guessing this is because by this point the selected option has already changed.
What are other ways of doing this?

Try this:
http://jsfiddle.net/qk2Pc/
var my_condition = true;
var lastSel = $("#my_select option:selected");
$("#my_select").change(function(){
if(my_condition)
{
lastSel.prop("selected", true);
}
});
$("#my_select").click(function(){
lastSel = $("#my_select option:selected");
});

In the event someone needs a generic version of mattsven's answer (as I did), here it is:
$('select').each(function() {
$(this).data('lastSelected', $(this).find('option:selected'));
});
$('select').change(function() {
if(my_condition) {
$(this).data('lastSelected').attr('selected', true);
}
});
$('select').click(function() {
$(this).data('lastSelected', $(this).find('option:selected'));
});

If you simply want to prevent interaction with the select altogether when my_condition is true, you could always just capture the mousedown event and do your event prevent there:
var my_condition = true;
$("#my_select").mousedown(function(e){
if(my_condition)
{
e.preventDefault();
alert("Because my_condition is true, you cannot make this change.");
}
});
This will prevent any change event from ever occurring while my_condition is true.

Another option to consider is disabling it when you do not want it to be able to be changed and enabling it:
//When select should be disabled:
{
$('#my_select').attr('disabled', 'disabled');
}
//When select should not be disabled
{
$('#my_select').removeAttr('disabled');
}
Update since your comment (if I understand the functionality you want):
$("#dropdown").change(function()
{
var answer = confirm("Are you sure you want to change your selection?")
{
if(answer)
{
//Update dropdown (Perform update logic)
}
else
{
//Allow Change (Do nothing - allow change)
}
}
});
Demo

None of the answers worked well for me. The easy solution in my case was:
$("#selectToNotAllow").focus(function(e) {
$("#someOtherTextfield").focus();
});
This accomplishes clicking or tabbing to the select drop down and simply moves the focus to a different field (a nearby text input that was set to readonly) when attempting to focus on the select. May sound like silly trickery, but very effective.

You can do this without jquery...
<select onchange="event.target.selectedIndex = 0">
...
</select>
or you can do a function to check your condition
<select onchange="check(event)">
...
</select>
<script>
function check(e){
if (my_condition){
event.target.selectedIndex = 0;
}
}
</script>

I was looking for "javascript prevent select change" on Google and this question comes at first result. At the end my solution was:
const $select = document.querySelector("#your_select_id");
let lastSelectedIndex = $select.selectedIndex;
// We save the last selected index on click
$select.addEventListener("click", function () {
lastSelectedIndex = $select.selectedIndex;
});
// And then, in the change, we select it if the user does not confirm
$select.addEventListener("change", function (e) {
if (!confirm("Some question or action")) {
$select.selectedIndex = lastSelectedIndex;
return;
}
// Here do whatever you want; the user has clicked "Yes" on the confirm
// ...
});
I hope it helps to someone who is looking for this and does not have jQuery :)

You might need to use the ".live" option in jQuery since the behavior will be evaluated in real-time based on the condition you've set.
$('#my_select').live('change', function(ev) {
if(my_condition)
{
ev.preventDefault();
return false;
}
});

Implement custom readonly like eventHandler
<select id='country' data-changeable=false>
<option selected value="INDIA">India</option>
<option value="USA">United States</option>
<option value="UK">United Kingdom</option>
</select>
<script>
var lastSelected = $("#country option:selected");
$("#country").on("change", function() {
if(!$(this).data(changeable)) {
lastSelected.attr("selected", true);
}
});
$("#country").on("click", function() {
lastSelected = $("#country option:selected");
});
</script>
Demo : https://jsfiddle.net/0mvajuay/8/

This was the ONLY thing that worked for me (on Chrome Version 54.0.2840.27):
$('select').each(function() {
$(this).data('lastSelectedIndex', this.selectedIndex);
});
$('select').click(function() {
$(this).data('lastSelectedIndex', this.selectedIndex);
});
$('select[class*="select-with-confirm"]').change(function() {
if (!confirm("Do you really want to change?")) {
this.selectedIndex = $(this).data('lastSelectedIndex');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id='fruits' class="select-with-confirm">
<option selected value="apples">Apples</option>
<option value="bananas">Bananas</option>
<option value="melons">Melons</option>
</select>
<select id='people'>
<option selected value="john">John</option>
<option value="jack">Jack</option>
<option value="jane">Jane</option>
</select>

This worked for me, no need to keep a lastSelected if you know the optionIndex to select.
var optionIndex = ...
$(this)[0].options[optionIndex].selected = true;

$('#my_select').bind('mousedown', function (event) {
event.preventDefault();
event.stopImmediatePropagation();
});

if anybody still interested, this solved the problem, using jQuery 3.3.1
jQuery('.class').each(function(i,v){
jQuery(v).data('lastSelected', jQuery(v).find('option:selected').val());
jQuery(v).on('change', function(){
if(!confirm('Are you sure?'))
{
var self = jQuery(this);
jQuery(this).find('option').each(function(key, value){
if(parseInt(jQuery(value).val()) === parseInt(self.data('lastSelected')))
{
jQuery(this).prop('selected', 'selected');
}
});
}
jQuery(v).data('lastSelected', jQuery(v).find('option:selected').val());
});
});

None of the other answers worked for me, here is what eventually did.
I had to track the previous selected value of the select element and store it in the data-* attribute. Then I had to use the val() method for the select box that JQuery provides. Also, I had to make sure I was using the value attribute in my options when I populated the select box.
<body>
<select id="sel">
<option value="Apple">Apple</option> <!-- Must use the value attribute on the options in order for this to work. -->
<option value="Bannana">Bannana</option>
<option value="Cherry">Cherry</option>
</select>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.js" type="text/javascript" language="javascript"></script>
<script>
$(document).ready()
{
//
// Register the necessary events.
$("#sel").on("click", sel_TrackLastChange);
$("#sel").on("keydown", sel_TrackLastChange);
$("#sel").on("change", sel_Change);
$("#sel").data("lastSelected", $("#sel").val());
}
//
// Track the previously selected value when the user either clicks on or uses the keyboard to change
// the option in the select box. Store it in the select box's data-* attribute.
function sel_TrackLastChange()
{
$("#sel").data("lastSelected", $("#sel").val());
}
//
// When the option changes on the select box, ask the user if they want to change it.
function sel_Change()
{
if(!confirm("Are you sure?"))
{
//
// If the user does not want to change the selection then use JQuery's .val() method to change
// the selection back to what it was previously.
$("#sel").val($("#sel").data("lastSelected"));
}
}
</script>
I hope this can help someone else who has the same problem as I did.

Related

How to disable non selected options in select boxes using jQuery?

I have a model in Laravel that can be edited with dynamic form but i want to prevent changing the selected option in select box so when i open the edit page i should be able to see the select boxes with selected items but all other options should be disabled.
Maybe i could just select all select with jQuery and disable all non selected values?? How to do that?
I have tried this:
// disable non selected items
$('select').each(function(){
$('option').each(function() {
if(this.selected) {
this.attr('disabled', true);
}
});
});
But it doesn't work, i just need a little help
this is the select box and all others are the same:
<select name="car">
<option selected="selected" value="1">Volvo</option>
<option value="2">Saab</option>
<option value="3">Mercedes</option>
<option value="4">Audi</option>
</select>
just other values selected
Your code has two problems.
First: you should check if option isn't selected (!this.selected) then disable it.
Second: this.attr('disabled', true) doesn't work in jQuery. You should use $(this) instead.
$('select').each(function(){
$('option').each(function() {
if(!this.selected) {
$(this).attr('disabled', true);
}
});
});
$('select').each(function(){
$('option').each(function() {
if(!this.selected) {
$(this).attr('disabled', true);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="car">
<option selected="selected" value="1">Volvo</option>
<option value="2">Saab</option>
<option value="3">Mercedes</option>
<option value="4">Audi</option>
</select>
Note that first .each() loop in you code is additional. The bottom code is enough.
$('option').each(function() {
!this.selected ? $(this).attr('disabled', true) : "";
});
$(function(){
var Obj=$('select').find('option');
$.each(Obj,function(){
$(this).is(":selected") ? "" :$(this).attr('disabled',true);
});
});
You can replace "this" by "$(this)" and add "!" in the if and it can work:
$('select').each(function(){
$('option').each(function() {
if(!$(this).selected) {
$(this).attr('disabled', true);
}
});
});
Ok I am not really sure what you want to do, but I can fix your first code snippet for you:
// disable non selected items
$('select').each(function(){
$('option').each(function() {
if(!this.selected) {
$(this).parent().attr('disabled', true);
}
});
});
This is just an update for others:
I have found (for me even better solution)
https://silviomoreto.github.io/bootstrap-select/examples/#disabled-select-box
with this plugin you can set the select box to disabled and then you can see what was previously selected and you can't change it.
Just load the plugin in your view and add class .selectpicker and set the select box to disabled and it looks like this:

addEventListener, "change" and option selection

I'm trying to have dynamic select list populate itself, from a single selection to start:
<select id="activitySelector">
<option value="addNew">Add New Item</option>
</select>
and then JavaScript code we have:
addEventListener("select", addActivityItem, false);
The problem is that various events don't fire when you have one item: not "change" because, the text is no different when you select that item; not "select" (as I have here), for a roughly similar reason, because I'm not really selecting anything because there's only one item. What is the event that should be fired here? It seems silly to list a blank item in my option list to fire the event, so I hope there is another solution. Or is that the best solution?
You need a click listener which calls addActivityItem if less than 2 options exist:
var activities = document.getElementById("activitySelector");
activities.addEventListener("click", function() {
var options = activities.querySelectorAll("option");
var count = options.length;
if(typeof(count) === "undefined" || count < 2)
{
addActivityItem();
}
});
activities.addEventListener("change", function() {
if(activities.value == "addNew")
{
addActivityItem();
}
});
function addActivityItem() {
// ... Code to add item here
}
A live demo is here on JSfiddle.
The problem is that you used the select option, this is where you went wrong. Select signifies that a textbox or textArea has a focus.
What you need to do is use change.
"Fires when a new choice is made in a select element", also used like blur when moving away from a textbox or textArea.
function start(){
document.getElementById("activitySelector").addEventListener("change", addActivityItem, false);
}
function addActivityItem(){
//option is selected
alert("yeah");
}
window.addEventListener("load", start, false);
Another way to make your code understandable is :
let selector = document.getElementById("Selector");
let result = document.getElementById("result");
// when client clicked on select element
selector.addEventListener("click", () => {
// if default value is changed
selector.addEventListener("change", () => {
// if value switched by client
switch (selector.value) {
case "add":
//do somthing with , "add" value
result.innerHTML = selector.value;
break; // then take break
case "remove":
//do somthing with , "remove" value
result.innerHTML = selector.value;
break; // then take break
}
});
});
#Selector{
margin: 1rem 0;
}
<label for"Selector">chose an option:</label>
<select id="Selector" name="Selector" >
<option value="add">Add new item</option>
<option value="remove">Remove existing item</option>
</select>
<div id="result">option selected : "The default value is first option"</div>

How do I get the change event for a datalist?

I am using a datalist and need to detect when the user selects something from the drop-down list. A similar question has been asked BUT I need it so that the event fires ONLY when the user selects something from the datalist. If they type something in the input then I do NOT want the event to fire. (Notice in the accepted answer to the question I linked that they bind the input, which is not what I want). I've tried (with no success):
<datalist>
<option>Option 1 Here</option>
<option>Option 2 Here</option>
</datalist>
$(document).on('change', 'datalist', function(){
alert('hi');
});
EDIT:
This question is different than the suggested question because it's a completely different question.
You can manually check it on change. But you need to check change of the input of datalist.
FIDDLE
$(document).on('change', 'input', function() {
var options = $('datalist')[0].options;
var val = $(this).val();
for (var i = 0; i < options.length; i++) {
if (options[i].value === val) {
console.log(val);
break;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<input list="ff">
<datalist id="ff">
<option>Option 1 Here</option>
<option>Option 2 Here</option>
</datalist>
In browser with the inputType property on the InputEvent you can use that to filter out any unwanted onInput events. This is "insertReplacementText" on Firefox 81 and null for Chrome/Edge 86. If you need to support IE11 you will need to validate the value is valid.
document.getElementById("browser")
.addEventListener("input", function(event){
if(event.inputType == "insertReplacementText" || event.inputType == null) {
document.getElementById("output").textContent = event.target.value;
event.target.value = "";
}
})
<label for="browser">Choose your browser from the list:</label>
<input list="browsers" name="browser" id="browser">
<datalist id="browsers">
<option value="Edge">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
<div id="output">
</div>
The solutions above all have a big problem. If the datalist has the option of (for example) "bob" and "bobby", as soon as someone types "bob", they code immediately says it's the same as clicking "bob"... but what if they were attempting to type "bobby"?
For a better solution, we need some more information. When listening for the 'input' event on the input field:
In Chromium-based browsers, when you type, delete, backspace, cut, paste, etc. in an input field, the event that is passed to the handler is an InputEvent, whereas when you select an option from the datalist, the event is just an Event type with a property of type that equals 'input'. (This is also true during an auto-fill, at least with BitWarden).
So you can listen for an 'input' event and check to see if it's an instance of InputEvent to determine if it's from autofill (which I think should be allowed since most of the time autofill won't be filling these types of fields, and if they do, it's usually a legit choice) / datalist selection.
In Firefox, it's different, though. It still provides an InputEvent, but it has an inputType property with the value of "insertReplacementText", which we can also use. Autofill does the same thing as Chromium browsers.
So here's a better solution:
$('#yourInput').on('input', function(){
if (
!(e instanceof InputEvent) ||
e.inputType === 'insertReplacementText')
) {
// determine if the value is in the datalist. If so, someone selected a value in the list!
}
});
I wish the browsers had the same implementation that had an event type/property that was exclusive to datalist selection, but they don't so this is the best I've got. I haven't tested this on Safari (I don't have access or time right now) so you should probably take a look at it and see if it's the same or has other distinguishing differences.
UPDATE:
I noticed that if you already have the full word typed up (e.g. you typed in "Firefox") and then selected the option that matched what you had typed (e.g. you selected the "Firefox" option), it would not fire an "input" event, so you would not know that one of the options was chosen at that point. So, you'll also need a keydown/keypress/keyup event listener to listen to when they press enter. In Chromium browsers, though, it actually provides a key code of undefined when you hit enter or click on an option (yes, the click makes a keyup event). In Firefox, it says you hit Enter, but it doesn't fire any events I can find when you click an option.
Optimized Solution
$("input").on('input', function () {
var inputValue = this.value;
if($('datalist').find('option').filter(function(){
return this.value == inputValue;
}).length) {
//your code as per need
alert(this.value);
}
});
Please have look for your solution it's good to go.
Have look for Demo
$(document).on('change', 'input', function(){
var optionslist = $('datalist')[0].options;
var value = $(this).val();
for (var x=0;x<optionslist.length;x++){
if (optionslist[x].value === value) {
//Alert here value
console.log(value);
break;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input list="data">
<datalist id="data">
<option value='1'>Option 1 Here</option>
<option value='2'>Option 2 Here</option>
</datalist>
More Optimize
$("input").on('input', function () {
if($('datalist').find('option[value="'+this.value+'"]')){
//your code as per need
alert(this.value);
}
});
This might only be Chrome, untested anywhere else!, but I see a change event triggered when an option is selected. Normally change only happens in textfields when the field loses focus. The change event triggers before the blur event IF it's a normal non-datalist change, so we have to check both: we're looking for a change that's not immediately followed by a blur:
var timer;
el.addEventListener('change', function(e) {
timer = setTimeout(function() {
el.dispatchEvent(new CustomEvent('datalistchange'));
}, 1);
});
el.addEventListener('blur', function(e) {
clearTimeout(timer);
});
And then you can listen for the custom datalistchange event like normally. Or you can just put your specific logic instead of the dispatchEvent.
jsFiddle here
jQuery('input').on('input', function () {
if($('datalist[id="' + jQuery(this).attr('list') + '"]').find('option[value="'+this.value+'"]')){
//your code as per need
alert(this.value);
}
});
so it will find the datalist associated with the input
8 years, and still no good answer
Simple space-suffix trick will do what you need, add at the end of each option, and then detect (and remove) it in "input" handler
<input list="my-options" id="my-input">
<datalist id="my-options">
<option>Option 1 Here </option>
<option>Option 2 Here </option>
</datalist>
<script>
$('#my-input').on('input',function (e)
{
var v=$(e.target).val();
if (v.slice(-1)=='\xa0')
{
$(e.target).val(v=v.slice(0,-1));
console.log("option selected '"+v+"'");
};
});
</script>

jQuery UI Combobox clear selection event

I have a combo box of which the HTML looks like this:
<select id="myCombo">
<option value=""></option> <!-- Not shown in jQuery UI Combobox because empty value -->
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
I've attached the jQuery UI Combobox to I as such:
$("#myCombo").combobox({
select: function () {
if ($("#myCombo").val() == "") {
//DO SOMETHING
}
else {
//DO SOMETHING ELSE
}
}
});
When I select an option by either typing and/or selecting an option, the "DO SOMETHING ELSE" part is triggered like it should, so no issue there.
However, when I clear the selection (this selects the first option of my original combo) by deleting the text or clicking the "x", nothing get's triggered, so I can't execute the "DO SOMETHING" part of my function.
How can I trigger this part? Is there maybe another event that is triggered when clearing a selection?
I have searched and found lots of topic on selecting an item, but none on clearing/deselecting something(that were answered at least).
This can be accomplished with select2.
$("#myCombo").select2({
placeholder: "Select report type",
allowClear: true,
});
$("#myCombo")
.on("select2-selecting", function(e) {
log("selecting val=" + e.val + " choice=" + JSON.stringify(e.choice));
})
.on("select2-removed", function(e) {
log("removed");
})
After looking further into it I've found a way to trigger an event when clearing the text.
For this I had to edit the original custom.combobox widget JS, provided by the example on the jQuery UI site
In this js look for the _removeIfInvalid function and edit it like so
_removeIfInvalid: function (event, ui) {
// Selected an item, nothing to do
if (ui.item) {
return;
}
// Search for a match (case-insensitive)
var value = this.input.val(),
valueLowerCase = value.toLowerCase(),
valid = false;
this.element.children("option").each(function () {
if ($(this).text().toLowerCase() === valueLowerCase) {
this.selected = valid = true;
return false;
}
});
// Found a match, nothing to do
if (valid) {
//**ADD this piece of code**
this._trigger("change", event, {
item: null
});
return;
}
// Remove invalid value
this.input
.val("")
.attr("title", value + " didn't match any item")
.tooltip("open");
this.element.val("");
this._delay(function () {
this.input.tooltip("close").attr("title", "");
}, 2500);
this.input.data("ui-autocomplete").term = "";
//**ADD this piece of code**
this._trigger("change", event, {
item: null
});
}
The added piece of code (I know it's added 2 times, but the code would otherwise jump out of the function before it was ran), will add a change event to the combobox that can be used in your own script. This change event, I can use to run any code I want when the selection is cleared.
$("#myCombo").combobox({
select: function () {
//DO SOMETHING ON SELECT
//IMPORTANT: The other function can't be triggered before the combobox loses focus!!
$(".custom-combobox-input").blur();
},
change:function () {
//DO SOMETHING ON CLEAR
}
});
The removeIfInvalid function is always called by default when an option can't be found and by adding an event to the control when this function is invoked is invoked, we finally have a place to execute our algorithmns.
Hopefully, more people are helped with this small fix.
Empty value cannot be selected in the browser. Hence select() is never called on empty contents.
If you try this, it becomes a bit more clear:
<select id="myCombo">
<option value=""></option> <!-- Not shown in jQuery UI Combobox because empty value -->
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
<option value="4"></option>
<option value="5">Option 5</option>
</select>
I have slightly modified the javascript, note that I'm empty is never logged.
$("#myCombo").combobox({
select: function(event, ui) {
var idx = $("#myCombo").val();
var txt = $("#myCombo option:selected").text();
alert(idx);
if (idx === undefined) {
console.log("select: I'm empty");
} else {
console.log("select: " + idx + ": " + txt);
}
}
});
Interestingly, none of the other callbacks (search(), change(), response(), focus()) seems to function from autocomplete, so there is no way to detect a zero-ing out of the select.
I had spent what felt like a lot of time trying proposed solutions for this and those did not work for me, then I solved it myself.
Look for the _createAutocomplete function where you created your combobox instance.
Look for the chain of properties being set to this.input.
Then add
.on("focus",function(){
$(this).val('');
})
Anywhere in the chain.
So there are many examples on here of how to do this, but they are all (my opinion) cumbersome. You can clear the selection much easier by doing the following:
1) your _createAutocomplete: function() needs to have the following:
.attr( "title", "mytitle" )
Use any title that you want, or set another attribute (name, id etc)- I just happened to have a use for the title, so this worked for me.
2) whatever function you are running only needs the following to clear:
$("input[title='mytitle']").val('');
$("#combobox").val('');
(You have to clear both).
My need was a form with one of the fields being an autocomplete with minimum number of characters. There's an add entry button that submits, refreshes the entry list and resets the form line for additional entries. Much cleaner.

Jquery: Hide a link button based on contains in option

EDIT: Will be more specific with requirements see bottom for additions:
I am trying to hide an a link (button formatted as a href), however I am trying to do it based on text found with in an option drop down menu.
So for example
<form id="phonetypeform">
<select name="porting-p1" class="dropdown">
<option value="">Please select an option...</option>
<option value="1">I want to keep my current phone number</option>
<option value="2">I want to choose a new number</option>
</select>
</form>
Next Step
If the 'please select an option' is selected it hides the a link, if anything else is selected then it shows the link
here is the jquery I have which is not working
$(document).ready(function() {
$("a.nextbutton").hide()
$('.dropdown').change(function() {
if($('.dropdown option:contains'Please)') {
$('a.nextbutton',this).hide();
} else {
$("a.nextbutton")show();
}
});
});
EDIT starts here:
thanks to everyone that has given me some answers, but what I now have works, but its not ideal, and ideally would like to use the contains, simple reason is I have about 20 of these scripts I would have to create and target the value, ugly!
to show my exact requirement please see the fiddle, while this is working, as I said I have many of these scripts to put in place, ideally I would like to:
1. target the text 'select...'
2. Have it so that it stays hidden until all options no longer contain 'Select...' (the contains should take care of that right)
Here is a fiddle to make life easier for anyone that can help?
http://jsfiddle.net/p3ewE/
END EDIT
Try this instead:
$("a.nextbutton").hide();
$('.dropdown').change(function () {
if ($('.dropdown').val() == "") {
$('a.nextbutton', this).hide();
} else {
$("a.nextbutton").show();
}
});
jsFiddle example
You had a few syntax issues with missing periods and brackets.
Typo here
if($('.dropdown option:contains(Please)')
^ ^
:contains()
Use this code
DEMO
$('.dropdown').change(function () {
if (this.value == "") {
$('a.nextbutton').hide();
} else {
$("a.nextbutton").show();
}
}).change();
Here is the link http://jsfiddle.net/XXDwr/5/
have a look at it.
$(document).ready(function() {
$(".nextbutton").hide();
$('.dropdown').on('change',function() {
var h= $('.dropdown').val();
if(h=="")
{
$(".nextbutton").hide();
}
else{
$(".nextbutton").show();
}
});
});
I hope you wanted to achieve this.
$(document).ready(function() {
var btnNext = $("a.nextbutton").hide();
$('.dropdown').change(function() {
if(this.value){
btnNext.show();
} else {
btnNext.hide();
}
});
});
You had a typo right before "please".
You could/should save the button in a variable so you don't have to make that query every time.

Categories

Resources