0

Facebook の公開ページからアルバムや写真をダウンロードして自分の Web サイトに表示するためにFacebooks Javascript APIjquery モバイル Web サイトでを使用しています。

API は、物事がどのように行われるかについて非常に簡単であり、私はすべてがかなり簡単に機能するようにしました.

私がこれまでに行ったこととISが機能していること

ユーザーがボタンを押すと、javascript FB API が呼び出されるページが読み込まれ、特定の facebook ページのすべてのアルバムのリストがすべての写真などとともに動的に生成されます。これはうまく機能します。API が呼び出されると 25 枚のアルバムしかフェッチされず、フェッチするアルバムがさらにある場合は、ユーザーが API に別の呼び出しを行い、より多くのアルバムをフェッチするために押す「その他のアルバム」ボタンがあります。それも大活躍...

問題

アルバム/写真をインポートしたい2つの異なるFacebookページが必要だと決めたときに、私の問題が発生しました。そこで、2 つのオプション (facebook ページ 1、facebook ページ 2) を持つ水平ボタンを作成し、navBar を永続化し、ボタンの 1 つを押すと、API 呼び出しを実行して各ページのアルバムを取得する必要があります。これは悲しいことに機能しません... 2つのページのいずれかに電話をかけると、すべてが機能します。「その他のアルバム」ボタンも機能します。しかし、他のFacebookページに移動すると、APIへの呼び出しが機能しません...理由がわかりません...「その他のアルバム」ボタンが機能します。つまり、APIに対して複数の呼び出しを行うことができます。しかし、ajax を使用して jquery モバイル サイトの他のページに移動すると、呼び出しが完了しないのはなぜですか? JavaScriptファイル内にアラートを配置すると、それが表示されます。つまり、コードが呼び出されます。しかし、APIへの実際の呼び出しの中にアラートを入れると、アラートが表示されません....それは、何らかの理由で呼び出しがブロックされていることを意味すると思います...

ここで何が起こっているのでしょうか?

2 つのアルバムの 1 つに対する私の 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 のみが変更されます。この時点で、最初に他のページをロードし、次にこれを再びロードすると、2番目の呼び出しが機能していないことを指摘したいと思います。つまり、2 番目の呼び出しが決して実行されないという問題ではなく、アルバムの 1 つに特定の問題があるわけではありません。

私が何をしようとしているのかを確認する必要がある場合に備えて、次の 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/

マルチメディアに移動すると、 「Photos Noche Joven」「Photos Espacio Joven」の2 つのタブがあります。最初のものは正常にロードされていることがわかります。また、下に移動すると、[その他のアルバム] ボタンが表示されます。これも正常に機能し、API を呼び出します。問題は、「Photos Espacio Joven」に移動すると、説明した理由で通話が機能しないことです。

4

2 に答える 2

2

window.fbAsyncInitまず、loadMoreAlbumsハンドラーには必要ありません。以前に同じ関数を定義しました - それで十分です。

第二に、FB.init何度も使用するのではなく、一度だけ使用します。これは 内で定義されてwindow.fbAsyncInitおり、その関数は SDK がロードされたときに Facebook SDK によって呼び出されるためです。そして、スクリプトが既にロードされているかどうかのチェックがあります:

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

つまり、FB スクリプトを 1 回ロードし、FB を 1 回初期化します。

主なことは、あるスコープ (「pageshow イベント」ハンドラーの 1 つ) で FB オブジェクト (FB.init) を初期化し、別のスコープ (他のハンドラー) で FB.api を使用できないことです。そのため、空の結果が得られます。

いくつかの解決策を試すことができます。

1.ページが変わるたびにFBを初期化できます。

FB オブジェクトが存在することを確認して、window.fbAsyncInit() を呼び出すだけです。変更することで、このソリューションをすばやく試すことができます

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

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

これは醜い方法です。

2.コードをリファクタリングする必要があります。

2 つのハンドラーではなく、トップ レベルで FB を初期化します。1 つのハンドラーを作成し、ページが変更されたときにそれを呼び出します。必要なパラメーターを渡すか、DOM 要素のデータを使用できます。

PS。ページが変更されるたびに、loadMoreAlbums の新しいハンドラーが追加されます。別のアルバムに切り替えて、戻って 2 つの通話と 2 つのデータを取得し、もう一度切り替えて 3 つのデータを取得します。

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

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

うーん、言いたいことは山ほどある…

  1. 「ページ」ごとに関数を作成しないように、要素を考慮に入れる必要があります
  2. は 1 回だけ呼び出され、次に呼び出すときにアルバムを取得するためのクエリが起動されないため、FB.init複数回呼び出す必要はありません(これが、2 番目のデータをロードできない理由です)。ページ)fbAsyncInitFB.apiFB.init
  3. はい、リクエストが関数内にないFB.initため、があっても詳細ボタンは機能しますFB.apifbAsyncInit
  4. ページが公開されているため、ユーザーが接続されているかどうか、またはユーザーがアプリを受け入れたかどうかを知る必要がないため、 のFB.api直後にを起動できますFB.initが、それ以外の場合は、FB.login関数を実装するか、少なくともステータス変更イベントのリスナーを使用して、ユーザーが接続されているかどうかを確認し、リクエストを発行します
  5. ...

これらすべてを実現する 1 つの方法を見たい場合は、こちらをご覧ください: http://jsfiddle.net/ZES3X/

于 2013-08-25T15:44:26.510 に答える