I'm trying to get the last 50 tweets using a certain hash tag, on a mobile device using PhoneGap (0.9.6) and jQuery (1.6.1). Here's my code:
function getTweets(hash, numOfResults) {
var uri = "http://search.twitter.com/search.json?q=" + escape(hash) + "&callback=?&rpp=" + numOfResults;
console.log("uri: " + uri);
$.getJSON(uri, function(data) {
var items = [];
if(data.results.length > 0) {
console.log("got " + data.results.length + " results");
$.each(data.results, function(key, val) {
var item = "<li>";
item += "<img width='48px' height='48px' src='" + val.profile_image_url + "' />";
item += "<div class='tweet'><span class='author'>" + val.from_user + "</span>";
item += "<span class='tweettext'>" + val.text + "</span>";
item += "</div>";
item += "</li>";
items.push(item);
});
}
else {
console.log("no results found for " + hash);
items.push("<li>No Tweets about " + hash + " yet</li>");
}
$("#tweetresults").html($('<ul />', {html: items.join('')}));
});
}
This code works great in a browser, and for a while worked in the iPhone simulator. Now it's not working on either the iPhone or Android simulator. I do not see any of the console logs and it still works in a browser.
What am I doing wrong? If it's not possible to call getJson() on a mobile device using PhoneGap, what is my alternative (hopefully without resorting to native code - that would beat the purpose).
Bonus: how can I debug this on a mobile simulator? In a browser I use the dev tools or Firebug, but in the simulators, as mentioned, I don't even get the log messages.
As always, thanks for your time,
Guy
Update:
As #Greg intuited, the function wasn't called at all. Here's what I found and how I bypassed it:
I have this <a> element in the HTML Get tweets
Then I have this code in the $(document).ready() function:
$("#getTweets").click(function() {
var hash = "#bla";
getTweets(hash, 50);
});
That didn't call the function. But once I changed the code to:
function gt() {
var hash = "#bla";
getTweets(hash, 50);
}
and my HTML to:
Get Tweets
it now works and calls Twitter as intended. I have no idea what's screwed up with that particular click() binding, but I ran into similar issues with PhoneGap before. Any ideas are appreciated.
Considering that (a) there isn't much that could go wrong with the first line of your function and (b) the second line is a log command, then it would seem that the function isn't being called at all. You'll have to investigate the other code in your app.
Or are you saying that you don't have a way to read logged messages on your mobile devices?
Related
I'm using AJAX to add more articles to a list of articles when you press a button. So my AJAX call returns data that includes a title, author and 1 to 3 images associated with the article. Below is the code I'm using to output it, but it feels VERY clunky.
What are the best practices for printing out HTML with JavaScript/jQuery in a scenario like this where I need to add many new tags with new information? Thanks for the help!
Also, I know some of the code isn't super well written because it's a first draft just to make stuff work, so please only answer this question with regards to printing out the HTML or things that will make printing the HTML easier
$j.getJSON(ajaxurl, {action: 'load_articles', issues: $issues}, function(data) {
if (data.message != null) {
alert(data.message);
return
}
list = $j('.all-articles ul');
for (i in data.articles) {
article = data.articles[i];
//Hides articles already on page
if ($j("#" + article.id).size() === 0) {
list.append('<li class="article-preview" id="' + article.id + '">' +
'<h3 class="article-headline">' + article.title + '</h3>' +
'</li>');
current = $j("#" + article.id)
current.append('<p class="authors"></p>');
authors = $j("#" + article.id + " .authors")
for (a in article.authors) {
authors.append(article.authors[a].data.display_name + " ");
}
current.append('<div class="images"></div>');
images = $j("#" + article.id + " .images")
for (i in article.image) {
text = "<div class='image-expand-container'>";
if (i == 0) {
text += ('<img id="' + article.image[i].id + '"class="selected" src="' + article.image[i].medium + '"></img>');
}
else {
text += ('<img id="' + article.image[i].id + '" src="' + article.image[i].medium + '"></img>');
}
text += '<div class="dashicons dashicons-editor-expand"></div></div>';
images.append(text);
}
}
}
There are a few approaches you can take.
As you're doing here, you can return data from your ajax call (e.g. as JSON) and then use a javascript function to generate the corresponding HTML by building strings. This, as you're finding, is often messy.
You can generate the actual HTML on the server side, and have the ajax call return an HTML fragment, which you insert into your DOM. This has the advantage that, if some of your HTML is loading when the page loads, and some is loading via ajax, you can use the same approach (PHP, XSLT, ASP.NET Razor, any kind of server-side templating) to generate all of the HTML.
You can use a javascript templating framework to turn your JSON data into HTML. If all of your HTML is being generated via javascript (e.g. in a single-page application) this may be your best bet.
I've been working on some JavaScript for a little while, and one of the most frustrating things so far is that it seems my JavaScript is refusing to load if Back, Forward or Hard Refresh are used. Considering my website is built on static HTML pages generated repeatedly through a MySQL database connection, I had to manually add a moderator menu, but it seems to sometimes just refuse to appear?
if (getCookie('opt23') !== '1') {
var ajaxtwo = new XMLHttpRequest();
var wrap = '';
if (document.getElementById("firstpage") !== null) {
wrap = document.getElementById("firstpage");
} else {
wrap = document.getElementById("firstpageinside");
}
var main = document.createElement("div");
main.setAttribute("id","modmenu");
wrap.appendChild(main);
ajaxtwo.onreadystatechange = function() {
var reports = (ajaxtwo.responseText === '0' ? 'flagblue.png' : 'flag.png');
reportcount.innerHTML = '<img src=' + ku_cgipath + '/css/images/mods/' + reports + ' style="height:15px;' +
'width:15px;" />' + ajaxtwo.responseText;
};
ajaxtwo.open("GET",ku_cgipath + "/manage_page.php?action=reports&count",true);
ajaxtwo.send();
var threadid = document.getElementsByName("replythread");
// taking the initiative of togglePassword, this makes things less needlessly lengthy.
main.innerHTML =
'<h2>Quick Mod</h2>' +
'<input type="hidden" name="threadid" value="' + threadid[0].value +'" />' +
'<label for="modaction">Action </label><select id="action" name="modaction">' +
'<option value=""><none></option>' +
'<option value="delpost">Delete posts</option>' +
'<option value="rebuildone">Rebuild board</option>' +
'<option value="bans">View Bans</option>' +
'<option value="appeals">View Appeals</option>' +
'<option value="stickypost">Sticky Thread</option>' +
'<option value="unstickypost">Unsticky Thread</option>' +
'<option value=lockpost>Lock Thread</option>' +
'<option value="unlockpost">Unlock Thread</option>' +
'<option value="bump">Instant Bump</option>' +
'<option value="viewthread">Switch to Moderator View</option>' +
'</select>' +
'<input type="submit" name="submit" value="Submit">' +
'<a href="' + ku_cgipath + '/manage_page.php?action=reports" target="_blank">' +
'<span id="reportcount"></span></a> ';
}
My second issue is in another JavaScript that I'm using to try to make these HTML pages function dynamically. I'm using AJAX to interact with a PHP script, however, when it brings back the page (basically taking the next page and straps it next to the first one with CSS, creating a 'duo view'), my JavaScript doesn't get applied, like time settings, or generated links. How does one deal with that? I can't use window.onload as it can only be used once - it's being used in another JavaScript. Do I just somehow modify the results of the PHP file as they come? I'm using a Regular Expression to grab the next page, so I can't actually modify the results inside the PHP... can I?
Willing to concede to most solutions, including rewrites.
Answer to the First Question
This is a little JavaScript "problem" caused by the browser's Back-Forward cache! I've already answered a similar question, but for completeness, here's the solution:
Firefox and the iOS Safari are the only ones (as of this writing) known to have this issue. The solution is to hook into window.unload event, and a specific condition to reload the page inside window.onpageshow!
Firefox fix
jQuery:
$(window).unload(function () { $(window).unbind('unload'); });
JavaScript:
function UnloadHandler() { window.removeEventListener('unload', UnloadHandler, false); }
window.addEventListener('unload', UnloadHandler, false);
iOS Safari fix
jQuery:
$(window).bind('pageshow', function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
JavaScript:
window.addEventListener('pageshow', function (event) {
if (event.persisted) {
window.location.reload()
}
}, false);
Answer to the Second Question
You can actually hook into the onload event with multiple scripts/multiple functions. Instead of using the overwriting form of hooking into an event, such as ajaxtwo.onreadystatechange - you should "add" an event listener.
Simple example would be:
ajaxtwo.addEventListener('readystatechange', function () {
alert("hi! I'm done!");
}, false);
As for a helper function that will "do this for you" with backwards compatibility with some older versions of Internet Explorer; you can use this simple function:
function AttachEventListener(element, event, handler) {
if (element.addEventListener) {
element.addEventListener(event, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + event, handler);
} else {
alert('Invalid element specified for AttachEventListener');
}
}
Usage:
AttachEventListener(ajaxtwo, 'readystatechange', function () {
alert("hi! I'm using an awesome helper function!");
});
I have a Flash app set up in a Facebook canvas and it's using ExternalInterface to call a JavaScript function, then calling a Flash function from JavaScript when the first function completes:
Flash objects & vars:
this.dBug.text += "\ngetting user albums...\n"
var usrAlbums:Array = new Array();
var pageLimit:Number = 48;
var pageOffset:Number = 0;
this.dBug.text += "\ttotal albums before call: " + usrAlbums.length + "\n";
Callback function:
this.dBug.text += "\tadding getAlbumResponse callback to ExternalInterface\n";
ExternalInterface.addCallback('getAlbumResponse', getAlbumResponse);
this.dBug.text += "\tcreating getAlbumResponse callback\n";
function getAlbumResponse(rtrn):void{
dBug.text += "\nresponding to album get...\n";
this.dBug.text += "\t\t\tresult: " + rtrn['data'] + "\n";
var album:Array = rtrn['data'];
this.dBug.text += "\t\tadding objects to usrAlbums array...\n";
for(prop in rtrn['data']){
usrAlbums.push(new Array(album[prop], new Array()));
this.dBug.text += "\t\t\tadded " + album[prop] + ", new Array() to usrAlbums array\n";
++pageOffset;
this.dBug.text += "\t\t\t\talbumCount: " + pageOffset + "\n";
}
this.dBug.text += "\tcheck for more albums\n";
if(pageOffset == pageLimit){
getAlbum(++pageOffset, pageLimit);
}else{
this.dBug.text += "\t\ttotal albums after call: " + usrAlbums.length + "\n";
}
}
ExternalInterface call function to JavaScript:
function getAlbum(offset:Number, limit:Number){
this.dBug.text += "\t\tcalling swfGetAlbum(/me/albums?offset=" + offset + "&limit=" + limit + ")...\n";
ExternalInterface.call('swfGetAlbum', '/me/albums?offset=' + offset + '&limit=' + limit);
}
Call the EI function:
getAlbum(pageOffset, pageLimit);
Javascript on hosting page:
function swfGetAlbum(graph){
console.log('swfGetAlbum(' + graph + ')');
FB.api(graph, function(response){ console.log(response); swfGetAlbumCallback(response); });
}
var swfGetAlbumCallback = function(response){
console.log(response);
console.log(document.getElementById('app-root'));
document.getElementById('app-root').getAlbumResponse(response);
}
Everything works fine on my Mac under my Facebook account on Chrome, Safari, Opera and Firefox. It also works under the same browsers on my testing PC, and additionally on Internet Explorer.
For some reason when my friend tests the app using his Facebook account, he gets an error when the Javascript code initiates the callback and attempts to run document.getElementById('app-root').getAlbumResponse(response);. He is testing on his own PC with the same browsers, all producing the same result. Under Chrome, the error reads as Uncaught Error: Error calling method on NPObject.
To make things more interesting; this error appears when he is testing the app on MY machine using his Facebook account and does not happen when I test the app on HIS machine using my Facebook account.
I've also been able to test the app with two other Facebook accounts. One of them on my Mac under Safari and another on my friend's wife's PC using Chrome. Neither of those tests had the error.
The target version for Flash for this app is at least v11 (all tested machines/browsers have the latest Flash player,) and inserted into the page using swfobject 2.
I am totally baffled by this behavior. Anyone come across something like this?
Thanks in advance!
Total shot in the dark that we even tried this...
To conform with Facebook's https, we're on a secure server. We checked under my friend's settings to discover that the https browsing setting was unchecked. Once it was checked again, everything worked.
I seem to have a memory leak in IE9. It works just fine in Chrome. The memory leak is on the client machine. I left this page open for days in chrome and no leak.
Using jquery 1.9.0, signalr rc2
This page uses signalr and refreshes it's contents every 5 seconds with what comes from the server.
I have four tabs/divs that do this.
proxy.on('newRequests', function (data, updatetime) {
newrequestupdatetime.text('Last updated: ' + updatetime);
numberofnewrequests.text('Number of cases found: ' + data.length);
numberofnewrequeststab.text('(' + data.length + ')');
var h = '';
$.each(data, function (i, val) { h += '<li>' + val.Ref + ' ' + val.Type + '</li>'; });
newrequests.html(h);
});
newrequests is an ul on the page which I initialized like this
var newrequests = $('#newrequests');
in
$(function () {});
Not really sure what is the cause.
I can make it a lot worse by doing this.
newrequests.empty();
$.each(data, function (i, val) { newrequests.append('<li>' + val.Ref + ' ' + val.Type + '</li>'); });
I'm guessing that it has something to do with the last line of code, that puts the new html inside the ul tag.
Try changing the line into this (old code):
document.getElementById('newrequests').innerHTML = h;
See also: jQuery - Internet Explorer memory leaks
I've been developing a web game, with jquery doing some of the work. It was on a server, but I've moved it back to my laptop. Everything seems to work fine, except the most important function, which imports the contents of an html file.
$(".ReportList a").live('click', function(){
var getreportname = $(this).text();
$("#scroller").append("<span>The reportname is " + getreportname + "</span>");
var usersreport = "ReportList_" + User + "";
jQuery.get('Reports/' + getreportname + '.html', function (data) {
$("#" + usersreport).html(data);
$("#" + usersreport + " span").addClass("Py" + User);
updateCount();
});
});
Not sure why it stopped working. Would appreciate any insight.
I didn't need the .get() method to do what I wanted, .html() was good enough if I re-formulated the script.