JavaScript: add extra attribute after new Option() - javascript

I have a piece of code that dynamically adds options to a select field depending on some other criteria. It looks somewhat like this:
if (chosen == "a_value") {
selbox.options[selbox.options.length] = new Option('text_1','value_1');
selbox.options[selbox.options.length] = new Option('text_2','value_2');
selbox.options[selbox.options.length] = new Option('text_3','value_3');
}
What I need is to add an extra attribute to that new option that contains a specific value. In this case the attribute will be called "discount" and the value will be an integer. Later on I'll read the attribute values and process them based on the value in the Option field.
So an option will look like this, once the script is ready;
<option value="value_1" discount="integer">text_1</option>
Makes sense?
Now how can I do this without the use of JS frameworks. It's just this small part of code that I need, so a framework would be overkill for this project.
Cheers! :-)

you can do something like
var o1 = new Option("key","value");
selbox.options[selbox.options.length] = o1;
o1.setAttribute("key","value");

I know this is old but I came across this question when I forgot it's add and not push today.
The correct way is to use select.options.add.
var opt = document.createElement('option');
opt.value = 'hello';
opt.text = 'world';
opt.setAttribute('data-discount', 'integer');
selbox.options.add(opt);

You can combine this into one line of code:
(selbox.options[selbox.options.length] = new Option("key","value")).setAttribute("key","value");
Note that this will only work if you have just one attribute to add, otherwise you will need a temporary variable.

Related

Dynamic dictionary using Javascript from two sources

I'm new to JavaScript, and I think at this point I may have bit off more than I could chew. Essentially, I'm trying to make a dictionary (which will eventually be serialized to JSON, if that's relevant) that allows the user to define any number of entries and set both the key and value as they wish. I'm up for another implementation ideas, but this is how I've tried to solve it so far.
I have a button that calls the following code, which is mimicked exactly for newVariableDescription class. This creates the text input boxes on the web form.
var nameElement = document.createElement("input");
nameElement.type = "text";
nameElement.className = "newVariableName";
var nameDiv = document.createElement("div");
nameDiv.type = "div";
nameDiv.appendChild(nameElement);
var newVariableNamesDiv = document.getElementById("newVariableNamesDiv");
newVariableNamesDiv.appendChild(nameDiv);
var descriptionElement = document.createElement("input");
descriptionElement.type = "text";
descriptionElement.className = "newVariableDescription";
var descriptionDiv = document.createElement("div");
descriptionDiv.type = "div";
descriptionDiv.appendChild(descriptionElement);
var newVariableDescriptionsDiv = document.getElementById("newVariableDescriptionsDiv");
newVariableDescriptionsDiv.appendChild(descriptionDiv);
Now, this part works. I get all of the text boxes showing up just like I want, and can type into them. However, I can't figure out how to dynamically get access to this list AND pair them together.
This thread is very similar to what I want to do: dynamic dictionary using javascript
But I can't figure out how to get this code to do what I want:
var dictionary = {};
$('.newVariableName).each(function (index) {
dictionary['['+index+'].Key'] = $(this).val();
dictionary['['+index+'].Value'] = //access corresponding newVariableDescription here
});
I can obviously create a second loop with the other class (newVariableDescription), but that won't tie them together properly. I could store each of them in their own separate lists, and then combine those two lists into a dictionary, but I'm concerned about order remaining consistent and that's not an elegant solution.
Thanks in advance for any help.
If i understand right you want something like this with :eq selector
var dictionary = {};
$('.newVariableName').each(function (index) {
dictionary['['+index+'].Key'] = $(this).val();
dictionary['['+index+'].Value'] = $('.newVariableDescription:eq('+index+')').val();
});

Is it possible to link container to other one?

I have an array of data. I have put this data on my site in different places over different attributes, how innerHTML value placeholder etc.
Is it possible to link this values with the array from where I can take data? So that when I change the data in array, it going automatic changed on the site?
Also I try to show how I did it mean:
var test = Array();
test['place1'] = 'NY';
var myspan = document.createElement('span');
myspan.innerHTML = test['place1'];
On some event the value of test['place1'] is changed to 'LA', and at the same moment the value of myspan.innerHTML must be changed too.
Native JS only please.
This needs to be manually managed. A simple solution would be something like this:
function Place(container, initVal) {
this.container = container ? container : {};
this.set(initVal);
}
Place.prototype.place = "";
Place.prototype.get = function() {
return this.place;
}
Place.prototype.set = function(val) {
this.place = val;
this.container.innerHTML = val;
}
var test = {}; // object
test['place1'] = new Place(document.createElement('span'), "NY")
test['place1'].set('New Value');
This is not a full-feature solution, but gives you an idea of the coordination that needs to take place.
If you're only supporting modern browsers, then the syntax can be cleaned up a bit by using getters/setters.
In the future, you'll be able to use Proxy, which will make it even easier and cleaner.
There is no native way to bind an attribute of an HTML element to the values of an array, but you aren't actually using an array; you're using an object, and it is a simple matter to define special features on an object. For example:
First, define your object:
function boundArray(){
this._bindings = {};
this.setBinding = function(key,element){
this._bindings[key] = element;
};
this.setValue = function(key,value){
this[key] = value;
if(this._bindings[key]){
this._bindings[key].innerHTML = value;
}
}
}
Then use it in your code:
// create a new instance of the boundArray
var test = new boundArray();
// create the HTML element to use, and add it to the DOM
var myspan = document.createElement('span');
document.body.appendChild(myspan);
// bind the HTML element to the required key in the boundArray
test.setBinding('place1',myspan);
// Now every time you set that key on the boundArray (using setValue), it will also change the innerHTML field on the element
test.setValue('place1','NY');
// You can access your information from the boundArray in the usual ways:
var somevar = test.place1;
var anothervar = test['place1'];
What you are talking about is an MVVM solution. Most MVVM JavaScript solutions uses some object that represents an observable, which is a field within the object. When the value in the object changes, the observable lets the framework know to update the DOM. It also listens to the DOM for change events, and updates the object in reverse. For arrays, it's a similar process: it listens for adds or removes of the array, and updates the UI accordingly.
As #MCL points out in the comments on this post below, there is a way to watch changes to an object, and it isn't overly difficult to generically attach to an element on the DOM. However, There are a lot of good frameworks out there that make this REALLY easy, so that may be something to consider.

Why am I getting "undefined" when I call .options on my select box?

I am trying to follow this tutorial (http://railscasts.com/episodes/88-dynamic-select-menus) to get dynamic select boxes working with RoR. No need to worry about the RoR bit, this is a Javascript specific question.
Every time this function runs I get the error that the "options" is undefined. I've tried running the command manually in the console, but regardless, it spits out undefined. I have it typed exactly as I see it in the tutorial, but somehow it's not working for me...
Here's the javascript in question:
function clientSelected() {
var client_id = $('#piece_client_id').val();
// THIS IS THE PROBLEM LINE
var options = $('piece_campaign_id').options;
options.length = 0;
campaigns.each(function(campaign) {
if (campaign[0] == client_id) {
options[options.length] = new Option(campaign[1], campaign[2]);
}
});
if (options.length == 1) {
$('campaign_field').hide();
} else {
$('campaign_field').show();
}
}
Here is the HTML that it's trying to work on:
<select id="piece_campaign_id" name="piece[campaign_id]"><option value=""></option>
<option value="1">Feed The Dogs</option>
<option value="2">Watch Television</option>
<option value="3">End The Suffering</option>
<option value="4">Brian Bilbrey</option>
<option value="5">SummerHill Homes / Yes on A&B</option>
</select>
Thanks a bunch for taking a look! Let me know if there's anything else I can add to make my question more clear.
Try:
var options = $('#piece_campaign_id').get(0).options;
or
var options = $('#piece_campaign_id')[0].options;
As you were using a jQuery object, which doesn't have an options property. Also, make sure to include the id selector (#).
The following code in is not accurate.
var options = $('piece_campaign_id').options;
Should be
var options = $('#piece_campaign_id')[0].options;
You will notice two changes.
The addition of the # in the selector
The addition of the [0] after the jQuery object.
In jQuery to select an element by an ID you need to append # before the idvalue (which is similar to CSS. Here is some reference http://api.jquery.com/id-selector/
The next issue was you were trying to access a property that does not exist on a jQuery object. options is an HTML DOM property. Because of this you must access the DOM Object from inside the jQuery Object.
var options = $('#piece_campaign_id') //Returns jQuery Object
var options = $('#piece_campaign_id')[0] //Returns HTML DOM Object
//The line above will return the same as
var options = document.getElementById('piece_campaign_id')
NOTE
The following Selectors in your code are most likely inaccurate
$('campaign_field').hide();
...
$('campaign_field').show();
$('piece_campaign_id')
needs to be
$('#piece_campaign_id')

Javascript: give a variable a name made of 2 variables

I want to create a new variable in javascript but it's name should made of a stale part and a variable one like this:
tab_counter = 1;
var editor + tab_counter = blabla
well i want the new variable name to be in this case editor1, is this possible?
You cannot create a stand-alone variable name that way (except as a global) (edit or except with eval()), but you can create an object property:
var tab_counter = 1;
var someObject = {};
someObject['editor' + tab_counter] = "bla bla";
You can create globals as "window" properties like that, but you probably shouldn't because global variables make kittens cry.
(Now, if you're really just indexing by an increasing counter, you might consider just using an array.)
edit also see #Birey's somewhat disturbing but completely correct observation that you can use "eval()" to do what you want.
It is possible
var tab_counter=1;
eval("var editor"+tab_counter+"='blah'")
alert(editor1);
eval("var editor"+tab_counter+1+";")
editor2='blahblah';
alert(editor2);
http://jsfiddle.net/5ZLYe/
You can do the eval method used by Birey or you can create a custom property of an object such as...
obj[editor + tab_counter] = blabla;
But it sounds like you're going about doing whatever you're doing in a particularly horrible way. If you just want to store multiple items which you can index into use an array...
var array = [];
array[0] = blabla;
array[1] = blabla2;
alert(array[0]); //shows value of blabla
alert(array[1]); //shows value of blabla2
It seems like you may want to consider using a Dictionary for something like this. This link which references this link describes your options there.

problem with dynamicallly adding values to dropdown box

i want to dynamically add options to drop down boxes
var x =document.getElementById("c");
var optn = document.createElement("OPTION");
optn.text="hhh"
optn.value="val"
x.options.add(optn);
I am doing it inside a loop,with diff values of for val and hhh.Bur sometime i dont see any any values in drop down box , what may be the problem?
Try this one:
var objSelect = document.getElementById("subComponentOSID");
objSelect.options[objSelect.options.length] = new Option('1','1');
objSelect.options[objSelect.options.length] = new Option('2','2');
add is a method of HTMLSelectElement objects, not of HTMLCollection objects.
x.add(optn)
Assuming the element with the id "subComponentOSID", the only apparent issues in your javascript are missing semicolons on the lines where you assign values to optn.text and optn.value. Also, while most browsers will resolve what you mean when calling the add function on an options collection for a select element, you should move your add to the select itself. See the Mozilla reference for HTMLSelectElement, which provides an example.
In the meantime, try replacing the code snippet you provided with this:
var x =document.getElementById("subComponentOSID");
var optn = document.createElement("OPTION");
optn.text="hhh"; //Added semi-colon
optn.value="val"; //Added semi-colon
x.add(optn); // Moved add to HTMLSelectElement

Categories

Resources