Can't figure out why exactly a variable can't be used to help call a value in an array with JS/Jade. This is being called inside a script on a .jade file.
The array contains roughly 400 entries and one of the entries is as follows:
myFood[10]['Cake'] = 50
When using the variable i instead of directly putting in the number 10 an error occurs.
Works:
alert (i) // 10
alert (#{myFood[10]['Cake']}) // 50
Error:
alert (#{myFood[i]['Cake']}) // Error, Cannot read property 'Cake' of undefined.
First of all, know that Jade recently was renamed to "pugjs".
I'm assuming that i is a javascript variable as you stated in the comments.
The pug (jade) context and the browser Javascript context are two very different things, so if you define i in browser Javascript, jade will not see it as a variable, just plaintext waiting to be interpreted by the browser. That's why myFood[i] is undefined and thus resulting in this error.
The correct way to define a jade variable is by prefixing your line by a dash (-), as described here.
The full code is:
- var i = 10;
alert (#{i}) // 10
alert (#{myFood[10]['Cake']}) // 50
You note that I also changed the first alert to tell pug to replace the #{i} part by the actual value of i.
If you want to access each value I would highly suggest that you use loops instead of using an i to access the array.
Mixing pug and javascript is a bit tricky, so good luck!
Related
This is a very basic JS question, but this "issue" drives me crazy.
From simple algebra I would expect that both first and the second statement are vaild. But the second is always throwing "Invalid assignment" error.
Does anyone have a good explanation for it?
fieldname1 = document.getElementById("emailID1");
document.getElementById("emailID2") = fieldname2;
Thanks so much,
Most common programming languages, including JavaScript, require that the left-hand side of an assignment (the "target") be something called an l-value. That means it's an expression that denotes a place to put a value. A simple variable name, or a reference to an object followed by .propertyName suffix, works as an l-value.
In your case, the function call return value is not an l-value, because JavaScript does not make that possible (some languages do). A function call is always an r-value, meaning something that appears on the right-hand side of an assignment.
Now, in your particular case, because getElementById() returns a reference to a DOM element, you can do something like this:
document.getElementById("something").name = "frederick";
The function still returns an r-value, but that .name works as a property reference and thus as an l-value.
The assignment operator resolves the right side of the equal sign and stores it in the variable on the left side, which is what is happening in the first line.
The second line is basically trying to take the value of a variable fieldname2 and store it in a function call document.getElementById("emailID2")
JavaScript doesn't know how to resolve that at runtime, so it's throwing an invalid assignment operation.
There's more information on assignment from MDN here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators
You can't assign a value to an object itself in this case.
document.getElementById("emailID2") = fieldname2;
As i guess you want to do something like this:
document.getElementById("emailID2").name = fieldname2;
I have a website in which I use javascript and pannellum API to load multiple 360 panoramic views.
Occasionally the browser crashes, particularly when on my iPhone 6 in VR mode when a total of six pannellum instances are required in different DIVs.
As best I can tell, the browser crashes on the call to pannellum which I am doing from inside an eval function as the data I pass to pannellum is contained in a variable.
Here's the call, plus the subsequent line that lets us know that the panorama is loaded.
eval("RightPanoInt=pannellum.viewer('RightPanoIntermediary', " + PanoDataIntermediary +");");
RightPanoInt.on("load", function() { LoadedRightPanoIntermediary(); });
Where
RightPanoInt is a variable I can use to check if the panorama is loaded
RightPanoIntermediary is the id of the DIV the panorama is to be loaded into.
and
PanoDataIntermediary is a variable containing the data / parameters need by the pannellum API.
For example
{"autoLoad": true,"pitch": 0,"yaw": 73,"vaov": 180,"haov": 360,"vOffset": 0,"maxPitch": 90,"minPitch": -90,"maxYaw": 180,"minYaw": -180,"maxHfov": 100,"hfov": 100,"minHfov": 10,"showFullscreenCtrl": false,"orientationOnByDefault": false,"showControls": false,"panorama": "002.jpg","preview":"BackgroundPaleGreen.jpg"}
The data will be different the next time the call is made, so the parameters must be in the PanoDataIntermediary variable.
What alternative method to the eval function can I use to make the same call?
Okay, the responses above have made me realise that instead of using a variable, I really should be using an object. For example...
var PanoDataIntermediary={"type":"equirectangular"}; // to initiate
PanoDataIntermediary.panorama="Church_HDR_x4_000.jpg"; // to add more parameters
PanoDataIntermediary.autoLoad = true;
PanoDataIntermediary.pitch=0;
PanoDataIntermediary.yaw=73;
PanoDataIntermediary.hoav=360; // etc
RightPanoInt=pannellum.viewer('panorama', PanoDataIntermediary);
This will work without the need for using eval. It will take me awhile to rehash my existing code to see if it resolves the browser crash problem.
Thanks again.
Have you tried this (without eval)?
var RightPanoInt = pannellum.viewer('RightPanoIntermediary', PanoDataIntermediary);
According to your question, PanoDataIntermediary is a variable holding data. The only reason you'd need eval is if PanoDataIntermediary merely held the name of another variable that held the data.
Furthermore, the statement eval("RightPanoInt=pannellum.viewer('RightPanoIntermediary', " + PanoDataIntermediary +");"); treats your PanoDataIntermediary object as if it were a string but it is not a string and so cannot be concatenated as a string. This may be causing your browser crash. At the very least, it's throwing an exception.
A sample use of eval:
var myVariable = {a: 1, b:2, c:'test'};
var myVariableName = 'myVariable';
alert(eval(myVariableName).c);
Note: I'm not promoting the use of eval here. I'm just trying to offer some context.
Hope that helps.
I've worked out the "how" of this, so it's not urgent, but the "why" is bugging me!
I am creating a bank of about 500 test items for making mock practice tests for the Thai national English test (ONET). Each item is declared as an object containing html, answer key etc.
Then all items are placed into an array, which is shuffled, and the first n items become the mock test.
Up until now, I've used a separate js file to create the question objects, but the code creating the array of questions remained on my main js file. But, today I realised that if I shifted this array declaration to my secondary page, then as I added items, I would only need to update the secondary page on the computers that run this app. (Because of poor Internet connections, this is mostly run as a stand-alone off-line electron app.)
So I replaced the array declaration from my main page with one at the top of my secondary js page as follows:
var onet_full_array = new Array(cloze005, pass002, pass007, single001,
single002, single003, single004, single005); //abbreviated
However, when I tried to access that array, the elements showed as undefined. After trying several other things, I finally tried putting the array declaration at the bottom of the page, after the object declarations and it worked.
What's bugging me is why this should be necessary. It seems we constantly refer to variables, functions and so forth that may appear anywhere on the page, provided the scope is correct. I would have thought that the browser would read the entire page before deciding that it couldn't find my objects. After all, when my array declaration was on a different page, it didn't complain.
What am I missing?
Edit: Just for clarity, what I was missing, as stated in the comments, was that my original array declaration was inside a function that was not run during set-up. So by the time that function was run, the objects had been declared.
new Array(cloze005, pass002, ..)
This is creating a new array and is trying to place the value of cloze005 into it. If cloze005 is not yet defined/does not yet have a value assigned, then no value can be placed in the array. You cannot assign values to the variable after you have placed it in an array and expect the value to be retroactively placed in the array as well. Code doesn't execute in random order and anything goes at any time.
You seem to expect variables to act like pointers. Your array contains values, not references. Whatever the value at the time the array was created is the value that remains.
I think a demo helps to clarify more than just words. Consider the following code. Before you click ► Run code snippet, think about what you expect to be logged.
var a = [x];
var x = 0;
var b = [x];
x = 1;
var c = [x];
log(a);
log(b);
log(c);
function log(val) { document.write("<pre>[ " + val[0] + " ]</pre>"); }
Based on your question, it seems like you expected to see:
[ 1 ]
[ 1 ]
[ 1 ]
You don't see this because, rather than containing a pointer-like reference to x, the arrays are created by evaluating the value of x and storing that value.
I saw many code that began like that
var a=a||{};
Now I know that its check if a exist.
My question is why to check it if its at the first of the code?
I mean the programmer know that a is not exist.
The programmer should know if the variable exists or not.
It's used to mash different pieces of script together without having to keep track of which part of the script is loaded first. Several scripts will have the same piece of code at the start, so they share the same variable.
For the first script, the variable is declared, and there is no previous value for it, so the {} value is used.
For the following scripts that use it, the var is ignored as the variable is already declared, and the previously set value of the variable is used.
Of course, declaring the same variable in several places has a code smell to it. Preferrably you should keep track of what you are doing so that you only declare it once.
Translated into clearer code
var a; // The variable declaration gets brought up because of hoisting
More info on hoisting here
if( a ) {
a = a; // if a is a truthy value then assign it to itself
} else {
a = {}; // if a is a falsy value then set the default to an empty object
}
Hope that helps
That's a shortcut to fall back on a default value - {} in this case.
Basically, javascript can be written in multiple files and within each file you can have multiple declarations and functions defined.
Even if the programmer knows for a given instance if the variable exists or not, there is no way to know if it already exists when this code is called from somewhere else.
This should not happen in well written code (all from one developer / house) but it does happen in projects where the js code is amalgumated from multiple places.
This SO question has a very nice answer about variable scopes in javascript, it should clarify your doubts.
I'm using JSON to communicate some data through AJAX from the backend to the frontend (Javascript, of course). The XMLHttpRequest is done by a Prototypejs-written AJAX-handler (I'm still in the process of migrating to jQuery, but the noConflict-mode allows me to run both simultaneously), after which PHP sends the X-Json header with some data like objects = {'foo': 'bar'}.
The Prototypejs-Ajax.Request passes a json variable to the onSuccess-callback, containing all the JSONdata, so the processing isn't the hard part. However, I noticed that since the JSON is automatically evaluated, the objects variable is made global (and thus a member of the window object.
I know it's not really a problem since it's just an unused variable, but I always tried to stay away from global variables as much as possible. Additionally, the datasets may be pretty large on some occasions, so it'll just be a huge duplicate variable of which one is never used. So, if possible, I'd rather lose the global.
My question: how? If there's a good reason for this happening, or if this is just a Prototypejs-specific issue, or if this just indicates I'm doing something very wrong, please tell me :-)
Thanks!
Are you sending back objects = {"foo":"bar"} from PHP? When sending JSON, you just send {"foo":"bar"} and get the data as the return result of eval:
var json = '{"foo":"bar"}'; // This string would really be coming from PHP
// ...
var objects = eval('(' + json + ')'); // objects variable will be limited to the
// current scope.
If, for some reason, you must evaluate objects = ..., you can limit the variable to the current scope before running eval:
var objects;
eval('objects = {"foo":"bar"}');
Note that the PHP functions json_encode and json_decode will create "proper" JSON for you, which means it will use double quotes, and it will not use any kind of assignment (True JSON is limited to an array/object as the outer-most value, and it may not contain assignment or function calls. See the JSON specification.)
If the PHP is outputting objects = {'foo': 'bar'} then it isn't outputting JSON. JSON can't include the '=' character outside a string and uses the double quote character not the single quote. This means it is outputting JavaScript.
You have two options here.
The first is to try to restrict the scope of the JavaScript, the second is to fix the PHP so it outputs real JSON.
I would recommend the second option. Deal with JSON not JavaScript.
If you want to try to restrict it, then you need to limit the scope somehow. Possibly with:
function () {
eval("var " + php_generated_code);
doSomethingWith(object);
}
… although I'm not sure what the scope of eval() is.