0

Facebooks Javascript API在我的jquery 移动网站中使用,以便从 facebook 公共页面下载专辑和照片并将它们呈现到我的网站。

API 对事情的完成方式非常直截了当,我让一切工作变得相当容易。

到目前为止我所做的并且正在工作

当用户点击一个按钮时,我加载一个页面,调用 javascript FB API 并动态生成特定 facebook 页面的所有专辑的列表,以及所有照片等。这很好用。当调用 API 时,它只获取 25 个专辑,当我有更多专辑要获取时,我有一个“更多专辑”按钮,用户点击该按钮可以再次调用 API 并获取更多专辑。这也很好用……

问题

我的问题出现了,当我决定我想要 2 个不同的 Facebook 页面时,我想从中导入相册/照片。所以我制作了一个带有 2 个选项的水平按钮(facebook 第 1 页,facebook 第 2 页),使导航栏保持不变,当我点击其中一个按钮时,我需要进行 API 调用并获取每个页面的相册。可悲的是,这不起作用...当我拨打两页之一时,一切正常。甚至“更多专辑”按钮也有效。但是当我导航到另一个 facebook 页面时,对 api 的调用不起作用......我不明白为什么......“更多专辑”按钮有效,这意味着我可以多次调用 api。但是为什么当我使用 ajax 导航到我的 jquery 移动网站上的另一个页面时,调用无法完成?我在javascript文件中放了一个警报,我看到了,这意味着代码被调用。但是当我将警报放在对 api 的实际调用中时,我看不到任何警报......我想这意味着由于某种原因调用被阻止......

有什么想法可能在这里发生吗?

我的 2 张专辑之一的 javascript 如下所示:

$('#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));
        });
});

您可以看到对 api 的调用、html 页面的动态创建以在列表视图中显示相册、带有照片的相册的数量、更多相册按钮等......我的另一个 facebook 页面的 javascript 是相同的,并且只有页面 ID 更改。在这一点上,我想指出,如果我先加载另一个页面,然后再加载这个页面,那么第二个调用就是不工作的那个。这意味着我对其中一张专辑没有具体问题,而不是第二个电话永远不会运行的问题。

这是 html 页面,以防您需要查看我到底想要做什么:

<!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><a href="#espaJoven"><img src="themes/icons/news.png" alt="Information" class="ui-li-icon">Es Joven</a></li>
                <li><a href="#noJoven"><img src="themes/icons/research.png" alt="Information" class="ui-li-icon">La Noche es Joven</a></li>
                <li><a href="#photosNJ"><img src="themes/icons/staff.png" alt="Information" class="ui-li-icon">Multimedia</a></li>
                <li><a href="#sanrJoven"><img src="themes/icons/students.png" alt="Information" class="ui-li-icon">Sar Joven</a></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>
        <a href="#" data-icon="back" data-rel="back" title="Go back">Back</a>
        <div data-role="navbar">
            <ul>
                <li><a href="#photosNJ" class="ui-btn-active ui-state-persist">Photos Noche Joven</a></li>
                <li><a href="#photosEJ">Photos Esp Joen</a></li>
                <li><a href="#videos">Videos</a></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>
        <a href="#" data-icon="back" data-rel="back" title="Go back">Back</a>
        <div data-role="navbar">
            <ul>
                <li><a href="#photosNJ">Photos Noche Joven</a></li>
                <li><a href="#photosEJ" class="ui-btn-active ui-state-persist">Photos Espacio Joven</a></li>
                <li><a href="#videos">Videos</a></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>

如果你决定读到这里,非常感谢。任何,绝对任何对此的评论或想法对我来说都是非常有价值的,所以如果你有任何想法请与我分享:)

提琴手:http: //jsfiddle.net/lessisv/GW4PK/

转到多媒体,我有 2 个选项卡“Photos Noche Joven”“Photos Espacio Joven”。可以看到第一个加载正常。此外,如果您向下看,您可以看到“更多专辑”按钮,该按钮也可以正常工作并调用 API。问题是,当我转到“Photos Espacio Joven”时,由于我描述的原因,该电话无法正常工作。

4

2 回答 2

2

首先,你不需要window.fbAsyncInit在你的loadMoreAlbums处理程序中。您之前定义了相同的函数——这就足够了。

其次,你不会使用FB.init很多次——只有一次。因为它是在内部定义的window.fbAsyncInit,并且该函数在加载 SDK 时由 Facebook SDK 调用。并且检查脚本是否已经加载:

if (d.getElementById(id)) {return;}

这意味着您加载一次 FB 脚本并初始化一次 FB。

主要的是,您不能在一个范围(“pageshow 事件”处理程序之一)中初始化 FB 对象(FB.init),然后在另一个范围(另一个处理程序)中使用 FB.api。这就是你得到空结果的原因。

您可以尝试多种解决方案。

1.每次页面变化都可以初始化FB。

只需检查是否存在 FB 对象并调用 window.fbAsyncInit()。您可以通过更改快速尝试此解决方案

if (d.getElementById(id)) {return;}

if (d.getElementById(id)) {window.fbAsyncInit(); return;} 

这是丑陋的方式。

2.你真的应该重构你的代码。

在顶层初始化 FB - 不在两个处理程序中;创建一个处理程序 - 并在页面更改时调用它。您可以传递必要的参数或使用 DOM 元素数据。

PS。每次页面更改时都会添加一个新的 loadMoreAlbums 处理程序。您切换到另一张专辑,返回并获得两次通话和双倍数据,再次切换并获得三倍数据。

$(document).on("pageshow", '#photosNJ', function () {
   ...

    $("#loadMoreAlbums").click(function () {
        ...
    });
   ...
});
于 2013-08-21T22:02:23.280 回答
1

嗯,有很多话要说……

  1. 您确实必须考虑因素以避免为每个“页面”创建函数
  2. 您不必多次调用FB.init,因为fbAsyncInit只会调用一次,并且FB.api下次调用时不会触发检索相册的查询FB.init(这就是您无法加载第二个数据的原因页)
  3. 是的,即使您有 more 按钮也可以使用FB.init,因为您的FB.api请求不在fbAsyncInit函数内
  4. 由于您的页面是公开的,因此您不需要知道用户是否已连接或他是否已接受您的应用程序,因此您可以在FB.api之后触发FB.init,但在其他情况下,您必须实现一个FB.login函数或至少一个侦听状态更改事件以了解您的用户是否已连接,然后触发请求
  5. ...

如果你想看看实现这一切的一种方法,请看这里:http: //jsfiddle.net/ZES3X/

于 2013-08-25T15:44:26.510 回答