开发者

Why doesn't filterJSON work with more complex JSON hierarchy?

I would like to use jQuery filterJSON with flickr, and I found that it does render remote JSON files and not only local ones as shown in its author's demo page. When replacing the default path to local JSON file with remote Twitter JSON file, it renders fine. BUT when using other JSON feeds like the flickr JSON in the code below, returns undefined variable and nothing renders, why is that? I have went through the plugin code line by line many times and I still cannot understand why it only renders twitter JSON.

I must be overlooking something and would appreciate your help. Thanks a lot!

This Works:

$('body').filterJson({
 data : 'http://twitter.com/status/user_timeline/billgates.json?count=10&callback=?',
 limit : 2,
 anchorWrap : '[p]',
 nextText : 'See More',
 prevText : 'Go Back',
 transition: 'fade',
 delay : 400,

 complete : function(i, r) {
       $('body').append('[p]' + r[i].text + '[/p]')}  // [p] replace [] with brackets as the code tag does not seem to be wo开发者_开发问答rking for me :(

This Does Not Work: ... Why?

$('body').filterJson({
 data : 'http://api.flickr.com/services/feeds/photos_public.gne?tagmode=any&id=7218238@N08&format=json&jsoncallback=?',
 limit : 2,
 anchorWrap : '[p]',
 nextText : 'See More',
 prevText : 'Go Back',
 transition: 'fade',
 delay : 400,

 complete : function(i, r) {
       $('body').append('[img src="'+r[i].items.media.m+'" /]')}  // [img /] replace [] with brackets as the code tag does not seem to be working for me :(

== EVEN deeper JSON hierarchy ==

({
    "something1": {
        "someArray": [{
            "1stproperty": {
                "text": "textstring",
            },
            "2ndproperty": "moretext",
            "image": [{
                "t1": "r1"
            },
            "t2": "r2"
            }]
        }] 
    }
})


filterJSON expects an array of items in the JSON result whereas Flickr provides an single parent object in the result which contains an array of items inside the 'items' property of that parent object.

This is an inherent limitation in filterJSON that you cannot fix without modifying the plugin itself as follows:

24a27
>      itemsLocation: null,
39a43,49
>        if (options.itemsLocation && $.isArray(options.itemsLocation)) {
>          // extract the items from the object hierarchy
>          $.each(options.itemsLocation, function () {
>            r = r[this];
>          });
>        }
>

You can then specify an array of property names (e.g. itemsLocation: ['items'] for the Flickr result) to extract the items that you want filterJSON to work with.

Working Demo

http://jsbin.com/enudu3 (editable via http://jsbin.com/enudu3)

Full Source

https://gist.github.com/290420

/*
 * filterJSON v.9.1 - http://www.jeffrey-way.com
 * Last Updated: January 29, 2009

 * When you attach a JSON file, it will parse it with getJSON, and then allow you to filter through and display the items on the page according to 
 * a specified limit, delay, transition, etc. 

 * Developed by Jeffrey Way
 * http://jeffrey-way.com/filterjson-a-jquery-plugin/
 * jeffrey@effrey-way.com
 * Modified by Brian Peiris
 * http://twitter.com/brianpeiris
*/

(function($) {

    $.fn.filterJson = function(options) {
        
        var defaults = {
            anchorWrap : '<p>',
            complete : null,
            data : null,
            delay : 500,
            limit : 5,
            index : 0,
            transition : 'fade',
            itemsLocation: null,
            
            nextId : 'next',
            nextText : 'More',
            
            prevId : 'prev',
            prevText : 'Last'
        },
        
        options = $.extend(defaults, options);
        
        this.each(function() {
        
            var $this = $(this);
            
            $.getJSON(options.data, function(r) {
                if (options.itemsLocation && $.isArray(options.itemsLocation)) {
                    // extract the items from the object hierarchy
                    $.each(options.itemsLocation, function () {
                        r = r[this];
                    });
                }

                // add the NEXT button
                $this
                   .after(options.anchorWrap)
                   .next()
                   .append('<a></a>')
                   .children()
                   .attr('href', '#')
                   .attr('id', options.nextId)
                   .text(options.nextText);
                
                // Get first set of items
                options.index = getItems(r);                
                
                // when the user clicks the NEXT button
                $('a#' + options.nextId).live('click', function() { 

                    // If a previous button doesn't exist, create it!
                    if($('a#' + options.prevId).length == 0) {
                        $this
                           .after(options.anchorWrap)
                           .next().append('<a></a>')
                           .children()
                           .attr('href', '#')
                           .attr('id', options.prevId)
                           .text(options.prevText);                 
                    }
                    
                    // If the user chose the "slide" transition, slideUp...otherwise fadeOut.
                    if(options.transition === 'slide') $this.slideUp(options.delay, emptyAndContinue);
                    else $this.fadeOut(options.delay, emptyAndContinue);        
                    
                    // remove the current items and get the next set, passing in the json file - represented by "r"
                    function emptyAndContinue() {
                        $this.empty();
                        options.index = getItems(r);
                    }                   
                    
                    return false;
                }); // end nextId click     
        
                
                // When the previous button is clicked, add the NEXT button if one doesn't exist.
                $('a#' + options.prevId).live('click', function() {
                    if($('a#' + options.nextId).length == 0) {
                        $this
                           .after(options.anchorWrap)
                           .next().append('<a>')
                           .children()
                           .attr('href', '#')
                           .attr('id', options.nextId)
                           .text(options.nextText);
                    }   
                    
                    // If the user chose the "slide" transition, slide up...oitherwise fadeOut
                    if(options.transition === 'slide') $this.slideUp(options.delay, emptyAndContinue);
                    else $this.fadeOut(options.delay, emptyAndContinue);
                    
                    // remove the current items and get the next set, passing in the json file - represented by "r"
                    function emptyAndContinue() {
                        $this.empty();
                        options.index = getPreviousItems(r);                        
                    }                   
                    
                    return false;                   
                }); 
                
                return this;
                
            }); // end getJSON
        
            // Acccepts the parsed JSON file as a parameter "r", and then gets the next set of items. 
            function getItems(r) {  

                var i = options.index, // the current index, or offset. 
                    dataLength = r.length; // total # objects in the JSON file.
                    
                    (function append() {            
                        if(i === dataLength) {$('a#' + options.nextId).remove(); return; } // if the index is equal to total # of items in JSON file, remove the "next" link and exit.
                        if(i >= options.limit + options.index) return; // if index is gte to the current index + the limit, return because reached the max.
                                                    
                        options.complete(i, r); // call userdefined "complete" function, which appends necessary html to the page.
                        
                        // If the user chose the "slide" transition, slide up...oitherwise fadeOut                      
                        if(options.transition === 'slide') $this.slideDown(options.delay);
                        else $this.fadeIn(options.delay);
                        i++;
                        append(); // Rinse and repeat until i equals the limit          
                    })();   
    
                // Increase INDEX by current offset to allow for the next grouping.
                return options.index + options.limit;
            } /// end getItems
            
            
            // Used when the PREVIOUS BUTTON is clicked. 
            function getPreviousItems(r) {
                // Need to reduce the current options.index back to what it would have been on the previous page. A bit confusing...
                var i = options.index - options.limit * 2;          
                    
                (function append() { // if the user has chosen to delay the appearance of each new image...     
                    if(i === 0) $('a#' + options.prevId).remove(); // If i = 0, we don't need a previous button.        
                    if(i >= options.index - options.limit) return;

                    options.complete(i, r); // call userdefined "complete" function, which appends necessary html to the page.
                    
                    if(options.transition === 'slide') $this.slideDown(options.delay);
                    else $this.fadeIn(options.delay);
                    i++;
                    append(); // Rinse and repeat until i equals the specified options.limit.
                })();       
    
                // REDUCE index by the limit, because "PREVIOUS BUTTON" was clicked
                return options.index - options.limit;
            } /// end getPreviousItems



        }); // end this.each
        
        
        
    };  // end plugin. Go eat some cake.
    
})(jQuery);


Because you are accessing a feed, not an API with the Flickr url. The feed format needs to be either an Atom or RSS variant. It won't return a javascript call, but rather data in the chosen format.


Try this:

complete : function(i, r) {
       $('body').append('[img src="'+r.items[0].media.m+'" /]')} 

Looking at the json it seems the first one returns an array of objects (r[i]) and the 2nd only returns a single object. One of the fields in that object (items) is an array.

This should work for you. (However, I don't think the plugin will work as expected since it expects an array and is getting a single object.)

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜