I expected the following code to iterate through a select options and remove options having a certain value, otherwise restore the select html
var initialHTML = $('#myselect').html();
$('#myselect option').each(function(){
if($(this).val() === 'b'){
$(this).remove();
console.log('matching. removed.');
return false;
}else{
$('#myselect').html(initialHTML);
console.log('not matching. html restored.');
}
});
Expected select would be:
<select id="myselect">
<option value="a">a</option>
<option value="c">c</option>
</select>
but it actually is
<select id="myselect">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
What I'm doing wrong? FIDDLE
Update e.g. as someone suggested:
The $('#myselect option') constructs a list of options, and
$(this).remove() removes option b, but the list of options is no
longer linked to the HTML, because the HTML had been already changed
by $('#myselect').html(initialHTML) which was executed for option
a
so, I've realised that the actual problem is not even related to what I asked initially in my question. Sorry for that and I'll try to put it in the right section.
p.s. a working solution:
var initialHTML = $('#myselect').html();
function doIt(){
$('#myselect').html(initialHTML);
$('#myselect option').each(function(){
if($(this).val() === 'b'){
$(this).remove();
}
});
}
Thank you so much for help.
The main issue is this line:
$('#myselect').html(initialHTML);
It is executed for option a and then option b can no longer be removed because the HTML has changed even though it is actually identical. So remove that line and your code will work.
$('#myselect option') constructs a list of options, and $(this).remove() removes option b from the list, but the list is no longer associated with the HTML, because the HTML had been already changed by $('#myselect').html(initialHTML) which was executed for option a.
var initialHTML = $('#myselect').html();
$('#myselect option').each(function() {
if (this.value === 'b') {
$(this).remove();
console.log('matching. removed.');
return false;
} else {
//$('#myselect').html(initialHTML);
console.log('not matching. html restored.');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="myselect">
<option>a</option>
<option>b</option>
<option>c</option>
</select>
I changed $(this).val() to this.value. Both will work, but the second one is a bit more efficient because there is no point in converting the JavaScript object to a jQuery object just to get the value.
However, remember that the line:
return false;
will cause the each() loop to exit once a match is found. That's OK if there will only be one match. If there can be more that one match, remove that line so the loop can go through all options.
Here is an alternative way:
Other answers already point out the reason, as because you refresh the option list the during the first iteration, $(this).remove() no longer works because it lose contact of the original item. Thus, a simple fix here would be re-select the target based on it's value. And you can keep your original code of $('#myselect').html(initialHTML); in the loop.
var initialHTML = $('#myselect').html();
$('#myselect option').each(function(){
if($(this).val() === 'b'){
$("option[value='" + $(this).val() + "']").remove();
console.log('matching. removed.');
return false;
} else {
$('#myselect').html(initialHTML);
console.log('not matching. html restored.');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="myselect">
<option value='a'>a</option>
<option value='b'>b</option>
<option value='c'>c</option>
</select>
Try this:
you don't need else part as it is already present and put your jquery inside document.ready so that it will ensure DOM is ready and you can run the jquery script.
var initialHTML = $('#myselect').html();
$(document).ready(function(){
$('#myselect option').each(function(){
if($(this).text() == 'b'){
$(this).remove();
console.log('matching. removed.');
return false;
}
});
});
JSFiddle
What is happening here is that you have something that only needs to be false once to restore the entire select. So it does remove 'b' when it finds it, but then restores the whole select once it sees that 'c' !== 'b'.
You can achive your expected behavior by removing:
else{
$('#myselect').html(initialHTML);
console.log('not matching. html restored.');
}
Depending on what your ultimate goal is, there may be better ways of approaching this, though.
Hope that helps.
Related
I have the following HTML select:
<select class="form-control" id="band_id" name="band_id">
<option selected="selected" value="">Choose a band...</option>
<option value="66">Adolfo Little</option>
<option value="96">Aisha Bosco</option>
<option value="90">Alize Glover</option>
</select>
I need to build a filter where the condition is the #band_id selected so I made this jQuery code:
$("select#band_id").change(function (ev) {
ev.preventDefault();
var band_id = $('select#band_id');
if (band_id.val() != undefined) {
band_id.attr('selected', 'selected');
}
location.href = '/albums/bands/' + band_id.val();
});
Because the location.href the page gets reloaded and the URL changes so the SELECT is reset and I "loose" the selected value.
I can think in two ways to fix this:
Using AJAX which I don't want because is over complicate something easy
Grab the band_id from the URL and then set the selected property which I don't know how to achieve.
I don't know is there any other way to achieve this. Do you have any other idea? (if it's with an example better)
You can use localStorage for that:
if (localStorage.getItem("band_id")) {
$("select#band_id").val(localStorage.getItem("band_id"))
}
$("select#band_id").change(function (ev) {
ev.preventDefault();
if ($(this).val() != undefined) {
$(this).attr('selected', 'selected');
localStorage.setItem("band_id", $(this).val());
}
location.href = '/albums/bands/' + $(this).val();
});
If we have the value saved - set the value of the select element to that values.
Once we change the value in the select element - save the new value in the localStorage.
Note that I removed the usage of the band_id from this example as it's not needed. You have this you can use inside the change function.
I'm also not sure why you change the selected attribute - you redirect the user immediately to a new page (this change will have no effect at all).
I was wondering if it's possible to get jQuery to select an option with having predefined change method.
Let me give me an example; I have a drop-down list like this:
<select id="ddl_BankRequestType">
<option>-- Request Type ---</option>
<option value="val1">Item1</option>
<option value="val2">Item2</option>
</select>
If user selects Item1 or Item2 some logic will be executed:
$('#ddl_BankRequestType').change(function () {
var selectedItem = $(this).find(":selected").text();
if (selectedItem === 'Item1') {
// codes
} else if (selectedItem === 'Item2') {
//other codes
}
});
It works like a charm. Now in document.ready I want the second option be selected item, so I put this code:
$('#ddl_BankRequestType > option:eq(2)').attr('selected', true);
It also works, but I want the logic for Item2 to execute. I have tried the following, but they do nothing:
$('#ddl_BankRequestType > option:eq(2)').attr('selected', true).change();
$('#ddl_BankRequestType > option:eq(2)').attr('selected', true).trigger('change');
You can check the code from DEMO
$(function (){
$('#ddl_BankRequestType').change(function () {
var selectedItem = $(this).find(":selected").text();
console.log(selectedItem)
if (selectedItem === 'Item1') {
alert('item1');
} else if (selectedItem === 'Item2') {
alert('item2');
}
});
$('#ddl_BankRequestType > option:eq(2)').attr('selected', true).change();
});
A quick fix should be something like below,
$('#ddl_BankRequestType').on("change",function () {
var selectedItem = $(this).find(":selected").text();
if (selectedItem === 'Item1') {
doItem1();
} else if (selectedItem === 'Item2') {
doItem2();
}
});
function doItem1(){
alert('Item1');
//other codes
}
function doItem2(){
alert('Item2');
//other codes
}
$(document).ready(function(){
$('#ddl_BankRequestType > option:eq(2)').attr('selected', true);
doItem2();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="ddl_BankRequestType">
<option>-- Request Type ---</option>
<option value="val1">Item1</option>
<option value="val2">Item2</option>
</select>
The problem is .attr() returns a string. So, you can't chain it to trigger the change event. You could do the following:
var ddl_BankRequestType = $('#ddl_BankRequestType');
ddl_BankRequestType.find('option:eq(2)').attr('selected', true);
ddl_BankRequestType.trigger('change');
This is likely a timing issue - since theoretically your code should be firing that trigger event based on the way you're doing it. I think it's simply firing the event before the change function is registered. jQuery's Document load lifecycle loops through all of the defined loaders in the order they're registered, so if you're not able to change when you set the option element as "selected" to after the change event is bound, you may be able to use the native timeout function to ensure it gets fired last.
I generally avoid using timeout like this, but in your scenario it may work:
setTimeout(function() { /* Set the option element true here */ }, 1000);
Best bet is to try and set the element after the change event is bound.
I have this HTML:
<select id="select-one">
<option value="">Choose</option>
<option value="1">House</option>
</select>
<select id="select-two">
<option value="">Choose</option>
<option value="A">Table</option>
</select>
And this Javascript with JQuery
$("#select-two").focus( function() {
if( $("#select-one").val() == "" ) {
alert("Fill select-one first!");
return false;
}
});
So i am getting a infinite loop with alerts because after call alert() Javascript puts the focus again in the same select (select-two).
Someone can help me to solve this please?
Note: based on your comments, this assumes you must listen to the focus event.
Solution 1 - using blur() - effective but buggy in Chrome
In theory, the focus event is not cancelable, so return false or event.preventDefault() will have no effect in this case. However, in practice, you can reverse the event by using the blur() method.
For example:
$('#select-two').on('focus',function () {
if ($("#select-one").val() == "") {
$(this).blur();
alert('Fill select-one first!');
return false;
}
});
See jsFiddle demo
This effectively prevents the field from regaining focus after the alert call and so the focus event is not repeated. The only problem is that in Chrome even though the field is not focused anymore, the dropdown remains open (see demo).
Solution 2 - using remove() and clone() - costly but cross-browser
If Chrome's behavior is problematic, you can take a more crude approach, whereby you remove() the select from the DOM, clone() it and then reinsert it into the DOM. This will effectively "reset" the select element completely, leaving it without focus as well as closed.
For example:
$(document).on('focus','#select-two',function (e) {
if ($("#select-one").val() == "") {
$(this).remove().clone().insertAfter('#select-one');
alert('Fill select-one first!');
return false;
}
});
See jsFiddle demo
The upside of this approach is that it works well in Chrome too. The downside of this approach is that it involves manipulating the DOM for a very trivial issue.
I think you need an extra event that change content select-two when the value of select-one has "" like this:
HTML
<select id="select-one">
<option value="">Choose</option>
<option value="1">House</option>
</select>
<select id="select-two">
<option value="">Choose</option>
<option value="A">Table</option>
</select>
JS
$("#select-one").change(function() {
if ($(this).val() == "") {
$("#select-two").val("");
}
});
$("#select-two").focus(function() {
if( $("#select-one option:selected").val() == "" ) {
alert("Fill select-one first!");
$("#select-one").focus();
return false;
}
});
Demo
How can i check if an item is in a select drop down list and disable it if it fulfills some condition?
Thanks in advance!
BTW i tried the following and nothing is happening
$('#select-box option').each(function()
{if (this.val() == item)
{$('#select-box option').attr("disabled","disabled");}});
EDITED*
The second code i used while debugging. It went through smoothly until i did the comparison with item. I am wondering if it is because of the this value. If so how do i overcome it?
function checkSelectBox(item){ <!--alert(item);-->
$('#SCOPE option').each(function()
{
if($(this).val()==item)
{ alert('Camein')
$(this).attr("disabled", "disabled");
return false;
}
});
}
Do you mean:
$('#yourSelectId option').each(function(){
if ($(this).val() == 'some_value_to_check') {
$(this).attr("disabled", "disabled");
return false;
}
});
Hey this is working example: http://jsfiddle.net/R6GAr/11/
HTML: Sample
<SELECT NAME="SCOPE" id="SCOPE">
<OPTION VALUE="G"> Global
<OPTION VALUE="D" selected="selected"> Dynamic
</SELECT>
JQuery: sample
$('#SCOPE').change(function(){
if($(this).val() == 'G') {
// **disables the option here with attr as below**
$('#SCOPE option[value="'+$(this).val()+'"]').attr("disabled","disabled");
// **Now you want that disable to be not selectable as well, this line does that.**
$('#SCOPE option[value="'+$(this).val()+'"]').attr("selected",false);
}
});
Hope this helps, cheers!
ok so i have some select tags of cities
<select onchange="storeCity(this.value, false)" name="search[city]" id="search_city" class="left">
<option value="">== Select City ==</option>
<optgroup label="Florida"><option selected="selected" value="ft-myers-sarasota-fl">Ft. Myers / Sarasota </option>
<option value="jacksonville-fl">Jacksonville</option>
<option value="miami-fl">Miami / Ft. Lauderdale </option>
<option value="orlando-fl">Orlando</option>
<option value="tampa-fl">Tampa</option></optgroup></select>
Some cities are not available now so i needed a lightbox to popup when they are clicked...which i have working with this code
$('#search_city').change(function(e) {
e.preventDefault();
if ($(this).val() == 'jacksonville-fl' || $(this).val() == 'miami-fl' || $(this).val() == 'tampa-fl' || $(this).val() == 'ft-myers-sarasota-fl') {
}
The problem I have is that it goes to the link anyways and i need it to get rid of the link or the onchange on the select...something is getting the page to refresh...but i dont know what
storeCity(this.value, false) might have caused the refresh
BTW, you can merge the code like this:
$('#search_city').change(function(e) {
storeCity(this.value, false);
if (this.value.match(/(jacksonville-fl|miami-fl|tampa-fl|ft-myers-sarasota-fl)/i)) {
//do some stuff
}
e.preventDefault();
});
You could probably use jQuery's .one() function for this. E.g.
$('#search_city').one('change', function() {
/* Your code */
});
The change event will only execute once.
you have a method called
storeCity(this.value, false)
on change event , this might be refreshing the page. check that out.
Also a word of warning - I'd not use e.preventDefault() on a CHANGE event (unless you really need to), as it can have some weird behaviour in some browsers. Usually that's just for CLICK events.