WANDERLUST Project Requests JS


#1

Hi :slight_smile:

Course: Introduction to JavaScript -> Requests -> Wanderlust Project

I have a problem with the second part of task 43:
Return more than 4 venues and randomize which ones are added to the page.

I don’t even know how to start.
Any suggestions?
Thanks.


JS Requests: Project Wanderlust
#2

Please post a link to the exercise or project. Thanks.


#3

link: https://www.codecademy.com/courses/intermediate-javascript-requests/projects/wanderlust?course_redirect=introduction-to-javascript


#4

I have a general idea that somewhere should be ‘for’ and ‘random’ but I do not know where to put it and I could be wrong. The requests are new for me and I don’t handle them too well. Brainwashed :confused:


#5

Not having done that project, I can only speculate. Am I safe to assume you have pulled down a number of objects and have them in an array? If that is the case, then create a loop with four iterations. If doesn’t have to be a for since we won’t be using the iterator.

// assume a data object for this demo
let choices = [];
while (choices.length < 4) {
    choices.push(data[Math.floor(Math.random() * data.length)]);
}

Now you have four random choices to distribute to the page.

The above does not test for duplicates. Another approach would be to just stack the indexes, to start with, then populate the page using those indexes.

let choices = [];
while (choices.length < 4) {
    let x;
    while (true) {
        x = Math.floor(Math.random() * data.length);
        if (choices.indexOf(x) === -1) {
            choices.push(x);
            break;
        }
    }
}

#6

this is my code:

// Foursquare API Info
const clientId = '';
const clientSecret = '';
const url = 'https://api.foursquare.com/v2/venues/explore?near=';
const imgPrefix = 'https://igx.4sqi.net/img/general/150x200';

// APIXU Info
const apiKey = '';
const forecastUrl = 'https://api.apixu.com/v1/forecast.json?key=';

// Page Elements
const $input = $('#city');
const $submit = $('#button');
const $destination = $('#destination');
const $container = $('.container');
const $venueDivs = [$("#venue1"), $("#venue2"), $("#venue3"), $("#venue4"), $("#venue5")];
const $weatherDivs = [$("#weather1"), $("#weather2"), $("#weather3"), $("#weather4")];
const weekDays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

// AJAX functions
// Forsquare (venue) response object
async function getVenues() {
  const city = $input.val();
  const urlToFetch = url + city + '&venuePhotos=1&limit=10&client_id=' + clientId + '&client_secret=' + clientSecret + '&v=20171121';
  try { 
    let response = await fetch(urlToFetch);
    if(response.ok) {
      let jsonResponse = await response.json();
      console.log(jsonResponse);
      let venues = jsonResponse.response.groups[0].items.map(location => location.venue);
      console.log(venues);
      return venues;
    }
  } catch (error){
    console.log(error);
  }
};

// Apixu (forecast) response object
async function getForecast() {
  const urlToFetch = forecastUrl + apiKey + '&q=' + $input.val() + '&days=4&hours=11';
  try {
    let response = await fetch(urlToFetch);
    if(response.ok) {
      let jsonResponse = await response.json();
      console.log(jsonResponse);
      let days = jsonResponse.forecast.forecastday;
      return days;
    }
  } catch (error) {
    console.log(error);
}
}


// Render functions
function renderVenues(venues) {
  $venueDivs.forEach(($venue, index) => {
    let venueContent =
      '<h2>' + venues[index].name + '</h2>' +
      '<img class="venueimage" src="' + imgPrefix +
      venues[index].photos.groups[0].items[0].suffix + '"/>' +
      '<h3>Address:</h3>' +
      '<p>' + venues[index].location.address + 			             '</p>' +
      '<p>' + venues[index].location.city + '</p>' +
      '<p>' + venues[index].location.country + '</p>' +       '<p> Rating: ' + venues[index].rating + '</p>';
    $venue.append(venueContent);
  });
  $destination.append('<h2>' + venues[0].location.city + '</h2>');
}

function renderForecast(days) {
  $weatherDivs.forEach(($day, index) => {
    let weatherContent =
      '<h2> High: ' + days[index].day.maxtemp_c +                 '</h2>' +
      '<h2> Low: ' + days[index].day.mintemp_c +                 '</h2>' +
      '<h2> Rainfall: ' + days[index].day.totalprecip_mm       + '</h2>' +
      '<img src="http://' +          
      days[index].hour[0].condition.icon +
      '" class="weathericon" />' + '<h2>' +          
      weekDays[(new Date(days[index].date)).getDay()] +           '</h2>';
    $day.append(weatherContent);
  });
}

function executeSearch() {
  $venueDivs.forEach(venue => venue.empty());
  $weatherDivs.forEach(day => day.empty());
  $destination.empty();
  $container.css("visibility", "visible");
  getVenues().then(venues => renderVenues(venues));
  getForecast().then(forecast => renderForecast(forecast));
  return false;
}

$submit.click(executeSearch)

#7

Still just a guess but I’m assuming this will involve the renderVenues function?


#8

Thanks very much. It helps a lot. Now I’m going to bed (it’s midnight time in my country). “I’ll think of it tomorrow, at Tara". :smiley: Bye, bye.


#9

Ping this topic when you get back to work on this. I’d like to see how you handle it.


#10

Just inside the function, before the forEach, call a function using the code above to generate four (or however many) random choices, and return them to a local array. Change venues to the name of the array inside the loop.

Eg.

const getChoices = (data, count) => {
  let choices = [];
  while (choices.length < count) {
    let x;
    while (true) {
      x = Math.floor(Math.random() * data.length);
      if (choices.indexOf(x) < 0) {
        choices.push(x);
        break;
      }
    }
  }
  return choices
}

Now inside the render function,

function renderVenues(venues) {
  const data = getChoices(venues, 4);
  data.forEach( ...


#11

That’s what I was thinking also.


#12

trying to come up with a solution now


#13

It might be simpler to return an array of objects (from getChoices) so the index does not have be used in the render function. It means a slight tweak to the helper function.


#14

Hi guys:)
I took the easier way with it and came up with this:
function renderVenues(venues) {



// Example of adding venues from array
  let randomVenues = [];
  for (let i = 0; i < 5; i++) {
    randomVenues.push(venues[Math.floor(Math.random() * venues.length)]);
  }
  
  randomVenues.forEach((venue, index) => {
  let venueContent = '<h2>' + venue.name + '</h2>' +
      '<img class="venueimage" src="' + imgPrefix +
      venue.photos.groups[0].items[0].suffix + '"/>' +
      '<h3>Address:</h3>' +
      '<p>' + venue.location.address + 			             '</p>' +
      '<p>' + venue.location.city + '</p>' +
      '<p>' + venue.location.country + '</p>' + '<p> Rating: ' + venue.rating + '</p>';
  
    $venueDivs[index].append(venueContent);
  })
  
  /*
  $venueDivs.forEach(($venue, index) => {
    let venueContent = 
      '<h2>' + venues[index].name + '</h2>' +
      '<img class="venueimage" src="' + imgPrefix +
      venues[index].photos.groups[0].items[0].suffix + '"/>' +
      '<h3>Address:</h3>' +
      '<p>' + venues[index].location.address + 			             '</p>' +
      '<p>' + venues[index].location.city + '</p>' +
      '<p>' + venues[index].location.country + '</p>' + '<p> Rating: ' + venues[index].rating + '</p>';
    $venue.append(venueContent);
  });
 */
  $destination.append('<h2>' + venues[0].location.city + '</h2>');
}

The problem is a duplicates venues


#15

Hi guys,
I have a problem with finding the proper way to obtain an url. I understand the hint in the exercise:

const urlToFetch = url + city + ‘&venuePhotos=1&limit=10&client_id=’ + clientId + ‘&client_secret=’ + clientSecret + ‘&v=20170305’;

But I cannot find guidelines on

https://developer.foursquare.com/docs/api/venues/photos

Could anyone help me find an answer like there is no hint? Not sure where fixed parts of urlToFetch come from.

Thanks!