I am using Facebooks Javascript API , in my jquery mobile website , in order to download albums and photos from a facebook public page and present them to my website.
The API is really straightforward on how things are done and i made everything working fairly easily.
What i have done so far and IS working
When a user hits a button i load a page , where the javascript FB API is called and dynamically generate a list of all the albums of a specific facebook page , with all the photos etc. This works great. When the API is called it fetches only 25 albums and when i have more albums to fetch , i have a "More Albums" button which the user hits to make another call to the API and fetch more albums. That works great too...
The Problem
My problem appeared , when i decided that i want to have 2 different facebook pages that i would like to import albums/photos from. So i made a horizontal button with 2 options (facebook page 1 , facebook page 2) , made the navBar persistant and when i hit one of the buttons i need an API call to be made and get the albums of each page. THIS sadly doesnt work... When i make a call to one of the 2 pages , everything works. Even the "more albums" button works. But when i navigate to the other facebook page , the call to the api doesnt work... I cant understand why... The "More Albums" button works , that means i can make multiple calls to the api. But why when i navigate with ajax , to the other page on my jquery mobile site , the call cant be completed? I put an alert inside the javascript file and i see it , that means that the code is called. But when i put the alert inside the actual call to the api , i cant see anything alerted.... I guess that means that for some reason the call is blocked...
Any ideas what might be happening here?
My javascript for one of the 2 albums looks like this :
$('#photosNJ').on("pageshow", function() {
var albumPhotos = new Array();
var albumThumbnails = new Array();
var x=0;
var next;
var times=0;
var dataLength=0;
// start the entire process
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '564984346887426', // App ID from the app dashboard
channelUrl : 'channel.html', // Channel file for x-domain comms
status : true, // Check Facebook Login status
xfbml : true // Look for social plugins on the page
});
$.mobile.loading("show");
FB.api('169070991963/albums', checkForErrorFirst(getAlbums));
//$.mobile.loading("hide");
}
// checkForErrorFirst wraps your function around the error checking code first
// if there is no response, then your code will not be called
// this allows you to just write the juicy working code
// and not worry about error checking
function checkForErrorFirst(myFunc) {
return function(response) {
if (!response || response.error) {
alert("Error !");
} else {
myFunc(response);
}
};
}
function getAlbums(response) {
//if statement checks , if there are any more albums to load. If not we disable the "More Albums" button.
if(response.paging.next == undefined) $("#loadMoreAlbums").parent().hide();
//variable next holds the URL for the next 25(or less) albums
next = response.paging.cursors.after;
dataLength = response.data.length + dataLength;
for (var i=0; i < response.data.length; ++i) {
processAlbum(response.data[i], i+x);
}
x = x+i;
console.log(x);
}
function processAlbum(album, i) {
FB.api(album.id + "/photos?limit=300", checkForErrorFirst(populateAlbum(album, i)));
}
function populateAlbum(album, i) {
return function(response) {
for (var k=0; k < response.data.length; ++k){
albumThumbnails[i] = albumThumbnails[i]||[];
albumThumbnails[i][k] = response.data[k].picture;
albumPhotos[i] = albumPhotos[i]||[];
albumPhotos[i][k] = response.data[k].source;
}
// now that we've populated the album thumbnails and photos, we can render the album
FB.api(album.cover_photo, checkForErrorFirst(renderAlbum(album, i)));
};
}
function renderAlbum(album, i) {
times++;
if(times == dataLength) $.mobile.loading("hide");
return function(response) {
var albumName = album.name;
var albumCover = album.cover_photo;
var albumId = album.id;
var numberOfPhotos = album.count;
// render photos
$(".albums").append('<li>'+
'<a href="#Gallery' + i + '"' + 'data-transition="slidedown">'+
'<img src= "' + response.picture + '" />'+
'<h2>' + albumName + '</h2>'+
'<p>' + "Number of Photos: " + numberOfPhotos +'</p>'+
'</a>'+
'</li>').listview('refresh');
$("#photosNJ").after('<div data-role="page" data-add-back-btn="true" id=Gallery'+ i +
' class="gallery-page"' + ' data-url="Gallery' + i + '"> ' +
' <div data-role="header"><h1>Gallery</h1></div> ' + ' <div data-role="content"> ' +
' <ul class="gallery"></ul> ' + ' </div> ' +
' </div> ');
for(var n=0; n < albumPhotos[i].length; n++) {
$('#Gallery' + i + ' .gallery').append('<li><a href="' + albumPhotos[i][n]
+ '" rel="external"><img src="' + albumThumbnails[i][n] + '"' + '/> </a> </li>');
}
//adding a "More Photos" button inside every album
// $('#Gallery' + i + ' .gallery').after('<button type="button" class="loadMorePhotos">More Photos...</button>');
};
}
// Load the SDK asynchronously
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
//"More Albums" button
$("#loadMoreAlbums").click(function(){
// start the entire process
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '564984346887426', // App ID from the app dashboard
channelUrl : 'channel.html', // Channel file for x-domain comms
status : true, // Check Facebook Login status
xfbml : true // Look for social plugins on the page
});
}
//when the "More Albums" button is pressed , we make a call at the API for the next 25(or less) albums , using the "next" URL
$.mobile.loading("show");
FB.api('169070991963/albums?after=' + next +"'", checkForErrorFirst(getAlbums));
});
});
You can see the call to the api , the dynamic creation of the html page to show the albums in a listview , the population of the albums with photos , the more albums button etc... The javascript for my other facebook page is IDENTICAL and only the page ID changes. At this point , i want to point out that if i load the other page first and then this one AGAIN the second call is the one that is not working. That means that i dont have a specific problem with one of the albums , rather than a problem that the second call NEVER runs.
Here is the html page just in case you need to see what i am exactly trying to do:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery Mobile Web App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--<link href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" rel="stylesheet" type="text/css"/>-->
<link rel="stylesheet" href="themes/EspacioJoven.min.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile.structure-1.3.1.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
<link rel="stylesheet" href="themes/custom.css" />
<!--Used by PhotoSwipe Plugin -->
<script type="text/javascript" src="photoSwipe/klass.min.js"></script>
<script type="text/javascript" src="photoSwipe/code.photoswipe.jquery-3.0.5.min.js"></script>
<script type='text/javascript' src='photoSwipe/photoSwipeCall.js'></script>
<link href="photoSwipe/jquery-mobile.css" type="text/css" rel="stylesheet" />
<link href="photoSwipe/photoswipe.css" type="text/css" rel="stylesheet" />
<!--Used by PhotoSwipe Plugin -->
<script type='text/javascript' src='javascript/createFb2.js'></script>
<script type='text/javascript' src='javascript/createFb.js'></script>
</head>
<body>
<div data-role="page" id="home" data-theme = "a" >
<div data-role="content">
<h2 id="banner">Joven Mobile</h2>
<div class="main_menu">
<ul data-inset="true" data-role="listview">
<li><img src="themes/icons/news.png" alt="Information" class="ui-li-icon">Es Joven</li>
<li><img src="themes/icons/research.png" alt="Information" class="ui-li-icon">La Noche es Joven</li>
<li><img src="themes/icons/staff.png" alt="Information" class="ui-li-icon">Multimedia</li>
<li><img src="themes/icons/students.png" alt="Information" class="ui-li-icon">Sar Joven</li>
</ul>
</div> <!-- /main_menu -->
</div> <!-- /content -->
</div> <!-- /page -->
<div data-role="page" id="photosNJ" data-theme="a" data-add-back-btn="true" data-back-btn-text="Back">
<!--<script type='text/javascript' src='javascript/createFbAlbums.js'></script> -->
<div data-role="header" data-id="fixedNav" data-position="fixed">
<h1>Application Title</h1>
Back
<div data-role="navbar">
<ul>
<li>Photos Noche Joven</li>
<li>Photos Esp Joen</li>
<li>Videos</li>
</ul>
</div> <!-- /navbar -->
</div> <!-- /header -->
<div data-role="content">
<ul data-role="listview" data-inset="true" class="albums">
<!-- Here the albums are created through javascript (createAlbums.js) -->
</ul>
<button type="button" id="loadMoreAlbums">More Albums...</button>
</div> <!-- /content -->
<!-- <div id="fb-root"></div> -->
</div>
<div data-role="page" id="photosEJ" data-theme="a" data-add-back-btn="true" data-back-btn-text="Back">
<!--<script type='text/javascript' src='javascript/createFbAlbums2.js'></script>-->
<div data-role="header" data-id="fixedNav" data-position="fixed">
<h1>Application Title</h1>
Back
<div data-role="navbar">
<ul>
<li>Photos Noche Joven</li>
<li>Photos Espacio Joven</li>
<li>Videos</li>
</ul>
</div> <!-- /navbar -->
</div> <!-- /header -->
<div data-role="content">
<ul data-role="listview" data-inset="true" class="albums2">
<!-- Here the albums are created through javascript (createAlbums.js) -->
</ul>
<button type="button" id="loadMoreAlbums2">More Albums...</button>
</div> <!-- /content -->
<!-- <div id="fb-root"></div> -->
</div>
</body>
</html>
Thank you VERY VERY much if you decided to read till this far. ANY, absolutely ANY comment or idea on this one would be super valuable to me , so please if you have any thought share with me :)
FIDDLER: http://jsfiddle.net/lessisv/GW4PK/
Go to Multimedia and there i have 2 tabs "Photos Noche Joven" , "Photos Espacio Joven". You can see that the first one is loading normally. Also if you go down you can see the "More Albums" button , that also works normally and make calls to the API. The problem is that when i go to "Photos Espacio Joven" , the call is not working for the reasons i described.
First, you don't need window.fbAsyncInit in your loadMoreAlbums handlers. You define the same function earlier - that is enough.
Second, you don't use FB.init many times - only once. Because it is defined inside window.fbAsyncInit, and that function is called by Facebook SDK when SDK is loaded. And there is a check whether the script is already loaded:
if (d.getElementById(id)) {return;}
That means you load FB script once and init FB once.
The main thing is that you cannot init FB object (FB.init) in one scope (one of the "pageshow event" handlers) and then use FB.api in another scope (the other handler). That is why you get empty result.
There are several solutions you can try.
1.You can init FB every time the page changes.
Just check for FB object is present and call window.fbAsyncInit(). You could try quickly this solution by changing
if (d.getElementById(id)) {return;}
to
if (d.getElementById(id)) {window.fbAsyncInit(); return;}
This is the ugly way.
2.You really should refactor your code.
Init FB on top level - not in the two handlers; create one handler - and call it when the page is changed. You can pass necessary parameters or use DOM elements data.
PS. A new handler for loadMoreAlbums is added every time the page changes. You switch to another album, go back and get two calls and double data, switch again and get triple data.
$(document).on("pageshow", '#photosNJ', function () {
...
$("#loadMoreAlbums").click(function () {
...
});
...
});
Well, there is a lot to say...
You do have to factor things to avoid creating your functions for each "page"
You don't have to call FB.init more than once, as the fbAsyncInit will be called only once, and the FB.api query to retrieve the albums won't be fired the next time you call FB.init (this is why you can't load the data of the second page)
Yes the more button works even if you have a FB.init, because your FB.api request is not inside the fbAsyncInit function
As your pages are public, you don't need to know if the user is connected or if he has accepted your app, so you can fire the FB.api just after the FB.init, but in other cases you would have to implement a FB.login function or at least a listener to the status change event to know if your user is connected, and then fire the requests
...
If you want to look at one way to achieve all this, look at here: http://jsfiddle.net/ZES3X/
Related
It has an embedded system, which operates with an IP (example: 192.168.0.237) different from each device, where the Import/Load file functionality depends on JQuery. The goal is to get this feature to work without needing an internet connection, it is currently using pointing to https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js and it works without problems.
Changing the code, to access the "jquery.js" file locally.
The page that loads the UPLOAD functionality is operating on port 8989. This, the path can be placed in the HEAD of the files, like this:
<script type='text/javascript' src='jquery.js'></script>
When running, inspecting the NETWORK tab, we have the result path:
"192.168.0.237:8989\jquery.js"
that is, it maps through port 8989, it fails to find the file, as it is stored in the root with port 80. Therefore, to validate the solution FORCE doing:
<script src='http://192.168.0.237/jquery.js'></script>
I added this instruction at the top of the file inside HEAD, AND the file UPLOAD feature WORKED correctly. Validating, which solution is suitable.
But, in order to work correctly, it must obtain the IP of the device, so a SCRIPT was made using "window.location.hostname" to obtain the IP of the device and assemble the URL.
<script>
let k2 = '#http://';
let k3 = window.location.hostname;
let k4 = '#jquery.js';
let fim = `${k2} ${k3} ${k4}`;
fim = fim.replace(' #', '/');
fim = fim.replace('#', ' ');
fim = fim.replace('// ', '//');
fim = fim.trim();
document.getElementById('demo').innerHTML = window.jQuery;
document.getElementById('kkk').innerHTML = fim;
document.head.appendChild(document.createElement('script')).src = fim;
</script>
In this SCRIPT we have the last line "document.head.appendChild(document.createElement('script')).src = fim"
which inserts the statement to load JQuery into the HEAD. Clicking on the "Check JQuery Status" button, the message that JQuery is loaded and available appears.
But now comes the problem, when pressing the submit button, update, the shown below occurs:
Imagem upload1
Imagem upload2
Imagem upload3
In short, an error occurs because it points to "serverIndex:1" and the correct would be only "serverIndex".
In other words, we have the INITIATOR pointing to "serverIndex:1" which doesn't exist (it doesn't even have to adjust the instruction, a syntax error will happen).
So, in short, with statement adding "jquery.js" STATIC = WORKS, but with statement ADDING "jquery.js" DYNAMICLY DOES NOT WORK.
With the STATIC instruction inserted in the HEAD, we have the expected operation as indicated below: (Note the INITIATOR = serverIndex)
WORKS OK RESULT
I need guidance as I don't know how to solve and also if this solution is suitable.
Below is the rendered code:
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<script>
function checa() {
if(jQuery) {
alert('Jquery ONLOAD!');
} else {
alert('Jquery NOT HAVE - NUNCA EXECUTA');
}
}
</script>
<script src='http://192.168.0.237/jquery.js'></script>
</head>
<button onclick='checa()'>Check Status JQuery</button>
<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>
<h4>valor:</h4>
<p id='demo'> </p>
<p id='kkk'></p>
<h3>Verificador de preço</h3>
<h3>Update Firmware</h3>
<input type='file' name='update' id='file' onchange='sub(this)' style=display:none accept='.bin' required>
<label id='file-input' for='file'> Selecione o arquivo ...</label>
<input type='submit' class=btn value='Atualizar'>
<br>
<br>
<div id='prg'></div>
<br>
<div id='prgbar'>
<div id='bar'></div>
</div>
<br>
</form>
<script>
let k2 = '#http://';
let k3 = window.location.hostname;
let k4 = '#jquery.js';
let fim = `${k2} ${k3} ${k4}`;
fim = fim.replace(' #', '/');
fim = fim.replace('#', ' ');
fim = fim.replace('// ', '//');
fim = fim.trim();
document.getElementById('demo').innerHTML = window.jQuery;
document.getElementById('kkk').innerHTML = fim;
document.head.appendChild(document.createElement('script')).src = fim;
</script>
<script> <!-- DOWN IS SCRIPT UPLOAD FILE !-->
function sub(obj) {
var fileName = obj.value.split('\\');
document.getElementById('file-input').innerHTML = ' ' + fileName[fileName.length - 1];
How the code is structured: (it is enclosed in QUOTES because as soon as it is stored in the String)
Code up
Code bottom
Code call String serverIndex
Finally, I hope to be guided on how to resolve the situation and whether this solution is adequate and correct.
I feel there is something fundamental missing here.
This is a node app and the getData is an AJAX database call that gets info about a blog post.
I can load the pages just fine, it simply splits the URL string and uses the right-hand side as the postid, then the post id is sent via getData. That part works but I noticed that if I hit the page twice, and hit back it won't load the old page, it just changes the URL in the address bar, but doesn't actually load the page again.
So if say I put http://localhost:3000/post/&2 it will load the post with the id of 2. I then put http://localhost:3000/post/&3 it will load post with the id of 3. Now from there, if I hit back button, I will have the URL in the bar go back to http://localhost:3000/post/&2 but it will retain the data of http://localhost:3000/post/&3
My current idea, is that the back button does not actually treat them as separate URL's for some reason, so it loads the cache it has from http://localhost:3000/post/&3 because http://localhost:3000/post/&2 and http://localhost:3000/post/&3 are the same to it.
<html>
<head>
<link rel="stylesheet" type="text/css" href="../css">
</head>
<body onLoad="buildPage()">
<div id='container'>
<div id='head'>header icons</div>
<div id='body'>
<div id='sidebar'>sidebar
<div id='sidebarLinks'></div>
<div id='sidebarAdSpace'></div>
</div>
<div id='mainpage'>mainpage</div>
</div>
</div>
<script src='../public/grabdata.js'>
</script>
<script>
function buildPage() {
var page=3;
var url= window.location.href.split('&');
var page=url[1];
//alert(param);
getData(page, function(str) {
str = JSON.parse(str);
var linkHTML = '';
var postHTML = '';
linkHTML += "<ul>";
for (var i in str) {
linkHTML += "<li><a href='../post/&" + str[i].id + "'>" + str[i].title + "<i>~" + str[i].published.slice(0, 10) + "</i></a></li>";
}
linkHTML += "</ul>";
postHTML+="<div class='poster'><div class='posterHead'><div class='postTitle'>"+str[0].title+"</div><div class='postSeries'>Part of the "+str[0].series+" series</div></div><div class='postBody'>"+str[0].body+"</div><div class='postAuther'>"+str[0].auther+"</div><div class='postPublished'>"+str[0].published+"</div></div>";
document.getElementById('sidebarLinks').innerHTML = linkHTML;
document.getElementById('mainpage').innerHTML = postHTML;
})
}
</script>
</body>
</html>
well, in case anyone else finds the question useful
i solved my own problem
i misunderstood how the history cache works. it never unloaded the data because it does not recognize a paramater change as a new page.
i solved my issue using pushState and altering the state inside the history itself.
thanks for trying though guys and gals.
Not sure what's wrong but I'm getting this error from my chrome console:
jquery-3.2.1.slim.min.js:1244 jQuery.Deferred exception: $.ajax is not a function TypeError: $.ajax is not a function
at HTMLDocument.<anonymous> (file:///C:/Users/Adam/Desktop/UseTime/js/example.js:3:7)
at j (file:///C:/Users/Adam/Desktop/UseTime/js/jquery-3.2.1.slim.min.js:1193:55)
at k (file:///C:/Users/Adam/Desktop/UseTime/js/jquery-3.2.1.slim.min.js:1199:45) undefined
r.Deferred.exceptionHook # jquery-3.2.1.slim.min.js:1244
jquery-3.2.1.slim.min.js:1247 Uncaught TypeError: $.ajax is not a function
at HTMLDocument.<anonymous> (example.js:3)
at j (jquery-3.2.1.slim.min.js:1193)
at k (jquery-3.2.1.slim.min.js:1199)
From this JavaScript:
$(function() { //when the DOM is ready
var times; //declare global variable
$.ajax({ //set up request
beforeSend: function (xhr) { //before requesting data
if (xhr.overrideMimeType) { //if supported
xhr.overrideMimeType("application/json"); // set MIME to prevent errors
}
}
});
//funciton that collect data from the json file
function loadTimetable() { //decalre function
$.getJSON('data/example.json') //try to collect json data
.done(function (data) { //if succesful
times = data; //store in variable
}).fail(function () { //if a problem: show message
$('#event').html('Sorry! we couldnt load your time table at the moment');
});
}
loadTimetable(); //call the function
//CLICK ON TEH EVENT TO LOAD A TIME TABLE
$('#content').on('click', '#event a', function (e) { //user clicks on place
e.preventDefault(); //prevent loading page
var loc = this.id.toUpperCase(); //get value of id attr
var newContent = "";
for (var i = 0; i < times[loc].length; i++) { // loop through sessions
newContent += '<li><span class = "time">' + times[loc][i].time + '</span>';
newContent += '<a href = "descriptions.html#';
newContent += times[loc][i].title.replace(/ /g, '-') + '">';
newContent += times[loc][i].title + '</a></li>';
}
$('#sessions').html('<ul>' + newContent + '</ul>'); // Display Time
$('#event a.current').removeClass('current'); // update selected link
$(this).addClass('current');
$('#details').text('');
});
//CLICK ON A SESSION TO LEAD THE DESCRIPTION
$('#content').on('click', '#sessions li a', function (e) { //click on session
e.preventDefault(); // prevent loading
var fragment = this.href; //title is in href
fragment = fragment.replace('#', ' #'); //Add Space before #
$('#details').load(fragment); //to load info
$('#sessions a.current').removeClass('current'); //update selected
});
//CLICK ON PRIMARY NAVIGATION
$('nav a').on('click', function (e) { //click on nav
e.preventDefault(); //prevent loading
var url = this.href; //get UR: to load
$('nav a.current').removeClass('current');
$(this).addClass('current');
$('#container').remove(); //remove old
$('#content').load(url + ' #container').hide().fadeIn('slow'); // add new
});
});
I'm not sure if it's an issue with the way I'm initiating .ajax or if my jquery isn't correctly implemented. I think it is. Any Thoughts?
edit: here's the html that goes with the script above
<!DOCTYPE html>
<body>
<header>
<h1>UseTime</h1>
<nav>
HOME
PROFILE
MANAGE TASKS
TIME TABLE
</nav>
</header>
<section id="content">
<div id="container">
<div class="third">
<div id="event">
<a id="class1" href="class1.html"><img src="" alt="class1" /> Class 1 </a>
<a id="class2" href="class2.html"><img src="" alt="class2" /> Class 2 </a>
<a id="class3" href="class3.html"><img src="" alt="class3" /> Class 3 </a>
</div>
</div>
<div class="third">
<div id="sessions"> Select a Class from the left </div>
</div>
<div class="third">
<div id="details"> Details </div>
</div>
</div>
<!-- container -->
</section>
<!-- content -->
<script src="js/jquery-3.2.1.slim.min.js"></script>
<script src="js/example.js"></script>
</body>
You are using slim version of jQuery. It Doesn't support ajax Calling.
Use
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
instead of it.
Slim build
Sometimes you don’t need ajax, or you prefer to use one of the many
standalone libraries that focus on ajax requests. And often it is
simpler to use a combination of CSS and class manipulation for all
your web animations. Along with the regular version of jQuery that
includes the ajax and effects modules, we’ve released a “slim” version
that excludes these modules. All in all, it excludes ajax, effects,
and currently deprecated code. The size of jQuery is very rarely a
load performance concern these days, but the slim build is about 6k
gzipped bytes smaller than the regular version – 23.6k vs 30k. These
files are also available in the npm package and on the CDN:
https://code.jquery.com/jquery-3.1.1.slim.js
https://code.jquery.com/jquery-3.1.1.slim.min.js
Referred from jQuery Blog
jQuery 3 slim version doesn't support ajax.
According to the release docs,
Along with the regular version of jQuery that includes the ajax and
effects modules, we’re releasing a “slim” version that excludes these
modules. All in all, it excludes ajax, effects, and currently
deprecated code.
To use .ajax method, simply use the full version one.
Try this one (jquery-3.2.1.min.js) instead of slim (jquery-3.2.1.slim.min.js)
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
I use the code below to load a page using YQL :
$(document).ready(function() {
var url = "http://www.google.com";
$.getJSON("http://query.yahooapis.com/v1/public/yql?" +
"q=select%20*%20from%20html%20where%20url%3D%22" +
encodeURIComponent(url) + "%22&format=xml'&callback=?",
function(data) {
$('#container').html(data.results);
alert('Finish');
$('#container2').text($('#container #hplogo').attr('alt'));
}
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container" style="background-color:#eee;max-height:200px;overflow:scroll;background-color:#eee;">
All Page
</div>
<div id="container2">
Specific Content
</div>
You can see it loads Google website, but I don't know why it stops before executing Alert('Finish'); command. I want to extend my code to get the content of specific element inside the data.results after that.
Any help would be appreciated.
im new to javascript and phonegap and im sitting here the whole day and try to solve this problem.
I have a list and i want to filter some data. And before i filter it, i want to download some data from a server and add it to the list. ( the list is local and if someone uses the search function, new data should pop up too).
The idea is that i create the list with jquery and use the listviewbeforefilter-event to download the data from a server and add it to the list. Then jquery should filter the list.
It works fine when i search filter for 2 chars.
But this doesnt work as expected when i search for more than 2 chars.
I receive the correct data from the server and it will be added to my list but the there is no more filtering in my original list. So i see my original list + the loaded data.
Also the console.log("second") is shown first and then console.log("first). Somehow jquery/phonegap skips the .then part and then comes back to it.
I tried to put the 3 lines ($ul.html( content );$ul.listview( "refresh" );$ul.trigger( "updatelayout");) below the second console.log and then the filter of my local data works but the data from the server wont be shown.
I hope someone can help me with this weird problem.
Heres my code for the listviewbeforefilter-event:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<title>Listview Autocomplete - jQuery Mobile Demos</title>
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.min.css" />
<script src="cordova.js"></script>
<script src="js/jquery-2.0.3.min.js"></script>
<script src="js/jquery.mobile-1.3.2.min.js"></script>
<script>
$( document ).on( "pageinit", "#myPage", function() {
$( "#autocomplete" ).on( "listviewbeforefilter", function ( e, data ) {
// this is a second list which is a backup. It is needed because after each search the original list is flooded with old entries.
var content = document.getElementById("autocomplete2").innerHTML;
var requestdata = "";
var $ul = $( this );
$input = $( data.input ),
value = $input.val();
// ajax call returns cities with at least 3 characters
if ( value && value.length > 2 ) {
$.ajax({
url: "http://gd.geobytes.com/AutoCompleteCity",
dataType: "jsonp",
crossDomain: true,
data: {
q: $input.val()
}
})
// The response is saved in html which i append to the original content
.then( function ( response ) {
var html = "";
console.log("first");
$.each( response, function ( i, val ) {
html += "<li>" + val + "</li>";
});
content = content + html;
$ul.html( content );
$ul.listview( "refresh" );
$ul.trigger( "updatelayout");
});
console.log("second");
}
});
});
</script>
and that is the body with the list:
</head>
<body>
<div data-role="page" id="myPage">
<div data-role="header" data-theme="f">
<h1>Listview </h1>
</div><!-- /header -->
<div data-role="content">
<div class="content-primary">
<ul id = "autocomplete" data-role="listview" data-filter="true" data-filter-placeholder="Search people..." data-filter-theme="d"data-theme="d" data-divider-theme="d">
<li data-role="list-divider">A</li>
<li>Adam Kinkaid</li>
<li>Alex Wickerham</li>
<li>Avery Johnson</li>
</ul>
</div><!--/content-primary -->
</div><!-- /content -->
<script type="text/javascript" charset="utf-8">
$(function(){
$( "#autocomplete2" ).hide();
});
</script>
<ul id = "autocomplete2" data-role="listview" data-filter-theme="d"data-theme="d" data-divider-theme="d">
<li data-role="list-divider">A</li>
<li>Adam Kinkaid</li>
<li>Alex Wickerham</li>
<li>Avery Johnson</li>
</ul>
</div><!-- /page -->
</body>
</html>
i fixed the issue. I changed the code :
content = content + html;
$ul.html( content );
to
$ul.append( html);
i made a custom filter and recognized that the .then was always called AFTER the filter began.
Thats really weird because this method listviewbeforefilter should do everything before the filtering begins. I guess its because the ajax takes so long and will be skipped but later coming back to the .then method when the response received. I thought maybe async:false would help, but nope.
So basically it filters my local data and hides the list which are not needed and than i append the received data to the list.