litel
litel

Reputation: 3990

Having trouble appending object

I am trying to create a simple demo that retrieves movie theater showtimes based on input of a given zipcode. The theater listings are nested in an object of movie object, so I'm running a for loop inside an each loop that parses the JSON. I'm also using timeConvert function to turn the timestamp into a US 12hr time.

Currently, it looks something like this:

 for (var j=0; j<movie.showtimes.length; j++) {
           listing += '<li class="times-and-places">
                   <div class="movie-theater">' 
                   + movie.showtimes[j].theatre.name
                   + '</div><div class="movie-time"><li>' 
                   + timeConvert(movie.showtimes[j].dateTime.slice(11,16)) 
                   + '</li></div></li>';
        }

This works fine, but it returns a different item for each movie theater showtime with the movie theater in it, which looks a little unwieldy. The API I'm using does not combine showtimes by theaters, and there's a different entry for each showtime. I'm basically replicating this in the HTML. So if a movie plays a bunch of times, it will show:

MoviePlace1 1:30PM MoviePlace1 1:45PM MoviePlace1 2:00PM

I'd like to be able to combine the showtimes to read:

MoviePlace1 1:30PM 1:45PM 2:00PM

The movie API assigns an ID to each movie theater, so I tried writing an if-else conditional inside my for loop.

 for (var j=0; j<movie.showtimes.length; j++) {
          tList.push(movie.showtimes[j].theatre.id);
          var thingToFind = $(this).prev().find('.movie-time');
           var mTime = movie.showtimes[j].dateTime.slice(11,16);
          var mTimeConverted = timeConvert(mTime).toString();

          if (tList[j] != tList[(j-1)] || tList[(j-1)] === null ) {
                    listing += '<li class="times-and-places">
                   <div class="movie-theater">' 
                   + movie.showtimes[j].theatre.name
                   + '</div><div class="movie-time"><li>' 
                   + timeConvert(movie.showtimes[j].dateTime.slice(11,16)) 
                   + '</li></div></li>';

        } else {
          console.log(mTimeConverted);
          listing += thingToFind.append($("li").append(mTimeConverted + '</li>'));

        }

The if statement, which works fine, checks whether the current movie theater ID is unique when compared to the previous one—or if the previous ID is nonexistent (the array I am pushing ID values clears after I run through the movie showtimes loop).

The else statement—intended to combine the different showtimes—appends a bunch of blank jQuery objects to the previous listing:

MoviePlace1 4:30PM [object Object][object Object]

I've tried modifying it a million different ways to return an actual value instead of a blank jQuery object, but I can't seem to figure it out. Can anyone help?

Here is a sample movie object, including the showtimes.

{
    "tmsId": "MV007117430000",
    "rootId": "11455160",
    "subType": "Feature Film",
    "title": "Me and Earl and the Dying Girl",
    "releaseYear": 2015,
    "releaseDate": "2015-01-25",
    "titleLang": "en",
    "descriptionLang": "en",
    "entityType": "Movie",
    "genres": [
        "Comedy drama"
    ],
    "longDescription": "An awkward high-school senior (Thomas Mann) and a gravely ill classmate (Olivia Cooke) surprise themselves by becoming inseparable friends.",
    "shortDescription": "A shy, awkward teenager and a gravely ill classmate become inseparable friends.",
    "topCast": [
        "Thomas Mann",
        "Olivia Cooke",
        "Ronald Cyler II"
    ],
    "directors": [
        "Alfonso Gomez-Rejon"
    ],
    "officialUrl": "http://meandearlmovie.com/",
    "qualityRating": {
        "ratingsBody": "TMS",
        "value": "3.5"
    },
    "ratings": [
        {
            "body": "Motion Picture Association of America",
            "code": "PG-13"
        }
    ],
    "advisories": [
        "Adult Language",
        "Adult Situations"
    ],
    "runTime": "PT01H45M",
    "preferredImage": {
        "width": "240",
        "height": "360",
        "caption": {
            "content": "Me and Earl and the Dying Girl (2015)",
            "lang": "en"
        },
        "uri": "assets/p11455160_p_v5_aa.jpg",
        "category": "Poster Art",
        "text": "yes",
        "primary": "true"
    },
    "showtimes": [
        {
            "theatre": {
                "id": "10420",
                "name": "Violet Crown Cinema"
            },
            "dateTime": "2015-07-21T11:00",
            "barg": false
        },
        {
            "theatre": {
                "id": "10420",
                "name": "Violet Crown Cinema"
            },
            "dateTime": "2015-07-21T17:10",
            "barg": false
        },
        {
            "theatre": {
                "id": "10420",
                "name": "Violet Crown Cinema"
            },
            "dateTime": "2015-07-21T22:10",
            "barg": false
        },
        {
            "theatre": {
                "id": "10984",
                "name": "Alamo Drafthouse South Lamar"
            },
            "dateTime": "2015-07-21T14:15",
            "barg": false
        },
        {
            "theatre": {
                "id": "10984",
                "name": "Alamo Drafthouse South Lamar"
            },
            "dateTime": "2015-07-21T17:05",
            "barg": false
        },
        {
            "theatre": {
                "id": "10984",
                "name": "Alamo Drafthouse South Lamar"
            },
            "dateTime": "2015-07-21T19:50",
            "barg": false
        },
        {
            "theatre": {
                "id": "10984",
                "name": "Alamo Drafthouse South Lamar"
            },
            "dateTime": "2015-07-21T22:10",
            "barg": false
        }
    ]

}

Upvotes: 0

Views: 70

Answers (3)

Matt Burland
Matt Burland

Reputation: 45155

Given your input data, you best approach might be to reorganize it like so:

var shows = showtimes.reduce(function (p, c) {
    if (!p[c.theatre.id]) {
        p[c.theatre.id] = {
            theatreName: c.theatre.name,
            showtimes: [c.dateTime]
        };
    } else {
        p[c.theatre.id].showtimes.push(c.dateTime);
    }
    return p;
}, {});

This would give you an object that looked something like this:

{
    "9489": {
        "theatreName": "Alamo Drafthouse at the Ritz",
        "showtimes": [
            "2015-07-21T16:30",
            "2015-07-21T19:30",
            "2015-07-21T22:30"
        ]
    },
    "10420": {
        "theatreName": "Violet Crown Cinema",
        "showtimes": [
            "2015-07-21T12:00",
            "2015-07-21T13:20",
            "2015-07-21T15:50",
            "2015-07-21T18:25"
        ]
    }
}

Now you can iterate through this object (or convert it back to an array if you really want to) with a for...in loop and construct your HTML from it.

Something like:

for (var t in shows) {
    if (shows.hasOwnProperty(t)) {         
        listing += '<li class="times-and-places">'
               + '<div class="movie-theater">' 
               + shows[t].theatreName
               + '</div><div class="movie-time">'; 
        for (var i=0; i < shows[t].showtimes.length; i++) {
            listing += '<li>' 
               + timeConvert(shows[t].showtimes[i].slice(11,16)) 
               + '</li>';
        }

        listing += '</div></li>';
    }
}

Which would give HTML that eventually looked something like this (ignoring whatever timeConvert might do):

<li class="times-and-places">
    <div class="movie-theater">Alamo Drafthouse at the Ritz</div>
    <div class="movie-time">
        <li>16:30</li>
        <li>19:30</li>
        <li>22:30</li>
    </div>
</li>
<li class="times-and-places">
    <div class="movie-theater">Violet Crown Cinema</div>
    <div class="movie-time">
        <li>12:00</li>
        <li>13:20</li>
        <li>15:50</li>
        <li>18:25</li>
    </div>
</li>

Upvotes: 1

MinusFour
MinusFour

Reputation: 14423

You could reduce the showtimes array:

var showtimes = [{
  "theatre": {
    "id": "10420",
    "name": "Violet Crown Cinema"
  },
  "dateTime": "2015-07-21T11:00",
  "barg": false
}, {
  "theatre": {
    "id": "10420",
    "name": "Violet Crown Cinema"
  },
  "dateTime": "2015-07-21T17:10",
  "barg": false
}, {
  "theatre": {
    "id": "10420",
    "name": "Violet Crown Cinema"
  },
  "dateTime": "2015-07-21T22:10",
  "barg": false
}, {
  "theatre": {
    "id": "10984",
    "name": "Alamo Drafthouse South Lamar"
  },
  "dateTime": "2015-07-21T14:15",
  "barg": false
}, {
  "theatre": {
    "id": "10984",
    "name": "Alamo Drafthouse South Lamar"
  },
  "dateTime": "2015-07-21T17:05",
  "barg": false
}, {
  "theatre": {
    "id": "10984",
    "name": "Alamo Drafthouse South Lamar"
  },
  "dateTime": "2015-07-21T19:50",
  "barg": false
}, {
  "theatre": {
    "id": "10984",
    "name": "Alamo Drafthouse South Lamar"
  },
  "dateTime": "2015-07-21T22:10",
  "barg": false
}];

function reduceShowtimes(showtimes) {
  var theatres = {}
  var showsReduced = showtimes.reduce(function(arr, obj) {
    var theatreName = obj.theatre.name;
    if (theatres[theatreName] !== undefined) {
      var theatreIndex = theatres[theatreName];
      var theatreObj = arr[theatreIndex];
      theatreObj.dateTime.push(obj.dateTime);
    } else {
      theatres[theatreName] = arr.length;
      obj.dateTime = [obj.dateTime];
      arr.push(obj);
    }
    return arr;
  }, []);
  return showsReduced;
}
var result = document.getElementById('result').innerHTML = JSON.stringify(reduceShowtimes(showtimes), null, '\t');
<pre id="result"></pre>

Upvotes: 0

Barmar
Barmar

Reputation: 782653

Change:

listing += thingToFind.append($("li").append(mTimeConverted + '</li>'));

to:

listing += '<li>' + mTimeConverted + '</li>';

After the loop is completed, do:

thingToFind.append(listing);

Upvotes: 0

Related Questions