Facebook work history fql - javascript

I am creating facebook application where in user will be able to fetch the company name of all the friends in friends list
FB.api('/me', function(response) {
var query = FB.Data.query('select name,work,work_history,pic_square
from user where uid IN (SELECT uid2 FROM friend WHERE uid1={0})', response.id)
query.wait(function(rows){
var data = "";
for (var i = 0; i < rows.length;i++) {
data += rows[i].name + " => " +'<img src="' +rows[i].pic_square + '" alt="image" />' + "===> ";
if(rows[i].work[i]||rows[i].work_history[i]) {
data+=rows[i].work_history[0].company_name+ "<br/>";
}
data += "<br />";
}
document.getElementById('location').innerHTML = data;
});
});
}

You should check out https://developers.facebook.com/blog/post/561/
FB.Data.query was deprecated a very long time ago. Here's an example of how to achieve the same goal: http://www.fbrell.com/saved/b9b65bf81dc84b58fc1e167167b13112 (Note it only uses work_history, take a look at work too.
A few things to consider:
When you have JS strings spreading on more rows, make sure you concatenate as in the example I included, you'll save yourself a lot of headaches.
Why check rows[i].work[i]? i contains the value of the index of the current friend. Work and work_history are arrays of my previous jobs, you should check the length of the array and make sure it's > 0.

Related

Insert to sqlite only runs the last statement [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
I'm quite frustrated by a seemingly simple sqlite problem. I have a table with 3 records on the client. After collecting these records up and making a trip to the server to insert them, I have a cleanup function that hunts down new records on the server and runs deletes on the client in preparation to add them back in with server-specific ids. I don't necessarily like deleting, when updating would be preferable, however, the web-based app I've written may be accessed from multiple iPad devices and users, and we need a way to keep the client data in sync with the server. I have tried various methods that became problematic once offline possibilities were factored in.
So, to the code. I collect ids and perform a delete (that multiple_records_deleted is a boolean used to indicate to a setTimeout when the delete statement has completed).
ids = ids.substring(0,ids.length-1);
db.transaction(function (tx) {
tx.executeSql("DELETE FROM " + table + " WHERE id IN (" + ids + ")", [], function (tx, results) {
console.log("DELETE FROM " + table + " WHERE id IN (" + ids + ")");
multiple_records_deleted = true;
});
});
Then, the goal is to insert new records that may or may not be identical (there are keys and timestamp fields and other complex relationships crucial to the app that only the server has.)
sqlInserts[0] = "sql to insert first record";
sqlInserts[1] = "sql to insert second record";
sqlInserts[2] = "sql to insert third record";
function insertMultipleRecords() {
for (var x = 0; x < sqlInserts.length - 1; x++) {
db.transaction(function (tx) {
tx.executeSql(sqlInserts[x],[]);
}, badCB, goodCB);
}
}
The long and short of my problem, is that every time I run this code, only the last item in the array seems to execute. I have tried just about every variation of db.transaction I can think of. used timers. used other callbacks. but to no avail. The weird thing is that I run a similar code block in another part of the app and it works fine.
Any ideas why it is only ever the last item in the array that successfully runs, while the rest seem to go nowhere?
Thanks..
Robin
EDIT:
Here is a follow up snip of code.
for (var rec in response.table.records.record) {
db.transaction(function (tx) {
console.log("DELETE FROM " + table + " WHERE id = " + response.table.records.record[rec].f[record_idnumber_fld_ctr]);
tx.executeSql("DELETE FROM " + table + " WHERE id = " + response.table.records.record[rec].f[record_idnumber_fld_ctr], [], function (tx, results) {
// then insert
fld_ctr = 0;
setTableColumns("table_columns",table); // ensure we are using the right table
sql = "INSERT INTO " + table + " (";
for (x = 0; x < table_columns.length; x++) {
sql += table_columns[x] + ",";
}
sql = sql.substring(0,sql.length-1) + ") ";
sql += "SELECT ";
for (var fld in response.table.fields.field) {
var obj = response.table.fields.field[fld];
for (var prop in obj) {
if (prop === "#attributes") { // cast the data
sql += formatData(obj[prop].field_type,response.table.records.record[rec].f[fld_ctr]) + ",";
}
}
fld_ctr++;
}
// special cases for certain tables
if (table == "orders") {
if (response.table.records.record[rec].f[43] != "") sql += formatData("string","YES") + ","; // siggy
else sql += formatData("string","") + ",";
}
if (table == "pictures") {
sql += formatData("string","") + ","; // datauri
}
sql += "'SYNCED',";
sql += "'NO',";
sql += formatData("integer",response.table.records.record[rec].f[record_idnumber_fld_ctr]) + ",";
sql += "'VALID',";
sql += "'NO ERRORS'";
console.log(sql);
db.transaction(insertRecords(sql), errorHandler);
});
});
}
I run through a resultset of records from the server. And for each one, I attempt to delete from the table where a key is the same. Both console.logs display the same verbiage all 3 times... matching the last one in the array. I'm sure this is a closure problem, just not sure how to attack it.
It is the classic issue where the variable is just a reference and not a snapshot in time. So by the time the callback is executed, the value of x has been changed. So you need to either pull out the function into a separate function or use a closure.
function runTrans (x) {
db.transaction(function (tx) {
tx.executeSql(sqlInserts[x],[]);
}, badCB, goodCB);
}
function insertMultipleRecords() {
for (var x = 0; x < sqlInserts.length - 1; x++) {
runTrans(x);
}
}
or
function insertMultipleRecords() {
for (var x = 0; x < sqlInserts.length - 1; x++) {
(function(x) {
db.transaction(function (tx) {
tx.executeSql(sqlInserts[x],[]);
}, badCB, goodCB);
}(x));
}
}

How to change form display from = to :?

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);
}

Appending to HTML a content of a Javascript object

Trying to crack this little issue I have..
I am using parse.com to store and retrieve data and I have a JSON object I am trying to retrieve a part of to append to an HTML
var tempObject = Parse.Object.extend("Dev");
var query = new Parse.Query(tempObject);
query.notEqualTo("objectId", "Dan Stemkoski");
query.find({
success: function(results) {
alert("Successfully retrieved " + results.length + " receipts");
for (var i = 0; i < results.length; i++) {
var object = results[i];
$("#receipts").html(object.get('receipt_title'));
console.log(object)
//alert(object.id + ' - ' + object.get('receipt_title'));`
The result I want to show in
<div id = receipts>
<div>
Unfortunately for some reason I am getting only one line instead of the 10 that I should be getting.
I know I should loop somehow to get the results but all my tries have failed me so far.
Thanks in advance for help!
You need to add the result to the html, as right now you just replace the previous result with the next one. Instead of
$("#receipts").html(object.get('receipt_title'));
try
var html = $("#receipts").html();
$("#receipts").html(html + object.get('receipt_title'));
Also, just to mention, if you want to be efficient it might be better to just keep adding to a variable and write to the DOM only once. So:
var html = "";
for(/* Do your for loop here, thats all correct*/){
/*Do everything the same apart from the $("#receipts").html() line*/
html += object.get('receipt_title');
}
$("#receipts").html(html);
The less times you modify the DOM, the better.
From the looks of it, you are actually getting only the last line.
Try fixing it like this:
var tempObject = Parse.Object.extend("Dev");
var query = new Parse.Query(tempObject);
query.notEqualTo("objectId", "Dan Stemkoski");
query.find({
success: function(results) {
alert("Successfully retrieved " + results.length + " receipts");
// Clear existing html from #receipts
$("#receipts").html("");
for (var i = 0; i < results.length; i++) {
var object = results[i];
// Adds to html of previous results (empty on first result)
$("#receipts").html($("#receipts").html() + object.get('receipt_title'));
console.log(object)
//alert(object.id + ' - ' + object.get('receipt_title'));
}
}
});
Nice.. I actually managed to solve it a bit differently:
$("#receipts").append(object.get('reciept_title'));
$("#receipts").append("<br>");
I am trying to figure out how to center the results, tried to add HTML after the append function but it broke the code for some reason
You're overwriting the contents of #receipts every time you loop through. Try this (after the first alert):
var datas = new Array();
$.each(results, function(index, data) {
datas.push('<span>'+ data.receipt_title +'</span>');
});
$("#receipts").data(options.join(''));
Play around with it a little until it does what you want it to.

Javascript Ajax help..multiple values [i]

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.

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