'addEventListener' of undefined - javascript

I am trying to make it so that when the user clicks one of the 30 teams, the team that is clicked is queried with the Giphy API.
The giphy API key used is the public API key.
// all 30 NBA Teams //
var predefinedButtons = [
"Atlanta Hawks",
"Boston Celtics",
"Brooklyn Nets",
"Charlotte Hornets",
"Chicago Bulls",
"Cleveland Cavaliers",
"Dallas Mavericks",
"Denver Nuggets",
"Detroit Pistons",
"Golden State Warriors",
"Houston Rockets",
"Indiana Pacers",
"LA Clippers",
"LA Lakers ",
"Memphis Grizzlies",
"Miami Heat",
"Milwaukee Bucks",
"Minnesota Timberwolves",
"New Orleans Hornets",
"New York Knicks",
"Oklahoma City Thunder",
"Orlando Magic",
"Philadelphia Sixers",
"Phoenix Suns",
"Portland Trail Blazers",
"Sacramento Kings",
"San Antonio Spurs",
"Toronto Raptors",
"Utah Jazz",
"Washington Wizards"
];
console.log(predefinedButtons);
// The Buttons added dynamically //
var $nbaTeams;
var nbaButtons = function nbaGiphy() {
for ( i in predefinedButtons ) {
$nbaTeams = $("<button class='.btn btn-secondary' 'onclick='getNBAGiphy()''>").text(predefinedButtons[i]);
$("#nbaTags").append($nbaTeams);
}
}
nbaButtons();
// The code below is where the event listener is 'undefined' //
function getNBAGiphy() {
var nbaSearchGifs;
nbaSearchGifs.addEventListener('click', function() {
nbaSearchGifs = $(".btn btn-secondary").val();
xhr = $.get("http://api.giphy.com/v1/gifs/search?q="+nbaSearchGifs+"&api_key=dc6zaTOxFJmzC&limit=15");
xhr.done(function (response) {
console.log("success got data", response);
nbaTeamData = response.data
$("#giphyContent").html("");
console.log(nbaSearchGifs);
})
});
}
getNBAGiphy();

You are declaring variable and you have not assigned any value to it. So by default it is undefined. Code i am referring to is:
function getNBAGiphy() {
var nbaSearchGifs;
nbaSearchGifs.addeventListner

Related

Javascript: stuck with comparison function

I am stuck and need help finishing this fetch request.
I need a function to check if the movie (a single object) in the request has previously been rated by the user.
The ratings are in the ratedMovies array. If the movie was rated I need the userRating property with it's value to be added to the response. If it has not been rated, I need the userRating value to be null
const ratedMovies = useStore((state) => state.ratedMovies)
const getMovieDetails = () => {
const key = `https://www.omdbapi.com/?i=${movie.imdbID}&apikey=b46dc190`
axios
.get(key)
.then((response) => {
// Here a comparison is required, to check if the movie in the response (a single object)
// has ever been rated before and its ID (imdbID) and userRating (property to be added) is
// present in the ratedMovies array
// if it is present I need the property userRating nad it's value to be added to the response
// or when it is empty, to have the userRating be null
setModalDetails(response.data)
})
.then((response) => {
console.log(modalDetails)
})
.catch((error) => console.log(error))
}
Sample axios response:
{
"Title": "Star Wars: Episode V - The Empire Strikes Back",
"Year": "1980",
"Rated": "PG",
"Released": "20 Jun 1980",
"Runtime": "124 min",
"Genre": "Action, Adventure, Fantasy",
"Director": "Irvin Kershner",
"Writer": "Leigh Brackett, Lawrence Kasdan, George Lucas",
"Actors": "Mark Hamill, Harrison Ford, Carrie Fisher",
"Plot": "After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda, while his friends are pursued across the galaxy by Darth Vader and bounty hunter Boba Fett.",
"Language": "English",
"Country": "United States, United Kingdom",
"Awards": "Won 2 Oscars. 25 wins & 20 nominations total",
"Poster": "https://m.media-amazon.com/images/M/MV5BYmU1NDRjNDgtMzhiMi00NjZmLTg5NGItZDNiZjU5NTU4OTE0XkEyXkFqcGdeQXVyNzkwMjQ5NzM#._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "8.7/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "94%"
},
{
"Source": "Metacritic",
"Value": "82/100"
}
],
"Metascore": "82",
"imdbRating": "8.7",
"imdbVotes": "1,209,128",
"imdbID": "tt0080684",
"Type": "movie",
"DVD": "21 Sep 2004",
"BoxOffice": "$292,753,960",
"Production": "N/A",
"Website": "N/A",
"Response": "True"
}
Sample rating:
ratedMovies = [{imdbID: 'tt0080684', userRating: 8}]
Ok if I understand it correctly it goes like this:
let data = response.data;
let newMovieId = data.imdbID;
ratedMovies.forEach((movie) => {
if(movie.imdbID === newMovieId) {
data.userRating = movie.userRating;
}
});
setModalDetails(data)
code above goes inside the axios success callback
You can use .filter function like this:
ratedMovies = [{imdbID: 'tt0080684', userRating: 8}]
notratedMovies = [{imdbID: 'tt0080111', userRating: 8}]
let result = ratedMovies.filter(obj => {
return obj.imdbID === imdb.imdbID
});
console.log(result);
let notresult = notratedMovies.filter(obj => {
return obj.imdbID === imdb.imdbID
});
console.log(notresult);

Google Maps is undefined when I reload the page due to script loading issues, how can I fix this?

I've implemented the Google Maps API onto my page and it works perfectly except when I do a refresh of the screen.
Once I hit refresh, I get this type error:
Cannot read property of maps, undefined
Specifically, it's happening around line 28 in the Map class.
This is where I'm setting the script for my API and when I inspect the page I can see that it is present (even when I refresh the page):
class App extends Component {
// Render a script tag for scriptUrl in head of the HTML page
addScriptToPage(scriptUrl) {
const script = document.createElement("script");
script.src = scriptUrl;
document.head.appendChild(script);
}
componentDidMount() {
// CreateReactApp requires the REACT_APP_ prefix for env vars
let MAPS_API_KEY = process.env.REACT_APP_MAPS_API_KEY;
// place the google maps api as a script tag in the head
// this script places a google object on window.google
let mapsApiUrl = `https://maps.googleapis.com/maps/api/js?key=${MAPS_API_KEY}`;
this.addScriptToPage(mapsApiUrl);
}
render() {
return (
<div className='app-wrapper'>
<Modal />
<NavBarContainer />
<div className="app-main-content-wrapper">
<Switch>
<Route exact path='/' component={SpotIndex} />
<Route exact path='/spots/:spotId' component={SpotDetail} />
<Route exact path='/search/:find_loc' component={SearchContainer} />
</Switch>
</div>
</div>
);
}
};
And this is my Map class:
class Map extends Component {
constructor(props) {
super(props);
}
// Initially mounts the map with first search input
componentDidMount() {
this.drawMap(this.props.find_loc);
}
componentWillReceiveProps(newProps) {
this.drawMap(newProps.find_loc);
}
drawMap(address) {
// Solves problem of linting rule in ReactJS that forbids unknown global vars
const google = window.google;
const map = document.getElementById('map-container');
// Creating the map
MapUtil.setOptionsFromLocation(address)
.then(options => {
this.map = new google.maps.Map(map, options);
// before adding markers, set up bounds
let bounds = new google.maps.LatLngBounds();
// Displaying nearby spots
this.props.spots.forEach(spot => {
// Create a position from spot coordinates
const latitude = spot.latitude;
const longitude = spot.longitude;
const position = new google.maps.LatLng(latitude, longitude);
// Place markers on the map
const marker = new google.maps.Marker({
position,
map: this.map
});
// extend the bounds to fit this position
bounds.extend(position);
});
// Autozooming and autocentering if there are results
if (this.props.spots.length) {
// Autozooming
this.map.fitBounds(bounds);
// Adjust zooming value if too large
let theMap = this.map;
var listener = google.maps.event.addListener(theMap, "idle", function () {
if (theMap.getZoom() > 16) theMap.setZoom(16);
google.maps.event.removeListener(listener);
});
// Autocentering
this.map.panToBounds(bounds);
}
});
}
// Renders Map component
render() {
return <div id="map-container"></div>;
}
}
Per the suggestions below, it appears that the error is not in the above components. Doing some digging, I did find another place where I'm calling the Map component.
This is a general search component that renders both the Map and the SearchIndex (the search results):
class Search extends React.Component {
constructor(props) {
super(props);
this.state = { find_loc: this.props.find_loc };
}
// Triggers a re-render when component receives new props
componentWillReceiveProps(newProps) {
this.setState({ find_loc: newProps.match.params.find_loc });
}
// Gets spots matching search input
getSpots(spots) {
// Library of state abbreviations
const states = {
"AL": "alabama",
"AK": "alaska",
"AS": "american samoa",
"AZ": "arizona",
"AR": "arkansas",
"CA": "california",
"CO": "colorado",
"CT": "connecticut",
"DE": "delaware",
"DC": "district of columbia",
"FL": "florida",
"GA": "georgia",
"GU": "guam",
"HI": "hawaii",
"ID": "idaho",
"IL": "illinois",
"IN": "indiana",
"IA": "iowa",
"KS": "kansas",
"KY": "kentucky",
"LA": "louisiana",
"ME": "maine",
"MD": "maryland",
"MA": "massachusetts",
"MI": "michigan",
"MN": "minnesota",
"MS": "mississippi",
"MO": "missouri",
"MT": "montana",
"NE": "nebraska",
"NV": "nevada",
"NH": "new hampshire",
"NJ": "new jersey",
"NM": "new mexico",
"NY": "new york",
"NC": "north carolina",
"ND": "north dakota",
"OH": "ohio",
"OK": "oklahoma",
"OR": "oregon",
"PA": "pennsylvania",
"PR": "puerto rico",
"RI": "rhode island",
"SC": "south carolina",
"SD": "south dakota",
"TN": "tennessee",
"TX": "texas",
"UT": "utah",
"VT": "vermont",
"VI": "virgin Islands",
"VA": "virginia",
"WA": "washington",
"WV": "west Virginia",
"WI": "wisconsin",
"WY": "wyoming"
}
// Getting lowercased location string from search input
const location = this.state.find_loc;
let locationArr;
let lowercasedLocation = [];
let foundSpots = [];
if (location) {
locationArr = location.split(' ');
locationArr.forEach(word => lowercasedLocation.push(word.toLowerCase()));
lowercasedLocation = lowercasedLocation.join(' ');
}
// Searching for spots matching location
spots.forEach(spot => {
const city = spot.city.toLowerCase();
const stateAbbr = spot.state.toLowerCase();
const stateFull = states[spot.state];
if (city === lowercasedLocation || stateAbbr === lowercasedLocation || stateFull === lowercasedLocation) {
foundSpots.push(spot);
}
});
return foundSpots;
}
// Renders Search component
render() {
const { spots } = this.props;
const foundSpots = this.getSpots(spots);
return (
<div className="search-container">
<div className="search-results-wrapper">
<SearchIndex spots={foundSpots} find_loc={this.state.find_loc} fetchSpots={this.props.fetchSpots} />
<Map spots={foundSpots} find_loc={this.state.find_loc} />
</div>
<Footer />
</div>
);
}
}
I had a similar loading issue with SearchIndex earlier, due to the spots not being fetched when the page reloaded. But I solved it by explicitly telling the SearchIndex component to fetch all spots when the component was mounted; I thinking that perhaps it might be a similar issue for the Map (specifically window.google)?
Add a listener for the tilesloaded event:
this.map = new google.maps.Map(map, options);
this.map.addListener('tilesloaded', function () {
...

Get json array value from observable and give data to frontend

Trying get JSON array from json-server using observables and then giving the value to frontend and perform search on the JSON array received through observable
created a service and used HTTP get to connect to server and subscribed to it
created for loop to get value from returned value of subscription
**service.ts**
export class FormdtService {
baseul='http://localhost:3000/objects'//jsonserver url
constructor(private http:HttpClient) { }
getdt():Observable<any>{
return this.http.get(this.baseul)
}
}
**component.ts**
export class FormsComponent implements OnInit {
constructor(public fbu:FormBuilder,private fdts:FormdtService) {}
//creates the reactive form
form=this.fbu.group({
un:'',
id:''
})
// baseul='http://localhost:3000/objects/';
//ngsubmit control of form brings this function
ser(){
this.fdts.getdt().subscribe(dt=>{
console.log("data: "+dt[0])
this.formdt.push(dt)
//console.log("formdt :"+this.formdt[0])
for (let ite in this.formdt){
let ite1=JSON.parse(ite)
// console.log("ite :"+this.formdt[ite]);
//console.log("ite1"+ite1);
this.idlist.push(ite1.person.bioguideid.value)
if(ite1.person.bioguideid.stringify==this.idsearch)
this.objson=ite1
}});
}
idsearch:string
formdt:string[]
idlist:string[]
objson:JSON
ngOnInit() {
}
//this function is attached to button in frontend
ser(){
this.fdts.getdt().subscribe(dt=>
this.formdt.push(dt)//subscribes to service
for (let ite in this.formdt){
let ite1=JSON.parse(ite)
this.idlist.push(ite1.person.bioguideid.value)
if(ite1.person.bioguideid.value==this.idsearch)
this.objson=ite1
})}
**json**
[
{
"caucus": null,
"congress_numbers": [
114,
115,
116
],
"current": true,
"description": "Senior Senator for Tennessee",
"district": null,
"enddate": "2021-01-03",
"extra": {
"address": "455 Dirksen Senate Office Building Washington DC 20510",
"contact_form": "http://www.alexander.senate.gov/public/index.cfm?p=Email",
"fax": "202-228-3398",
"office": "455 Dirksen Senate Office Building",
"rss_url": "http://www.alexander.senate.gov/public/?a=rss.feed"
},
"leadership_title": null,
"party": "Republican",
"person": {
"bioguideid": "A000360",
"birthday": "1940-07-03",
"cspanid": 5,
"firstname": "Lamar",
"gender": "male",
"gender_label": "Male",
"lastname": "Alexander",
"link": "https://www.govtrack.us/congress/members/lamar_alexander/300002",
"middlename": "",
"name": "Sen. Lamar Alexander [R-TN]",
"namemod": "",
"nickname": "",
"osid": "N00009888",
"pvsid": "15691",
"sortname": "Alexander, Lamar (Sen.) [R-TN]",
"twitterid": "SenAlexander",
"youtubeid": "lamaralexander"
},
"phone": "202-224-4944",
"role_type": "senator",
"role_type_label": "Senator",
"senator_class": "class2",
"senator_class_label": "Class 2",
"senator_rank": "senior",
"senator_rank_label": "Senior",
"startdate": "2015-01-06",
"state": "TN",
"title": "Sen.",
"title_long": "Senator",
"website": "https://www.alexander.senate.gov/public"
},//end of single json array object
{
"caucus": null,
"congress_numbers": [
114,
115,
116
],
"current": true,
"description": "Senior Senator for Maine",
"district": null,....same repetition of structure
The ser function should give whole JSON array present in server to formdt[] and then iterate over it and get every object and convert to JSON and push bioguide to id array,search id from input and match with JSON nested value of each object in the array
nothing happens gives error in console :
_this.formdt is undefined at line 37 (this.fdts.getdt().subscribe(dt=>this.formdt.push=dt))
Given error is pretty explicit : this.formdt is undefined.
You've declared preperty type but haven't initialize it.
So replace formdt:string[] with formdt:string[] = []

jQuery: How do I deal with self-closing tags and multiple loops?

I have 3 arrays: one with a list of cities, one with a list of states (which correspond to the cities), and one that's just a list of states with the duplicates removed.
I'm trying to generate a list that looks like this:
State 1
City 1
City 2
State 2
City 3
Here's what I've got:
$.each(stateArrayUnq, function(i) {
$('#list').append("<li>" + stateArrayUnq[i] + "<ul>");
$.each(stateArray, function(j) {
if (stateArray[j] == stateArrayUnq[i]) {
$('#list').append("<li>" + cityArray[j] + "<\/li>");
}
});
$('#list').append("<\/ul><\/li>");
});
I know I can't structure my code like this without having the browser auto-close my tags prematurely, but unfortunately I don't have the slightest idea how to rebuild this. I've read through a few related threads, but I'm still pretty confused. I think I'm supposed to set the "append" code to variables or something, but I don't know how to handle the loops.
I appreciate any help you can give. Thanks a bunch!
UPDATE: Here are my arrays:
var cityArray = ["Concord", "Lafayette", "Lewisville", "Madison", "NW Freeway Houston", "North Miami", "Casselberry", "South Fort Myers", "SW Freeway", "Woodbury", "Tarpon Springs"]
var stateArray = ["North Carolina", "Louisiana", "Texas", "Wisconsin", "Texas", "Florida", "Florida", "Florida", "Texas", "Minnesota", "Florida"]
var statearrayUnq = ["Florida", "Louisiana", "Minnesota", "North Carolina", "Texas", "Wisconsin"]
You can do this by building an html string which is stored in a variable. When you are done with your logic you can append the build html string.
//Test data
var cityArray = ["Concord", "Lafayette", "Lewisville", "Madison", "NW Freeway Houston", "North Miami", "Casselberry", "South Fort Myers", "SW Freeway", "Woodbury", "Tarpon Springs"];
var stateArray = ["North Carolina", "Louisiana", "Texas", "Wisconsin", "Texas", "Florida", "Florida", "Florida", "Texas", "Minnesota", "Florida"];
var stateArrayUnq = ["Florida", "Louisiana", "Minnesota", "North Carolina", "Texas", "Wisconsin"];
//Generate the html string and append it.
var html = "";
$.each(stateArrayUnq, function(i) {
html += "<li>" + stateArrayUnq[i] + "<ul>";
$.each(stateArray, function(j) {
if (stateArray[j] == stateArrayUnq[i]) {
html += ("<li>" + cityArray[j] + "<\/li>");
}
});
html += "<\/ul><\/li>";
});
$('#list').append(html);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<p>test</p>
</div>
If list were a ul, you could nest them using actual jQuery objects like so.
var cityArray = ["Concord", "Lafayette", "Lewisville", "Madison", "NW Freeway Houston", "North Miami", "Casselberry", "South Fort Myers", "SW Freeway", "Woodbury", "Tarpon Springs"];
var stateArray = ["North Carolina", "Louisiana", "Texas", "Wisconsin", "Texas", "Florida", "Florida", "Florida", "Texas", "Minnesota", "Florida"];
var data = cityArray.map((c,i) => ({state: stateArray[i], city: c})); //flatten the data
var $list = data.reduce(($ul, item) => {
var $cityLi = $(`<li>${item.city}</li>`); //Create <li> for city
var $stateLi = $ul.children(`li[data-state='${item.state}']`); //Find state <li>
if (!$stateLi.length) //Create state <li> if it doesn't yet exist
$stateLi = $(`<li data-state='${item.state}'>${item.state}<ul></ul></li>`);
$stateLi.children("ul").append($cityLi).end().appendTo($ul); //Add the city to the state
return $ul;
}, $("<ul />"));
$("body").append($list);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Set and Display current Data on ng-click?

I'm using Yeoman - angular generator.
JSBin: JSBin Link
I have a simple list of airports being set from a factory angApp.factory("Airports", function() {}); and displayed from ng-repeat <ul ng-repeat="airport in airports.detail">.
I would like to have an interaction that when each link is clicked it will match the airport code and display it in a new paragraph tag <p class="current">Current: {{currentAirport.name}}</p>.
Why wont the setAirport(airport.code) function set the currentAirport.name(or display?) when airport link is clicked in html?
Controller
angular.module("ang6App")
.controller("AirportsCtrl", function ($scope, Airports) {
$scope.formURL = "views/_form.html";
$scope.currentAirport = null;
$scope.airports = Airports;
$scope.setAirport = function(code) {
$scope.currentAirport = $scope.airports[code];
};
});
Factory Service in the same module
angApp.factory("Airports", function() {
var Airports = {};
Airports.detail = {
"PDX": {
"code": "PDX",
"name": "Portland International Airport",
"city": "Portland",
"destinations": [
"LAX",
"SFO"
]
},
"STL": {
"code": "STL",
"name": "Lambert-St. Louis International Airport",
"city": "St. Louis",
"destinations": [
"LAX",
"MKE"
]
},
"MCI": {
"code": "MCI",
"name": "Kansas City International Airport",
"city": "Kansas City",
"destinations": [
"LAX",
"DFW"
]
}
};
return Airports;
});
HTML
<div class="container" ng-controller="AirportsCtrl">
<ul ng-repeat="airport in airports.detail">
<li>{{airport.code}} -- {{airport.city}} </li>
</ul>
<p class="current"> current: {{currentAirport.name}}</p>
</div>
Your setAirport function should be written as:
$scope.setAirport = function (code) {
$scope.currentAirport = $scope.airports.detail[code];
};
But then, this could be simplified by passing the actual airport object directly:
<a href ng-click="setAirport(airport)">{{airport.code}}</a>
$scope.setAirport = function (airport) {
$scope.currentAirport = airport;
};

Categories

Resources