0

I'm trying to test for an "empty-ish" value of an object. In other words, if the object's properties have no values, or contain only whitespace values, let's consider it empty.

I referred to this post

https://coderwall.com/p/_g3x9q/how-to-check-if-javascript-object-is-empty

and found some helpful things to try. This one I liked the most uses JSON.stringify as a one liner. I'm not sure I understand exactly how it works -- I think when the console outputs a pair of {} curly braces from it means it found an object, but maybe there is more nuance than that?

I want to avoid writing a custom function or importing any libraries if possible.

Here is a MVP code example that demonstrates the error I am having. Notice the two TD elements on the far right appear empty, but they have tabs in them. I include the logic tests for "empty-ish" that I tried and their results after this code:

console.clear();

// Set selector values
var selectors = {
  blockSel: "td",
  titleSel: "span",
  urlSel: ""
};

var styles = {
  // reddish text
  style1: "background: bisque; color: brown; font-weight: bold; margin-top: .2em; padding-top: .3em; border-top: solid red 3px;",
  style2: "background:aliceblue;",
  style3: "background:orange;",
  h2: "color: black; font-weight: 700; font-size: 1.2em;"
};

var outObj = {};

// var titles = document.querySelectorAll('#res h3');
var blocks = document.querySelectorAll(selectors.blockSel);

[...blocks].forEach(function(block, i) {
  // Debugging ...
  console.log("%cNumber %s", styles.style1, i);

  console.log("%c\tVALUES:\t\t\t", styles.h2);

  console.log("%cblock.innerText = %s", styles.style2, block.innerText);
  console.log(
    "%cJSON.stringify(block.innerText) = %s",
    styles.style2,
    JSON.stringify(block.innerText)
  );
  console.log(
    "%cJSON.stringify(block.innerText.trim()) = %s",
    styles.style2,
    JSON.stringify(block.innerText.trim())
  );

  console.log("%c\tTESTS:\t\t\t", styles.h2);

  console.log(
    '%cJSON.stringify(block.innerText.trim()) == ""',
    styles.style3,
    JSON.stringify(block.innerText.trim()) == ""
  );
  console.log(
    "%cJSON.stringify(block.innerText) !== undefined",
    styles.style3,
    JSON.stringify(block.innerText) !== undefined
  );
  console.log(
    "%cJSON.stringify(block.innerText) != undefined",
    styles.style3,
    JSON.stringify(block.innerText) != undefined
  );
  console.log(
    '%cJSON.stringify(block.innerText) != ""',
    styles.style3,
    JSON.stringify(block.innerText) != ""
  );
});
body {
  background-position: center bottom;
  padding: 0px;
  margin: 0px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  color: #000000;
  background-image: url('images/abstract_background.jpg');
  background-repeat: no-repeat;
  background-attachment: fixed;
  background-color: #00111B;
}

td {
  background: #ffffb3;
  min-width: 13vw;
  text-align: center;
}

#description {
  color: white;
  font-size: 1.2em;
  max-width: 1024px;
}
<div id="description">

  <h2>DESCRIPTION</h2>

  <section>
    <h3>Purpose:</h3>
    <p>This pen demonstrates an issue I'm having with trying test for an "empty-ish" value of an object. In other words, if the object has no values, or contains only whitespace values, let's consider it empty. This isn't working so I'm posting my code to
      help me debug this issue.</p>

    <p>Please open the JavaScript console to view output</p>

    <h3>Errors</h3>

    <ul>
      <li>None.</li>
    </ul>

  </section>

</div>

<table>
  <tr>
    <td valign="top">
      <div id="Archives1_DataList1_ctl40_div1" class="rlvI">
        <div style="width: 175px; float: left; margin-bottom: 5px;">
          <span id="Archives1_DataList1_ctl40_Label2">January 17, 2018</span>
        </div>
        <div>
          <a class="example7" href="/editionviewer/default.aspx?Edition=1ca546d2-2e81-486c-b199-a3d056d157a2" target="_self">
            <img id="Archives1_DataList1_ctl40_Image1" src="https://media.iadsnetwork.com/edition/1964/136061/resized/175_0_1964719d1738-a4a9-46a0-a45e-a1f9aadb7fa7.jpg" style="border-width:0px;">
          </a>
        </div>
      </div>
    </td>
    <td valign="top">
      <div id="Archives1_DataList1_ctl41_div1" class="rlvI">
        <div style="width: 175px; float: left; margin-bottom: 5px;">
          <span id="Archives1_DataList1_ctl41_Label2">January 10, 2018</span>
        </div>
        <div>
          <a class="example7" href="/editionviewer/default.aspx?Edition=cd43c968-1e66-4919-9f97-fc0fe69d749f" target="_self">
            <img id="Archives1_DataList1_ctl41_Image1" src="https://media.iadsnetwork.com/edition/1964/135726/resized/175_0_19644b88f108-6e80-46d6-b7fb-d22f4cebac54.jpg" style="border-width:0px;">
          </a>
        </div>
      </div>
    </td>
    <td valign="top">
      <div id="Archives1_DataList1_ctl42_div1" class="rlvI">
        <div style="width: 175px; float: left; margin-bottom: 5px;">
          <span id="Archives1_DataList1_ctl42_Label2">January 3, 2018</span>
        </div>
        <div>
          <a class="example7" href="/editionviewer/default.aspx?Edition=fd6fb6f4-6b86-4489-a65f-eeb41d64eade" target="_self">
            <img id="Archives1_DataList1_ctl42_Image1" src="https://media.iadsnetwork.com/edition/1964/135385/resized/175_0_1964a8b1cc88-08f4-49f0-ace1-ca84b8a26d55.jpg" style="border-width:0px;">
          </a>
        </div>
      </div>
    </td>
    <td></td>
    <td></td>
  </tr>
</table>

Here is a screenshot of the 3rd and 4th TD's. As you can see, item 3 shows an innerText value, but item 4 has no text, just a TAB character. But, they both test the same.

enter image description here

CAVEAT:

This post How do I test for an empty JavaScript object? was suggested as a possible duplicate. I wish it was, but it is not. Further, I tried the top rated answer, using the Pre-ECMA 5 solution for maximum compatibility, to no avail. Implementing that function did not work. I will update with a minimum verifiable code shortly...

Code Attempt 2:

In this attempt I try two different functions to test for an empty object. Like I said already, my objects aren't necessarily empty, but they may contain whitespace characters. I've eliminated a lot of debugs from the first example to make this more precise and smaller.

Here are the functions I used

Pre-ECMA 5

function isEmpty(obj) {
    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            return false;
    }

    return JSON.stringify(obj) === JSON.stringify({});
} 

ECMA 5

function isEmpty2(obj) {
  if ( Object.keys(obj).length === 0 && obj.constructor === Object ) {
    return true;
  }

  return false;
}

Again, NEITHER of the these functions worked. And here is the complete code example for this attempt:

console.clear();

var outObj = {};

var blocks = document.querySelectorAll('td');

[...blocks].forEach(function(block, i) {
  // Debugging ...
  console.log("%cNumber %s", styles.style1, 1+i);

  console.log(block);
  console.log("%cisEmpty(block) = %s", styles.style4, isEmpty(block));
  console.log("%cisEmpty2(block) = %s", styles.style4, isEmpty2(block));
  
});

/* isEmpty() */
function isEmpty(obj) {
    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            return false;
    }

    return JSON.stringify(obj) === JSON.stringify({});
} 

/* isEmpty2() */
function isEmpty2(obj) {
  if ( Object.keys(obj).length === 0 && obj.constructor === Object ) {
    return true;
  }
  
  return false;
}
body
{
    background-position: center bottom;
    padding: 0px;
    margin: 0px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    color: #000000;
    background-image: url('images/abstract_background.jpg');
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-color: #00111B;
}

td {
  background: #ffffb3;
  min-width: 13vw;
  text-align: center;
}

#description {
  color: white;
  font-size: 1.2em;
  max-width: 1024px;
}
<table>
  <tr>
    <td valign="top">
      <div id="Archives1_DataList1_ctl40_div1" class="rlvI">
        <div style="width: 175px; float: left; margin-bottom: 5px;">
          <span id="Archives1_DataList1_ctl40_Label2">January 17, 2018</span>
        </div>
        <div>
          <a class="example7" href="/editionviewer/default.aspx?Edition=1ca546d2-2e81-486c-b199-a3d056d157a2" target="_self">
               <img id="Archives1_DataList1_ctl40_Image1" src="https://media.iadsnetwork.com/edition/1964/136061/resized/175_0_1964719d1738-a4a9-46a0-a45e-a1f9aadb7fa7.jpg" style="border-width:0px;">
               </a>
        </div>
      </div>
    </td>
    <td valign="top">
      <div id="Archives1_DataList1_ctl41_div1" class="rlvI">
        <div style="width: 175px; float: left; margin-bottom: 5px;">
          <span id="Archives1_DataList1_ctl41_Label2">January 10, 2018</span>
        </div>
        <div>
          <a class="example7" href="/editionviewer/default.aspx?Edition=cd43c968-1e66-4919-9f97-fc0fe69d749f" target="_self">
               <img id="Archives1_DataList1_ctl41_Image1" src="https://media.iadsnetwork.com/edition/1964/135726/resized/175_0_19644b88f108-6e80-46d6-b7fb-d22f4cebac54.jpg" style="border-width:0px;">
               </a>
        </div>
      </div>
    </td>
    <td valign="top">
      <div id="Archives1_DataList1_ctl42_div1" class="rlvI">
        <div style="width: 175px; float: left; margin-bottom: 5px;">
          <span id="Archives1_DataList1_ctl42_Label2">January 3, 2018</span>
        </div>
        <div>
          <a class="example7" href="/editionviewer/default.aspx?Edition=fd6fb6f4-6b86-4489-a65f-eeb41d64eade" target="_self">
               <img id="Archives1_DataList1_ctl42_Image1" src="https://media.iadsnetwork.com/edition/1964/135385/resized/175_0_1964a8b1cc88-08f4-49f0-ace1-ca84b8a26d55.jpg" style="border-width:0px;">
               </a>
        </div>
      </div>
    </td>
    <td></td>
    <td></td>
  </tr>
</table>
  • 3
    Possible duplicate of [How do I test for an empty JavaScript object?](https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object) – codeepic Oct 17 '18 at 13:39
  • 1
    The problem with relying on `JSON.stringify()` is that not all objects can be rendered as JSON, and it can throw an exception. I think writing a "custom function" to check according to your definition of "empty" would be much more stable. – Pointy Oct 17 '18 at 13:39
  • 2
    "I want to avoid writing a custom function or importing any libraries if possible." If there is no native JS function that can accomplish this, you're going to have to do one of these. – Bucket Oct 17 '18 at 13:42
  • 1
    You mention an empty "object", but then mention checking the contents of a ``. The latter can be found using `document.querySelectorAll('td:empty')` (i.e., the [`:empty' pseudo class](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty)). – Heretic Monkey Oct 17 '18 at 13:42
  • @HereticMonkey I was not aware of the :empty pseudo class ... that could solve my issue altogether. Thanks. I will give it a try and report back. – Eric Hepperle - CodeSlayer2010 Oct 17 '18 at 13:45
  • 1
    @codeepic Give me a few minutes to check that one to determine if the content in the same or if the names are only similar. If it is a true duplicate I will delete my post, but I don't want to delete it prematurely, because I may not be able to add it back based on however Stack Overflow caches the database servers. – Eric Hepperle - CodeSlayer2010 Oct 17 '18 at 13:47
  • @Pointy I was not aware of that issue with JSON.stringify(). I appreciate that insight. – Eric Hepperle - CodeSlayer2010 Oct 17 '18 at 13:48
  • You don't have to delete your question; duplicates can serve as guideposts for others using similar keywords that may not be present in the duplicate. – Heretic Monkey Oct 17 '18 at 13:54
  • @HereticMonkey -- Very good, I will be happy to serve as a guidepost if it can help others. What I'm really trying to do is select all TD's that are NOT EMPTY. I tried this: `td:not:empty` but no love. Suggestions? – Eric Hepperle - CodeSlayer2010 Oct 17 '18 at 14:04
  • 1
    @HereticMonkey I figured it out. I couldn't find it anywhere on Google, but I just reordered stuff and this worked `td:not(:empty)`. NOTE, this code doesn't solve the issue I posted about, so I will still have to test that code, then update my answer with the results. Thanks for your help! – Eric Hepperle - CodeSlayer2010 Oct 17 '18 at 14:18
  • @codeepic Thanks for the link. I checked, but it did not have a workable solution though the titles are similar. I've posted updated code based on testing suggestions from that post. – Eric Hepperle - CodeSlayer2010 Oct 17 '18 at 15:20

1 Answers1

0

!!Object.getOwnPropertyNames({}).length => false

!!Object.getOwnPropertyNames({a: 'abc'}).length => true

============================================

Object.getOwnPropertyNames({}).length => 0

Object.getOwnPropertyNames({a: 'abc'}).length => 1