Random Quote Machine - Cant tweet quote - javascript

I have to tweet a quote that I randomly generated using APIs, but my code isn't working. Here is my code, I added comments trying to make it look clearer. I am a novice in coding so it probably has a terrible sintax.
I manage to get my quote by clicking on the "Get another quote" button, but when i want to tweet my quote, clicking on the "Tweet quote" button it wont work and i get the "Uncaught ReferenceError: data is not defined
at pen.js:10" error.
I dont know what i am doing wrong.
(This is a task for FreeCodeCamp). Thanks to everyone who will answer!
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css">
<h2 class="title">Random Quote Generator</h2>
<h4 class="subtitle">A project for the FreeCodeCamp challenge</h4>
<div class="container-box">
<div class="container-quote">
<p class="quote" id ="quote"></p>
<div class="container-author" id="author">
<p></p>
</div> <!--closing div for container author-->
<div class="row">
<div class="col-md-6">
<button id="tweetQuote" href="https://twitter.com/intent/tweet?text=data.quoteText">Tweet this quote!</button>
</div>
<div class="col-md-6">
<button id="newQuote">Get another quote</button>
</div>
</div> <!--row-->
</div> <!--closing div for container quote-->
</div> <!--closing div for container-->
And now the javascript
//setting html elements to variables
var $newQuote = $('#newQuote');
var $quote = $('#quote');
var $tweetQuote = $('#tweetQuote');
//execute function by clicking on button
$newQuote.click(getQuote);
$tweetQuote.click(tweetIt);
var text = data.quoteText;
var author = data.quoteAuthor;
//when getQuote is called call the APIs and get the quote by executing
getQuoteFromAPI
function getQuote() {
$quote.empty();
getQuoteFromAPI();
};
function getQuoteFromAPI() {
var url='https://api.forismatic.com/api/1.0/?
method=getQuote&format=jsonp&lang=en&jsonp=?';
//when the APIs are completely called execute the parseQuote function
$.getJSON(url).done(parseQuote);
//log the datas on the console and transform them into real html elements
function parseQuote (response) {
console.log(response);
document.getElementById('quote').innerHTML = response.quoteText;
document.getElementById('author').innerHTML = response.quoteAuthor;
};
};
function tweetIt() {
var url='https://api.forismatic.com/api/1.0/?
method=getQuote&format=jsonp&lang=en&jsonp=?';
$('#tweetQuote').attr('href', 'https://twitter.com/intent/tweet?text=' + text + '-' + author);
};

Related

Second AJAX call not functioning

Last Update
I realized why I was getting undefined when I created the result2 variable I set it to undefined instead of let result2 = ''; setting it to a string. Once I made that adjustment the undefined went away. Final script.js is below.
Update 4
It finally works it came down to the following line which was incorrect document.querySelectorAll("weathers").innerHTML = result2; I had to go back and change weathers to an id and not a class and I had to change the line above to document.querySelector("#weathers").innerHTML += result2; and now it works. I just have to figure out on my own why I get an undefined in my code see image.
Update 3
I am down to my last portion which is I get the results I want if I console log my results which look like this:
With this line I am not getting anything in my html document.querySelectorAll("weathers").innerHTML = result2; I am going to try something else to see if I could get this to work. If you notice though I am getting an undefined in my code in the image does anyone know if that impacts why I am not getting any output? I get no error messages either.
UPDATE 2
I made the adjustments to eliminate too much code the updates code will just be in my script.js file listed below. I get the following output which is an array of objects:
When I run the code I get the following error message:
Uncaught TypeError: Cannot read property 'name' of undefined
at XMLHttpRequest.xhr2.onload (script.js:57) xhr2.onload # script.js:57 load (async) loadWeathers # script.js:33
I am going to work on the correct syntax to extract the information I need since it is now an array of objects and not just an object.
UPDATE 1
With a suggestion below I was able to finally get something to work off of. Now I can see that instead of giving me one city at a time it is putting all of the cities inside of the api request url and I get the following error message:
script.js:77 GET
http://api.openweathermap.org/data/2.5/weather?q=San_Francisco,Miami,New_Orleans,Chicago,New_York_City&APPID=XXXXXXXX
404 (Not Found)
Background:
I am learning about API's and am building a mini weather web app. I am learning the long way Vanilla Javascript before I move onto doing the same thing in Jquery.
Goal:
I would like to have two things going on at once:
When a user inputs a name of a city a card will pop up with weather information.
When a user visits the page there will be already about five major cities populated on the page like so:
What I have so far:
So far I have been able to build the functionality for the input so when a user inputs the name of the city a card will pop up on the page and looks like this:
I also have some code to get into the next topic which is my problem.
Problem:
I have added a second ajax call that contains an array of cities that will be added to the URL. I have added a second button ("Get Weathers") for testing purposes that when I click on the button all of the cities will pop up like in the first image. I have done some research but everything I find involves jquery and not vanilla javascript Ajax. I cannot figure out why nothing is populating. I have checked the console for errors and I am not getting any. When I check the network traffic I am not getting any call requests. I am not getting anything and I cannot figure out why.
Here is my html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<LINK REL=StyleSheet HREF="style.css" TYPE="text/css">
<title>Current Weather App</title>
</head>
<body>
<main role="main">
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Today's Weather</h1>
<p class="lead text-muted">Curious about weather in your location? Just fill in below and submit.</p>
<p>
<div class="input-group mb-3">
<input type="text" class="form-control" id="city">
<div class="input-group-append">
<button class="btn btn-outline-secondary" id="buttonW" type="button">Get Weather</button>
<button class="btn btn-outline-secondary" id="buttonW2" type="button">Get Weathers</button>
</div>
</div>
</p>
</div>
</section>
<div id="weather"></div>
<div class="album py-5 bg-light">
<div class="container">
<div class="row" id="weathers"></div>
</div>
</div>
</main>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous">
</script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous">
</script>
<script src="script.js"></script>
</body>
</html>
Here is my FINAL script.js file:
// Create an event listener
document.getElementById("buttonW").addEventListener("click", loadWeather);
document.getElementById("buttonW2").addEventListener("click", loadWeathers);
///////////////THIS IS PART OF THE loadWeathers///////////////////////////////////////////////////////////////////////////////////////////
function getCity(locations) {
for (let i = 0; i < locations.length; i++) {
}
return locations;
}
function loadWeathers() {
let xhr2 = new XMLHttpRequest();
const cities = [
"5368361",
"4173495",
"4335045",
"4887398",
"5128638"
];
const base_path2 =
"http://api.openweathermap.org/data/2.5/group?id=" + getCity(cities) + "&APPID=XXXXXXXXXXXXXXXXXXXXXX";
xhr2.open("GET", base_path2, true);
xhr2.onload = function () {
if (this.status == 200) {
let cityWeathers2;
try {
cityWeathers2 = JSON.parse(this.responseText);
} catch (e) {
// JSON not valid, show error message
}
console.log(cityWeathers2)
// //add weather info
for (let i = 0; i < cities.length; i++) {
let result2 = '';
result2 +=
`<div class="col-md-4">
<div class="card mb-4 box-shadow">
<div class="card-body">
<h5 class="card-title">${cityWeathers2.list[i].name}</h5>
<p class="card-text">Here are some weather details for your City</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Weather: ${cityWeathers2.list[i].weather[0].main} <img class="card-img-top weather-icon" src="${getIconURL(cityWeathers2.list[i].weather[0].icon)}" alt="Card image cap"></li>
<li class="list-group-item">Temperature: ${convertKtoF(cityWeathers2.list[i].main.temp) }° </li>
<li class="list-group-item">Wind Speed: ${convertMPStoMPH(cityWeathers2.list[i].wind.speed) } </li>
<li class="list-group-item">Geo Location: ${cityWeathers2.list[i].coord.lat} , ${cityWeathers2.list[i].coord.lon}</li>
</ul>
</div>`
// console.log(result2)
document.querySelector("#weathers").innerHTML += result2;
}
}
}
xhr2.send();
}
function loadWeather() {
// console.log(city);
let xhr = new XMLHttpRequest();
const city = document.getElementById("city").value;
const base_path =
"http://api.openweathermap.org/data/2.5/weather?q=" + city + "&APPID=XXXXXXXXXXXXXXXXXXXXXXX";
xhr.open("GET", base_path, true);
xhr.onload = function () {
// const city = document.getElementById("city").value;
if (this.status == 200) {
let cityWeathers;
try {
cityWeathers = JSON.parse(this.responseText);
} catch (e) {
// JSON not valid, show error message
}
const result =
`<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">${cityWeathers.name}</h5>
<p class="card-text">Here are some weather details for your City</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Weather: ${cityWeathers.weather[0].main} <img class="card-img-top weather-icon" src="${getIconURL(cityWeathers.weather[0].icon)}" alt="Card image cap"></li>
<li class="list-group-item">Temperature: ${convertKtoF(cityWeathers.main.temp) }° </li>
<li class="list-group-item">Wind Speed: ${convertMPStoMPH(cityWeathers.wind.speed) } </li>
<li class="list-group-item">Geo Location: ${cityWeathers.coord.lat} , ${cityWeathers.coord.lon}</li>
</ul>
</div>`;
document.getElementById("weather").innerHTML = result;
}
}
xhr.send();
}
// Convert from Kelvins to Fahrenheit
function convertKtoF(kelvin) {
return Math.round((kelvin - 273.15) * 1.8);
}
// Convert from Meters Per Second to Miles Per Hour
function convertMPStoMPH(mps) {
return (Math.round(10 * mps * 2.2369362920544) / 10) + " mph";
}
// Weather icon
function getIconURL(icon) {
return "https://openweathermap.org/img/w/" + icon + ".png";
}
Any guidance or suggestions would be greatly appreciated!
I can't speak to the accuracy of the request (per comments), but the problem is xhr2.send(); is within the body of your xhr2.onload function.
For multiple cities, you may need to use city Ids, see https://openweathermap.org/current#severalid. The docs don't seem to mention multiple cities by name as you are attempting to do.

JS function Cant get the Value from vbhtml

How can I get value from my html action link, I tried to set the value in js function and it is work, and the problem is js not get the value form html file, and this forloop only the first one will call the Javascript function.
this is my js function
function selectTemplate() {
$('#choose').on('click', function () {
var objTemplate = $(".styTemplate").val();
$.post(strRoot + "/Home/Index/", { styTemplate: objTemplate });
});
};
and this is my vbhtml code
#For Each item In Model
Dim currentItem = item
'<!-- single-awesome-project start -->
#<div Class="col-md-4 col-sm-4 col-xs-12 #Html.DisplayFor(Function(modelItem) currentItem.strTemplateType)">
<div Class="single-awesome-project">
<div Class="awesome-img">
<img src="#Url.Content("~/Content/TemplateCSS/img/portfolio/" & currentItem.strTemplateType & ".jpg")" alt="" />
<div Class="add-actions text-center">
<div Class="project-dec">
<a Class="venobox" data-gall="myGallery" href="#Url.Content("~/Content/TemplateCSS/img/portfolio/" & currentItem.strTemplateType & ".jpg")">
<h4>#currentItem.strTemplateName</h4>
<span> Web Development</span>
#Html.ActionLink("Choose", "companyInfomation", "Home", New With {.id = "choose"}, New With {.styTemplate = currentItem.strTemplateName})
</a>
</div>
</div>
</div>
</div>
</div>
'<!-- single-awesome-project end -->
Next
</div>
<script>
selectTemplate();
</script>
Maybe it's better to use onclick attribute? Use this instead of Html.ActionLink:
Choose

I have a 100 button, click each button to display its corresponding bomb box, With javascript and angular

a button corresponding to a prompt box,each box is different shells;Although implements the desired function, but my code is too complicated, and that there is no simple way. how can I do? This is my code
<--html button-->
button1
button2
...
button100
<--html pop box-->
<div class="note1" style="display:none;">
<img class="title-css" src="note1.png">
<p class="one">note1</p>
</div>
...
<div class="note100" style="display:none;">
<img class="title-css" src="note100.png">
<p class="one">note100</p>
</div>
<--angular js-->
$scope.showRulePop = function(index) {
for(var i=1;i<=8;i++) {
$('.note'+i).hide();
}
$('.note'+index).show();
};
Well first of all, don't use jQuery, unless your in the directive level of angular jQuery have nothing to do there.
First let's get rid of the links part using a simple ng-repeat :
<--html button-->
<div ng-repeat="button in buttons">
{{button.label[i]}}
</div>
// JS in the controller
$scope.buttons = [{
label:'button1'
},{label:'button2'}];
As you can see i declare in the javascript all your buttons and i just loop over it.
Now the "bombox" or whatever it is let's make it a simple template :
<div class="{{currentnote.class}}" ng-if="currentNote">
<img class="title-css" src="{{currentNote.img}}">
<p class="one">{{currentNote.content}}</p>
</div>
// and use ng-repeat for the eight first when there is no button selected
<!-- show 1 to 8 if note current note selected -->
<div ng-repeat="button in buttons1To8" ng-if="!currentNote">
<div class="{{button.note.class}}">
<img class="title-css" src="{{button.note.img}}">
<p class="one">{{button.note.content}}</p>
</div>
</div>
// JS
$scope.buttons = [{
label:'button1'
note:{class:'note1', img:'note1.png', content:'note1'//assuming no HTML or you' ll need something more
}},{label:'button2', note:{...}}, ...];
$scope.showRulePop = function(index){
$scope.currentNote = $scope.buttons[index].note;
}
$scope.buttons1To8 = $scope.buttons.slice(0, 8);//0 to 7 in fact
That's all, no need of jQuery.

Reload content from JS api in bootstrap container when button is clicked

I'm trying to make a random quote generator and I want to make the container with the content reload when I click a button in another container. The commented area "what should go here" is where I think the action code should go. I'm not sure if I should go with something like $('quotecontainer').container(function(){}); and go from there, or if something else is needed entirely.
Here's the JS:
$('#newquotebutton').button();
$('#newquotebutton').click(function(){
$(this).button('loading');
// what should go here
$(this).button('reset');
});
Here's the HTML:
<div id="wherebuttonis" class="jumbotron-transparent">
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4 text-center">
<button id="newquotebutton" class="btn btn-default" data-text-loading="loading...">New Quote</button></div></div></div></div>
<div id="quotetron" class="jumbotron-transparent">
<div id = "quotecontainer" class="container text-center">
<script type="text/javascript" src="http://www.brainyquote.com/link/quotefu.js"></script>
<small><i>more Funny Quotes</i></small></div></div>
The remote script you provided seem to provide only one quote per day...
So you'll have to create your own local array of quotes to pick another quotes:
var quotes = ['quote one', 'quote two', 'quote three'];
$('#newquotebutton').button();
$('#newquotebutton').click(function(){
var random_quote = quotes[Math.floor(Math.random()*quotes.length)];
$(this).button('loading');
$('#newquotebutton').text(random_quote);
$(this).button('reset');
});

how to change values in a hidden chunk of html code

I have this hidden block of code that i want to call based on the values that are received from server:
<div id="hiddenChart" style="display:none;">
<li style="height:auto;">
<div class="col-sm-4" id="chart_0_0">
<div class="panel panel-success" style="width:550px; height:auto;" id="accordion_0_0">
<div class="panel-heading">
<div class="btn-group" style="float:right;">
<i class="glyphicon glyphicon-minus" id="minimize_0_0"></i>
<i class="glyphicon glyphicon-remove" id="close_0_0"></i>
</div>
<h3 class="panel-title">title</h3>
</div>
<div class="panel-body" style="height:400px;">
<nvd3-multi-bar-chart data="Sec1Graf1Data" id="dataChart_0_0" height="400" showXAxis="true" reduceXTicks="true" showYAxis="true" showLegend="true" showControls="true" tooltips="true">
<svg></svg>
</nvd3-multi-bar-chart>
</div>
</div>
</div>
</li>
</div>
but i need to change some values: ids, tags, data variables.
I know how to show the code using "$('ul').append($('div').html());" but i have to change it before doing it.
How can i do it?
How do i define in which fields i have to insert the string i'me receiving?
Thk
UPDATE:
I was able put it to work, here is the fiddle with it fiddle.
When i inspect the element, the ids that i want to change, instead of #1, it returns chart_0_0.
Thank you all for your posts and help
You can get a reference to your div like this:
var $div = $('#hiddenChart');
To clone it,
var $clonedDiv = $div.clone();
Then, in the $cloneDiv object, you make the changes:
$clonedDiv.find(--selector of a node--).attr(atributeName, atributeValue); //change/add attribute
$clonedDiv.find(--selector of a node--).removeAttr(atributeName); //remove attribute
And so on. I won't explain how jQuery works, Lekhnath gave you a link.
Finally you insert the $clonedDiv with .appendTo() wherever you want. The original div remains untouched so you can clone it again and again.
Jquery Change text/html from a hidden div content :
Simple
maintain a copy of the hidden content
replace the content based on the element class/id selector with the server response
then paste the html into another div
replace the content of the hidden back to original (optional)
http://jsfiddle.net/austinnoronha/ZJ3Nt/
$(document).ready(function(){
var serverRes = {
title: "New Title In Header",
body: "New body text from server <\/br><nvd3-multi-bar-chart data=\"Sec1Graf1Data\" id=\"dataChart_0_0\" height=\"400\" showXAxis=\"true\" reduceXTicks=\"true\" showYAxis=\"true\" showLegend=\"true\" showControls=\"true\" tooltips=\"true\"><svg><\/svg><\/nvd3-multi-bar-chart>"
};
var tmpOldCont = $("#hiddenChart").html();
var counter = 1;
$(".serverres").click(function(){
$("#hiddenChart").find(".panel-body").html(counter + " = " + serverRes.body);
$("#hiddenChart").find(".panel-title").text(serverRes.title + " " + counter);
counter++;
$(".box-container").html($("#hiddenChart").html());
$("#hiddenChart").html(tmpOldCont);
});
});

Categories

Resources