Javascript Ajax help..multiple values [i] - javascript

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.

Related

Assigning a list of labels values generated from a list of objects

I have an ajax call that returns a Serialized JSON string with various keys and values within it, I want to loop through these values and assign each individual key and value to a different label, I already have 8 labels set up. (I am quite new to Javascript so any help or constructive feedback would be greatly appreciated)
Haven't tried much as I am quite new to JavaScript
var obj = response.ret.SearchCriteria;
var resultJSON = obj;
var result = $.parseJSON(resultJSON);
var count = Object.keys(result).length;
for (i = 1; i < count; i++) {
var c = $('#lbl' + [i]);
$.each(result, function(k, v) {
c.text(k + ' is ' + v);
});
};
I have 6 labels and the last item of the JSON array (String) is displayed in each label
I believe your issue is why only last item of JSON array is being displayed in each label.
This is because of c.text(k + ' is ' + v).
Here the existing text content is replaced with every iteration of 'each' loop
Instead, you can consider doing this, which will append existing content as well with $.each loop.
c.text(c.text() + k + ' is ' + v)
OR
Simply
c.append( k + ' is ' + v)
If I am wrong in my assumption, please describe your scenario more, so that we can help you out :)

Performing calculations on data via json

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.

Assign an array value to another array called dynamically

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.

using localStorage to keep a count

var nicWinsVsMac;
if (tempresult === win) {
wincount = JSON.parse(localStorage.getItem (playerName + 'wincount'));
wincount += 1;
localStorage.setItem(playerName + 'wincount', wincount);
winsvsopponent = 'WinsVs' + opponent;
winsvsopponent = JSON.parse(localStorage.getItem(playerName + 'WinsVs' + opponent));
winsvsopponent += 1;
console.log(winsvsopponent);
localStorage.setItem(playerName + 'WinsVs' + opponent, 'winsVs' + opponent);
console.log(localStorage.getItem(nicWinsVsMac));
}
playerName and opponent are parameters passed in. In this case, playerName = 'nic' and opponent = "Mac"
My browser is giving me "unexpected token w" on the line where i parse out the localStorage. I cannot figure out what is going on. Any help would be great. Thanks!
Instead of using a separate localStorage variable for each attribute of the player. Why not store all the players attributes in a single object and then save that to localStorage.
For example, you can do the following:
var player = new Object();
player.name = 'Mac';
player.winCount = 3;
player.winAgainst = new Array();
localStorage.setItem(player.name, JSON.stringify(player));
var player1 = JSON.parse(localStorage.getItem(player.name));
console.log(player1.name + " has " + player1.winCount + " wins.");
This allows you to save all the player's attributes to a single localStorage variable making it much easier to read and write from.
In regards to the error you are recieving, I believe the issue with your code is that you are not using JSON.stringify in the call to setItem.

Optimizing JS Array Search

I am working on a Browser-based media player which is written almost entirely in HTML 5 and JavaScript. The backend is written in PHP but it has one function which is to fill the playlist on the initial load. And the rest is all JS. There is a search bar that refines the playlist. I want it to refine as the person is typing, like most media players do. The only problem with this is that it is very slow and laggy as there are about 1000 songs in the whole program and there is likely to be more as time goes on.
The original playlist load is an ajax call to a PHP page that returns the results as JSON. Each item has 4 attirbutes:
artist
album
file
url
I then loop through each object and add it to an array called playlist. At the end of the looping a copy of playlist is created, backup. This is so that I can refine the playlist variable when people refine their search, but still repopulated it from backup without making another server request.
The method refine() is called when the user types a key into the searchbox. It flushes playlist and searches through each property (not including url) of each object in the backup array for a match in the string. If there is a match in any of the properties, it appends the information to a table that displays the playlist, and adds it to the object to playlist for access by the actual player.
Code for the refine() method:
function refine() {
$('#loadinggif').show();
$('#library').html("<table id='libtable'><tr><th>Artist</th><th>Album</th><th>File</th><th> </th></tr></table>");
playlist = [];
for (var j = 0; j < backup.length; j++) {
var sfile = new String(backup[j].file);
var salbum = new String(backup[j].album);
var sartist = new String(backup[j].artist);
if (sfile.toLowerCase().search($('#search').val().toLowerCase()) !== -1 || salbum.toLowerCase().search($('#search').val().toLowerCase()) !== -1 || sartist.toLowerCase().search($('#search').val().toLowerCase()) !== -1) {
playlist.push(backup[j]);
num = playlist.length-1;
$("<tr></tr>").html("<td>" + num + "</td><td>" + sartist + "</td><td>" + salbum + "</td><td>" + sfile + "</td><td><a href='#' onclick='setplay(" + num +");'>Play</a></td>").appendTo('#libtable');
}
}
$('#loadinggif').hide();
}
As I said before, for the first couple of letters typed, this is very slow and laggy. I am looking for ways to refine this to make it much faster and more smooth.
$('#search') isn't cheap. Move it outside the loop.
Move append() outside the loop. Just accumulate the markup in a string and append it once after the loop.
This should be much faster
function refine() {
$('#loadinggif').show();
$('#library').html("<table id='libtable'><tr><th>Artist</th><th>Album</th><th>File</th><th> </th></tr></table>");
playlist = [];
var srchText = $('#search').val().toLowerCase();
var markup = ["<tbody>"];
for (var j = 0; j < backup.length; j++) {
var sfile = backup[j].file.toLowerCase();
var salbum = backup[j].album.toLowerCase();
var sartist = backup[j].artist.toLowerCase();
if (sfile.search(srchText) !== -1 || salbum.search(srchText) !== -1 || sartist.search(srchText) !== -1) {
playlist.push(backup[j]);
num = playlist.length-1;
markup.push("<tr><td>" + num + "</td><td>" + sartist + "</td><td>" + salbum + "</td><td>" + sfile + "</td><td><a href='#' onclick='setplay(" + num +");'>Play</a></td></tr>");
}
}
markup.push("</tbody>");
$("#libtable").append(markup.join(''));
$('#loadinggif').hide();
}
I would suggest building your playlist information a little differently. You could probably get a pretty decent performance gain just by splitting up your playlist info by first letter.
albums = {
'a': [list of albums starting with a],
'b': ...
}
And doing the same for files and artists, of course.
One thing you could do is to take advantage of jQuery's ability to cache document fragments (the example is from a talk John Resig gave but you could apply it to your code):
// SLOW AS IT IS NOT CACHED. BECAUSE OF FOO
$("ul").append("<li><a>" + foo + "</a></li>");
// FAST. DOCUMENT FRAGMENT IS CACHED
$("<li><a></a></li>")
.find("a").text(foo).end()
.appendTo("ul");
This would be applicable to your line above:
$("<tr></tr>").html("<td>" + num + "</td><td>" + sartist + "</td><td>" + salbum + "</td><td>" + sfile + "</td><td><a href='#' onclick='setplay(" + num +");'>Play</a></td>").appendTo('#libtable');

Categories

Resources