some jQuery/javascript help. Add items to optgroup - javascript

I have an array called tmp
var tmp = ["05", "13", "27"];
if an option value is equal to a value within tmp, I want to add that option to a particular optgroup, else add it to the other optgroup. I keep getting everything added to optgroup #2, except the option with the value "27". What am I doing incorrectly?
var groups = $("optgroup");
$("option").each(function() {
var value = $(this).val();
for (var x = 0; x < tmp.length; x++) {
var isMatch = (tmp[x] === value);
if (isMatch) {
$(this).appendTo($(groups[0]));
} else if (value.length > 0) {
$(this).appendTo($(groups[1]));
}
}
});
Thanks for any pointers to correct this.
~ck in San Diego

You should add a break after each appendTo statement so that you don't keep comparing the option to all tmp values.
var groups = $("optgroup");
$("option").each(function() {
var value = $(this).val();
for (var x = 0; x < tmp.length; x++) {
var isMatch = (tmp[x] === value);
if (isMatch) {
$(this).appendTo($(groups[0]));
break;
} else if (value.length > 0) {
$(this).appendTo($(groups[1]));
break;
}
}
});

Firstly,
$(this).appendTo($(groups[1]));
can be changed to
$(this).appendTo(groups[1]);
you don't need to wrap the element again into a jQuery object in order to append to it, a HTMLElement will work fine.
Do you have the HTML that you're using and where are your <option> elements that you are checking the value of?
EDIT:
I've rewritten your code slightly and this works correctly (N.B. appending won't work in IE6 and I believe 7 and 8 too - In IE the innerHTML property for a select element is readonly, so use createElement or the Option constructor to create options),
Working Example. add /edit to the URL to see the code. I have the option elements in an array in the working example, I assume that you have them in a similar structure.
var groups = $("optgroup");
$('options').each(function() {
var $this = $(this);
var val = $this.val();
if (tmp.indexOf(val) !== -1) {
$this.appendTo(groups[0]);
}
else if (val.length > 0) {
$this.appendTo(groups[1]);
}
});

Related

How can I remove options from Select list without affecting the index?

I am writing the following JavaScript which is going to remove some options from a select list:
var selectobject = document.getElementById("Approver_90afaad9-2b54-46fb-8ac1-7374e4efa11e_$DropDownChoice");
for (var i = 0; i < selectobject.options.length; i++) {
var isCM = false;
for (var ii = 0; ii < assets.length; ii++) {
if (assets[ii].Title == selectobject.options[i].value) {
isCM = true;
}
}
if (isCM == false) {
selectobject.remove(i);
}
}
but the problem I am facing is that is that when I remove an option using selectobject.remove(i); then i index inside the selectobject will be changed so is there a way to preserve the original index after the selectobject.remove(i);?? I tried to copy the selectobject inside a new var but still I faced the same issue...
Thanks
I have a workaround. May be you can use it. Instead of
selectobject.remove(i);
You can use :
selectobject.style.display = "none";
This will even preserve your original index.

Adding an option tag to existing select in JavaScript [duplicate]

I want this javascript to create options from 12 to 100 in a select with id="mainSelect", because I do not want to create all of the option tags manually. Can you give me some pointers? Thanks
function selectOptionCreate() {
var age = 88;
line = "";
for (var i = 0; i < 90; i++) {
line += "<option>";
line += age + i;
line += "</option>";
}
return line;
}
You could achieve this with a simple for loop:
var min = 12,
max = 100,
select = document.getElementById('selectElementId');
for (var i = min; i<=max; i++){
var opt = document.createElement('option');
opt.value = i;
opt.innerHTML = i;
select.appendChild(opt);
}
JS Fiddle demo.
JS Perf comparison of both mine and Sime Vidas' answer, run because I thought his looked a little more understandable/intuitive than mine and I wondered how that would translate into implementation. According to Chromium 14/Ubuntu 11.04 mine is somewhat faster, other browsers/platforms are likely to have differing results though.
Edited in response to comment from OP:
[How] do [I] apply this to more than one element?
function populateSelect(target, min, max){
if (!target){
return false;
}
else {
var min = min || 0,
max = max || min + 100;
select = document.getElementById(target);
for (var i = min; i<=max; i++){
var opt = document.createElement('option');
opt.value = i;
opt.innerHTML = i;
select.appendChild(opt);
}
}
}
// calling the function with all three values:
populateSelect('selectElementId',12,100);
// calling the function with only the 'id' ('min' and 'max' are set to defaults):
populateSelect('anotherSelect');
// calling the function with the 'id' and the 'min' (the 'max' is set to default):
populateSelect('moreSelects', 50);
JS Fiddle demo.
And, finally (after quite a delay...), an approach extending the prototype of the HTMLSelectElement in order to chain the populate() function, as a method, to the DOM node:
HTMLSelectElement.prototype.populate = function (opts) {
var settings = {};
settings.min = 0;
settings.max = settings.min + 100;
for (var userOpt in opts) {
if (opts.hasOwnProperty(userOpt)) {
settings[userOpt] = opts[userOpt];
}
}
for (var i = settings.min; i <= settings.max; i++) {
this.appendChild(new Option(i, i));
}
};
document.getElementById('selectElementId').populate({
'min': 12,
'max': 40
});
JS Fiddle demo.
References:
node.appendChild().
document.getElementById().
element.innerHTML.
The most concise and intuitive way would be:
var selectElement = document.getElementById('ageselect');
for (var age = 12; age <= 100; age++) {
selectElement.add(new Option(age));
}
Your age: <select id="ageselect"><option value="">Please select</option></select>
You can also differentiate the name and the value or add items at the start of the list with additional parameters to the used functions:
HTMLSelect​Element​.add(item[, before]);
new Option(text, value, defaultSelected, selected);
Here you go:
for ( i = 12; i <= 100; i += 1 ) {
option = document.createElement( 'option' );
option.value = option.text = i;
select.add( option );
}
Live demo: http://jsfiddle.net/mwPb5/
Update: Since you want to reuse this code, here's the function for it:
function initDropdownList( id, min, max ) {
var select, i, option;
select = document.getElementById( id );
for ( i = min; i <= max; i += 1 ) {
option = document.createElement( 'option' );
option.value = option.text = i;
select.add( option );
}
}
Usage:
initDropdownList( 'mainSelect', 12, 100 );
Live demo: http://jsfiddle.net/mwPb5/1/
I don't recommend doing DOM manipulations inside a loop -- that can get expensive in large datasets. Instead, I would do something like this:
var elMainSelect = document.getElementById('mainSelect');
function selectOptionsCreate() {
var frag = document.createDocumentFragment(),
elOption;
for (var i=12; i<101; ++i) {
elOption = frag.appendChild(document.createElement('option'));
elOption.text = i;
}
elMainSelect.appendChild(frag);
}
You can read more about DocumentFragment on MDN, but here's the gist of it:
It is used as a light-weight version of Document to store a segment of
a document structure comprised of nodes just like a standard document.
The key difference is that because the document fragment isn't part of
the actual DOM's structure, changes made to the fragment don't affect
the document, cause reflow, or incur any performance impact that can
occur when changes are made.
The one thing I'd avoid is doing DOM operations in a loop to avoid repeated re-renderings of the page.
var firstSelect = document.getElementById('first select elements id'),
secondSelect = document.getElementById('second select elements id'),
optionsHTML = [],
i = 12;
for (; i < 100; i += 1) {
optionsHTML.push("<option value=\"Age" + i + "\">Age" + i + "</option>";
}
firstSelect.innerHTML = optionsHTML.join('\n');
secondSelect.innerHTML = optionsHTML.join('\n');
Edit: removed the function to show how you can just assign the html you've built up to another select element - thus avoiding the unnecessary looping by repeating the function call.
See: What is the best way to add options to a select from an array with jQuery?
$('#mySelect')
.append($('<option>', { value : key })
.text(value));
When you create a new Option object, there are two parameters to pass: The first is the text you want to
appear in the list, and the second the value to be assigned to the option.
var myNewOption = new Option("TheText", "TheValue");
You then simply assign this Option object to an empty array element, for example:
document.theForm.theSelectObject.options[0] = myNewOption;
var selectElement = document.getElementById('ageselect');
for (var age = 12; age <= 100; age++) {
selectElement.add(new Option(age, age));
}
Your age: <select id="ageselect"><option value="">Please select</option></select>
Notice the value was added as a second parameter to new Option
None of the above solutions worked for me. Append method didn't give error when i tried but it didn't solve my problem. In the end i solved my problem with data property of select2. I used json and got the array and then give it in select2 element initialize. For more detail you can see my answer at below post.
https://stackoverflow.com/a/41297283/4928277
Often you have an array of related records, I find it easy and fairly declarative to fill select this way:
selectEl.innerHTML = array.map(c => '<option value="'+c.id+'">'+c.name+'</option>').join('');
This will replace existing options.
You can use selectEl.insertAdjacentHTML('afterbegin', str); to add them to the top instead.
And selectEl.insertAdjacentHTML('beforeend', str); to add them to the bottom of the list.
IE11 compatible syntax:
array.map(function (c) { return '<option value="'+c.id+'">'+c.name+'</option>'; }).join('');
for (let i = 12; i< 101; i++){
let html = ""
html += `
<option value="${i}">${i}</option>
`
mainSelect.innerHTML += html
}
const mainSelect = document.getElementById("mainSelect")
This is a very easy-to-understand way to solve your problem! Hope it heps:)

Compare 2 records on screen with javascript

Im looking for a way to compare 2 json records on screen. The way i want is that, i want to show these 2 records side by side and mark the matched or unmatched properties.
Is there a library that does it already, and if not, how can i do it ??
Edit
My goal is to identify the same/different properties & to show them to users with different styles, rather than comparing the objects as a whole.
Someone made a jQuery plugin for this - jQuery.PrettyTextDiff.
https://github.com/arnab/jQuery.PrettyTextDiff
$("input[type=button]").click(function () {
$("#wrapper tr").prettyTextDiff({
cleanup: $("#cleanup").is(":checked")
});
});
JSFiddle
Here is a quick JavaScript function to help you compare the to JSON strings.
First, it checks that they have same number of properties, then compares that they have the same properties (by name) and then it compares the values.
You may want to tweak the value comparison (to allow for undefined or null).
Hope it is a good starter for you.
<script type="text/javascript">
var so = {}; // stackoverflow, of course.
so.compare = function (left, right) {
// parse JSON to JavaScript objects
var leftObj = JSON.parse(left);
var rightObj = JSON.parse(right);
// add object properties to separate arrays.
var leftProps = [];
var rightProps = [];
for(var p in leftObj) { leftProps.push(p); }
for(var p in rightObj) { rightProps.push(p); }
// do they have the same number of properties
if (leftProps.length != rightProps.length) return false;
// is every right property found on the left
for (var r = 0; r < rightProps.length; r++) {
var prop = rightProps[r];
if (leftProps.indexOf(prop) < 0) {
return false;
}
}
// is every left property found on the right
for (var r = 0; r < leftProps.length; r++) {
var prop = leftProps[r];
if (rightProps.indexOf(prop) < 0) {
return false;
}
}
// do the values match?
for (var q = 0; q < leftProps.length; q++) {
var propname = leftProps[q];
var leftVal = leftObj[propname];
var rightVal = rightObj[propname];
if (leftVal != rightVal) {
return false;
}
}
return true;
}
</script>

count total duplicates in js array

I'm looping through all classnames in my html body.
I'd like to store the classname with textSize value. Each time there is a duplicate value for a given classname, I want to increment its textSize.
$("*").each(function() {
classname = $(this).get(0).className;
myarray.push({"className" : classname, "textSize" : 5});
Here, I attempt to sort the classnames, then get a count for each duplicate:
myarray.sort();
var current = null;
var dupCount = 0;
for (var i = 0; i < myarray.length-1; i++) {
if (myarray[i]["className"] !== "") {
if (myarray.indexOf(myarray[i]["className"]) == -1) {
log(myarray[i]["className"]);
}
else {
log("DUP");
myarray[i]["textSize"] = myarray[i]["textSize"] += 5;
dupCount++;
}
}
}
log(myarray[i]["className"]);, shown in the image below, clearly shows duplicates:
Yet, log("DUP"); is never called once. Why is that?
Moreover, why doesn't myarray.sort(); sort them alphabetically? If it did that, I could just do if (myarray[i]["className"] === myarray[i++]["className"]) { to check if the value equals the next value in the array. But sort doesn't work.
Edit:
So when looping through, I should be able to alter the css per classname, right?
for(var classname in classes) {
console.log(classes[classname].textSize);
var $val = $(classes[classname]);
$val.css({
"color" : "blue",
"fontSize": $val.textSize+"px"
});
}
This doesn't work even though console.log(classes[classname].textSize); gives text sizes per element
Try using an object instead of an array, using class names as the keys:
var classes = {};
$("*").each(function() {
var classname = $(this).get(0).className;
var c = classes[classname] ||
(classes[classname] = { className: classname, textSize: 0 });
c.textSize += 5;
});
for(var classname in classes) {
console.log(classes[classname]);
}
Remember that any element can have multiple classes. If you want to account for that, you'll have to split up the class names:
$("*").each(function() {
var classnames = $(this).get(0).className.split(' ');
for(var i=0; i<classnames.length; i++) {
var classname = classnames[i];
var c = classes[classname] ||
(classes[classname] = { className: classname, textSize: 0 });
c.textSize += 5;
}
});
See this demonstration: http://jsfiddle.net/FSBhv/
UPDATE: the OP clarified that he wants to set the text size on the elements based on the number of elements that have that class. Doing that will take a slightly different approach (we'll actually have to store the elements):
var eltsByClass = {};
$("*").each(function() {
var $this = $(this);
$this.get(0).className.split(' ').forEach(function(cname) {
var c = eltsByClass[cname] ||
(eltsByClass[cname] = []);
c.push($this.get(0));
});
});
for(var cname in eltsByClass) {
var elts = eltsByClass[cname];
$(elts).css('font-size', (elts.length + 1) * 5 + 'px');
}
Store your data in an object, not an Array. And it can be simplified as:
var classes = {};
$("*").each(function() {
var classname = $(this).get(0).className;
classes[classname] = (classes[classname] || 0) + 5;
});
for(var classname in classes) {
console.log(classname + " textSize:" + classes[classname]);
}
myarray.indexOf(myarray[i]["className"]) is a problem.
You know that myarray contains only objects, but you're asking for the position of a string within that list. That's never going to return anything but -1.
Consider using a second array to store the frequency count, instead of trying to do both with myarray.
var frequency = {};
myarray.forEach(function (i) {
frequency[i.className] = frequency[i.className] || 0
frequency[i.className]++;
}
This will hely you to sort array alphabetically based on classname
var myarray=[];
$("*").each(function()
{
classname = $(this).get(0).className;
myarray.push({"className" : classname, "textSize" : 5});
});
function compare(a,b)
{
if (a.className < b.className)
return -1;
if (a.className > b.className)
return 1;
return 0;
}
myarray.sort(compare);

Javascript: Failing to add text into Array

The problem I am having is that my text is not being added into the array for some reason. The code looks fine, but I can confirm it's not being added by having it print out the array.length.
<script>
function addradio(value)
{
var element = document.createElement("input");
var label = document.createElement("label");
var tele = document.getElementById("Telephone");
var selected_text = tele.options[tele.selectedIndex].innerHTML;
// Array uses to stop duplicate radio button
var countryArray = new Array();
// Used to check if country is already in array, defaults to false
var contain = new Boolean();
// Checks if text contains a "1", returns "-1" if it doesn't
var str = selected_text.indexOf("1");
// For loop to check if country name is already in the array
for(var i = 0; i <= countryArray.length; i++)
{
if(countryArray[i] == selected_text)
contain = true;
else
contain = false;
}
// If value is not empty and text does not contain a "1" and array doesn't contain specified country
if(value != "" && str == "-1" && contain == false)
{
// Creating the attributes for a radio button
element.setAttribute("type", "radio");
element.setAttribute("value", value);
element.setAttribute("name", "telephone");
label.appendChild(element);
label.innerHTML += selected_text + "<br>";
// Creating the radio button
var newradio = document.getElementById("fillme");
newradio.appendChild(label);
// Adds country into the array if its' not already there
countryArray.push(selected_text);
}
}
</script>
Can anyone identify the issue with my Array.push() function?
You create an empty array and then try to loop over it. Since it's empty it has no length, so loop will never run. At the end you push a value into array, but next time method runs the array starts empty all over again
I suspect you intent to use the same array and call the function several times, in which case you would need to declare the array outside of your function.
You could also get rid of the for loop and use indexOf() to see if value you want is in array.
// Move this outside function
var countryArray = new Array();
/* shorter syntax*/
var countryArray =[];
function addradio(value)...
Your for loop is incorrect. It's missing the last element in the array.
// For loop to check if country name is already in the array
for(var i = 0; i < countryArray.length; i++)
{
if(countryArray[i] == selected_text)
contain = true;
else
contain = false;
}
Instead of doing the following:
for(var i = 0; i <= countryArray.length; i++)
{
if(countryArray[i] == selected_text)
contain = true;
else
contain = false;
}
I find this easier:
if(!!countryArray.indexOf(selected_text) && countryArray.indexOf(selected_text) > -1)
{
//then item exist in array. You do not have to use the base bool operator, but secondary check.
}
So basically:
if(countryArra.indexOf(selected_text) > -1)
{
//it exist!
}

Categories