I am trying to make a simple Chrome Extension.
At the top of the document, I have put var maxLengthVar;.
I have stored a number using the chrome.storage API. I am getting the value using:
chrome.storage.sync.get('maxLength', function (items) {
maxLengthVar = items.maxLength;
console.log(maxLengthVar);
});
The console.log displays the correct value (2). But when I try to use this variable, I get undefined:
console.log(maxLengthVar);
document.getElementById("textToChange").innerHTML = maxLengthVar;
Note: this code is directly below the first piece of code.
I expect to have the console log the number 2 and the div textToChange's content to change to 2, but, instead, I get undefined in the console and the div stays the same. Why is this?
From what I understand, I have a global variable because at the top of the document, I declared the variable, so what makes the document.getElementById... not read the variable?
Another thing is that even though the console.log's I said above are in the same order in the document, they appear in the console reversed (ie. I get undefined first and then 2.) I know because I added some text ('text' + maxLengthVar) to the console.log's. Why is this?
You need to read up on async methods.
Basically the get method is an async method. While this method is executing the remainder of your script will execute printing out undefined
chrome.storage.sync.get('maxLength', function (items) {
maxLengthVar = items.maxLength;
console.log(maxLengthVar);
});
// <- at this point the async GET method may not have finished executing
// but your code continues anyway
console.log(maxLengthVar);
document.getElementById("textToChange").innerHTML = maxLengthVar;
Your code can be re-written using callbacks
chrome.storage.sync.get('maxLength', function (items) {
maxLengthVar = items.maxLength;
document.getElementById("textToChange").innerHTML = maxLengthVar;
});
Related
I have a script that scrapes a website and is supposed to send data back to client... JUST SO YOU KNOW IT'S ALL WITHIN app.get
Here is the code... The second .then does not work. It's supposed to send the arrays to the client after they have been populated once cheerio iterated through them. Yet it does not work... Maybe something wrong with the way I set up the second promise? Please help.
axios.get("https://www.sciencenews.org/").then(function(response){
var $ = cheerio.load(response.data);
$("div.field-item-node-ref").each(function(i,element){
if($(element).children('.ad').length == 0 && $(element).children('article').length > 0) {
array1.push($(element).find('h2.node-title').text());
array2.push($(element).find('div.content').text());
array3.push(`https://www.sciencenews.org${$(element).find('a').attr('href')}`);
array4.push(`${$(element).find('img').attr('src')}`);
}
})
}).then(()=>{
res.send({titles:array1,summaries:array2,links:array3,base64img:array4});
})
In the provided code snippet, none of the arrays are declared and there is no res object to call 'send' on since none is passed into the function.
Once the arrays are declared and res is temporarily replaced with a console.log, it appears to work on my end.
Working Repl.it
I'm assuming on your end that this function is called within a route, so there should be a 'res' object available within the scope of this function. If that's the case, it looks like it was just a matter of declaring your arrays before pushing data to them.
I have a JS file where I initialize this variable:
var totalSlideNumber = $(".background").length;
in file scope. I then try to print it to console on the next line:
var totalSlideNumber = $(".background").length;
console.log($(".background").length);
But this always prints 0. When I print the same variable in a function I get 3:
function parallaxScroll(evt) {
console.log($(".background").length);
...
Why are the values different from file scope to function scope?
Why are the values different from file scope to function scope?
It's not a question of "file scope" and "function scope", it's simply that the value is changing between the time you first execute the code and the time you next execute the code.
Specifically, this code:
$(".background")
When that selector queries the DOM the first time, it doesn't find anything. So the number of results is 0. When you execute it again later, it does file matches. So the number of results is 3 in this case.
It sounds like the first time you're executing the code is before the DOM structure has fully loaded. So the elements you're looking for simply don't exist yet. You can wait until the DOM structure is loaded and ready by using a document.ready handler:
$(document).ready(function () {
console.log($(".background").length);
});
Or, shorter:
$(function () {
console.log($(".background").length);
});
I have a problem with QlikView in the browser: I have a listbox and try to access it using an initialize script.
The script is registered by using the InitWorkbench function, using its BodyOnLoadFunctionNames parameter. So far, this works, and the initializer is run at startup.
Inside the initializer I try to do the following:
var doc = Qv.GetCurrentDocument();
var listbox = doc.GetObject('LB01');
Afterwards, when I have a look at listbox.Type, unfortunately it is undefined. If I delay execution of this query, it correctly says LB, hence apparently the query works - but only when it is executed delayed.
So, obviuosly there's a timing problem, and it seems as if the initializer runs too early (or I am doing something wrong).
Can anybody point out what the solution is (or give me a hint on what I am doing wrong)?
Okay, I've found the solution: The internal update function did not run yet, and all the values are only available once this function ran, so you need to provide a callback to the call to GetObject (that gets called after the update function):
var doc = Qv.GetCurrentDocument();
var listbox = doc.GetObject('LB01', function () {
console.log(listbox.Type); // => 'LB'
});
I'm working my way through the Eloquent JavaScript Book and in it there is the following code:
function createFunction(){
var local = 100;
return function(){return local;};
}
When I run this via the node console (run node from command prompt) by calling createFunction(), I get [Function] as a returned value. However, according to the book I should get 100.
So my two questions: Why is this? and Second, is running these little examples in the node console a bad idea for testing JS code?
You need to call the response of createFunction().
createFunction()();
The first invocation (()) calls createFunction() and returns the inner function, which the second invocation executes and returns the local variable which was closed over.
Running small examples in a node console (or any other) is fine, so long as you know the environment, e.g. a browser's console is generally eval()'d, which can create side effects, such as how delete can apparently delete variables, not just object properties.
You get 100 by invoking the return value of createFunction, which is itself a function.
createFunction()();
...or perhaps more clearly...
var new_func = createFunction();
new_func();
function createFunction(){
var local = 100;
// v---v-----------------------v return a function from createFunction
return function(){return local;};
}
// v------- the returned function is assigned to the new_func variable
var new_func = createFunction();
// v------- the returned function is invoked
new_func();
For those that have a similar problem, I completely missed the double () so the call looks like createFunction()().
I've got a $.getJSON call in some code that appear to be not updating a global variable, and I'm at a loss to understand why. The JSON data is being loaded OK, but for some reason the global EventOptions array is not being updated in the for {} loop. The capitalised comments refer to the variable. Any ideas? Thanks
function LoadMeasurementTypes() {
// Clear out EventOptions
EventOptions = ["..."];
// Push a couple on to EventOptions - THESE ADD OK
EventOptions.push("Temperature");
EventOptions.push("Pulse rate");
// Call json to get measurementTypes off the table
$.getJSON('./get-measurement-types.php', function (measurementTypeData) {
// Process each json element ([0].BP, [1].ph (Urine) etc.
for (var i = 0; i < measurementTypeData.length; ++i) {
// e is a storage variable to contain the current element
var e = measurementTypeData[i];
// Add the new measurement type
alert(e.measure_type); // OK works - we can see the measure_type
EventOptions.push(e.measure_type); // THESE ARE NOT BEING ADDED
}
} // end anonymous function
) // end get json call
EventOptions.push("Last one"); // THIS ONE IS BEING ADDED
}
Your EventOptions[] is not globally visible. My guess would of been that it should still be visible locally to your $.getJSON call; but because it is now scoped to jquery, its clearly obscured (did you alert(EventOptions); inside your anon function to test?.
To properly scope, just declare it outside of LoadMeasureTypes().
var EventOptions = ["..."];
function LoadMeasureTypes(){...
-update
if this does not work - you could always pull the anonymous function outside of the $.getJSON() and assign it a variable name:
var retreiveTypes = function(){...};
$.getJSON("..path/php", retreiveTypes);
window.EventOptions = ["..."]
Good 'ol "hack" to put stuff in the global context
Got the answer: well kind of. It won't work on iTouch Safari, but is fine on Firefox (Mac). Bosworth I'm figuring it's a browser issue you noted above.
Interestingly, it may be something to do with threads. It appear the out loop runs before the inner anonymous loop has finished (the alerts are not in sequence!). I didn't think javascript used threads this way, but I may be wrong.
I now suspect the whole issue is a timing one - with a new thread as an anonymous function not completing in time.
Thanks guys.