I am getting an undefined when I try the post to twitter function. Should the quote_text variable be global and therefore accessible by the quoteTwitter function?
$(document).ready(function () {
loadJSON();
getQuote();
console.log(quote_text);
});
// Declare variables
var json_obj;
var num = 0;
var quote_text = "";
// Display a quote - this method is not perfect since the random number will repeat itself and it appears as if no new quote is delivered
function getQuote(callback) {
var html = "";
num = randNum();
quote_text = json_obj[num].quote;
html += "<strong> " + quote_text + " </strong>";
$("#quote").html(html);
$("#author").html(json_obj[num].author);
};
// Post the current quote on twitter
function quoteTwitter(quote_text){
var tweet = quote_text;
window.open('https://twitter.com/home?status=' +encodeURIComponent(tweet),"_blank");
}
Your function definition includes quote_text as a parameter, so inside the function it's trying to use that instead of the global variable with the same name. You're presumably not passing anything to the function when you call it, so it comes out as undefined.
You can fix this by changing this:
function quoteTwitter(quote_text){
to this:
function quoteTwitter(){
...but it'd probably be better in the long run to pass the correct value in as a parameter, if possible, instead of depending on global variables.
Related
I have a problem understanding Javascript's engine technique called hoisting.
I've tried to create a var in the top of my file to quickly access and edit, but i want to use a variable that has yet to be declared.
First attempt:
var easy_to_edit_value = "some text " + a_yet_to_be_defined_var;
//imagine loads of code so its hard to find the correct funtion to edit the log
function my_function (a_yet_to_be_defined_var){
console.log(easy_to_edit_value);
}
my_function("more text");
This generates an error at line 1 since a_yet_to_be_defined_var is not defined.
After looking at this post: post-by-apsillers i tried again but this time declaring the var without value (so its known but undefined untill declared somewhere futheron)
var a_yet_to_be_defined_var; // now its known so this error is gone
var easy_to_edit_value = "some text " + a_yet_to_be_defined_var;
function my_function (a_yet_to_be_defined_var){
console.log(easy_to_edit_value);
}
my_function("more text");
//still undefined
//new attempt with a fresh var being set in the function before being called
var new_var;
var easy_to_edit_value = "some text " + new_var;
function my_function2 (a_yet_to_be_defined_var2){
new_var = a_yet_to_be_defined_var2;
console.log(easy_to_edit_value);
}
my_function2("more text");
//still undefined
But this outputs: some text undefined where i was expecting the some text more text since i filled the var before asking for it.
Please note these functions aren't ran using my_function("something") but are triggered by this: client.on('message', my_function);, i've seen arrow function solutions for related questions but i'm not sure how i would get that to work here.
Is it possible to make this work?
Instead of defining a value called easy_to_edit_value, change it to a function called easy_to_call_function that will return "some text " concatenated with the current value of new_var.
Once a (var or let) variable is assigned, it must be reassigned or reevaluated each time.
let new_var;
const easy_to_call_function = () => "some text " + new_var;
function my_function2(a_yet_to_be_defined_var2) {
new_var = a_yet_to_be_defined_var2;
console.log(easy_to_call_function()); // Call the function
}
my_function2("more text");
You need to re-declare the variable inside of the function:
var new_var;
var easy_to_edit_value = "some text " + new_var;
function my_function2(a_yet_to_be_defined_var2) {
new_var = a_yet_to_be_defined_var2;
easy_to_edit_value = "some text " + new_var;
console.log(easy_to_edit_value);
}
my_function2("more text");
If one variable is changed, other variable will not update according to the new value. That kind of programming requires a really high level compiler, which not many people are willing to make. The programmer must update variables on their own.
I can't figure out what's wrong with the following code and why would it work when I do it using the second way. Can anyone please help me understand this?
I have this following Javascript code:
var clsFunc = function(prefix) {
var id = 0;
return function() {
id = id + 1;
console.log(prefix + id);
}
}
First way (did not work):
If I try to call this function like this nothing happens
clsFunc('div')
Second way (worked)
var getId = {'div': clsFunc('div')}
getId.div()
Result:
div1
undefined
getId.div()
Result:
div2
The clsFunc function creates a function and returns it. So just doing
clsFunc('div');
...is pointless, because it creates a function and then just throws it away, because you didn't store it anywhere.
The second way stores the function that was created in an object property. That function has a reference to the context that created it (the call to clsFunc), even though that call has returned, which contains the id variable. When you call the function (getId.div()), it adds 1 to id and then outputs the prefix ("div") followed by the new value if id (1, then 2, then, 3, etc.).
You don't need an object for your second way, you could just use a variable:
var clsFunc = function(prefix) {
var id = 0;
return function() {
id = id + 1;
console.log(prefix + id);
}
};
var f = clsFunc('div');
f(); // "div1"
f(); // "div2"
(The undefineds you're seeing are just because you're running this in a JavaScript console that shows you the result of calling the function; since the function doesn't return anything, the result of calling it is undefined.)
I've built a simple html input so that users can input a zip code and then I have a variable in javascript set to that input. I can console.log this to prove the variable is set and that it is a string. I then try to run an ajax call and sub in the zip but it doesn't work. I can console.log the variable at any stage and see the variable has been updated, but somehow it's a hoisting issue or something where the ajax call value 'userInputZip' always reads to what I initially set. The ajax call works when 'userInputZip' is initially set to a valid zipoAny help is appreciated.
$(document).ready(function(){
});//end of document.ready
var inputDate = '2015-12-04T20:00:00';
var inputZipCode = '60618';
var userInputZip;
function runAjax(){
console.log(userInputZip);
$.ajax(getJambaseData);
}
// var dataArr = [];
var getJambaseData = {
type: 'get',
url:
'http://api.jambase.com/events?zipCode='+userInputZip+'&api_key=[inserted my key here]',
// 'http://api.jambase.com/events?zipCode='+userInputZip+'&api_key=[inserted my key here]',
success: function (data){
for (i=0; i< 10; i++){
if(data.Events[i].Date == inputDate){
var shortDate = data.Events[i].Date.substring(0,10);
var shortTime = data.Events[i].Date.substring(11,19);
// dataArr.push(data.Events[i].Date, data.Events[i].Artists[0].Name);
$("#divID").append('</p>' + 'date::: '+ shortDate + ' time:::' + shortTime + ' show::: ' + data.Events[i].Artists[0].Name + ' time::: ' + data.Events[i].Date + ' address::: ' + data.Events[i].Venue.Address + ' city::: ' + data.Events[i].Venue.City + '</p>');
}
}
},
error: function(){
console.log('failed');
},
}
function findShows(){
var userZip = document.getElementById("userInput");
userInputZip = userZip.value;
document.getElementById("divID").innerHTML = userInputZip;
runAjax();
}
////////////////////
You've mentioned
but somehow it's a hoisting issue or something where the ajax call value 'userInputZip' always reads to what I initially set
You define getJambaseData as a variable when the script is initially executed. You set the url value to url:
'http://api.jambase.com/events?zipCode='+userInputZip+'&api_key=[inserted my key here]'. What else did you expect to happen?
That's like saying var x = 10; and expecting it to magically change when you call a function.
What you have to do is move the whole var getJambaseData = {...} initialization into runAjax function and it should fix it. Or you could skip the variable initialization part and just pass the part inside {...} (including the curly braces obviously) inside the $.ajax call instead of variable. If you look at jQuery docs you'll see that in most examples and it's the usual syntax.
Not related to your question, but here are some friendly words of advice:
Don't use variable before you define it (reading top to bottom), it will save you a lot of headaches.
Another recommendation is don't use so much global variables, you could get the userInputZip inside findShows function and pass it to runAjax as function argument. If you'll develop applications in a way where you rely on global state a lot, you'll have a bad time very soon.
I am writing an extension for Google Chrome in HTML/Javascript. I am trying to use a global variable to pass information between two functions, however even if I assign my variable in one function it hasn't changed when I read it from the other function.
var type = 0; //define global variable
window.onload=function(){onCreated()}; //set onCreated function to run after loading HTML
function onCreated()
{
chrome.history.search({'text': ''},function(historyItems){gotHistory(historyItems)});//search for historyItems and then pass them to the gotHistory function
}
function gotHistory(historyItems)
{
var idcount=0;//used to increment the ids of each new element added
for(var count=0; count < historyItems.length; count++)//go through each history item
{
chrome.history.getVisits({'url':historyItems[count].url}, function(visitItems){gotVisits(visitItems)}); //search for visitItems for the url and pass the results to gotVisists function (atm all this function does is assign the global variable to =3)
var body = document.getElementById("outputid");//find the body of the HTML
var newt = document.createElement("p");//create a new element
newt.setAttribute("id","url"+idcount);//give it a unique id
newt.innerHTML = historyItems[count].title;//set the text to say the title of the url
if(type != 0)//if the other function was successful, type=3 and the text should be green
{
newt.style.color="green";
}
body.appendChild(newt);//add the new element to the body
idcount++;
}
}
function gotVisits(visitItems)
{
//assign the global variable to be 3
type = 3;
}
But, the elements are NEVER green. They should always be green. This means that in the function gotVisits, type is not being successfully assigned to 3.
Can anyone explain what is going on here?
Cheers,
Matt
p.s I realise the gotVisits function is useless here really, but I'm using it to demonstrate a point. In reality I will use it to pass back useful information to
Rather than:
var type = 0;
Try:
window.type = 0;
Optionally you can also use a closure such as:
(function() {
var type = 0;
var type = 0; //define global variable
window.onload=function(){onCreated()}; //set onCreated function to run after loading HTML
function onCreated()
{
chrome.history.search({'text': ''},function(historyItems){gotHistory(historyItems)});//search for historyItems and then pass them to the gotHistory function
}
function gotHistory(historyItems)
{
var idcount=0;//used to increment the ids of each new element added
for(var count=0; count < historyItems.length; count++)//go through each history item
{
chrome.history.getVisits({'url':historyItems[count].url}, function(visitItems){gotVisits(visitItems)}); //search for visitItems for the url and pass the results to gotVisists function (atm all this function does is assign the global variable to =3)
var body = document.getElementById("outputid");//find the body of the HTML
var newt = document.createElement("p");//create a new element
newt.setAttribute("id","url"+idcount);//give it a unique id
newt.innerHTML = historyItems[count].title;//set the text to say the title of the url
if(type != 0)//if the other function was successful, type=3 and the text should be green
{
newt.style.color="green";
}
body.appendChild(newt);//add the new element to the body
idcount++;
}
}
function gotVisits(visitItems)
{
//assign the global variable to be 3
type = 3;
}
})();
This saves you from polluting the window object, which you should avoid doing anyhow and allows the inner functions access to the type variable.
It should do what you want.
Also the outer function wrapper for your window.onload is redundant, just do:
window.onload = onCreated;
It looks like chrome.history.getVisits executes the callback asynchronously, so you first try to check that variable, and it gets updated later. You can verify this with a pair of console.log messages.
Move the rest of the code inside the callback, so it gets executed at the right time.
I'm writing an application in javascript and cannot figure it out how to access the variables declared in my function, inside this jquery parse. Inside I can access global variables, but I don't really want to create global vars for these values.
Basically I want to extract file names from an xml document in the simulationFiles variable. I check if the node attribute is equal with the simName and extract the two strings inside the xml elements, that part I think it's working.
How can I extract those xml elements and append them to local variables?
function CsvReader(simName) {
this.initFileName = "somepath";
this.eventsFileName = "somepath";
$(simulationFiles).find('simulation').each(function() {
if ($(this).attr("name") == simName) {
initFileName += $(this).find("init").text();
eventsFileName += $(this).find("events").text();
}
});
}
The this in the CsvReader function is not the same this in the each() callback (where instead it is the current element in the iteration). To access the scope of the outer function within the callback, we need to be able to reference it by another name, which you can define in the outer scope:
function CsvReader(simName) {
this.initFileName = "somepath";
this.eventsFileName = "somepath";
var self = this; // reference to this in current scope
$(simulationFiles).find('simulation').each(function() {
if ($(this).attr("name") == simName) {
// access the variables using self instead of this
self.initFileName += $(this).find("init").text();
self.eventsFileName += $(this).find("events").text();
}
});
}
I made a working demo (I changed it to use classes so it would work with HTML).
function CsvReader(simName) {
this.initFileName = "somepath";
this.eventsFileName = "somepath";
var context = this;
$(simulationFiles).find('simulation').each(function() {
if ($(this).attr("name") == simName) {
context.initFileName += $(this).find("init").text();
context.eventsFileName += $(this).find("events").text();
}
});
}
The simplest change you can do to make it work is... Change your function in each from normal ( function() {}) to arrow function ( () => {} ) that will automatically take the context of the function in which it is defined.