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>
Related
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.
I've tried all the solutions from google. What am I missing? The option I want is not being selected.
Here's the section of code i'm having trouble with. I've included some other things I've tried (commented out).
If it matters, this list is built dynamically, but the code to select it by value is after that process.
i'm in Chrome Version 80.0.3987.149
// EDIT ADDED THIS CODE FROM MY APPLICATION
const url = '/api/Customers';
// Populate dropdown
$.getJSON(url, function (data) {
$.each(data, function (key, entry) {
dropdown.append($('<option></option>').attr('value', entry.CustomerID).text(entry.Name + ' - ' + entry.Email));
})
});
// END EDIT ^^^^^
//var customerID = window.location.hash;
var customerID = "6a1920b2-f388-4790-a720-75048e1407a7"; //Test User 5
console.log(customerID);
//$('#customer-dropdown option[value="'+ customerID +'"]').prop('selected', true);
//$("#customer-dropdown select").val(customerID);
$("#customer-dropdown option[data-value='" + customerID +"']").attr("selected","selected");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="customer-dropdown" name="c15905d7-8216-4e81-ac15-2fafd10b49e8">
<option disabled="">Select Customer</option>
<option value="297f8676-80bf-43e5-b463-031a5b5154aa">Test User 1</option>
<option value="83941899-8039-488f-bf6b-0d036c7d6556">Test User 2</option>
<option value="263356fd-d803-4436-a7fc-4df5a3095771">Test User 3</option>
<option value="2e31ee49-b096-4237-b07e-61071871334d">Test User 4</option>
<option value="6a1920b2-f388-4790-a720-75048e1407a7">Test User 5</option>
<option value="072f6800-570c-4004-b9cd-7bdb4cf98b0a">Test User 6</option>
<option value="c957f2c0-f72e-4de7-9b4f-9272cbbfd783">Test User 7</option>
<option value="d870225f-c020-4369-bd7b-9dc5d16f34a1">Test User 8</option>
</select>
Simply assign the value to select.
//var customerID = window.location.hash;
var customerID = "6a1920b2-f388-4790-a720-75048e1407a7"; //Test User 5
//$('#customer-dropdown option[value="'+ customerID +'"]').prop('selected', true);
//$("#customer-dropdown select").val(customerID);
$("#customer-dropdown").val(customerID);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="customer-dropdown" name="c15905d7-8216-4e81-ac15-2fafd10b49e8">
<option disabled="">Select Customer</option>
<option value="297f8676-80bf-43e5-b463-031a5b5154aa">Test User 1</option>
<option value="83941899-8039-488f-bf6b-0d036c7d6556">Test User 2</option>
<option value="263356fd-d803-4436-a7fc-4df5a3095771">Test User 3</option>
<option value="2e31ee49-b096-4237-b07e-61071871334d">Test User 4</option>
<option value="6a1920b2-f388-4790-a720-75048e1407a7">Test User 5</option>
<option value="072f6800-570c-4004-b9cd-7bdb4cf98b0a">Test User 6</option>
<option value="c957f2c0-f72e-4de7-9b4f-9272cbbfd783">Test User 7</option>
<option value="d870225f-c020-4369-bd7b-9dc5d16f34a1">Test User 8</option>
</select>
This ended up being my solution to combat the timing issue introduced by .getJSON (async):
I just selected it as I built the dropdown:
$.getJSON(url, function (data) {
$.each(data, function (key, entry) {
//console.log(entry.CustomerID + " | " + customerID + " | " + (entry.CustomerID == customerID))
if (entry.CustomerID == customerID) {
dropdown.append($('<option></option>').attr({ value: entry.CustomerID, selected: "selected" }).text(entry.Name + ' - ' + entry.Email));
dropdown.val(customerID);
} else {
dropdown.append($('<option></option>').attr('value', entry.CustomerID).text(entry.Name + ' - ' + entry.Email));
}
})
});
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 :)
I have a dynamically generated <select> field with <option>.
<select>
<option value=""></option>
<option value=""></option>
<option value=""> False</option>
<option value=""> True</option>
<option value="">False False</option>
<option value="">False True</option>
<option value="">True</option>
<option value="">True True</option>
</select>
I would like to remove the duplicate occurrences and combinations. The final <select> field with <option> should look like :
<select>
<option value=""></option>
<option value="">False</option>
<option value="">True</option>
</select>
Here is how my fiddle looks like. Been trying to solve this for hours.
var values = [];
$("select").children().each(function() {
if (values.length > 0) {
var notExists = false;
for (var x = 0; x < values.length; x++) {
var _text = this.text.replace(/\s/g, "");
var value = values[x].replace(/\s/g, "");
if (values[x].length > _text.length) {
//console.log('>>+', value, ' || ', _text, value.indexOf(_text))
notExists = value.indexOf(_text) > -1 ? true : false;
} else {
//console.log('>>*', value, ' || ', _text, _text.indexOf(value))
notExists = _text.indexOf(value) > -1 ? true : false;
}
}
if (notExists) {
//this.remove();
values.push(this.text);
}
} else {
values.push(this.text);
}
});
Any help to solve this is appreciated.
You can use map() to return all options text and use split() on white-space. Then to remove duplicates you can use reduce() to return object. Then you can empty select and use Object.keys() to loop each property and append to select.
var opt = $("select option").map(function() {
return $(this).text().split(' ')
}).get();
opt = opt.reduce(function(o, e) {return o[e] = true, o}, {});
$('select').empty();
Object.keys(opt).forEach(function(key) {
$('select').append(' <option value="">'+key+'</option>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
<option value=""></option>
<option value=""></option>
<option value="">False</option>
<option value="">True</option>
<option value="">False False</option>
<option value="">False True</option>
<option value="">True</option>
<option value="">True True</option>
</select>
You can loop through each of this children text , then use substring to get the first text & put it in an array.
Once done empty the select element and append the newly created options
var _textHolder=[]; // NA empty array to hold unique text
var _options="";
$("select").children().each(function(item,value) {
var _textVal = $(this).text().trim(); // Remove white space
//get the first text content
var _getText = _textVal.substr(0, _textVal.indexOf(" "));
// if this text is not present in array then push it
if(_textHolder.indexOf(_getText) ==-1){
_textHolder.push(_getText)
}
});
// Create new options with items from _textHolder
_textHolder.forEach(function(item){
_options+='<option value="">'+item+'</option>'
})
// Empty current select element and append new options
$('select').empty().append(_options);
JSFIDDLE
I would do with pure JS ES6 style. This is producing a words array from the whitespace separated options element's innerText value regardless the words are in the front, middle or the end; and it will create a unique options list from that. Basically we are concatenating these arrays and getting it unified by utilizing the new Set object. The code is as follows;
var opts = document.querySelector("select").children,
list = Array.prototype.reduce.call(opts, function(s,c){
text = c.innerText.trim().split(" ");
return new Set([...s].concat(text)) // adding multiple elements to a set
},new Set());
list = [...list]; // turn set to array
for (var i = opts.length-1; i >= 0; i--){ //reverse iteration not to effect indices when an element is deleted
i in list ? opts[i].innerText = list[i]
: opts[i].parentNode.removeChild(opts[i]);
}
<select>
<option value=""></option>
<option value=""></option>
<option value=""> False</option>
<option value=""> True</option>
<option value="">False False</option>
<option value="">False True</option>
<option value="">True</option>
<option value="">True True</option>
</select>
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);
});