Adding <optgroup> dynamically from javascript array - javascript

This may seem a cack-handed way of doing things, but I'm experimenting with this.
I have a list of UK counties, and a list of US states. When the user selects "UK" or "US" from the dropdown, it repopulates the second select list. (I DID get this to work by submitting the form each time the select options were changed, and rebuilding the HTML form ... but realised that was a somewhat server intensive mode, so now want to do it via Javascript)
I began by reading the text file into a javascript array, (actually, a PERL script reads the file, turns it into code, and then prints out the HTML) So I end up with:
var state_opt = new Array('1','2','3','4',' ...
var state_title = new Array('Alabama','Alaska','Arizona','Arkansas' ...
I then use a loop to load the second array:
for (x=0; x<state_opt.length; x++){
document.userChoice.c_s.options[x]=new Option(state_title[x],state_opt[x])
}
That works fine ... until I try the second array which features <optgroup></optgroup> The above loop automatically makes them into options!! Here are the arrays:
var county_opt = new Array('-','2','3','4', ...
var county_title = new Array('<optgroup label="England">','Bedfordshire','Berkshire','Bristol' ...
** Notice I have made the <optgroup> value into "-" so it can be distinguished. (When writing in PERL, this is the concept I used:
If ($county_opt[$x] eq "-"){
$option.=$county_title[$x];
}
else{
$option.="<option value=\"$county_opt[$x]\">$country_title[$x]";
}
And then write "<select>$option</select>
So what I'm seeking is code something like this:
for (x=0; x<county_opt.length; x++){
var str=county_title[x];
if (str.match(/optgroup/g)){
// ?? document.userChoice.c_s.options[x]=county_title[x];
// ie print the value as is without making it into an option
}
else{
document.userChoice.c_s.options[x]=new Option(county_title[x],county_opt[x])
}
}
Any SIMPLE ideas? If it can't be done, I'll just have to remove the labels

Hmmm ... that was a 'challenging' morning! The solution might be technically wrong in parts ... but it works.
I found a way to add the tags without making them into selectable options, but because they were not options, when changing to another option list, I could not remove these <optgroup> tags by using a loop that removed option elements!! (Does that make sense?)
Instead, the crude way I ended up doing it was to use innerHTML to set the text within the <select> form option to null. I then (incorrectly?) created a string built up with ≤optgroup><option> tags and values, and used innerHTML to replace it again
The "ind2" other option is the (correct) way to replace all option fields.
Hope this helps someone.
Incidentally, you'll also notice the "Not Available" have values of "-". Quite simply, if the user selects this option, an error trap routine sees these values, and simply returns to the form with a false value.
function checkCountry(){
document.userChoice.c_s.innerHTML=''
var ind=document.userChoice.countryChoice.selectedIndex;
// set 1 for UK, 2 for US
//'Please select a Country' has an option value of '0'
if (ind == 0){ // resets 2nd / 3rd option list if don't select US or UK
document.userChoice.c_s.options[0]=new Option("NOT AVAILABLE","-");
document.userChoice.service.options[0]=new Option("NOT AVAILABLE","-");
}
if (ind == 1){
var t='<option value="-">Please select a County</option>';
for (x=0; x<county_opt.length; x++){
var str=county_opt[x];
if (str.match(/-/)){
t+=county_title[x]; // Sets the <optgroup> tag with no option value
}
else{
t+='<option value="'+county_opt[x]+'">'+county_title[x];
}
}
document.userChoice.c_s.innerHTML=t;
}
if (ind == 2){ // preferred method that won't remove <optgroup> from <select> area
document.userChoice.c_s.options[0]=new Option('Please select a State','-');
for (x=1; x<state_opt.length; x++){
document.userChoice.c_s.options[x]=new Option(state_title[x],state_opt[x])
}
}
}
</script>

Related

Error adding options to a select menu with javascript

I was having two problems: the first is that javascript is not adding options to a menu, and the second was an "Unexpected or invalid token" error at the end of my for loop.
Update:
The token error was a weird character thing. I deleted the line that was causing the problem and retyped it and now I am not getting the error anymore, but my script still is not adding options.
I have read about adding options to a select menu but the answers I've found there haven't worked for me. I should point out that this is part of a Joomla website (v3.8), because that can cause some unexpected behaviour.
I have a function which is supposed to pick out a particular select menu based on the string "id", clear its contents, and re-populate it with the elements of the "options" array.
function resetSelectMenu(id, options){
// Selects the correct menu, enables it, and removes all of its options.
var selectMenu = jQuery('#sel-' + id);
selectMenu.prop('disabled', false);
selectMenu.empty();
// Makes an option element and sets its text and value.
var el = document.createElement("option");
el.text = 'blah';
el.value = 'blah';
// Does not succeed in adding an option to menu.
selectMenu.add(el);
// I declared loop variables here to make sure there are no re-declaration issues.
var i;
var opt;
// The loop is entered and the array is iterated through.
for(i = 0; i < options.length; i++){
opt = options[i];
el = document.createElement("option");
el.text = opt;
el.value = i + 1;
// Does not succeed in adding an option to menu.
selectMenu.add(el);
}​
}
The function does target the correct menu and clear its contents, but it is not adding the "blah" option or anything from the "options" array. I've tried using "appendChild(el)" instead of add but I get an error of the form "appendChild() is not a function". I did a lot of console logs to determine that all the parts of the code are working as expected except for "selectMenu.add(el);"
So this was just a noob mistake. I looked a bit harder and found this related question, and the top answer by Matt told me I needed to use append(el) instead of add(el). I looked into the documentation and the add method just affects the jQuery object but doesn't actually affect the DOM at all, whereas append does. If I were to use add I would need to explicitly tell the jQuery object to refresh the DOM.
It's also possible that there is still an issue with me using selectMenu.empty() instead of something like selectMenu.find('option').remove(), but at the moment it's not causing any errors. Since my select element only contains option elements I feel like these two commands would be the same, but on the other hand maybe the latter is better because it allows for the addition of different kinds of elements later.

Select2 v4 .val() does not maintain order of elements in data object

I have a select2 (v4) select box where people are choosing codes, and the order must be maintained. This works great when they originally add the elements:
However, this is a popup that is used for many different elements on the page. That means I must clear this array and load it with stored data objects on the fly.
My data object preserves the order as var codeArray = ['7990', '268'].
But when I use:
$(element).val(codeArray).trigger("change")
I get the following:
How can I maintain the order on load? Is there a sneaky workaround?
Okay, the fix was pretty hacky, but I'll post what I have:
function rebuildForm(codeArray) {
clearFormContents();
$.each(codeArray, function(j,obj){
var found = false;
code_list.some(function(el){
if (el.value == obj) {
var str = (el.text).split(")");
$("element option[value=" + el.value + "]").remove();
$(element).append(new Option("(" + el.value + ")" + str[1] , obj));
found = true;
}
})
if (!found) {
$(element).append(new Option("(" + obj + ") Custom Tag" , obj));
}
$(element).val(codeArray).trigger("change");
}
Sorry if the above code doesn't work perfectly, I had to clean it up to remove some fluff and hide the client/project identity.
Basically, on the rebuild of the form, I clear the old form contents then loop through the array grabbing each value/object. Then, if the value exists in the original code list of options in the select2 element I delete the option and rebuild it. This appends it to the bottom of the element list so that the order is maintained in the box. I also add any free form text tags using the 'found' boolean.
Once the new list of options are created in the "correct" order, then I am able to add the values back into the select input DOM element and trigger the select2 change to build the tags.
This thread posted by #RohitS in the comments showed the concept: https://github.com/select2/select2/issues/3106
I just adapted it to my needs.

I need to throw a pop up box based on a selection from a dropdown box that meet a range of criteria

I am trying to throw a pop up box when a selection is made on a drop down box, and the selection meets a range of criteria. (The dropdown box is created from a coldfusion output query). I am new to Javascript so I don't know what I am doing wrong. My code is as follows...
function secondoccupantcheck(obj){
qtenantid = new Array(#ValueList(qRecurring.iTenant_ID)#);
qoccupancy = new Array(#ValueList(qRecurring.ioccupancyposition)#);
qdescription = new Array(#ValueList(qRecurring.cdescription)#);
for (i=0;i<=(qRecurring.length-1);i++){
if ((obj.value ==qtenantid[i]) && (qoccupancy[i] == 1) && (qdescription[i].indexOf("Second Resident")>=0))
{
alert('Resident will be second occupant and occupancy will be zero');
break;
}
}
}
If an occupant in an assisted living house (iTenant_id) wants to move to another room and is currently the main tenant in his or room (iOccupancyposition =1). If he or she will be the second tenant in the room he or she wants to move to, I need to throw an alert box with a message. I can't seem to get it to work. Any help will be appreciated.
A few quick things:
I am assuming you have your JS code surrounded by a CFOUTPUT to
get actual values on client side.
Another assumption include number of values will be same in all
three fields viz. iTenant_ID, ioccupancyposition and
cdescription. If this is not the case or there are consecutive blank values then this logic will not work!
For qdescription you need to use quotedValueList() function
instead of valueList() otherwise browser will throw a JS error.
For the for loop the length should come from qtenantid.length
instead of qRecurring.length OR you need to change your code to: for (i=0;i<=(#qRecurring.recordCount#-1);i++){
Your JavaScrip function is using parameter as an obj and use only
one value out of this object. Why you are passing an object? Pass only the selected value and call is something like val and use it in if condition like: if ((val ==qtenantid[i]) && (qoccupancy[i] == 1) && (qdescription[i].indexOf("Second Resident")>=0))
There are more things that you can check for error handling. Hope this helps.

Using a html dropdown list to get the correct display text by value

I have some html that creates a dropdown list. The list has text values and text that is displayed to the user. I save some XML based on the “values” the user selects. At some other point in time I need to parse the XML and display the original text but not in the original list. At this point I only have the “value” from the list and not its display text. At first I was going to use a switch statement to get the display text but then had the idea of using the information that is held in the list. Is it possible to use a bit of javascript to use the value I have to look-up the display version on the list? If so, can someone supply a code snippet? I’ve tried different ways but so far drawn a blank. Shown below is a sample of the html that makes up the list.
'<select id="ifmgr_tr_Field">' +
'<option value="DeviceId">Device ID</option>' +
'<option value="DeviceMac">Device MAC</option>' +
'<option value="DeviceType">Device Type</option' +
'</select>';
Let’s say I have a value of “DeviceMac”, what I want from this list is “Device MAC”. Remember that I don’t want to use the list to display the value at this point.
EDIT
I could do this but it feels a bit dirty.
var item = $('#ifmgr_tr_Field')[0] ;
item.value = field; // field would be the value I have, EG “DeviceMac”
var text = item.options[item.selectedIndex].text; // This will give me “Device MAC” which is what I want.
I hope this might help. Well it still has a if condition. But as you said the value in the ListBox does not change. It uses list as a look-up and finds the option where the Text of option is "Device MAC" for example. emm... well i used jQuery cause it have a better loop(each) function than traditional javascript.
$('#ifmgr_tr_Field option').each(function () {
var option = this;
if(option.text == 'Device MAC')
alert(option.text + " Value : " + option.value);
});
I'm not sure EXACTLY what you want to do in the JS function, but you'll need to add the onchange attribute to your select item. It will need to point to your JS function, and pass the value when changed.
'<select onchange="doTheFunction(this.value);" id="ifmgr_tr_Field">' + ...
Then in your JS Code:
function doTheFunction(val){
//val will hold the newly selcted value
if (val=="DeviceId"){
//do something for DeviceId
} else if (val=="DeviceMac"){
//do something for DeviceMac
} else if (val=="DeviceType"){
//do something for DeviceType
}
}

How to avoid javascript retrieving values from non-existing elements

Update: clarified question (I hope)
Hi.
I'm developing a plugin in Wordpress and I'm outputting elements according to user privileges A and B.
In case of A, I ouput element "Foo".
In case of B, I output element "Bar".
Up till now, I haven't checked if an element exists before I try to retrieve the value.
This of course gives me a javascript error in some browsers (like IE7).
I've looked at using the typeof() function:
if(typeof(element) == 'undefined') {
//do something...
}
I'm also using jQuery. So one solution could be using this:
if ($("#mydiv").length > 0){
// do something here
}
Using the above methods, makes me having to check each element before trying to retrieve any values.
The "ideal" solution would be to get values based on user privileges. E.g:
if (userPriv == A) {
//get values from element 'Foo'
}
This way I can check once, and do the data gathering. The only solutions I can think of are setting the value of a hidden input element or use cookies.
<input type="hidden" id="userPriv" value="A" />
The other solution would be adding a value to the cookie.
setcookie("userPriv", "A");
Unfortunately, this last option gives me a warning message saying that cookie must be set in header (before html output). I think it's because I'm doing this in Wordpress.
I'm looking for opinions on which method is "the best way" to accomplis this.
Forgive me if I'm missing something, but checking for a DOM element in javascript is usually pretty easy.
var elementA = document.getElementById('id_of_a');
var elementB = document.getElementById('id_of_b');
if (elementA) {
//...
} else if (elementB) {
//...
}
The key is the if statement. getElementById will return nothing null if the element is not found, which will evaluate to false in the if statement.
Alternatively, if you don't really want to check for existence of individual DOM elements, can you send the users priv in a hidden input and act on that? That's a cookie free way of sending values clientside. Something like (edited to have jQuery code instead)
<input type="hidden" id="userPriv" value="A" />
...
var priv = $('#userPriv').val();
if (priv == 'A') {
//...
}
I'd still recommend checking for individual elements over checking a hidden input. It seems cleaner to me, more along the unobtrusive lines
You can use object as associative array:
var map = new Object();
map[A.toString()] = new Foo();
map[B.toString()] = new Bar();
In that case is much simpler to check and you will avoid "spaghetti code".

Categories