0

I will try to keep this post the shortest possible.

I am trying to create a jquery mobile web-page where , i import the photos and albums from a facebook page , using the facebook javascript sdk , and show them to my page. I also use the PhotoSwipe plugin to get the albums show nicely with carousel effects etc. You dont need to have any knowledge on the plugin or the sdk to help , as i can tell you exactly where is my problem and you only need to know javascript/jquery.

My problem is that i do import the albums and show them to the user but i cant get the carousel effect of the plugin. From the example code of the plugin , when a user selects a picture this code is executed:

$(document).ready(function(){

                $('div.gallery-page')
                    .live('pageshow', function(e){
                        var 
                            currentPage = $(e.target),
                            options = {},
                            photoSwipeInstance = $("ul.gallery a", e.target).photoSwipe(options,  currentPage.attr('id'));

                        return true;

                    })

                    .live('pagehide', function(e){

                        var 
                            currentPage = $(e.target),
                            photoSwipeInstance = PhotoSwipe.getInstance(currentPage.attr('id'));

                        if (typeof photoSwipeInstance != "undefined" && photoSwipeInstance != null) {
                            PhotoSwipe.detatch(photoSwipeInstance);
                        }

                        return true;

                    });

            });

        }(window, window.jQuery, window.Code.PhotoSwipe));

I use the same code(i use .on on my code) to my "dynamically-generated" web-page but it seems that the code inside $('div.gallery-page') is NEVER executed. And i really cant figure out why , as the page that i generate is identical to the example page. I give the same class names, i use the same divs everything.

This is my code :

<!DOCTYPE html> 
<html>
<head>
    <meta charset="utf-8">
    <title>CityInfo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
    <link href="photoSwipe/jquery-mobile.css" type="text/css" rel="stylesheet" />
    <link href="photoSwipe/photoswipe.css" type="text/css" rel="stylesheet" />

    <script type="text/javascript" src="photoSwipe/klass.min.js"></script>  
    <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>
    <script type="text/javascript" src="photoSwipe/code.photoswipe.jquery-3.0.5.min.js"></script>

    <script type="text/javascript">
        //PhotoSwipe
        /*
         * IMPORTANT!!!
         * REMEMBER TO ADD  rel="external"  to your anchor tags. 
         * If you don't this will mess with how jQuery Mobile works
         */
        (function(window, $, PhotoSwipe){
            $(document).ready(function(){
                $('div.gallery-page')
                    .on('pageshow', function(e){
                        var 
                            currentPage = $(e.target),
                            options = {},
                            photoSwipeInstance = $("ul.gallery a", e.target).photoSwipe(options,  currentPage.attr('id'));  
                        return true;    
                    })

                    .on('pagehide', function(e){
                        var 
                            currentPage = $(e.target),
                            photoSwipeInstance = PhotoSwipe.getInstance(currentPage.attr('id'));
                        if (typeof photoSwipeInstance != "undefined" && photoSwipeInstance != null) {
                            PhotoSwipe.detatch(photoSwipeInstance);
                        }
                        return true;    
                    }); 
            });
        }(window, window.jQuery, window.Code.PhotoSwipe));
    </script>

</head> 

<body> 

    <div id="fb-root"></div>
    <script>
        var albumPhotos = new Array();
        var albumThumbnails = new Array();
        // 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
            });

            FB.api('169070991963/albums', checkForErrorFirst(getAlbums));

        }


        // 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("Noo!!");
                } else {
                    myFunc(response);
                }
            };
        }


        function getAlbums(response) {
            for (var i=0; i < response.data.length; ++i) {
                processAlbum(response.data[i], i);
            } 
        }


        function processAlbum(album, i) {
            FB.api(album.id + "/photos", 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) {
            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');

               $("#Home").after('<div data-role="page" data-add-back-btn="true" id=Gallery'+ i +
               ' class="gallery-page"> ' +
               ' <div data-role="header"><h1>Gallery</h1></div> ' + ' <div data-role="content"> ' +
               ' <ul class="gallery"></ul> ' + ' </div> ' +
               ' </div> ');

               for(var x=0; x < albumPhotos[i].length; x++)
                    $('#Gallery' + i + ' .gallery').append('<li><a href="' + albumPhotos[i][x] 
                    + '"  rel="external"><img src="' +  albumThumbnails[i][x] + '"' + '/> </a> </li>');
             };
        }

        // 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'));

    </script>



    <div data-role="page" id="Home" data-theme="c">
        <div data-role="content">
            <h2 id="banner" align = "center">Photo Albums</h2>
            <ul data-role="listview" data-inset="true" class="albums">      
            </ul> 
        </div>      
    </div>



</body>
</html>

I think the important part here is this:

 $("#Home").after('<div data-role="page" data-add-back-btn="true" id=Gallery'+ i +
               ' class="gallery-page"> ' +
               ' <div data-role="header"><h1>Gallery</h1></div> ' + ' <div data-role="content"> ' +
               ' <ul class="gallery"></ul> ' + ' </div> ' +
               ' </div> ');

where as you can see i give the correct class name class="gallery-page" to every dynamically generated div.

I will also give here 2 screenshots when debugging with chrome , one from the example code that is working and one from my code , just to show you that the elements on the final html page look identical..

Example code(the example code given from the site has 2 galleries of photos , i expanded one to see how are the html elements):

enter image description here

My code(because i import the albums from a facebook page , here we have a lot more galleries. Again i expand one of them to show you that the html elements are identical to the example , and i use the same classes and divs):

enter image description here

In order to enlarge the images press ctrl + (+). To go back to normal press ctrl + (-).

If you have ANY idea why the javascript is not executed , please leave a hint. I am trying to fix this for more than a week without any success. Thank you very very much for reading till here.

Johny Jaz
  • 875
  • 2
  • 13
  • 26
  • `$('div.gallery-page')` is dynamically created, you need to attached events correctly this way `$(document).on('pageshow', '[data-role=page].gallery-page', function () { etc... })` Also get rid of `.ready`, never use it with jQuery Mobile. – Omar Jul 01 '13 at 15:15
  • Thank you very much Omar for your answer. Could you please provide it as an answer and explain a bit more what exactly you mean? I have 2 .on in the code. What exactly should i replace? – Johny Jaz Jul 01 '13 at 15:22

3 Answers3

3

live() is removed from jQuery 1.9, and I see this tag in your code.

jquery-1.9.1.min.js
Brad M
  • 7,857
  • 1
  • 23
  • 40
  • 1
    This isnt the issue , i do replace it with on. – Johny Jaz Jul 01 '13 at 15:17
  • 1
    @Omar and @Johny Jaz - Do not say this is not *the* issue. If you use `live()` and jQuery 1.9, this is clearly wrong. If you posted the wrong code, then edit it, but don't hate on people's answers. I'm not psychic; I only can help with code I see. – Brad M Jul 01 '13 at 15:20
  • 1
    Apparently you dont see well. I DO USE .on in my code dont you see it? The .live was IN THE EXAMPLE code. – Johny Jaz Jul 01 '13 at 15:25
3

Binding events to dynamically create items should be like this.

$(document).on('event', '.element', function () { magic });

Demo

This code applies for all types of dynamic elements.

Another important note, don't use .ready / $(function($) with jQuery Mobile. Use jQuery Mobile events.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Omar
  • 32,302
  • 9
  • 69
  • 112
1

You must change where you use live by on

$(document)
    .on('pageshow', 'div.gallery-page', function(e){
        var
                currentPage = $(e.target),
                options = {},
                photoSwipeInstance = $("ul.gallery a", e.target).photoSwipe(options,  currentPage.attr('id'));
        return true;
    })

    .on('pagehide', 'div.gallery-page', function(e){
        var 
            currentPage = $(e.target),
            photoSwipeInstance = PhotoSwipe.getInstance(currentPage.attr('id'));

        if (typeof photoSwipeInstance != "undefined" && photoSwipeInstance != null) {
             PhotoSwipe.detatch(photoSwipeInstance);
        }

        return true;

    });

});

documentation: http://api.jquery.com/on/

anacarolinats
  • 667
  • 8
  • 19