How can I search optgroup label with jQuery - javascript

I have a list with the states of the United States in a select and I need filter by the optgroup label.
For example:
If I search for Alabama, I need to return to another select with Birmingham and Huntsville
I'm using this jQuery code and this code works when I search by options, but I need search by groups.
How can I change the jQuery to return only the cities of the states in which I search?
Here is my working code: https://jsfiddle.net/km7s9er5/
Thanks in advance for someone helping me with this
$(document).ready(function() {
jQuery.fn.filterByText = function(textbox, selectSingleMatch) {
return this.each(function() {
var select = this;
var options = [];
$('#myfiltercities_id').hide();
$(select).find('option').each(function() {
options.push({
value: $(this).val(),
text: $(this).text()
});
});
$(select).data('options', options);
$(textbox).bind('change keyup', function() {
$('#myfiltercities_id').hide();
var options = $(select).empty().data('options');
var search = $(this).val().trim();
var regex = new RegExp(search, "gi");
$.each(options, function(i) {
var option = options[i];
if (option.text.match(regex) !== null) {
$(select).append(
$('<option>').text(option.text).val(option.value)
);
}
});
if (selectSingleMatch === true && $(select).children().length === 1) {
$(select).children().get(0).selected = true;
}
});
});
};
$(function() {
$('#myfiltercities_id').filterByText($('#textbox'), true);
$("select option").click(function() {
alert(1);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<select name="myfiltercities" id="myfiltercities_id">
<option value=""></option>
<optgroup label="AL"></optgroup>
<optgroup label="Alabama">
<option value="123">Birmingham</option>
<option value="123">Huntsville</option>
</optgroup>
<optgroup label="AK"></optgroup>
<optgroup label="Alaska">
<option value="456">Anchorage</option>
<option value="789">Juneau</option>
<option value="135">Fairbanks</option>
</optgroup>
<optgroup label="AZ"></optgroup>
<optgroup label="Arizona">
<option value="198">Phoenix</option>
<option value="065">Tucson</option>
</optgroup>
<optgroup label="AR"></optgroup>
<optgroup label="Arkansas">
<option value="835">Little Rock</option>
</optgroup>
<optgroup label="CA"></optgroup>
<optgroup label="California">
<option value="402">Los Angeles</option>
</optgroup>
</select>

Consider the following code.
https://jsfiddle.net/Twisty/zvtymk1r/29/
HTML
<form action="/action_page.php">
<label for="fname">Find City</label>
<input type="text" id="textbox" name="textbox"><br><br>
<select name="myfiltercities" id="myfiltercities_id">
<option value=""></option>
<optgroup label="Alabama" data-abbr="AL">
<option value="123">Birmingham</option>
<option value="123">Huntsville</option>
</optgroup>
<optgroup label="Alaska" data-abbr="AK">
<option value="456">Anchorage</option>
<option value="789">Juneau</option>
<option value="135">Fairbanks</option>
</optgroup>
<optgroup label="Arizona" data-abbr="AZ">
<option value="198">Phoenix</option>
<option value="065">Tucson</option>
</optgroup>
<optgroup label="Arkansas" data-abbr="AR">
<option value="835">Little Rock</option>
</optgroup>
<optgroup label="California" data-abbr="CA">
<option value="402">Los Angeles</option>
</optgroup>
</select>
</form>
JavaScript
jQuery.fn.filterByText = function(textbox, selectSingleMatch) {
return this.each(function() {
var select = this;
$('#myfiltercities_id').hide().children().hide();
$(textbox).on("change keyup", function(e) {
$('#myfiltercities_id').hide().children().hide();
var search = $(this).val().trim().toLowerCase();
if (search.length >= 2) {
$('#myfiltercities_id').show();
$("optgroup", select).each(function(i, el) {
var label = $(el).attr("label").toLowerCase();
var abbr = $(el).data("abbr").toLowerCase();
if (search.length == 2) {
if (abbr == search) {
console.log(search, label, abbr);
$(el).show();
}
} else {
if (label.indexOf(search) >= 0) {
console.log(search, label, abbr);
$(el).show();
}
}
});
}
});
});
}
$(function() {
$('#myfiltercities_id').filterByText($('#textbox'), true);
$("select option").click(function() {
alert(this.value);
});
});
First your HTML Structure was not conducive to a proper search. The abbreviation had no correlation with the results. I moved this to a Data attribute associated with the cities.
Your search feature was originally designed for Option elements and not good for groups. Also it was re-adding Options back to the select. It seemed overly complex.
I find it easier, when filtering, to simply Hide all items and then Show items that match the filter. based on the number of characters in the input, we might be searching for an abbreviation or a full state name. This is an easy condition to look at.
So if the User searches for "al", they will get Alabama, but if they then continue to "ala", they will Alabama and Alaska.

Related

Change option values of select 2 if select 1 has a value with jquery

I require a bit of jQuery to do the following:
A user can currently select Program and/or a region.
If a user selects Program AND a Region I require the option values of the region dropdown to change to "?region=1" and "?region=2"
<select class="program" id="program">
<option value="program1.html">Program 1</option>
<option value="program2.html">Program 2</option>
</select>
<select class="region" id="region">
<option value="region1.html">Region 1</option>
<option value="region2.html">Region2</option>
</select>
Greatly appreciate the assist.
My attempt at JQuery:
$('#program').on('change', function () { if($(this).val() !="0") { } else { // no option is selected } })
You need to further extend the change event for #program and include a similar one for #region.
var programSelected = null;
var regionSelected = null;
$('#program').on('change', function(element) {
programSelected = $('#program option:selected').text();
updateRegionOptions();
});
$('#region').on('change', function(element) {
regionSelected = $('#region option:selected').text();
updateRegionOptions();
});
function updateRegionOptions() {
if(programSelected != null && regionSelected != null) {
$('#region option').each(function() {
var modifiedString = '?';
modifiedString += $(this).val().replace(/\d+/,'');
modifiedString = modifiedString.replace('.html','');
modifiedString += '=';
modifiedString += $(this).val().match(/\d+/);
$(this).val(modifiedString);
});
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="program" id="program">
<option value="" selected disabled>Select Program</option>
<option value="program1.html">Program 1</option>
<option value="program2.html">Program 2</option>
</select>
<select class="region" id="region">
<option value="" selected disabled>Select Region</option>
<option value="region1.html">Region 1</option>
<option value="region2.html">Region2</option>
</select>
Explanation of the logic above:
on('change' event for both #region and #program
Set the relevant variable programSelected or regionSelected depending on the change event
Run function updateRegionOptions();
If the variables programSelected and regionSelected both have a value
For each of the options in #region
Mutate the existing value to be of the form "?region=1" and "?region=2"
Update the value section of each of the option elements to have this value
The relevant JSFiddle for review.
If this solved your issue, please accept this answer :)

Multiple values of <option>

I would like to put multiple values in tag within select, so I could adress precisely one or few items.
Example:
<select id="select1">
<option value="pf, nn">NN</option>
<option value="pf, x2, jj">JJ</option>
<option value="pf, uu">UU</option>
<option value="pf, x2, oo">OO</option>
<option value="tt">TT</option>
<option value="rr">RR</option>
</select>
In my js I got that one function that depend on one value that is common for many items:
if (document.getElementById("select1").value = "pf";) {
// do something;
}
if (document.getElementById("select1").value = "x2";) {
// do some-other-thing;
}
But I don't want to use (cos' and with more options gonna get messy)
var sel1 = document.getElementById("select1").value
if (sel1="nn" || sel1="jj" || sel1="uu" || sel1="oo") {
// do something;
}
if (sel1="jj" || sel1="oo") {
// do some-other-thing;
}
Neverthelesst I need to be able to set item by precise one value
if (document.somethingelse = true) {
document.getElementById("select1").value = "oo";)
}
Is there a nice way to achieve this? Maybe use some other "value-like" attribute of option (but which?)?
Only JS.
I think you can do what you want with selectedOpt.value.split(",").includes("sth") code:
$(document).ready(function(e){
selectedChange($("#select1")[0])
});
function selectedChange(val) {
var selectedOpt = val.options[val.selectedIndex];
var status1 = selectedOpt.value.split(",").includes("x2");
var status2 = selectedOpt.value.split(",").includes("pf");
console.log(status1);
console.log(status2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="select1" onchange="selectedChange(this)">
<option value="pf,nn">NN</option>
<option value="pf,x2,jj">JJ</option>
<option value="pf,uu">UU</option>
<option value="pf,x2,oo">OO</option>
<option value="tt">TT</option>
<option value="rr">RR</option>
</select>

Hide option from dropdown 2 when selected in dropdown 1

I have two dropdowns, both have the same items in them. If an option is selected in dropdown 1 then I would like to hide that option in dropdown 2. When it is unselected in dropdown 1 I would like it to appear again in dropdown 2 and whichever option is then selected to then be hidden in dropdown 2. I am trying to have this exclude the blank option in the first index.
Here is a codepen that I started, but I am not sure where to go from here:
http://codepen.io/cavanflynn/pen/EjreJK
var $dropdown1 = $("select[name='dropdown1']");
var $dropdown2 = $("select[name='dropdown2']");
$dropdown1.change(function () {
var selectedItem = $($dropdown1).find("option:selected").val;
});
Thanks for your help!
As said in comments, one of the options is to disable/enable options according to the selection in the first select, like below. This would work on all browsers as opposed to hide/show which doesn't.
var $dropdown1 = $("select[name='dropdown1']");
var $dropdown2 = $("select[name='dropdown2']");
$dropdown1.change(function() {
$dropdown2.find('option').prop("disabled", false);
var selectedItem = $(this).val();
if (selectedItem) {
$dropdown2.find('option[value="' + selectedItem + '"]').prop("disabled", true);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="dropdown1">
<option></option>
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</select>
<select name="dropdown2">
<option></option>
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</select>
Another option is to remove/add options in the 2nd dropdown based on the selection in the first via .clone(), as below.
var $dropdown1 = $("select[name='dropdown1']");
var $dropdown2 = $("select[name='dropdown2']");
$dropdown1.change(function() {
$dropdown2.empty().append($dropdown1.find('option').clone());
var selectedItem = $(this).val();
if (selectedItem) {
$dropdown2.find('option[value="' + selectedItem + '"]').remove();
}
});
A Demo
var $dropdown1 = $("select[name='dropdown1']");
var $dropdown2 = $("select[name='dropdown2']");
$dropdown1.change(function() {
var selectedItem = $(this).val();
var $options = $("select[name='dropdown1'] > option").clone();
$("select[name='dropdown2']").html($options);
$("select[name='dropdown2'] > option[value="+selectedItem+"]").remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<select name="dropdown1">
<option></option>
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</select>
<select name="dropdown2">
<option></option>
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</select>
Demo
You should use this plugin http://gregfranko.com/jquery.selectBoxIt.js
It has some really nice callbacks and customisation options.
When one changes you can put it in the callback to update the other.
Here is one way of doing it. You do need to include jQuery, and then as long as the value isn't empty hide the option with the similar value.
var $dropdown1 = $("select[name='dropdown1']");
var $dropdown2 = $("select[name='dropdown2']");
$dropdown1.change(function() {
$dropdown2.children().show();
var selectedItem = $($dropdown1).val();
if (selectedItem != "")
$('select[name="dropdown2"] option[value="' + selectedItem + '"]').hide();
});
$dropdown2.change(function() {
$dropdown1.children().show();
var selectedItem = $($dropdown2).val();
if (selectedItem != "")
$('select[name="dropdown1"] option[value="' + selectedItem + '"]').hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="dropdown1">
<option></option>
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</select>
<select name="dropdown2">
<option></option>
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</select>
Here's an approach that stores a set of the options on page load then filters the alternate select when a change is made. It works in both directions for changes made to either select
var $drops = $('.drop'),
// store a set of options
$options = $drops.eq(1).children().clone();
$drops.change(function(){
var $other = $drops.not(this),
otherVal = $other.val(),
newVal = $(this).val(),
$opts = $options.clone().filter(function(){
return this.value !== newVal;
})
$other.html($opts).val(otherVal);
});
Values will also be maintained and this is 2 directional so a change in either will filter the other
DEMO
Well, this code will find option by value in necessary selects and remove it.
http://codepen.io/anon/pen/LVqgbO
var $dropdown1 = $("select[name='dropdown1']");
var $dropdown2 = $("select[name='dropdown2']");
var populateDropdown = function(element) {
element.find("option").remove();
element.append("<option></option>");
// There should be real data
for (var i = 1; i <= 3; i++) {
element.append("<option value='" + i + "'>Test " + i + "</option>");
}
}
var getOptionProps = function(element) {
var selectedValue = element.val();
var selectedText = element.find("option[value=" + selectedValue + "]").text();
return { text: selectedText, value: selectedValue };
}
var removeOptionWithValue = function(element, value) {
element.find("option[value='" + value + "']").remove();
}
$dropdown1.on("change", function () {
var selectedProps = getOptionProps($(this));
populateDropdown($dropdown2);
removeOptionWithValue($dropdown2, selectedProps.value);
});
$dropdown2.on("change", function () {
var selectedProps = getOptionProps($(this));
populateDropdown($dropdown1);
removeOptionWithValue($dropdown1, selectedProps.value);
});

Select elements OptGroups from options with JQUERY

I essentially get a standard select back from the server. If the option value is 'GROUP' I need to change that option to an option group . If the option value is 'GROUPEND', I need to change it to an end option group . The select renders correctly, the function is fired, just not properly grouping...
I created a function as such, and it is not working. Any guidance would be greatly appreciated. here is the code. I left the comments in so that you can see what I have tried.
$('#residualModelSelector').multiselect({
header: true,
selectedList: 5,
click: function (e) {
//allow only 5 to be selected
if ($(this).multiselect("widget").find("input:checked").length > 5) {
return false;
}
}
}).multiselectfilter()
.live( updateModelGroups($('#residualModelSelector')));
function updateModelGroups(residualModelSelector){
$('#residualModelSelector').find('option').each(function () {
var strOptGroup = $(this).val().split('-');
var strOptGroupChk = strOptGroup[0];
var strOptGroupLabel = strOptGroup[1];
if (strOptGroupChk == 'GROUP') {
var replaceThisOption = document.createElement('optgroup');
replaceThisOption.label = strOptGroupLabel;
$(this).replaceWith(replaceThisOption);
//.html('<optgroup label=' + strOptGroupLabel + '>');
//.replaceWith('<optgroup label=' + strOptGroupLabel + '>');
} else if (strOptGroupChk == 'GROUPEND') {
var replaceThisOptionEnd = $('</optgroup>');
$(this).replaceWith(replaceThisOptionEnd);
//$(this).replaceAll('</optgroup>');
//.html('</optgroup>');
//.replaceWith('</optgroup>');
}
});
$('#residualModelSelector').multiselect('refresh');
}
I setup a jsFiddle for this to test http://jsfiddle.net/murCv/
1) I assume your select box looks something like
<select id="residualModelSelector">
<option value="some-node1">Out side opt groups 1</option>
<option value="GROUP-first">FirstGroup</option>
<option value="first-node1">Inside First group 1</option>
<option value="first-node2">Inside First group 2</option>
<option value="GROUPEND-first">End FirstGroup</option>
<option value="some-node2">Between Groups</option>
<option value="GROUP-second">SecondGroup</option>
<option value="second-node1">Inside Second group 1</option>
<option value="second-node2">Inside Second group 2</option>
<option value="GROUPEND-second">End SecondGroup</option>
<option value="some-node2">Out side opt groups 2</option>
</select>
Here is the working js
var group = null;
$('#residualModelSelector').find('option').each(function () {
var strOptGroup = $(this).val().split('-');
var strOptGroupChk = strOptGroup[0];
var strOptGroupLabel = strOptGroup[1];
if (strOptGroupChk == 'GROUP') {
group = $("<optgroup label='"+ strOptGroupLabel + "' ></optgroup>").insertBefore($(this));
} else if (strOptGroupChk == 'GROUPEND') {
group = null;
}
if (strOptGroupChk == 'GROUP' || strOptGroupChk == 'GROUPEND') {
$(this).remove();
return;
}
if (group != null)
$(this).appendTo(group);
});
The resulting html
<select id="residualModelSelector">
<option value="some-node1">Out side opt groups 1</option>
<optgroup label="first">
<option value="first-node1">Inside First group 1</option>
<option value="first-node2">Inside First group 2</option>
</optgroup>
<option value="some-node2">Between Groups</option>
<optgroup label="second">
<option value="second-node1">Inside Second group 1</option>
<option value="second-node2">Inside Second group 2</option>
</optgroup>
<option value="some-node2">Out side opt groups 2</option>
</select>

coding onchange event

hello
i need to load page based on the results of dropdown box. for example in my code i have value="userlog". if this selected it will load userlog.php and remove itself so that only userlog.php is being used. thanks
<select onchange="updatePage(this.value)">
<option value="">Select a report</option>
<option value="userlog">User Logs</option>
<option value="actionlog">Action Logs</option>
</select>
<select id="select_page">
<option value="">Select a report</option>
<option value="userlog">User Logs</option>
<option value="actionlog">Action Logs</option>
</select>
$('#select_page').change(function() {
var $el = $(this);
if($el.val() != '') {
$('#page').load($el.val()+'.php');
$el.find('option:selected').remove();
}
});
On change event you will get the selected options value. Using this value you can decide what you want to do.
something like this :
$(document).ready(function() {
$("select option ").each(function() {
if (location.href.indexOf($(this).val()) >= 0) {
$(this).remove();
}
});
$('select').change(function() {
var obj = $(this);
location.href = obj.val() + ".php";
});
});

Categories