I've got an array like this
pages['name'] = "Home";
pages['childs'][0]['name'] = "Sub page 1";
pages['childs'][1]['name'] = "Sub page 2";
pages['childs'][2]['name'] = "Sub page 3";
pages['childs'][2]['childs'][0]['name'] = "Sub sub page 1";
My problem is that I need to change portions of the array for example.
pages['childs'][0] = otherarray;
// or
pages['childs'][2]['childs'][0] = otherarray;
Obviously if otherarray was a string I can easily do something like
eval('pages' + where + ' = "' + stringvalue + '"');
But I've an array as value so I can't do
eval('pages' + where + ' = "' + otherarray + '"');
because the code executed will be
pages['childs'][0] = [object object];
What's the solution? Thanks
Rather than screw around with eval and stringifying things, you should just build an accessor. Many would agree that using eval like this is just bad practice in every way. I don't know if combining it with stringify makes it worse, but it certainly feels dirty.
Here's a basic, fairly stupid accessor, but it should give you the idea.
// Arguments: array to modify; new value; series of nested array keys.
function modifyArray(base, value){
var refObj = base;
for (var ii=2, max=arguments.length; ii < max; ii++){
if (!refObj) {
return false; // we supplied an invalid key.
}
if (ii == max-1){
refObj[arguments[ii]] = value;
return true;
}
refObj = refObj[arguments[ii]];
}
return false; // probably forgot to include keys.
}
modifyArray(pages, otherarray, 'childs', 2, 'childs', 0);
http://jsfiddle.net/2ts78brg/
For me this solution works
eval("pages" + where + " = JSON.parse('" + JSON.stringify(otherarray) + "')");
It sounds more like a workaround then a solution but it works and for me it's enough.
Related
I am trying to perform a simple addition on data I have gathered from an external source via JSON. The data I am getting is being returned as a string but is a number so I have tried using both parseInt() and Number() to no avail. I have shown a simple section of the code below:
var total_energy = 0;
var energy_val;
$.each(result.report.food.nutrients, function (i, v) {
if (v.name == "Energy"){
energy_val = v.value;
var energy = Number(energy_val);
total_energy = total_energy + energy;
console.log("energy " + energy);
console.log("totalenergy " + total_energy);
energy_val = "";
energy = 0;
}
}
The console returns the correct value for energy each time but the totalenergy value just seems to stay the same as the energy value. The sum doesn't seem to have any affect. Could anyone tell me where I am going wrong with this problem?
change console.log("energy " + total_energy); to console.log("energy " + energy);
try parseInt your values... can be this
I doubt if its due to the closure created in the loop where you are iterating over the items. Try the following code.
var total_energy = 0;
var energy_val;
$.each(result.report.food.nutrients, function (i, v) {
var item = v;
//Calling calculateEnergy() function so that each 'item' is the current instance 'v' value.
(function calculateEnergy(itemClicked))(item);
}
function calculateEnergy(itemClicked){
if(itemClicked.name == "Energy"){
energy_val = itemClicked.value;
var energy = Number(energy_val);
total_energy = total_energy + energy;
console.log("energy " + energy);
console.log("totalenergy " + total_energy);
energy_val = "";
energy = 0;
}
}
I have put comments within the code.
Update console.log() is buggy with ajax requests. So instead of logging, try creating an html div and populate the values there.
I want to display a list of items, now sometimes these items' title will just be a plain string, and sometimes it might be a value returned by a function.
How can I make both events work using eval() ?
Here is an example code:
var a1 = "formatDate('" + startTime + "') + ' - ' + formatDate('" + endTime + "')"
var a2 = "#america"
var result1 = eval(a1) // works well!
var result2 = eval(a2) // doesn't work, need to use eval('a2') but then first one doesn't work
Only thing I can think of is when creating the string for example "#america" have it saved like "'#america'" instead, but I would rather avoid it
[edit]
Eventually I will have something like this:
arr.push("formatDate('" + startTime + "') + ' - ' + formatDate('" + endTime + "')");
arr.push("#america");
for(var i = 0; i < arr.length; i++) {
var ev = eval(arr[i]);
console.log(ev);
}
What I would suggest is wrapping the eval in a try catch block, if the eval succeeds then return the value otherwise return the value originally passed to function. There are many cases where eval can fail as it is simply trying to parse the string as valid JavaScript so any invalid JS not just a simple string can cause it to fail so its better to be safe and catch any error that comes out of it.
var evaluate = function(value) {
try {
return eval(value);
}
catch(err)
{
return value;
}
}
var ev = eval(a2) would be equivalent to var ev = eval('#america') which doesn't make any real sense.
When you say eval('a2') works, I assume that ev = '#america' is the desired outcome. The 'a2' expression is evaluated as simply accessing the value of the variable of that name.
You're basically just having a series of strings that may be valid javascript code, or may not, and there's no way to tell which is which. In that case, the best you can do is something like
try {
ev = eval(arr[i]);
} catch(ex) {
ev = arr[i];
}
... which obviously looks terrible. Can you control the content of the entries in arr?
arr.push(function() {
return formatDate(startTime) - formatDate(endTime);
});
arr.push("#america");
In that case, you could check for the type of each entry, and act on it accordingly:
for(var i = 0; i < arr.length; i++) {
var ev = typeof arr[i] == 'function' ? arr[i]() : arr[i];
console.log(ev);
}
this is that i should do:
var a1 = function(){
return formatDate(startTime) + formatDate(endTime)
}
var a2 = "#america"
var result1 = a1();
var result2 = a2;
Yo can check with typeof(a1) if the var is a function or an object or anyting else.
if(typeof(a1)=='function'){
result = a1();
}else{
result=a1;
}
is there anyway that I can change the output from
Name: =daniel to Name: Daniel for all of the followings?
Picture in this URL > http://imgur.com/dgOMjhy
<h2>Your details have been submitted!</h2>
<h2>You have entered the following data: </h2>
<script type="text/javascript">
var formData = location.search;
formData = formData.substring(1, formData.length);
while (formData.indexOf("+") != -1) {
formData = formData.replace("+", " ");
}
formData = unescape(formData);
var formArray = formData.split("&");
document.write("<p>");
for (var i = 0; i < formArray.length; ++i) {
document.writeln(formArray[i] + "<br />");
}
document.write("</p>");
</script>
Sure, but this won't get you very far.
Change this line:
document.writeln(formArray[i] + "<br />");
to
document.writeln(formArray[i].replace("=", ": ") + "<br />");
But if I were you I would work on parsing the data into an actually usable object for further manipulation, currently you only work by doing String manipulations on the page URL.
Edit: To expand on the question you posted in the comment to this post:
To begin, you should try to move away from moving data via URL or GET requests, as these are quite visible, restrictive in encoding, prone to manipulation and recording. Especially data like credit card information should not be embedded in URLs.
Anyhow, in regard to parsing let's start with splitting your formArray further and storing the key-value pairs in an object:
var formArray = formData.split("&");
var formDataObj = {}; //in this we will store the data
//let's assume here that you have no key duplicates in your data
//and that it is always properly formatted
formArray.forEach(function (item) {
var key = item.split("=")[0];
var value = item.split("=")[1];
formDataObj[key] = value;
});
//if you processed your data like this you can then access it more precisely like so
document.writeln("<p>Customer " + formDataObj.customerNumber + " has card number " + formDataObj.cardNumber + "</p>");
I think it's obvious how this can be advantageous.
you can use a helper function
function capitalize(a)
{
return a[0].toUpperCase() + a.slice(1);
}
What I'm trying to do is post an array of messages asynchronously using this code. I spent over an hour trying to make it only post the four items in the array, but it keeps posting gibberish in addition to the 4 items. Also, it doesn't redirect when done.
var a = document.body.innerHTML;
formx = a.match(/name="post_form_id" value="([\d\w]+)"/)[1];
dts = a.match(/name="fb_dtsg" value="([^"]+)"/)[1];
composerid = a.match(/name="xhpc_composerid" value="([^"]+)"/)[1];
var msg = ['my first update',
'posting again',
'and again',
'done'
];
target = a.match(/name="targetid" value="([^"]+)"/)[1];
for (var i in msg) {
pst = "post_form_id=" + formx +
"&fb_dtsg=" + dts +
"&xhpc_composerid=" + composerid +
"&xhpc_targetid=" + target +
"&xhpc_context=home&xhpc_fbx=1&xhpc_message_text=" + encodeURIComponent(msg[i]) +
"&xhpc_message=" + encodeURIComponent(msg[i]) +
"&UIPrivacyWidget[0]=40&privacy_data[value]=40&privacy_data[friends]=0&privacy_data[list_anon]=0&privacy_data[list_x_anon]=0&=Share&nctr[_mod]=pagelet_composer&lsd&post_form_id_source=AsyncRequest";
with(newx = new XMLHttpRequest())
open("POST", "/ajax/updatestatus.php?__a=1"),
setRequestHeader("Content-Type", "application/x-www-form-urlencoded"),
send(pst);
}
redirect('http://apple.com');
I haven't looked at the code in depth because the formating is all messed up, but I bet the problem is on that for-in loop. for-in in Javascript is not a for-each loop and shouldn't be used to iterate over arrays. Use a normal for loop instead
for(var i=0; i<msgs.length; i++){
BTW, your code is full of bad practices, the worse of which is the use of the evil with statement.
How can I display object content without specifying the attributes ? (The object here is used as associative array)
alert(result[0].name);
alert(result[0].surname);
I actually would like to not have to write "name" and "surname", but display all the content (keys & values)
thanks
Try this.. (it uses for each loop):
var arr=[];
arr[0] = 'Test1';
arr['SomeKey'] = 'Test2';
for(var o in arr)
{
var val = arr[o];
alert("Key is: " + o);
alert("Value is: " + val);
for(var b in val)
{
alert("Inner Key is: " + b);
alert("Inner Value is: " + val[b]);
}
}
Maby this will help you:
for (var item in result[0]) {
var key=item;
var val=b[item];
alert('b['+key+']='+val);
}
Good luck!
Maybe as a clarification for the other answers:
result[0].name
is the same as
result[0]["name"]
However,
result[0][name]
would use whatever the current value of name is. E.g.
var name = "surname";
if (result[0][name] == result[0].surname) // this is true