2011-02-28 41 views
2

我使用jQuery和Flickr API來返回包含用戶照片流中的許多照片的json對象。如何部分和漸進地遍歷JavaScript對象?

我想遍歷結果對象最初顯示40張照片,然後是「加載更多」按鈕。每次點擊該按鈕時,下一批40張照片將被添加到現有照片列表中。一旦對象中沒有其他項目,該按鈕就會回到用戶的Flickr配置文件的超鏈接。

目前,我有工作代碼,顯示前40張照片。但是當單擊「加載更多」按鈕時,我將所有剩餘的項目添加到HTML中。這是因爲我無法找到一種方法來產生上述那種行爲。

也許有一種更有效的方法,我也錯過了。

這是我現有的代碼。任何其他意見或改進將是最受歡迎的。

$(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 = '<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) { 
    }); 
};
+0

東西,你可以做些什麼來幫助與性能,如果你不需要遍歷條目http://api.jquery.com/each/ HTTP其餘逃脫你的循環://的jsfiddle。 net/vj9JW/ – stanwilsonjr 2011-02-28 21:46:41

+0

感謝您的指針 – user638118 2011-02-28 23:05:23

回答

1

我建議在尋找模板

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

實際上,你可以只通過JSON的模板,並追加了。在你的代碼沒有循環:-)

這裏是一個教程:

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

編輯:

修改返回的JSON爲40個圖像塊,使用array.slice方法上data.photos陣列

喜歡的東西

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

現在你可以循環塊直到陣列結束...

+0

+1:編寫您自己的代碼來生成HTML是在您的代碼中重複的努力。模板幫助構建可維護且不易出錯的代碼。然而,我更喜歡使用像http://code.google.com/closure/templates/docs/helloworld_js.html – 2011-02-28 20:00:36

+0

@Mendes這樣的工具:我之前使用過模板,但我沒有看到如何回答我的問題關於以40個項目批次來檢查對象。它也好像很多額外的代碼。爲什麼在這種情況下使用$ .each更有效地包含模板插件? – user638118 2011-02-28 20:20:15

+0

添加了一些代碼重新組織飼料成40個照片塊.. – macarthy 2011-02-28 20:36:28

0

我從我的一個頁面獲得了這段代碼。我想這是你想要的東西。對不起,線沒有記錄..但我確定你可以從中提取邏輯。

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