I am projecting the selected value with innerHTML, I want to reset the innerHTML after each selected value
const body = document.body;
function dropdown(e) {
const select2 = document.querySelector(".select");
let selected = select2.options[select2.selectedIndex].value;
const div = document.createElement("div");
div.innerHTML = `<div>${selected}</div>`;
body.appendChild(div);
select2.options[select2.selectedIndex].value = "";
}
<select class="select" onchange="dropdown(event)">
<option>choose</option>
<option value="op1">Option 1</option>
<option value="op2">Option 2</option>
</select>
You can save the element to a variable and then remove it when the function is called again. (oldDiv in the example implementation below.)
<select class="select">
<option value="">choose</option>
<option value="op1">Option 1</option>
<option value="op2">Option 2</option>
</select>
<script>
let oldDiv = null // the newest created div will be stored here
document.querySelector(".select").addEventListener("change", function(event) { // this way of adding an event listener is preferable, as it allows you to add multiple listeners to the same element
if(oldDiv) oldDiv.remove() // remove the old div (if it exists)
const div = document.createElement("div") // create new div
div.textContent = event.target.value // set text content of new div to the selected value of the dropdown menu
document.body.append(div) // add new div to body
oldDiv = div // save new div in variable oldDiv, so it gets removed on next function call
})
</script>
Try adding the <div> in HTML instead of creating it everytime or you'll need to remove each one when a change event happens. When an element is removed or added to and from the DOM a reflow happens. A relow causes a broswer to recalculate position and distance of all content within the page. Changing an element that already exists on the page is less costly to browser processing. See this question on reflows and repaints. The example is a modified version of OP.
Do not use onevent attributes. Inline event handlers are garbage, so it's replaced by a onevent property handler, an .addEventListener() would be a better choice as well.
The event.target Event Object property is used to point to the changed element (ie .select), this would also work. No need to do a document.querySelector() inside of function.
🞲Added selected and disabled to first <option> popup as an actual value.
To get the current value of a <select> .value property will suffice.
The <div> is referenced with .nextElementSibling of .select and the text is overwritten by .textContent property.
Use .selectedIndex = "0"; to reset .select instead of .value="".
🞲 As per Oskar Grosser's comments below.
document.querySelector(".select").onchange = dropdown;
function dropdown(e) {
const sel = event.target;
let selected = sel.value;
const div = sel.nextElementSibling;
div.textContent = selected;
sel.selectedIndex = "0";
}
<select class="select">
<option selected disabled>choose</option>
<option value="op1">Option 1</option>
<option value="op2">Option 2</option>
</select>
<div></div>
Related
I have a select element where a user can select an option. I want to be able to duplicate that element WHILE retaining the user selected option for use elsewhere on the page. .clone() does not retain the selected option. Any suggestions?
IMPORTANT EDIT:
I'm asking: Is there a workaround for:
"Note: For performance reasons, the dynamic state of certain form elements (e.g., user data typed into textarea and user selections made to a select) is not copied to the cloned elements. When cloning input elements, the dynamic state of the element (e.g., user data typed into text inputs and user selections made to a checkbox) is retained in the cloned elements."
?
Minimum Reproducible Example:
Expected Behavior:
1. A user selects an option from the select#favorite-color element.
2. The user then clicks the button#clone-li element
3. I want a deep copy of the li.color-picker element to be appended as a child to the ul.last element, WHILE retaining the selected option inside the cloned select#favorite-color element.
<ul class="first">
<li class="color-picker">
<select name="favorite-color" id="favorite-color">
<option value="1">Blue</option>
<option value="2" class="red">Red</option>
<option value="3">Green</option>
</select>
</li>
</ul>
<ul class="last">
</ul>
<button type="button" id="clone-li">Clone Color Picker Li</button>
<script type="text/javascript"> $(document).ready(function() {
// ******************************** v INITIALIZE v ******************************** //
// Variables:
// DOM:
var color_picker_li = $('li.color-picker');
var favorite_color_select = $('select#favorite-color');
var last_ul = $('ul.last');
var clone_color_picker_li_button = $('button#clone-li')
// States:
// setTimeout(() => {
// $(favorite_color_select).find('option.red').prop('selected',true);
// setTimeout(() => {
// $(clone_color_picker_li_button).trigger('click');
// }, 3000);
// }, 1500);
// ******************************** ^ INITIALIZE ^ ******************************** //
// ********************************** v EVENTS v ********************************** //
// Handle a CLICK on the Cloen Color Picker Li Button:
$(clone_color_picker_li_button).on('click', function() {
$(color_picker_li).clone().appendTo(last_ul);
});
// ********************************** ^ EVENTS ^ ********************************** //
}); </script>
Just set the value of the clone based on value selected in the original
$('select.sel').change(function(){
const clone = $(this).clone().val(this.value);
$('#cont').append(clone);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="sel">
<option value="">--pick one --</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<div id="cont">
<h3>Clone</h3>
</div>
I have created a function to extend jQuery's built in ".clone()" function, to create a deep copy a set of matched elements with the dynamic state of all form elements copied to the cloned elements.
Here is a link to the repo: https://github.com/blackirishmec/jq-deepest-copy
Using this function in place of .clone() has solved my question.
I'm trying to change an element through a select drop down menu- however, I'm unable to get it to change dynamically.
<select id="optMapList">
<option>Map 1</option>
<option>Map 2</option>
</select>
<script>
document.getElementById("maptype").innerHTML=optMapList.options[optMapList.selectedIndex].text
</script>
Your code seems to run fine. I think you're missing the fact that you have to listen to a 'change'-event in order to by able to run code on changes. This is done as follows:
var optMapList = document.getElementById('optMapList');
optMapList.onchange = function() {
document.getElementById("maptype").innerHTML = optMapList.options[optMapList.selectedIndex].text;
}
Working example: http://jsfiddle.net/thijs_s/gx9mf1ct/
You can just use the value property of the select list inside an event listener as noted below.
var optMapList = document.getElementById('optMapList');
optMapList.onchange = function() {
document.getElementById("maptype").innerHTML = optMapList.value;}
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()
In this site, for example, there are 3 SELECT elements (Step 1, Step 2 and Step 3). I'm able to change the value of the first one with selectElement.value = selectElement.options[i].value;, but when I change it the Step 2 doesn't update it's options as it would if I would select it with the mouse. Is there any way to force it to update?
The best way to do this is to have a function that updates the contents of the second select box, and call that function when you update the value of the first one. You'd then have a change handler (or a click handler, or a timer; depends on what you prefer for a UX) on the first select box that calls that function when its value changes. E.g. (in near-pseudocode):
<select id="box1">...</select>
<select id="box2">...</select>
<select id="box3">...</select>
function setValueInBox1(val) {
var box1 = document.getElementById("box1");
box1.value = val;
fillBox2();
}
document.getElementById("box1").addEventListener("change", fillBox2);
So both the event and your logic call the same routine, fillBox2. Live example:
function setValueInBox1(val) {
var box1 = document.getElementById("box1");
box1.value = val;
fillBox2();
}
document.getElementById("box1").addEventListener("change", fillBox2);
function fillBox2() {
var box1Value = document.getElementById("box1").value;
var box2 = document.getElementById("box2");
box2.options.length = 0;
for (var n = 0; n < 3; ++n) {
box2.options[box2.options.length] = new Option(box1Value + " - sub " + n);
}
}
select {
min-width: 8em;
}
<select id="box1" size="3">
<option>a</option>
<option>b</option>
<option>c</option>
</select>
<select id="box2" size="3">
<option>none - sub 1</option>
<option>none - sub 2</option>
<option>none - sub 3</option>
</select>
<select id="box3"></select>
People routinely try to trigger the actual event handler of box1 (the change event in the above), but that can be difficult and error-prone. By having a common function that both the event handler and your logic can call, you avoid that issue.
If for whatever reason the above is impossible, if you're doing it specifically in IE and not worrying about cross-browser behavior (from your comment), you might look at the fireEvent method. For other browsers, you might look at the DOM dispatchEvent method.
Well , you could always invoke the method like
document.getElementById('x').onchange();
, where 'x' is the id of the select element
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