I have a simple for-loop in a JS file on an old aspx web page:
function SaveCurrentFilterDisplay() {
var currentFilterCode = document.getElementById('curfilt').value;
var currentFilterList, currentFilterDisplay;
var i, str;
if (currentFilterCode != '') {
currentFilterList = document.getElementById(currentFilterCode);
currentFilterDisplay = document.getElementById(currentFilterCode + '_display');
//save the previous filter text names
//alert(currentFilterCode + ': ' + currentFilterList.length);
if (currentFilterList.length) {
//multi-select list
str = '';
for (i = 0; i < currentFilterList.length; i++) {
if (currentFilterList.options[i].selected) {
if (str.length > 0) {
str = str + ', '
}
str = str + currentFilterList.options[i].text;
}
}
} else {
//text field
str = currentFilterList.value;
}
alert('finished looping');
currentFilterDisplay.value = str;
}
return true;
}
Sometimes this loop has to loop almost 50,000 times. Others just a few hundred or less.
What is perplexing me is that when the loop has to loop 50,000 times and I run this in Chrome, it takes around 2 minutes. But when I do the exact same thing in IE it takes just a few seconds, sometimes it even seems instantaneous.
I am wondering if there is an explanation having to do with how the Chrome based browsers handle Javascript?
EDIT: And perhaps any suggestions on how to optimize this so that it doesn't take 2 minutes in Chrome?
EDIT 2: I have updated my question to show the entire function. When I step through the function using the Chrome dev tools, all of the statements in the method execute instantly, but when I step over the loop it takes 2 minutes to hit the alert statement, so it is the loop that is taking 2 minutes.
Here is some HTML showing what currentFilterList is getting pointed to:
<select id="ID" name="adv" multiple="true">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
So as an example, currentFilterCode = "ID". This makes currentFilterList set to the select list above (Much shorter than the real one for obvious reasons).
Final Edit: After help from comments I did post my solution to the particular problem I was facing. It is not the best way to go about a similar situation, but it works within the constraints of the application I was working on. I chose the other answer as the solution because it is the way to go for similar situations.
So why are we looping to find the selections when we can do it with a selector? Use map and join to build up a string of the selected values.
document.querySelector("#select1").addEventListener("change", () => {
const out = [...document.querySelectorAll('#select1 option:checked')].map(x => x.text);
console.log(out.join(', '));
});
/*
document.querySelector("#select1").addEventListener("change", function() {
var out = Array.from(document.querySelectorAll('#select1 option:checked')).map(function(x) { return x.text; });
console.log(out.join(', '));
});
*/
<select id="select1" multiple>
<option>FOO1</option>
<option>FOO2</option>
<option>FOO3</option>
<option>FOO4</option>
<option>FOO5</option>
<option>FOO6</option>
<option>FOO7</option>
<option>FOO8</option>
<option>FOO9</option>
<option>FOO10</option>
</select>
OR with selected Options and map and join
document.querySelector("#select1").addEventListener("change", () => {
var out = [...document.querySelector('#select1').selectedOptions].map(x => x.text);
console.log(out.join(', '));
});
<select id="select1" multiple>
<option>FOO1</option>
<option>FOO2</option>
<option>FOO3</option>
<option>FOO4</option>
<option>FOO5</option>
<option>FOO6</option>
<option>FOO7</option>
<option>FOO8</option>
<option>FOO9</option>
<option>FOO10</option>
</select>