Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
{
"entries": [
    {
        "id": 23931763,
        "url": "http://www.dailymile.com/entries/23931763",
        "at": "2013-07-15T21:05:39Z",
        "message": "I ran 3 miles and walked 2 miles today.",
        "comments": [],
        "likes": [],
        "user": {
            "username": "DeanaLaughli",
            "display_name": "Deana O.",
            "photo_url": "http://s3.dmimg.com/pictures/users/361413/1329826045_avatar.jpg",
            "url": "http://www.dailymile.com/people/DeanaLaughli"
        },
        "workout": {
            "activity_type": "Fitness",
            "distance": {
                "value": 5,
                "units": "miles"
            },
            "felt": "great"
        }
    },
    {
        "id": 23931680,
        "url": "http://www.dailymile.com/entries/23931680",
        "at": "2013-07-15T21:01:03Z",
        "message": "More strength training",
        "comments": [],
        "likes": [],
        "location": {
            "name": "MA"
        },
        "user": {
            "username": "Ecm2571",
            "display_name": "Eileen",
            "photo_url": "http://s3.dmimg.com/pictures/users/323833/1368556483_avatar.jpg",
            "url": "http://www.dailymile.com/people/Ecm2571"
        },
        "workout": {
            "activity_type": "Weights",
            "title": "Upper and lower body "
        }
    }
]
}

Here is an example of a JSON array that I am getting via JSONP request from a URL. I am trying to display:

  • photo_url
  • username
  • message
  • location.name
  • workout.activity_type
  • workout.duration
  • workout.distance.value
  • workout.distance.units

However, as you can see in the array sometimes this information isn't given and when this happens the code stops loading more entries. I need a way to display a blank space when there is no data to load. Here is my code, thanks for any help.

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"> </script>
<script>

$(function() {

var entries = [];
var workout.activity
var dmJSON = "http://api.dailymile.com/entries.json?callback=?";
$.getJSON( dmJSON, function(data) {
$.each(data.entries, function(i, f) {
  var tblRow =      "<tr>" + 
            "<td><img src=" + f.user.photo_url + "></td>" +
            "<td>" + f.user.username + "</td>" + 
            "<td>" + f.message + "</td>" + 
            //"<td>" + f.location.name + "</td>" +
            "<td>" + f.workout.activity_type + "</td>" +
            "<td>" + f.workout.duration + "</td>" +
            "<td>" + f.workout.distance.value + f.workout.distance.units + "</td>" +
            "</tr>"
   $(tblRow).appendTo("#entrydata tbody");
});

});

});
</script>
</head>

<body>

<div class="wrapper">
<div class="profile">
<table id= "entrydata" border="1">
<thead>
        <th></th>
        <th>Username</th>
        <th>Message</th>
    <th>Exercise Type</th>
    <th>Duration</th>
    <th>Distance</th>
    </thead>
  <tbody>

   </tbody>
</table>

</div>
</div>

</body>

</html>
share|improve this question
1  
You'll get errors when f.workout.distance is undefined (because it is in the 2nd response). Read the error console to first determine what is wrong. Establish guards or sentinels or use a "path evaluator". –  user2246674 Jul 15 '13 at 22:09
3  
A simple guard with the ternary operator: f.workout.distance ? f.workout.distance.value + f.workout.distance.units : "" - but for anything non-trivial this is better written taking the larger context into account (e.g. don't show last td?). –  user2246674 Jul 15 '13 at 22:12
    
Is there a way to initialise/set the value to blank, so when the data isn't in the array it just shows as blank? –  Maggy Jul 15 '13 at 22:24
    
Arrays are not an issue here ({..} delineates a JSON/JS object, not an array). And yes, you could do that too. For instance, at the top of the each/generation function: f.workout.distance ||= { value: '', units: 'Not applicable' }; however, consider if this is appropriate here or makes future refactoring harder. I would actually suggest to change the HTML-string generation to an incremental builder (i.e. build each TD one at a time) or template with basic conditional support. This would allow using an "if" around the offending region to customize the result better. –  user2246674 Jul 15 '13 at 22:29
    
Thank you for the help, I will take your advice into consideration and shake up the code a bit. –  Maggy Jul 15 '13 at 22:35

1 Answer 1

First all run it in chrome and open the web tools. Once your "reach" error you will see the error in the console log.

Your problem is that you have undefined values that you try to read. You can solve it by checking each object before you try to read any value form it or to use function which return default value whenever teh value is missing.

Here is a full working code for you:

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
    <script>

        /**
         * Extract the property formthe object.
         * If teh property not found it will return empty string
         */
        function getProperty(object, property) {

            if (!property) {
                return '';
            }

            var
            // Break the property to its nested properties
                    properties = property && property.split('.'),
            // the current object that we want to extract the property from
                    current = object,
                    index;

            // Loop over the properties and process them
            for (index = 0; index < properties.length; index++) {
                property = properties[index];
                // Check to see that there is a property with the given name
                if (current.hasOwnProperty(property)) {
                    current = current[property];
                } else {
                    return '... N/A ...';
                }
            }

            // If we got so far it means the the 'current' contain the needed value
            return current;
        }

        $(function () {

            var entries = [],
                    dmJSON = "http://api.dailymile.com/entries.json?callback=?";

            $.getJSON(dmJSON, function (data) {
                $.each(data.entries, function (i, f) {
                    var tblRow = "<tr>" +
                            "<td><img src=" + getProperty(f, 'user.photo_url') + "></td>" +
                            "<td>" + getProperty(f, 'user.username') + "</td>" +
                            "<td>" + getProperty(f, 'message') + "</td>" +
                        //"<td>" + f.location.name + "</td>" +
                            "<td>" + getProperty(f, 'workout.activity_type') + "</td>" +
                            "<td>" + getProperty(f, 'workout.duration') + "</td>" +
                            "<td>" + getProperty(f, 'workout.distance.value') + getProperty(f, 'workout.distance.units') + "</td>" +
                            "</tr>";

                    $(tblRow).appendTo("#entrydata tbody");
                });

            });

        });
    </script>
</head>

<body>

<div class="wrapper">
    <div class="profile">
        <table id="entrydata" border="1">
            <thead>
            <th></th>
            <th>Username</th>
            <th>Message</th>
            <th>Exercise Type</th>
            <th>Duration</th>
            <th>Distance</th>
            </thead>
            <tbody>

            </tbody>
        </table>

    </div>
</div>

</body>

</html>
share|improve this answer
    
Excellent, was not sure exactly how to get to this conclusion so this is very helpful for me. –  Maggy Jul 15 '13 at 23:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.