开发者

How to partially and progressively iterate over a javascript object?

I'm using jQuery and the Flickr API to return a json object containing many photos from a user's photostream.

I would like to iterate over the resulting object to show 40 photos initially, followed by a "load more" button. Each time that button is clicked, the next batch of 40 photos will be appended to the existing list of photos. Once there are no further items in the object, the button goes back to acting as a hyperlink to the user's Flickr profile.

At the moment, I have working code that displays the first 40 photos. But when the "load more" button is clicked, I am adding all the remaining items to the HTML. This is because I couldn't find a way to produce the kind of behaviour described above.

Perhaps there is a more efficient approach that I have also missed.

Here is my existing code. Any additional comments or improvements would be most welcome.

$(function () {
    myApp.uri = myApp.flickrUrl + '&per_page=' + myApp.maxNum + '&api_key=' + myApp.flickrApiKey + '&user_id=' + myApp.flickrUserId;

    myApp.getPhotos(myApp.uri, myApp.callback);
});

var myApp = {
    flickrApiKey : 'xxxx',
    flickrUserId : 'xxxx',
    flickrUrl : 'http://api.flickr.com/services/rest/?format=json&extras=url_t&method=flickr.people.getPublicPhotos',
    callback : 'jsonFlickrApi',
    minNum : 40,
    maxNum : 500
};

myApp.getPhotos = function (u, c) { 
    var jxhr = $.ajax({
        dataType : 'jsonp',
        url : u,
        jsonpCallback : c,
        timeout : 5000
    })

    .success(function (data, status) { 
        var photosContainer = $('#photos');
        photosContainer.prepend('<ul/>');
        var photosList = $('#photos ul');

        // while there are more photos to load, the default link text
        // is replaced with a string stored in a data-* attribute
        var moreLink = $('#more');
        var moreLinkText = moreLink.text();
        var moreLinkTextJs = moreLink.attr('data-text-js');
        moreLink
         .attr('data-text-nojs', moreLinkText)
         .text(moreLinkTextJs)
         .insertAfter(photosContainer);

        // initially populate the Photo List with the first 40 photos
        $.each(data.photos.photo, function (i, item){
            if (i < myApp.minNum) {
                var photoEl = '<li><a href="' + 'http://www.flickr.com/photos/' + item.owner + '/' + item.id + '" target="_blank"><img src="' + item.url_s + '" alt="' + item.title + '"></a></li>';
                $(photoEl).appendTo(photosList);
            }
        });

        // click on "More" link loads in all remaining photos.
        // would like this to load the next 40 in the object
        // each click until there are no items left...at which point unbind
        moreLink.live('click', function (e) {
            e.preventDefault();
            $.each(data.photos.photo, function (i, item){
                if (i >= myApp.minNum) {
                    var photoEl = '<开发者_JAVA技巧li><a href="' + 'http://www.flickr.com/photos/' + item.owner + '/' + item.id + '" target="_blank"><img src="' + item.url_s + '" alt="' + item.title + '"></a></li>';
                    $(photoEl).appendTo(photosList);
                } 
            });

            // unbind events and revert the link text
            moreLink.text(moreLinkText).blur().die();
        });
    })

    .error(function (status) { 
    });
};


I would suggest looking at templates

http://api.jquery.com/category/plugins/templates/

You can actually just pass the JSON to the template and appended it. No loops in your code :-)

Here is a tutorial :

http://www.borismoore.com/2010/09/introducing-jquery-templates-1-first.html

EDIT:

To modify the returned JSON into 40 photo blocks, use the array.slice method on the data.photos array

Something like

var number_of_blocks = Math.floor(data.photos / 40)
var blocks = [];
var last_block_starts_at = number_of_blocks * 40;

for (var i = 0 ; i < number_of_blocks ; i++;)
{
blocks << data.photos.slice(i,40+i);
}
blocks << data.photos.slice(last_block_starts_at);

Now you can loop over the blocks until the array is ended...


I got this code from one of my pages. i guess it something like u wanted. sorry, lines are not documented..but im sure u can extract the logic from it.

function photoLookUp(btn, ImageToUpdateId, LookUpWindowId, ImageContainerId, ImageSize) {

    var wnd = $(LookUpWindowId);
    if (wnd.active) return (wnd.style.display == "none") ? show() : hide();

    var wndResize = wnd.children[1].children[0];
    var ImageToUpdate = $(ImageToUpdateId);
    var imgContainer = $(ImageContainerId); imgContainer.innerHTML = "";

    wndResize.onmousedown = resizeOnMouseDown;
    wnd.onmousemove = function (e) { wnd.tHide = false }
    wnd.onmouseout = function (e) { wnd.tHide = true }
    wnd.active = true;

    var ldr = document.createElement("img");
    ldr.src = "Images/preloader.gif";
    ldr.title = "Loading, please wait...";
    ldr.onmouseover = function (e) { wnd.tHide = false }
    imgContainer.appendChild(ldr);

    show();

    var svc = new WADService();
    var par = { UserID: User.Profile.UserID };
    var dat = svc.get("GetUserPhotos", false, par);

    if (dat.length > 0)
        load(dat.shift(), 15);
    else
        imgContainer.innerHTML = "no photo collection";

    function load(Photo, cnt) {
        var par = { ImageID: Photo.ImageID, ImageSize: ImageSize };
        svc.get("GetImageURL", true, par).onreadystatechange = function (e) {
            if (this.readyState == 4) {
                var res = svc.deserialize(this.responseText);
                if (res) render(res);
            }
        }
        function render(res) {
            Photo.ImageURL = res;
            var obj = new PhotoObj(Photo).frameElement;
            imgContainer.insertBefore(obj, ldr)
            if (dat.length > 0 && --cnt > 0) {
                ldr.onclick = null;
                ldr.src = "Images/preloader.gif";
                ldr.title = "Loading, please wait...";
                load(dat.shift(), cnt)
            } else if (dat.length > 0) {
                ldr.onclick = loadMore;
                ldr.src = "Images/ViewPhoto.png";
                ldr.title = "View more...";
                //none of the ff lines work, ugh! how can i scroll my div in firefox ?!?!
                //imgContainer.scroll(0, imgContainer.scrollHeight - imgContainer.clientHeight);
                //imgContainer.scroll(0, imgContainer.scrollHeight);
            } else {
                imgContainer.removeChild(ldr);
            }
        }
        function loadMore(e) {
            ldr.onclick = null;
            load(dat.shift(), 16);
        }
    }
    function show() {
        wnd.style.display = "inline-block";
        btn.children[0].src = "Images/ArrowU.gif";
        wnd.tHide = true;
        wnd.tInterval = setInterval(_hide, 2000);
        function _hide(e) {
            if (wnd.tHide) { clearInterval(wnd.tInterval); hide() }
        }
    }
    function hide(e) {
        wnd.style.display = "none";
        btn.children[0].src = "Images/ArrowD.gif";
    }
    function resizeOnMouseDown(e) {
        var X = e.clientX, Y = e.clientY;
        var W = imgContainer.offsetWidth, H = imgContainer.offsetHeight;
        wndResize.style.cursor = "se-resize";
        document.onmousemove = function (e) {
            imgContainer.style.width = Math.max(72, (W + e.clientX - X)) + "px";
            imgContainer.style.height = Math.max(72 + 16, (H + e.clientY - Y)) + "px";
            return false;
        }
        document.onmouseup = function (e) {
            document.onmousemove = null; document.onmouseup = null;
            wndResize.style.cursor = "default";
        }
        return false;
    }
    function PhotoObj(Photo) {
        var img = document.createElement("div");
        this.frameElement = img;
        img.title = Photo.Title;
        img.ImageID = Photo.ImageID;
        img.ImageURL = Photo.ImageURL;
        img.style.backgroundImage = "url(" + Photo.ImageURL + ")";
        img.onmouseover = function (e) { wnd.tHide = false }
        img.onclick = function select(e) {
            ImageToUpdate.ImageID = img.ImageID;
            ImageToUpdate.ImageURL = img.ImageURL;
            ImageToUpdate.style.backgroundImage = img.style.backgroundImage;
            hide();
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜