I'm having issues with adding and removing items from my list on click. The removal function works only once.
HTML
<h1 id="show-list></h1>
<ul id="my-list>
<li data-itemname="C1">C1</li>
<li data-itemname="B23">B23</li>
<li data-itemname="D52">D54</li>
...
JS
$('#my-list').each(function() {
var $widget = $(this),
$itemname = $(this).attr('data-itemname'),
...
$widget.on('click', function() {
$currentlist = document.getElementById('show-list').innerHTML;
// create current list array
var str = $currentlist; // C1, B23, D54, etc
var array = str.split(',');
// convert item number to string
var itemtocheck = $itemname.toString(); // works OK
// check if value in array
var result = $.inArray(itemtocheck, array); // so far so good
if (result == 0) {
selecteditems = $currentlist.replace(itemtoremove+',', '');
$('#show-list').html(selecteditems); // Works only once
return false;
} else {
$('#show-list').append($itemname+','); // will add OK
return false;
}
});
...
Also I feel that this function can be simplified?
EDIT: Rewrote it
var $showList = $('#show-list');
$('#my-list').find('li').click(function () {
var $this = $(this);
var itemName = $this.data('itemname');
var showListText = $showList.text();
var showListItems = showListText.split(',');
var itemIndex = showListItems.indexOf(itemName);
if (itemIndex > -1) {
// remove item
showListItems.splice(itemIndex, 1);
} else {
// append item
showListItems.push(itemName);
}
showListText = showListItems.filter(function (a) { return !!a; }).join(',');
$showList.text(showListText);
});
jsfiddle
EDIT 3:
Just from a best practices stand point I prefix jQuery objects with $ and nothing else. I feel like it makes the code much more readable and allows you to give a variable a "type" so you always know what's what.
Is this what you are needing? I'd skip converting to an array first. Also, what's $itemname in your code?
<html>
<head>
<script>
function removeItemFromList(listName, itemName) {
var selectobject=document.getElementById(listName);
for (var i=0; i<selectobject.length; i++){
if (selectobject.options[i].value == itemName) {
selectobject.remove(i);
}
}
}
function addItemToList(listName, itemName, itemValue) {
var selectobject=document.getElementById(listName);
var found = false;
for (var i=0; i<selectobject.length; i++){
if (selectobject.options[i].value == itemValue) {
found = true;
// already in list, don't re-add
break;
}
}
if (!found) {
var option = document.createElement("option");
option.text = itemName;
option.value = itemValue;
selectobject.add(option);
}
}
</script>
</head>
<body>
<select id="show-list">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<br/>
<input type="button" value="remove volvo" onclick="removeItemFromList('show-list', 'volvo');" />
<input type="button" value="remove saab" onclick="removeItemFromList('show-list', 'saab');" />
<input type="button" value="add delorean" onclick="addItemToList('show-list', 'DeLorean', 'delorean');" />
</body>
</html>
Related
I need to add a new select option in my HTML when they click it
<select class="statusButtonChange statusButton " data-value="49506">
<option value="0" selected=""></option>
<option value="1">Close</option>
<option value="2" disabled="" style="color:grey;">Taken</option>
</select>
This new option is dynamic and will be coming from an API response... I'm parsing the var value from the API response but for now, I made it static just to test.
Right now, I have this:
$(document).ready(function () {
var k = 1
$(".statusButton").on('focus', function () {
var value = "Disable";
var new_v = "";
var html = $(".statusButton").html();
if (k == 1) {
if (value == "Disable") {
new_v = "<option value='Disable' >Disable</option>";
}
else if (value == "Enable") {
new_v = "<option value='Enable' >Enable</option>"
}
var full = html + "" + new_v;
$(".statusButton").html(full);
k = 2;
}
});
});
It is working on JSFiddle but when I try to integrate it on my website, it's not reading it, even just the console log. WHat am I doing wrong?
I'm not sure exactly what's wrong, but I think a better approach might be to use jQuery's append method (https://api.jquery.com/append/).
Consider:
...
$(".statusButton").on('focus', function () {
var value = "Disable";
var new_v = "";
var $statusButton = $(".statusButton");
if(k == 1){
if(value == "Disable")
{
$statusButton.append("<option value='Disable' >Disable</option>");
}
else if(value == "Enable")
{
$statusButton.append("<option value='Enable' >Enable</option>")
}
...
If you do things that way, you don't have to mess around with any extra .html calls.
This is short answer without creating too many variable.
$(document).ready(function() {
var k = 1
$(".statusButton").on('focus', function() {
var value = "Disable";
if (k == 1) {
if (value == "Disable") {
$(".statusButton").append("<option value='Disable' >Disable</option>");
} else if (value == "Enable") {
$(".statusButton").append("<option value='Enable' >Enable</option>")
}
k = 2;
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="statusButtonChange statusButton " data-value="49506">
<option value="0" selected=""></option>
<option value="1">Close</option>
<option value="2" disabled="" style="color:grey;">Taken</option>
</select>
The following image shows the list structure that needs to be created. Using a recursive function it could be reused for n number of options. How can it be done?
Here is my Javascript code and below the HTML that I wrote:
var gender = ['male', 'female'];
var male = {
hair: ["Facial hair preferred?","Hair","No Hair"],
complexion: ["Preferred Complexion?","Pale","Dark"],
build: ["Build Type?","Strong","Weak"]
}
//Female Object
var female = {
hair: ["Hair Color?","Blonde","Brunette"],
height: ["Preferred Height?","Tall","Short"],
eyes: ["Preferred Eyes?","Green","Blue"]
}
function build(sel){
var selValue = sel;
if(selValue == gender[0]){
//console.log('male');
var sEle = document.createElement('select');
document.getElementsByTagName('body')[0].appendChild(sEle);
for(var i=0; i<male.hair.length; ++i){
var oEle = document.createElement('option');
if(i == 0){
oEle.setAttribute('disabled','disabled');
oEle.setAttribute('selected','selected');
}
var optionText = document.createTextNode(male.hair[i]);
oEle.appendChild(optionText);
document.getElementsByTagName('select')[1].appendChild(oEle);
}
}else{
//console.log('female');
var sEle = document.createElement('select');
document.getElementsByTagName('body')[0].appendChild(sEle);
for(var i=0; i<female.hair.length; ++i){
var oEle = document.createElement('option');
if(i == 0){
oEle.setAttribute('disabled','disabled');
oEle.setAttribute('selected','selected');
}
var optionText = document.createTextNode(female.hair[i]);
oEle.appendChild(optionText);
document.getElementsByTagName('select')[1].appendChild(oEle);
}
}
}
<body>
<h4>Select Sex </h4>
<select name="sel1" id="sel1" onchange="build(this.value)">
<option value="" selected disabled>Select Sex</option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</body>
However I am stuck and unable to create any more. Moreover I am not able to create a recursive function that I can reuse for any data.
You can create an object with tree hierarchy like this:
function Node(msg, treeChildNodes)
{
var _node = this;
this.msg = msg;
this.treeChildNodes = treeChildNodes;
this.completed = function() {
console.log(this.value);
this.disabled = true;
if (_node.treeChildNodes[this.value])
_node.treeChildNodes[this.value].renderTo(_node.container);
else
{
console.log('the leaf! end test');
$("<button/>").text('Finish test').appendTo(_node.container);
}
};
this.renderTo = function(container) {
_node.container = container;
$("<p/>").text(_node.msg).appendTo(container);
var $select = $("<select/>").appendTo(container).change(this.completed);
$("<option/>").text("Not selected...").appendTo($select);
for (var childKey in this.treeChildNodes)
{
$("<option/>").text(childKey).appendTo($select);
}
};
}
var tree = new Node('Men or Women?', {
'M': new Node('Facial hair?', {
'Hair': new Node('Complexion', {
'D': null,
'L': null
}),
'No Hair': new Node('Build', {
'B': null,
'S': null
})
})
});
tree.renderTo('body');
select {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Note that I haven't implemented women side of this tree, it is just an example, you can easily do it yourself :)
By the way, with this approach, your tree should not actually be a tree. For example, your test questions can split once, and then flock back into a single branch.
I need to create a menu of regions hat display two lists: a <select> for the region and another <select> for the available municipalities of that region. For this, I have a <form> and I update the municipalities through JavaScript. I have problems assigning the municipalities as <option>s of the second <select>. The option matrix of the menu doesn't accept the assignment of the values.
Here's the code.
HTML.
<html>
<head>
<title>
Página menú principal.
</title>
<?!= incluirArchivo('ArchivoJS'); ?>
</head>
<body onLoad = "preparar();">
<form id="formularioConductor" name="formularioConductor" method="post" enctype="multipart/form-data" autocomplete = "on">
<select name="menuDepartamento" id="menuDepartamento" tabindex="2" accesskey="e" onChange="municipiosDepartamento();">
<option value="x" selected="selected">ELIJA UN DEPARTAMENTO</option>
<option value="0">Antioquia</option>
<option value="1">Atlántico</option>
</select>
<select name="menuMunicipios" id="menuMunicipios" tabindex="3" disabled>
<option value=0>TODOS LOS MUNICIPIOS</option>
</select>
</form>
</body>
</html>
Javascript code:
<script lenguage="javascript">
function preparar() {
document.forms[0].elements.numeroLicencia.focus();
document.forms[0].elements.nombreConductor.disabled = true;
document.forms[0].elements.botonEnviar.disabled = true;
document.forms[0].elements.botonActualizar.disabled = true;
}
function municipiosDepartamento() {
var arregloMunicipiosDepartamento = new Array();
var posicionMunicipio = document.forms[0].elements.menuDepartamento.value;
arregloMunicipiosDepartamento = municipiosColombia(posicionMunicipio);
if(document.forms[0].elements.menuMunicipios.options.length > 1){
var totalMunicipios = document.forms[0].elements.menuMunicipios.length;
for (var i = 1; i < totalMunicipios; i ++){
document.forms[0].elements.menuMunicipios.options[1] = null;
}
}
if(document.forms[0].elements.menuDepartamento.value === "x"){
document.forms[0].elements.menuMunicipios.selectedItem = 0;
document.forms[0].elements.menuMunicipios.disabled = true;
}
else
{
document.forms[0].elements.menuMunicipios.options.length = arregloMunicipiosDepartamento.length;
for (var i = 0; i < arregloMunicipiosDepartamento.length; i ++) {
var opcionTemporal = new Option(arregloMunicipiosDepartamento[i], (i+1));
***document.forms[0].elements.menuMunicipios.options[i+1].text = opcionTemporal.text;
document.forms[0].elements.menuMunicipios.options[i+1].value = opcionTemporal.value;***
}
document.forms[0].elements.menuMunicipios.disabled = false;
}
}
function municipiosColombia(posicion) {
var antioquia, atlantico, arregloTodos, arregloMunicipiosDepartamento = new Array();
antioquia=["Medellín","Abejorral","Abriaqui","Alejandria"];
atlantico = ["Barranquilla","Baranoa","Campo De La Cruz","Candelaria"];
arregloTodos = [antioquia, atlantico];
arregloMunicipiosDepartamento=arregloTodos[posicion];
return arregloMunicipiosDepartamento;
}
</script>
I have highlighted the work that doesn't work.
The way I would do what you describe is to clear out the options each time and recreate the required ones, then add them into the particular select, like so:
var regions = {};
regions['A'] = ['mu', 'ni', 'ci', 'pal', 'it', 'y'];
regions['B'] = ['I', 'like', 'bananas'];
var selRegion = document.getElementById('region');
selRegion.onchange = setMunicipalities;
var selMun = document.getElementById('municipality');
function setMunicipalities(e)
{
while(selMun.length > 0)
{
selMun.remove(0);
}
if(selRegion.selectedOptions[0].value === 'ALL')
{
for(var r in regions)
{
if(regions.hasOwnProperty(r))
{
addMunicipalities(regions[r]);
}
}
}
else
{
var reg = selRegion.selectedOptions[0].value;
addMunicipalities(regions[reg]);
}
}
function addMunicipalities(region)
{
var allMun = document.createElement('option');
allMun.setAttribute('value', 'ALL');
var allMunText = document.createTextNode('ALL');
allMun.appendChild(allMunText);
selMun.add(allMun);
for (var mi = 0; mi < region.length; mi++)
{
var m = region[mi];
var mun = document.createElement('option');
mun.setAttribute('value', m);
var munText = document.createTextNode(m);
mun.appendChild(munText);
selMun.add(mun);
}
}
setMunicipalities(null);
<label for="region">Region</label>
<select id="region">
<option selected="selected" value="ALL">ALL</option>
<option value="A">A</option>
<option value="B">B</option>
</select>
<label for="municipality">Municipality</label>
<select id="municipality">
</select>
I haven't read your entire code because I had a hard time reading code with contents not in English but anyway, I get what you're trying to do here. Suppose that your first select list contains "Region A" and "Region B" as options; "Municipality A1", "Municipality A2", "Municipality B1","Municipality B2" are the possible options for the second select list. Here's a function that will change the options of the second select list depending on what is selected on the first select list:
function optionChanger(v_selected){
var whatisselected= v_selected.options[v_selected.selectedIndex].value;
var municipalities= {};
municipalities['A'] = ['Municipality A1','Municipality A2'];
municipalities['B'] = ['Municipality B1','Municipality B2'];
v_selected.options.length=0; //remove the contents of the second select list
v_selected.options[0] = new Option(municipalities[whatisselected][0],municipalities[whatisselected][0],false,true);// set the first option of the second list as the default selected value
for(x=1;x<municipalities[whatisselected].length;x++){ //add the remaining options to the second list
v_selected.options[x] = new Option(municipalities[whatisselected][x],municipalities[whatisselected][x],false,false);
}
}
Then add this inside the tag of your FIRST select list:
onchange='optionChanger(this)'
PS: Please notice that the return value of the first select list must be 'A', 'B'
Any help on this would be MUCH appreciated!
I am having a problem with this javascript code in IE and Safari only.
It works fine in other browser e.g firefox and chrome.
I believe in IE and Safari it's not cycling through all the select option values correctly. e.g. in firefox there are two values for p, however in safari only 1 value.
JAVASCRIPT
<script type="text/javascript">
function selected(val, val1)
{
var len = document.getElementById('attribute122').length;
var p;
for(p=0;p<len;p++)
{
if(document.getElementById('attribute122')[p].label == val1)
{
document.getElementById('attribute122').value = document.getElementById('attribute122')[p].value;
document.getElementById('att_'+val).className = 'active';
}
else
{
if(document.getElementById('attribute122')[p].label !="Choose an Option...")
{
var chalpeveere = document.getElementById('attribute122')[p].label;
// alert(chalpeveere);
chalpeveere = chalpeveere.replace('.','_');
// alert(chalpeveere);
document.getElementById('att_' + chalpeveere).className = 'none';
}
}
}
}
</script>
HTML
<div class="input-box">
<select id="attribute122" class="required-entry super-attribute-select" name="super_attribute[122]">
<option value="">Choose an Option...</option>
<option value="3" price="0">Medium</option>
</select>
</div>
<div class="Medium">
<a id="att_Medium" class="none" href="javascript:selected('Medium', 'Medium')"> </a>
</div>
Some comments:
function selected(val, val1) {
var len = document.getElementById('attribute122').length;
Much better to store a reference to the element. If it's a select element, its length is the number of options. It's clearer to write it that way:
var select = document.getElementById('attribute122');
var len = select.options.length;
But I wouldn't set len here, see below.
It's much more common to use i, j, k, etc. as loop counters and to initialise them in the for expression. It's common to set the limit here too:
for (var i=0, len=select.options.length; i<len; i++) {
if (select[p].label == val1) {
Again, while you can access the options as properties of the select element, it's clearer to access them via the options collection. Also, the label property is more commonly known as text, so:
if (select.options[i].text == val1) {
.
document.getElementById('attribute122').value = document.getElementById('attribute122')[p].value;
Setting the selected option by setting the value of the select element is also very new behaviour, it is far more common to set the option to selected:
select.selectedIndex = i;
or
select.options[i].selected = true;
.
document.getElementById('att_'+val).className = 'active';
}
else
{
if(document.getElementById('attribute122')[p].label !="Choose an Option...")
{
Pesumably that is the first option, so you can just test:
if (select.selectedIndex != 0) {
.
var chalpeveere = document.getElementById('attribute122')[p].label;
becomes:
var chalpeveere = select.optoins[i].text;
.
// alert(chalpeveere);
chalpeveere = chalpeveere.replace('.','_');
// alert(chalpeveere);
document.getElementById('att_' + chalpeveere).className = 'none';
}
}
}
}
So the tidied code becomes:
function selected(val, val1) {
var select = document.getElementById('attribute122');
var options = select.options;
for(var i=0, iLen=options.length; i<iLen; i++) {
if (options[i].text == val1) {
options[i].selected = true;
document.getElementById('att_'+val).className = 'active';
} else {
if (select.selectedIndex != 0) {
var chalpeveere = options[i].text;
// alert(chalpeveere);
chalpeveere = chalpeveere.replace('.','_');
// alert(chalpeveere);
document.getElementById('att_' + chalpeveere).className = 'none';
}
}
}
}
In the HTML:
<a id="att_Medium" class="none" href="javascript:selected('Medium', 'Medium')">foo</a>
If you want a button, use a button:
<button id="att_Medium" class="none" onclick="
selected('Medium', 'Medium')
">Set selected</button>
or use a style span.
I need to display the selected sub-categories (multi) in the below div and also in some situations I need to close the div elements that are selected wrongly from the select box, so that I can add and delete elements to the div (by the above selectbox).
Even I made the similar code, but its not working for multi selection.
Briefly, I need the selected categories (multi) with close buttons in the below div.
<script type="text/javascript">
function selectlist() {
checkboxhome = document.getElementById("check");
catogery = document.getElementById("cat");
value = catogery.options[catogery.selectedIndex].value;
checkboxhome.innerHTML = "<br/> <p>" + value + "</p>";
}
</script>
<body>
<form action="#" enctype="multipart/form-data">
<select name="cat" id="cat" onchange="selectlist();" multiple="multiple">
<option>Select subcatogery</option>
<option value="fashion">Fashion</option>
<option value="jewelry">Jewelry</option>
<option value="dresses">dresses</option>
<option value="shirts">Shirts</option>
<option value="diamonds">Diamonds</option>
</select>
<div id="check">
</div></form>
</body>
</html>
Loop over the options and check if they are selected, something like this:
function selectlist() {
var checkboxhome = document.getElementById("check");
var category = document.getElementById("cat");
checkboxhome.innerHTML = '';
for (var i = 0; i < category.options.length; i++) {
if (category[i].selected) {
checkboxhome.innerHTML += "<p>" + category.options[i].value + "</p>";
}
}
}
Here is a fiddle of what could work for you: http://jsfiddle.net/maniator/W6gnX/
Javascript:
function selectlist() {
checkboxhome = document.getElementById("check");
catogery = document.getElementById("cat");
value = getMultiple(catogery);
checkboxhome.innerHTML = "<br/> <p>" + value + "</p>";
}
function getMultiple(ob)
{
var arSelected = new Array(), length = ob.length, i = 0, indexes = [];
while (ob.selectedIndex != -1 && i < length)
{
if (ob.selectedIndex != 0 && !in_array(ob.selectedIndex, indexes)) {
indexes.push(ob.selectedIndex)
arSelected.push(ob.options[ob.selectedIndex].value);
}
ob.options[ob.selectedIndex].selected = false;
i++;
}
var count = 0;
while(count < indexes.length){
ob.options[indexes[count]].selected = true;
count ++;
}
return arSelected;
}
function in_array(needle, haystack)
{
for(var key in haystack)
{
if(needle === haystack[key])
{
return true;
}
}
return false;
}