I'm trying to change the currently selected option in a select with the Chosen plugin.
The documentation covers updating the list, and triggering an event when an option is selected, but nothing (that I can see) on externally changing the currently selected value.
I have made a jsFiddle to demonstrate the code and my attempted ways of changing the selection:
$('button').click(function() {
$('select').val(2);
$('select').chosen().val(2);
$('select').chosen().select(2);
});
From the "Updating Chosen Dynamically" section in the docs: You need to trigger the 'chosen:updated' event on the field
$(document).ready(function() {
$('select').chosen();
$('button').click(function() {
$('select').val(2);
$('select').trigger("chosen:updated");
});
});
NOTE: versions prior to 1.0 used the following:
$('select').trigger("liszt:updated");
My answer is late, but i want to add some information that is missed in all above answers.
1) If you want to select single value in chosen select.
$('#select-id').val("22").trigger('chosen:updated');
2) If you are using multiple chosen select, then may you need to set multiple values at single time.
$('#documents').val(["22", "25", "27"]).trigger('chosen:updated');
Information gathered from following links:
1) Chosen Docs
2) Chosen Github Discussion
Sometimes you have to remove the current options in order to manipulate the selected options.
Here is an example how to set options:
<select id="mySelectId" class="chosen-select" multiple="multiple">
<option value=""></option>
<option value="Argentina">Argentina</option>
<option value="Germany">Germany</option>
<option value="Greece">Greece</option>
<option value="Japan">Japan</option>
<option value="Thailand">Thailand</option>
</select>
<script>
activateChosen($('body'));
selectChosenOptions($('#mySelectId'), ['Argentina', 'Germany']);
function activateChosen($container, param) {
param = param || {};
$container.find('.chosen-select:visible').chosen(param);
$container.find('.chosen-select').trigger("chosen:updated");
}
function selectChosenOptions($select, values) {
$select.val(null); //delete current options
$select.val(values); //add new options
$select.trigger('chosen:updated');
}
</script>
JSFiddle (including howto append options):
https://jsfiddle.net/59x3m6op/1/
In case of multiple type of select and/or if you want to remove already selected items one by one, directly within a dropdown list items, you can use something like:
jQuery("body").on("click", ".result-selected", function() {
var locID = jQuery(this).attr('class').split('__').pop();
// I have a class name: class="result-selected locvalue__209"
var arrayCurrent = jQuery('#searchlocation').val();
var index = arrayCurrent.indexOf(locID);
if (index > -1) {
arrayCurrent.splice(index, 1);
}
jQuery('#searchlocation').val(arrayCurrent).trigger('chosen:updated');
});
Related
I have a dynamically generated dropdown select feature that numerically pages through a book. I wish to create a table of content feature that allows users to click a link to jump to pages within the book. I've implemented a vanilla javascript solution (see below) that selects by index BUT the update isn't triggered (page number changes in the pager but it doesn't advance the page).
I welcome a way to make the javascript change trigger or a jquery solution. Thanks!
function selectOption(index) {
document.getElementById("tei_pager").options.selectedIndex = index;
}
<select id="tei_pager" class="form-select">
<option value="10917">1</option>
<option value="10918">2</option>
<option value="10919">3</option>
</select>
Second Page
and this section of a separate jquery is binding the select
// Bind page changes to the select.
$("#tei_pager").change(function () {
Drupal.settings.islandora_paged_tei_seadragon_update_page(
$(this).val(),
$(this).children("option:selected").text()
);
});
I adapted a solution from here: Change <select>'s option and trigger events with JavaScript
Having the selection made by js rather than a mouseclick was inhibiting the process.
My solution looks like:
js
function selectOption(index){
if (index == 0) {
document.getElementById("tei_pager").options.selectedIndex = index;
}
else {
document.getElementById("tei_pager").options.selectedIndex = (index - 1);
}
if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
document.getElementById("tei_pager").dispatchEvent(evt);
}
else {
document.getElementById("tei_pager").fireEvent("onchange");
}
}
html
<select id="tei_pager" class="form-select">
<option value="10917" selected="selected">1</option>
<option value="10918">2</option>
<option value="10919">3</option>
<option value="10920">4</option>
<option value="10921">5</option>
<option value="11192">6</option>
<option value="11193">7</option>
</select>
First Page
Sixth Page
You can set the value of the select tag.
function selectOption(val) {
document.getElementById("tei_pager").value = val;
}
<select id="tei_pager" class="form-select">
<option value="10917">1</option>
<option value="10918">2</option>
<option value="10919">3</option>
</select>
Second Page
If the change event of the select element is to trigger the Drupal code you have at the end of your question,
then change:
$("#islandora_paged_tei_seadragon_pager").change(function () { ....
to:
$("#tei_pager").change(function () { ....
UPDATE
If by ....dynamically generated dropdown select.... you mean to say that the select element is created after DOM ready event, then consider re-writing it as follows:
$(document).on('change', '#tei_pager', function () { ....
I want to make a form in which the next field appears based on input done in the previous field by the user.
eg: If The user selects Beverages then below it show a fieldset with different beverages with checkbox, and if user select snacks then below it show fieldset with snacks items
I was trying it to do like this:
<select id="first-choice">
<option selected value="base">Please Select</option>
<option value="beverages">Beverages</option>
<option value="snacks">Snacks</option>
</select>
<br>
<select id="second-choice">
<option>Please choose from above</option>
</select>
JSON Data
{
"beverages": "Coffee,Coke",
"snacks": "Chips,Cookies"
}
Jquery
$("#first-choice").change(function() {
var $dropdown = $(this);
$.getJSON("jsondata/data.json", function(data) {
var key = $dropdown.val();
var vals = [];
switch(key) {
case 'beverages':
vals = data.beverages.split(",");
break;
case 'snacks':
vals = data.snacks.split(",");
break;
case 'base':
vals = ['Please choose from above'];
}
var $secondChoice = $("#second-choice");
$secondChoice.empty();
$.each(vals, function(index, value) {
$secondChoice.append("<option>" + value + "</option>");
});
});
});
I not only want append select option, I actually want to make a new division with text fields and file uploads etc
just guide me how to do it in a compact/dynamic way
By all means keep the JS that fills the selector elements (but make your options map a thing that's known before the user even gets to pick anything: don't rely on a network transfer for that!), but don't try to get the whole "conditional showing" to work in JS: CSS can already do that, and it'll do it better. You just need to remember to use the correct HTML markup:
// Load this script via src="..." with `async` and `defer` attributes
// so that it'll run before the user gets to interact with the page,
// after the DOM has been constructed. A feature that's been available
// since IE11, so there's no reason to still put scripts at the end of
// the page, or listening for DOMContentLoaded/ready events.
const first = document.getElementsByName('first-value')[0];
const second = document.getElementsByName('second-value')[0];
const initial = second.innerHTML;
// Either hard code this, or get it on page load, just make sure
// it's already available before users start picking values!
const optionMap = {
a: ['i', 'j', 'k'],
b: ['u', 'v', 'w'],
c: ['x', 'y', 'z'],
};
function addOption(selectElement, text) {
let option = document.createElement('option');
option.value = text;
option.textContent = text;
selectElement.append(option);
}
// Fill the first selector
Object.keys(optionMap).forEach(text => addOption(first, text));
// And only fill the second selector when we know the first value
first.addEventListener('change', evt => {
second.innerHTML = initial;
optionMap[evt.target.value].forEach(text => addOption(second, text));
});
select:not(:valid) {
border: 1px solid red;
}
select:not(:valid) + .followup {
display: none;
}
<select required name="first-value">
<option disabled selected>please select one</option>
</select>
<select required class="followup" name="second-value">
<option disabled selected>please select one more</option>
</select>
The trick here is to make sure you have an option that is both disabled and selected. The latter because <select> elements always have an option selected, but any option marked as disabled does not count as a valid choice (this lets you for instance put labels in a selector element).
So, we make a first <option> that is simply a label, but also make sure the selector always starts with that option selected. As it's disabled, that makes the selector invalid as far as form posting is concerned, so we can use the CSS :valid pseudo class to do all kinds of useful things, like hiding any adjacent element until the main select element is valid.
And of course you can still "fill" the second selector using JS, with an event listener on the first selector so that its change triggers some JS that appends a bunch of option elements to the second one, but this is really something you want to do without a network request: have your code already know which primary values map to which arrays of secondary values by doing a fetch for the full mapping on pageload, or even hardcoded it (e.g. during your site building step, or even manually)
I'm currently working on a dynamic form which enables the user to add as many variants as they would like. This form which can be added has a price, size and color. The size and color are select2 select boxes which enable the user to select multiple things. The form:
<div class="col-sm-4">
<label>Kleuren</label>
<select name="colors[{{$i}}][]" id='color-options' class="form-control multiple-select" multiple="multiple">
#foreach($colors as $id=>$color)
<option value="{{$id}}">{{$color}}</option>
#endforeach
</select>
</div>
When looking at the HTML code I have multiple of these forms which go by name: colors[0][], colors[1][], colors[2][] etc.
How do I print the value of a selected new color in a new div? The code which I have thus far:
$(document).ready(function() {
$('.multiple-select').select2({
language: 'nl'
});
$('.summernote').summernote();
var addVariantButton = document.getElementById('addVariant[0]');
addVariantButton.addEventListener('click', function(){
addVariant(0);
});
var colorSelected = document.getElementsByName('colors[0][]');
colorSelected.addEventListener("click", displayColorSelected);
});
function displayColorSelected() {
var selected_value = document.getElementById("color-options").value;
console.log(selected_value);
}
But this only works for the first colors input form, but how can I make this into a more dynamical function to get all colors input?
You can get all selected values in array as below:
function displayColorSelected() {
var selected_value = $("[id='color-options']").toArray().map(x => $(x).val());
console.log(selected_value);
}
Note: id selector will always return single element which will be first with that id. So you're getting value for first select only.
You can use attribute selector ([]) instead which will find every element with given id. So here $("[id='color-options']").toArray() will find every element with id equal to color-options and map(x => $(x).val()) will return only value part from the elements array.
Add all the selects a class ("color-select" for example), and run over all the selects -
$('.color-select').each(function() { console.log($(this).val()); })
You may need to delegate your event listener
document.addEventListener('event',function(e){
if(element){//do something}
})
Since you are using jquery its easier
$(document).on('event','element',function());
I have the following select field and based on whether the class .show-x-trend or show-x is selected I would like to conditionally reveal a separate div. If .show-x-trend <option> is selected, I'd like to reveal the already hidden #x-axis-trend-wrap <div> and if show-x option is selected I'd like to reveal the already hidden #x-axis-wrap <div>. In the code below, you'll see that I have both CSS classes and also values assigned to the 3 selection options because I tried to achieve the effect a few different ways but so far with no luck.
<div id="visualize-wrap">
<h3>Visualization Shows</h3>
<select id="visualize-shows" name="visualize">
<option class="no-show" value="00">Select One</option>
<option class="show-x-trend" value="01">Trend Over Time</option>
<option class="show-x" value="02">Breakdown of Sum Total</option>
<option class="show-x" value="03">Side-by-side Comparison</option>
</select>
</div>
You can use hasClass method to determine if the selected option contains the required class or not and act accordingly.
$('#visualize-shows').change(function(){
var $selectedOption = $(this).find('option:selected');
$('#x-axis-trend-wrap')
.toggle( $selectedOption.hasClass('show-x-trend'));
$('#x-axis-wrap')
.toggle( $selectedOption.hasClass('show-x'));
});
Working demo - http://jsfiddle.net/X2dPt/
Try something like this
$("#visualize-shows").change(function() {
$selected = $(this).find('option:selected'); // get selected option
if ($selected.hasClass('show-x-trend')) { // check the class
$('#x-axis-trend-wrap').toggle(); // toggle display
} else if ($selected.hasClass('show-x')) {
$('#x-axis-wrap').toggle();
}
});
this uses .hasClass()
I have two drop down lists:
<select name="branch">
<option value="b">Blacksburg</option>
<option value="c">Christiansburg</option>
<option value="f">Floyd</option>
<option value="m">Meadowbrook</option>
</select>
but I would like the second list to be different based upon what is selected from the first list. So FREX Blacksburg's might be:
<select name="room">
<option value="Kitchen">Kitchen Side</option>
<option value="Closet">Closet Side</option>
<option value="Full">Full Room</option>
</select
While Christiansburg's is:
<select name="room">
<option value="Window">Window Side</option>
<option value="Door">Door Side</option>
<option value="Full">Full Room</option>
and of course the options are also different for the other branches...
Is it possible to change the second drop down list based on what they select for the first one? I have used JavaScript a teensy bit, but not much so please explain in detail.
Yes, this is called a drilldown.
What you want to do is attach an onChange handler to your first dropdown that will grab new values based on the selected value (of the first dropdown) and populate those values into the second dropdown.
I recommend doing this with jQuery. It will make the experience much more pleasant. That being said:
var optionsMap = {
b: {
Kitchen: "Kitchen Side",
Closet: "Closet Side",
Full: "Full Room"
},
c: {
Window: "Window Side",
Door: "Door Side",
Full: "Full Room"
},
...
};
jQuery("#firstSelect").change(function() {
/* "this" is a reference to firstSelect element. Wrapping jQuery(...)
around it turns it into a jQuery object. Then you get the value
of the selected element with .val() */
var $select = jQuery(this);
var value = $select.val();
/* I'm doing the following to illustrate a point; in some cases
you may have to get it from a database with an AJAX request.
Basically YMMV */
var newOptions = optionsMap[value];
/* remove all the old options */
jQuery("#secondSelect").find("option").remove();
/* Iterate over the hash that you got and create new option
objects that use the key of the hash as the option value
and the value of the hash as the option text */
jQuery.each(newOptions, function(option, value) {
jQuery("#secondSelect").append(
jQuery("<option></option>").attr("value", option)
.text(value)
);
});
});
First, these kind of DOM modifying actions are made much easier with jQuery. It abstracts a lot of browser-specific crap away from you, making it much easier to do your thing. However, since you didn't mention the jQuery, I'll address the JavaScript issues. This is completely possible with JavaScript.
Second, you're going to want to give all of your select elements ids. This will make it much easier for JavaScript to identify them. Ids must be unique. I'm just going to follow the convention of naming the id after the name of the element.
Third, what we do is listen for the JavaScript event onchange on the select element and then do something with it (note the id attributes).
<select id="branch" name="branch" onchange="handleChange();">
<option value="b">Blacksburg</option>
<option value="c">Christiansburg</option>
<option value="f">Floyd</option>
<option value="m">Meadowbrook</option>
</select>
<select id="room" name="room">
</select>
The above code assigns the event listener handleChange to the branch select element. When a change event is fired, handleChange will be called. Now let's define the handleChange function:
<script type="text/javascript">
var handleChange = function() {
// get a handle to the branch select element
var branch = document.getElementById('branch');
// get the index of the selected item
var index = branch.selectedIndex;
// handle displaying the correct second select element
if (index === 0) {
// if the index is 0 (the first option,) call the Blacksburg function
doBlacksburg();
// I'll leave this up to you ;)
} else if (index === 1) {
// more stuff
}
}
</script>
Now we'll define the function that updates the second select list with Blacksburg information:
var doBlacksburg = function() {
var blacksburg = document.getElementById('room');
blacksburg.options[0] = new Option("Kitchen Side", "Kitchen", true, false);
blacksburg.options[1] = new Option("Closet Side", "Closet", false, false);
blacksburg.options[2] = new Option("Full Room", "Full", false, false);
}
That will update the second select list with the Blacksburg options. Reference for the JavaScript Option object.
That code is by no means extensive, but it should be enough to get you started. Like I said earlier, all of the above code can be done in as few as 5 lines of jQuery and it might be worth your time to look into jQuery or a similar library.
Are you familiar with / comfortable using a library like jQuery? I'd approach it with something like this:
var roomOpts = {
b: [
'<option value="Kitchen">Kitchen Side</option>',
'<option value="Closet">Closet Side</option>',
'<option value="Full">Full Room</option>'
]
....
};
$('select[name=branch]').change(function () {
$('select[name=room']).html(roomOpts[$(this).val()].join(''));
});
You can use an onchange event handler on the first list that calls a function to change the other list(s).
Look at this one:
http://www.webdeveloper.com/forum/showthread.php?t=97765