Troubles appending options to select in jquery - javascript

I have some <select> that needs to be populated with dynamic values, coming from an array. My code is pretty simple, the HTML is made by just some empty HTML <select> with the same class (.js-select).
The JS is quite simple:
var $select = $(".js-select");
var ioSensors = [1,2,3]; // The data I want to display in the select
var $optionTpl = $("<option></option>");
for( i=0 ; i<ioSensors.length ; i++ ){
//also show a leading "None" option
if(i === 0){
$optionTpl.attr('value','').text('None').appendTo($select);
}
$optionTpl.attr('value', ioSensors[i]-1).text(ioSensors[i]).appendTo($select);
}
With this code I'm having all my <select> correctly updated, but the last one is populated only with the last value of the Array, not showing even the "None" option.
Can anyone help me understand where the problem is and why is it behaving like that? Thanks!
I've made a pen Here

var $optionTpl = $("<option></option>"); creates an element once, then inside the loop you just keep moving that same element and just giving it a new value.
Create multiple elements inside the loop instead
var $select = $(".js-select");
var ioSensors = [1,2,3];
for( var i = 0; i < ioSensors.length; i++ ){
var $optionTpl = $("<option></option>");
if(i === 0){
$optionTpl.val('').text('None').appendTo($select);
}
$optionTpl.val(ioSensors[i]-1).text(ioSensors[i]).appendTo($select);
}

As others have already suggested, the reason it doesn't work is because you create a single element and keep moving it around. Move the creation of the element inside the loop, for example as follows:
var $select = $(".js-select");
var ioSensors = [1,2,3]; // The data I want to display in the select
for( i=0 ; i<ioSensors.length ; i++ ){
//also show a leading "None" option
if(i === 0){
$("<option></option>").attr('value','').text('None').appendTo($select);
}
$("<option></option>").attr('value', ioSensors[i]-1).text(ioSensors[i]).appendTo($select);
}
If you're wondering why your code seem to work for all the <select>s beside the last, according to the documentation when the target of an append is more than one element, jquery will clone the element for the first N-1 targets, and just move the element for the last:
If an element selected this way is inserted into a single
location elsewhere in the DOM, it will be moved into the
target (not cloned):
...
Important: If there is more than one target element, however,
cloned copies of the inserted element will be created for each
target except for the last one.

You need to clone the element to have multiple elements
var $select = $(".js-select");
var ioSensors = [1, 2, 3]; // The data I want to display in the select
var $optionTpl = $("<option></option>");
for (i = 0; i < ioSensors.length; i++) {
//also show a leading "None" option
if (i === 0) {
$optionTpl.clone().val('').text('None').appendTo($select);
}
$optionTpl.clone().val(ioSensors[i] - 1).text(ioSensors[i]).appendTo($select);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="js-select"></select>
You can also write the same like
var $select = $(".js-select");
var ioSensors = [1, 2, 3]; // The data I want to display in the select
var $optionTpl = $("<option></option>");
$("<option />", {
value: '',
text: 'None'
}).appendTo($select);
ioSensors.forEach(function(item) {
$("<option />", {
value: item - 1,
text: item
}).appendTo($select);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="js-select"></select>

Here is a simple solution (pen of the solution):
var ioSensors = [1,2,3];
$(".js-select").each(function(){
for(var i=0;i<ioSensors.length;i++) {
if(i === 0){
$("<option value=\"\">None</option>").appendTo($(this));
}
$("<option value=\"" + ioSensors[i] + "\">" + ioSensors[i] + "</option>").appendTo($(this));
}
});

Related

jQuery after ul list .remove() won't fill list again

When the page is loaded, there are 3 lists. First containing an active list and second and third are blank. When clicked on the active list li the second list (ul) is filled with one li element, the filling process continues to the third list automatically (on mouse click). Then when the button delete is pressed, both lists get removed and the process is supposed to work the same as described, but the second list for some reason doesn't get filled and everything goes to the third list.
I have tried methods: remove(), empty(), detach() but none of them seem to work.
Also in if statement I tried to check if (typeof ul.lenght === "undefined") but even this is not working.
Also to mention in console.log() when cheking ul.lenght property first time it returns 0 and undefined and fill the second list but after delete button is pressed it returns same value but won't fill the list.
Here is the code:
function myf() {
var orig = $("#ori li").length;
if ($("#ori li").length === 0 || typeof orig === "undefined") {
$(document).on('click', '#orglis li', function() {
$(this).remove();
$("#ori").append(this);
});
} else {
$(document).on('click', '#orglis li', function() {
$(this).remove();
$("#zam").append(this);
var lio = document.getElementById("ori").getElementsByTagName("li");
var larr = lio[0].innerText;
var arr = Array.from(document.querySelectorAll('#c>ul>li'), li => (li.textContent));
var tekst = "";
var i;
var j;
for (j = 0; j < arr.length; j++) {
arr[j] = arr[j].trim();
}
for (i = arr.length - 1; i >= 0; i--) {
tekst += larr + ", " + arr[i] + '\n';
}
document.getElementById("tare").innerHTML = tekst;
document.getElementById("imep").value = larr;
});
}
}
Here you can see demo.
EDIT: Also tried with outerHTML to set ul as before but still won't work
#freedomn-m was right about mixing onclick= and $(document).on("click" and I noticed that I had, without reason, two same functions

Looping out barcode divs

I am trying to loop through an array using barcode.js to then create a printable div. I need to have spacing in to make it a certain number per page (found under req.user.perpage)
My JS function to get the IDs and the loop out the divs
getSelected = function(){
var array = [];
$('.my_table tbody tr').each(function(index, object){
if($(this).find('input[type="checkbox"]').prop("checked"))
array.push($(this).find('.id').attr("name"));
});
var test = 'barcode';
// var test = document.getElementById("test123").innerHTML;
var codeType = document.getElementById("codeType").innerHTML;
console.log(test);
console.log(codeType);
for (i = 0; i < array.length; i++) {
var value = array[i];
$('#target').append('<img id="barcode"/>')
$('#barcode').JsBarcode(value, {format: codeType}, {width: 2, height: 90});
console.log(array[i]);
}
// window.print();
};
I can get it to output only one barcode but not multiple. I have 2 check boxes on the page that work and give the ids I need them to. I can't seem to get them to all show up though.
My HTML
<div id="target">
<!-- all divs will append here -->
</div>

HTML. Hide/Show a drop down menu depending on if an option is selected on another drop down menu

I am trying to have originally just one drop down menu when a website loads. Lets say that drop down menu only has two options "A" and "B". If the user selects option "A" I want another drop menu then to appear on the website (just below the original). If the user selects option "B" I want a different menu to appear below the original. I am also using PHP to make things even more complicated. Can anyone guide me on how I can accomplish this?
Modify the two dropdowns with attribute style="display:none". In your javascript function you would have an event registered that based on the SelectedIndex you would choose which dropdown element to remove the style="display:none" from.
This should do the work :
$("#drop").change(function() {
if( $('#drop option:selected').val() == "A") {
//Do what you want
}
else if ( $('#drop option:selected').val() == "B") {
//Do what you want
}
});
I don't know your level in js, if you need more explanations, please let me know.
Here's an example of manipulating the classes using native JavaScript. It could be cleaner, but it shows how you can check agains what classes exist in order to set CSS behaviour.
var cont = document.body.appendChild(document.createElement('div'));
cont.className = 'row';
for (var i = 0; i < 3; i++ ) {
var menuitem = cont.appendChild(document.createElement('div'));
menuitem.className = 'col';
var internal = menuitem.appendChild(document.createElement('div'));
internal.appendChild(document.createTextNode('item'+ (i + 1)));
(internal.attachEvent) ?
internal.attachEvent('onclick', function () {
for (var j = 0; j < cont.children.length; j++){
if (cont.children[j].className === 'col active') {
cont.children[j].className = 'col';
}
};
this.parentElement.className = 'col active';
}) :
internal.addEventListener('click', function () {
for (var j = 0; j < cont.children.length; j++){
if (cont.children[j].className === 'col active') {
cont.children[j].className = 'col';
}
};
this.parentElement.className = 'col active';
}, false);
};

Variable in getElementById

I need to go over all radio buttons of the form and paint the td that contain the checked ones.
Cant pass the variable of the TD id, in the loop (aca):
function veamos() {
var allElems = document.getElementsByTagName('input');
for (i = 0; i < allElems.length; i++) {
if (allElems[i].type === 'radio' && allElems[i].checked) {
var aca="pinta"+i;
document.getElementById(aca).style.backgroundcolor = '#9e0000';
} else {
//document.getElementById(estetd).style.backgroundColor = '#ffffff';
}
}
}
document.getElementById('pinta1').style.backgroundColor = '#9e0000', seems to work... cant build the variable to loop all form
Any ideas?
Thanks in advanced.
If i understand your question right I think you have 2 options.
function veamos () {
var allElems = document.getElementsByTagName('input');
for (var i = 0, len = allElems.length; i<len; i++) { /* do not use .length in the loop condition, that will have very bad performance on element arrays returned by getElementsByTagName. */
var elem = allElems[i];
if (elem.type==='radio') {
/* Option 1: This depends on the HTML structure, where is the TD in relation to the input? */
var td = elem.parentNode; /* if it is 2 levels up then use elem.parentNode.parentNode */
/* Option 2: This depends on having an ID on the <input> and <td> that are similar, like this <input id="r1"> <td id="r1TD"> */
var td = document.getElementById(elem.id + 'TD');
td.style.backgroundColor = elem.checked ? '#9e0000' : '#ffffff';
/* I would recommend using a class name (CSS) instead of using a hard coded color! */
}
}
}
You have a typo. Javascript is case sensitive. Change
document.getElementById(aca).style.backgroundcolor = '#9e0000';
to
document.getElementById(aca).style.backgroundColor = '#9e0000';
...
UPDATE See a working example
Instead
document.getElementById(aca).style.backgroundcolor = '#9e0000';
should be
allElems[i].style.backgroundcolor = '#9e0000';

javascript selected value

I have created function for creating a div, when u selet the value in dropdown box , based upon the length the number of divs will be created , so the code is
<select onchange="test()" id="selected_opt">
<option value="0" selected>-Select-</option>
<option value="1">Communication</option>
<option value="2">XXXXXXXXXXXXX</option>
</select>
the function test is
function test(){
var result = get_id.options[get_id.selectedIndex].value;
if(result == 1){
var i = 0,
c = model_details_json.communication,
j = c.length,
communications_div = document.getElementById("model_communication");
if(j == 0){
alert('nothing');
}
for (; i<j; i++){
var communication = c[i];
var create_div = document.createElement('div');
create_div.id = 'communication_id'+i;
create_div.name = 'communication';
var create_anchor = document.createElement('a');
create_anchor.innerHTML = communication.communication_name;
communications_div.appendChild(create_div);
document.getElementById(create_div.id).appendChild(create_anchor);
create_anchor.setAttribute("href", "javascript:void(0);");
create_anchor.setAttribute("onclick","sample('"+communication.communication_name+"','"+create_div.name+"')");
}
}
for example the length is 6 means the six number of divs will be created , so what the problem is when i again click on communication in select dropdown i.e already the six divs have been created , when do it again then agin six divs are created , so totally 12 divs created when u do it again it goes for 6 multiples.......
so what i need is the number of div would not be repeated. and it should be validate whether the user is clicking the same value in dropdown
Check this to remove div elements considering your parent div model_communication.
You need to implement logic by checking if the div exist and stop the loop when you get a message like 'Div is already removed' as shown in the example.
In order to do so create div elements along with id
var newdiv = document.createElement('div');
newdiv.setAttribute('id', id);
You need to remove all divs before create the new ones. Try adding a class name to it:
var create_div = document.createElement('div');
create_div.className = 'communication_div';
...
Now you can select the divs. Before the for statement add these lines to remove the divs with 'communication_div' class name:
var divs = document.getElementsByClassName('communication_div');
for(var i=0; i<divs.length; i++) {
divs[i].parentNode.removeChild(divs[i]);
}
Every script run will generate new divs and remove old ones.
use js map object to put selected value or length as key into the map then everytime user clicks a value, first check for its existence in the map. If not found in the map, that would mean length is not repeating and divs will be created.
something like:
var selectedValues = new Array();
.......
var result = get_id.options[get_id.selectedIndex].value;
if(selectedValues["val_"+result]) {
return;
}
selectedValues["val_"+result] = true;
you can check if the div is already created or present on page using getElementById('elementId') before creating it.
like in you code
for (; i<j; i++){
if(! document.getElementById('communication_id'+i)){ // do if element is not present on page
var communication = c[i];
var create_div = document.createElement('div');
create_div.id = 'communication_id'+i;
create_div.name = 'communication';
var create_anchor = document.createElement('a');
create_anchor.innerHTML = communication.communication_name;
communications_div.appendChild(create_div);
document.getElementById(create_div.id).appendChild(create_anchor);
create_anchor.setAttribute("href", "javascript:void(0);");
create_anchor.setAttribute("onclick",
"sample('"+communication.communication_name+"','"+create_div.name+"')");
}
}
Use replaceChild() instead of appendChild() on the Element object.

Categories

Resources