【问题标题】:Why doesn't filterJSON work with more complex JSON hierarchy?为什么 filterJSON 不适用于更复杂的 JSON 层次结构?
【发布时间】:2010-01-30 04:11:25
【问题描述】:

我想将jQuery filterJSON 与 flickr 一起使用,我发现它确实可以渲染远程 JSON 文件,而不仅仅是其作者​​演示页面中显示的本地文件。当用远程 Twitter JSON 文件替换本地 JSON 文件的默认路径时,它呈现正常。 但是当在下面的代码中使用像 flickr JSON 这样的其他 JSON 提要时,返回未定义的变量并且没有任何渲染,这是为什么? 我已经逐行浏览了插件代码,但我仍然无法理解为什么它只呈现 twitter JSON。

我一定忽略了一些事情,希望您能提供帮助。非常感谢!

这个作品:

$('body').filterJson({ 数据:'http://twitter.com/status/user_timeline/billgates.json?count=10&callback=?', 限制:2, 锚包装:'[p]', nextText : '查看更多', prevText : '返回', 过渡:'淡出', 延迟:400, 完成:函数(i,r){ $('body').append('[p]' + r[i].text + '[/p]')} // [p] 用括号替换 [] 因为代码标签似乎对我不起作用:(

这不起作用:...为什么?

$('body').filterJson({ 数据:'http://api.flickr.com/services/feeds/photos_public.gne?tagmode=any&id=7218238@N08&format=json&jsoncallback=?', 限制:2, 锚包装:'[p]', nextText : '查看更多', prevText : '返回', 过渡:'淡出', 延迟:400, 完成:函数(i,r){ $('body').append('[img src="'+r[i].items.media.m+'" /]')} // [img /] 用括号替换 [] 因为代码标签似乎对我不起作用:(

== 更深的 JSON 层次结构 ==

({ “东西1”:{ “一些阵列”:[{ “第一个属性”:{ “文本”:“文本字符串”, }, “第二个属性”:“更多文本”, “图片”: [{ “t1”:“r1” }, “t2”:“r2” }] }] } })

【问题讨论】:

    标签: jquery ajax json jquery-plugins


    【解决方案1】:

    filterJSON 需要 JSON 结果中的项目数组,而 Flickr 在结果中提供单个父对象,其中包含该父对象的“项目”属性内的项目数组。

    这是 filterJSON 的一个固有限制,如果不修改插件本身就无法修复,如下所示:

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

    然后,您可以指定一组属性名称(例如,itemsLocation: ['items'] 用于 Flickr 结果)以提取您希望 filterJSON 使用的项目。

    工作演示

    http://jsbin.com/enudu3(可通过http://jsbin.com/enudu3编辑)

    完整来源

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

    【讨论】:

    • @brianpeiris,干得好!无论如何让它实时从提要中附加新项目(通过使用setIntervalsetTimeout)或更好的方法?使用 slideDown 效果异步添加新添加会很酷。有什么想法吗?
    • +1 干得好,布莱恩。我修复了jsbin.com/enudu3/3 的小错误你有 itemsLocation 是一个数组,但只使用了数组的最后一个元素。我把它改成了一个名字。 Java代码在这里gist.github.com/290440
    • 我不完全确定您要的是什么(“实时”是什么意思?)但 filterJSON 似乎并没有比演示显示的更多。您必须为自己创建一个自定义解决方案或对 filterJSON 进行进一步的广泛修改。我会把它作为练习留给你;)虽然如果你需要帮助,我们总是欢迎你在 SO 上发布一个新问题。
    • @Hogan 恐怕你误解了我的代码。 itemsLocation 故意是一个数组;您可以在数组中指定多个属性名称,循环将向下迭代 JSON 结果的对象层次结构以查找您要使用的项目。
    • @brianpeiris,非常感谢!我将在另一个问题中重新表述我的“实时”请求。但是最后一件事,因为您修复了插件以使用复杂的层次结构,但它仅适用于数组,无论如何要使其与更深层次的层次结构一起使用,例如我在问题底部发布的示例 JSON 代码。再次感谢!
    【解决方案2】:

    因为您访问的是 feed,而不是带有 Flickr 网址的 API。提要格式需要是 Atom 或 RSS 变体。它不会返回 javascript 调用,而是返回所选格式的数据。

    【讨论】:

    • 插件使用 jQuery 的 getJSON 解析 JSON,因此 URL JSON 提要有效。
    【解决方案3】:

    试试这个:

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

    查看 json 似乎第一个返回一个对象数组 (r[i]) 而第二个只返回一个对象。该对象(项目)中的一个字段是一个数组。

    这应该适合你。 (但是,我认为该插件不会按预期工作,因为它需要一个数组并且正在获取单个对象。)

    【讨论】:

    • 不起作用。 URL 必须是 jsoncallback=? 因为插件使用 jQuery getJSON 来解析 JSONP。
    • 哎呀,对不起@unknown 我改变了我的答案——见上文。
    • 谢谢。它只解析第一个项目,但它会闪烁并中断分页。我也试过 r[i].items[0].media.m 但这不会渲染任何东西。所以,你是对的,它没有按预期工作。无论如何修改插件来渲染数组?
    猜你喜欢
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    相关资源
    最近更新 更多