Reputation: 3990
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
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
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
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