WillD
WillD

Reputation: 6552

Programmatically construct a condition for use in an if() statement

Let's assume for a moment that I have something like this:

if (document.getElementById('div1').innerHTML &&
    document.getElementById('div2').innerHTML &&
    document.getElementById('div3').innerHTML &&
    document.getElementById('div4').innerHTML &&
    document.getElementById('div5').innerHTML &&
    ...
    document.getElementById('div100').innerHTML)

Obviously typing out and maintaining a big conditional statement like this is problematic.

I would like some solution like:

var conditional = "";
for(var i = 1; i <= 100; i++){
  conditional += "document.getElementById('div" + i +"').innerHTML";
  if(i < 100) {
    conditional += " && ";
  }
}
if(interpretStringAsJSExpression(conditional)){
    console.log("all my divs have content");
}

Is something like this possible in JavaScript?

Great answers have been submitted, and I am sure that I and others will benefit from them. However, purely from a place of curiosity, is it possible to store and run JavaScript expressions or commands in strings?

Like I have proposed in my example: interpretStringAsJSExpression(conditional)

Upvotes: 33

Views: 2787

Answers (7)

S. Foster
S. Foster

Reputation: 106

Another option aside from eval is to use the Function constructor. Function is a bit more flexible and allows you to save compiled code instead of having to eval it each time. They both carry similar security risks, however.

var conditional = "";
for(var i = 1; i <= 6; i++){
  conditional += "document.getElementById('div" + i +"').innerHTML";
  if(i < 6) {
    conditional += " && ";
  }
}
const f = new Function('return (' + conditional + ') !== ""');

console.log(f());
<div id="div1">1</div>
<div id="div2"></div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5"></div>
<div id="div6">6</div>

Upvotes: 2

blue note
blue note

Reputation: 29099

You could just store the document.getElementById('divXX').innerHTML items in an array, and then, just use

items.reduce((a, b) => a && b);

That way, you can change individual div elements in your expression without having to re-created the whole list

Upvotes: 1

ibrahim mahrir
ibrahim mahrir

Reputation: 31712

Why interpret a string of code? There are other means like for loops:

var conditionResult = true;
for(var i = 1; conditionResult && (i < 101); i++) {
    conditionResult = conditionResult && document.getElementById('div' + i).innerHTML;
}

if(conditionResult) {
    // Do something here
}

The for loop condition conditionResult && (i < 101) will break the loop once conditionResult is determined to be falsy; no need to keep looping in this case.

You can also use array methods like some and every if you have the elements in an array:

var arr = [/* array of DOM elements */];

var conditionResult = arr.every(elem => elem.innerHTML);   // This is equivalent to (innerHTML && innerHTML && ...)

var conditionResult = arr.some(elem => elem.innerHTML);    // This is equivalent to (innerHTML || innerHTML || ...)

Upvotes: 8

jorbuedo
jorbuedo

Reputation: 2161

As the other answers said, you can solve your conditions problem more easily.

But, to answer your new question

purely from a place of curiosity, is it possible to store and run JavaScript expressions or commands in strings?

Yes, you can write JavaScript code to a string and execute it later with eval. Which you should not do if you are concerned with security or performance.

Upvotes: 20

user2182349
user2182349

Reputation: 9782

Use document.querySelectorAll for this type of operation

// Get all the divs that have ids which start with div
var theDivs = document.querySelectorAll('[id^="div"]');
var i,l,el,divsWithContent = [];

// Loop through all theDivs
l = theDivs.length;
for(i = 0; i < l; i++) {
    // el is the div 
    el = theDivs[i];
    
    // Test to make sure the id is div followed by one or more digits
    if (/^div\d+$/.test(el.id)) {
        // If the div has something in it other than spaces, it's got content
        if (el.textContent.trim() !== "") {
            // Save the divs with content in the array
            divsWithContent.push(el.id);
        }
    }
}

// Show the results 
document.getElementById("result").textContent = divsWithContent.join("\n");
<h1>Div test</h1>
<div id="div1">This</div>
<div id="div2">that</div>
<div id="div3"></div>
<div id="div4">and</div>
<div id="div5">the other thing</div>
<h2>Divs with content</h2>
<pre id="result"></pre>

Ref: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

Upvotes: 2

Barmar
Barmar

Reputation: 782683

You can do the tests in a loop.

var allOK = true;
for (var i = 1; i <= 100; i++) {
    if (!document.getElementById("div"+i).innerHTML) {
        allOK = false;
        break;
    }
}
if (allOK) {
    console.log("all my divs have content");
}

You could also give all your DIVs a common class, then use a built-in iterator.

var allDivs = document.getElementsByClassName("divClass");
if (Array.from(allDivs).every(div => div.innerHTML)) {
    console.log("all my divs have content");
}

Upvotes: 26

You Old Fool
You Old Fool

Reputation: 22969

You can set condition to true and check each one, setting condition to false and break out of the loop if any are false.

var conditional = true;
for(var i = 1; i <= 100; i++){
  if (!document.getElementById('div' + i).innerHTML) {
        condition = false;
        break;
    }
}

Upvotes: 2

Related Questions