javascript selected options function not working in IE and safari - javascript

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.

Related

How to dynamically create a dependent select list using one recursive function in pure javascript?

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.

JavaScript remove string from list on click if already exist

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>

select multiselect option limit up to 2

I am using multiselect for different subject's I want to limit the select up to 2 and make the other's disabled in the same way if user deselect, Again the option must be available for the user.
<select multiple="multiple" class="subjects" name="subjects[]" style="float:left;width:205px;" size="5">
<option value='1'>subject1</option>
<option value='2'>subject2</option>
<option value='3'>subject3</option>
<option value='3'>subject3</option>
</select>
So far I have achieved to deselect only the last option which was selected after 2 and the code is as follow
/**
* Make sure the subject's limit is 2
*/
$(".subjects option").click(function(e){
if ($(this).parent().val().length > 2) {
$(this).removeAttr("selected");
}
});
Thank you.
Improved jQuery example, notice the (else enable) option, this fixes a bug on previous examples that disabled the select options permanently. Also removed the "Please select only two options." error message when possible.
http://jsfiddle.net/c9CkG/25/
jQuery(document).ready(function () {
jQuery("select").on("change", function(){
var msg = $("#msg");
var count = 0;
for (var i = 0; i < this.options.length; i++)
{
var option = this.options[i];
option.selected ? count++ : null;
if (count > 2)
{
option.selected = false;
option.disabled = true;
msg.html("Please select only two options.");
}else{
option.disabled = false;
msg.html("");
}
}
});
});
As an improvment on RobG's answer, you could unselect an option if it makes count > 2.
See: http://jsfiddle.net/c9CkG/3/ for a working example using jQuery.
function checkSelected(el) {
var msgEl = document.getElementById('msg');
var count = 0;
for (var i=0, iLen=el.options.length; i<iLen; i++)
el.options[i].selected? count++ : null;
// Deselect the option.
if (count > 2) {
el.options[i].selected = false;
el.options[i].disabled = true;
msgEl.innerHTML = 'Please select only two options';
}
}
Something like the following will do the job:
function checkSelected(el) {
var msgEl = document.getElementById('msg');
var count = 0;
for (var i=0, iLen=el.options.length; i<iLen; i++)
el.options[i].selected? count++ : null;
msgEl.innerHTML = count > 2? 'Please select only two options' : '';
}
</script>
<span>Please select a maximum of two options:</span>
<select multiple onchange="checkSelected(this);">
<option>0
<option>1
<option>2
<option>3
</select>
<br>
<span id="msg"></span>
I don't think it's a good idea to disable options, you only care that only two are selected when the form is submitted. Until then, it doesn't matter.
$(document).ready(function() {
var last_valid_selection = null;
$('#testbox').change(function(event) {
if ($(this).val().length > 5) {
alert('You can only choose 5!');
$(this).val(last_valid_selection);
} else {
last_valid_selection = $(this).val();
}
});
});

Javascript Internet Explorer Issue - what am I doing wrong?

I've looked through many posts to no avail. I have the following in a simple form where one of the products changes based on the number of checkboxes checked. It works in every browser except IE. What am I doing wrong?
<body>
<script type="text/javascript">
function check(){
"use strict";
var count = 0, x=0, checkboxes=document.signup.getElementsByClassName("styled");
for(;x<checkboxes.length; x++){
if(checkboxes[x].checked){
count++;
}
}
if(count<3) {
document.getElementById("variable").value = "1";
}
else if (count == 3){
document.getElementById("variable").value = "74";
}
else if (count == 4){
document.getElementById("variable").value = "75";
}
else if (count == 5){
document.getElementById("variable").value = "76";
}
}
</script>
<form name="signup" id="signup" method="post" action="/subscribers/signup.php">
<input type="checkbox" id="variable" name="product_id[]" value="" class="styled"></input>product 1 - variable</div>
<input type="checkbox" id="same" name="product_id[]" value="3" class="styled"></input>product 2
<input type="checkbox" id="same2" name="product_id[]" value="2" class="styled"></input>product 3
<input type="checkbox" id="same3" name="product_id[]" value="4" class="styled"></input><div class="check-title">product 4
<input type="checkbox" id="same4" name="product_id[]" value="44" class="styled"></input><div class="check-title">product 5
Continue</td></tr>
</form>
</body>
All versions of IE prior to IE9 do not support getElementsByClassName(). You will need to use some sort of substitute.
Instead of this piece of your code:
checkboxes = document.signup.getElementsByClassName("styled");
I would suggest using this:
checkboxes = document.getElementById("signup").getElementsByTagName("input")
getElementsByTagName() is widely support in all versions of IE. This will obviously get all input tags, but only the checkboxes will have checked set so you should be OK.
If you need to filter by class, then you could do the whole thing this way:
function check() {
"use strict";
// initialize checkbox count to 0
var count = 0, item;
// get all input tags in the form
var inputs = document.getElementById("signup").getElementsByTagName("input");
// loop through all input tags in the form
for (var i = 0; i < inputs.length; i++) {
// get this one into the local variable item
item = inputs[i];
// if this input tag has the right classname and is checked, increment the count
if ((item.className.indexOf("styled") != -1) && item.checked) {
count++;
}
}
// get object for result
var obj = document.getElementById("variable");
// check count and set result based on the count
if(count < 3) {
obj.value = "1";
} else if (count == 3) {
obj.value = "74";
} else if (count == 4) {
obj.value = "75";
} else if (count == 5) {
obj.value = "76";
}
}
IE doesnt have method getElementsByClassName... you can try to define it:
if(document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(cl) {
var retnode = [];
var myclass = new RegExp('\\b'+cl+'\\b');
var elem = this.getElementsByTagName('*');
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) {
retnode.push(elem[i]);
}
}
return retnode;
}
};

Need help in adding selected items from selectbox to div (dynamic addition)

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;
}

Categories