动态Javascript数组.length

时间:2014-01-07 20:03:03

标签: javascript jquery arrays

我要做的是将新的“.post”(已被无限滚动脚本检索)推入到包含所有“.post”的数组中。

完整代码:https://gist.github.com/sxxfi/8296403
现场演示:http://soof-show.tumblr.com(使用键盘箭头键导航帖子)

最初,五个“.post”显示在“.content”div中,然后每次点击“更多”按钮时,它会再添加5个“.post”到“.content”。

问题是数组长度不计入新的“.post”,因此它会保持循环前5个。

如果你能帮忙解决这个问题,请提前感谢。

使用Javascript:

        $(document).ready(function(){

        // I N F I N I T E  S C R O L L
        $('.content').infinitescroll({
          navSelector  : ".navigation",
          nextSelector : ".navigation .next_page",
          itemSelector : ".content .post",
          behavior: "twitter"
        });

        $(window).unbind('.infscr');

        $('.next_page').click(function(){
          $(document).trigger('retrieve.infscr');
          return false;
        });

        $(document).ajaxError(function(e,xhr,opt){
          if (xhr.status == 404) $('.next_page').remove();
        });


        // I M A G E  S L I D E R
        var obj = $(".post");
        var arr = $.makeArray(obj);
        var lastDiv = $(".post");
        var indexNum = arr.length-1;

        $(window).keydown(function (e) {
            if (e.keyCode == 37) { // L E F T
                lastDiv.fadeOut(800);
                indexNum--;
                if (indexNum == -1) indexNum = arr.length-1; //if goes beyond first post, goto the last post
                $(arr[indexNum]).appendTo(".postslide").fadeIn(800);

                // C E N T E R
                var width = $(arr[indexNum]).width();
                var marginLeft = width / 2;
                $(arr[indexNum]).css('margin-left', -marginLeft);
            }

            if (e.keyCode == 39) { // R I G H T
                $('#instruction').fadeOut();
                lastDiv.fadeOut(800);
                indexNum++;
                if (indexNum == arr.length) indexNum = 0; //if goes beyond last post, goto the first post
                $(arr[indexNum]).appendTo(".postslide").fadeIn(800);

                // C E N T E R
                var width = $(arr[indexNum]).width();
                var marginLeft = width / 2;
                $(arr[indexNum]).css('margin-left', -marginLeft);
            }
        });

    });

更新

        $(document).ready(function(){


        // I N F I N I T E  S C R O L L
        $('.content').infinitescroll({
          navSelector  : ".navigation",
                         // selector for the paged navigation (it will be hidden)
          nextSelector : ".navigation .next_page",
                         // selector for the NEXT link (to page 2)
          itemSelector : ".content .post",
                         // selector for all items you'll retrieve
          behavior: "twitter"
        });

        // kill scroll binding
        $(window).unbind('.infscr');

        // manual click 
        $('.next_page').click(function(){
          $(document).trigger('retrieve.infscr');
          return false;
        });

        // remove the paginator done
        $(document).ajaxError(function(e,xhr,opt){
          if (xhr.status == 404) $('.next_page').remove();
        });




        // I M A G E  S L I D E R
        var obj = $(".post");
        var indexNum = obj.length-1;
        var lastDiv = $(".post");



        $(window).keydown(function (e) {

            if (e.keyCode == 37) { // L E F T

                lastDiv.fadeOut(800);
                indexNum--;
                if (indexNum == -1) indexNum = obj.length-1; //if goes beyond first post, goto the last post
                $(obj[indexNum]).appendTo(".postslide").fadeIn(800);

                // C E N T E R
                var width = $(obj[indexNum]).width();
                var marginLeft = width / 2;
                $(obj[indexNum]).css('margin-left', -marginLeft);
            }

            if (e.keyCode == 39) { // R I G H T

                $('#instruction').fadeOut();
                lastDiv.fadeOut(800);
                indexNum++;
                if (indexNum == obj.length) indexNum = 0; //if goes beyond last post, goto the first post
                $(obj[indexNum]).appendTo(".postslide").fadeIn(800);

                // C E N T E R
                var width = $(obj[indexNum]).width();
                var marginLeft = width / 2;
                $(obj[indexNum]).css('margin-left', -marginLeft);
            }
        });

    });

2 个答案:

答案 0 :(得分:3)

jQuery选择器在调用jQuery函数时查询DOM,因此它们在给定时刻选择与选择器匹配的元素。

即使应该与您的选择器匹配的新元素稍后添加到DOM中,它们也不会被选中,因为没有通知jQuery重新评估选择器,即使有什么事情,jQuery也没有内部状态保存所有创建的jQuery对象。这意味着选择器为not live

这里的主要问题是你永远不会更新所选DOM元素的数组,所以即使将新元素添加到DOM,你仍然会遍历原始数组。

更新jQuery对象很简单,您只需在代码中随时调用obj = $(".post")obj变量就会更新。我们只需要知道何时调用它。

由于您使用Infinite Scroll加载新元素,我们需要查看它documentation,或者由于文档中当前有大洞,因此最好查看{{3 }}

查看infinitescroll函数:

$.fn.infinitescroll = function infscr_init(options, callback) {
    ...

第二个参数称为callback,在检查源代码以及传递和调用此参数的方式后,您可以看到在检索到新元素后将调用它。我们试试这个参数:

$('.content').infinitescroll({
    navSelector : ".navigation",
    // selector for the paged navigation (it will be hidden)
    nextSelector : ".navigation .next_page",
    // selector for the NEXT link (to page 2)
    itemSelector : ".content .post",
    // selector for all items you'll retrieve
    behavior: "twitter"
}, function () {
    obj = $(".post");
    console.log("Current length is: " + obj.length); //this line is not necessary, just here for debug purposes.
});

假设变量obj已经存在,这将更新它的值。

请注意,在此答案的先前版本中,我调用了此回调函数recountPosts()。后来我决定它只是一个内联匿名函数,因为它只能从一个地方调用。

你差不多完成了,但是...你有其他变量取决于这个选择器。即arrlastDiv。检查您的源代码后,似乎没有必要:

  1. arr是一个由jQuery对象选择的元素组成的数组,虽然source code,它有一个基于零的数字索引器和一个长度属性就像一个数组,因此您可以在代码中的任意位置替换arr obj

  2. lastDiv有一个误导性的名字。它与obj具有相同的元素,而不仅仅是最后一个元素。因此,它也可以用obj替代。

  3. 因此,声明变量的部分可以缩小为:

    // I M A G E  S L I D E R
    var obj = $(".post");
    var indexNum = obj.length-1;
    

    我还查看了你的keydown事件处理程序。其中有很多重复的代码。这很容易在以后引入错误(事实上你已经有了一个错误:如果你在开始时按向左而不是向右,键盘的初始图片不会消失)。

    让我稍微为你重组一下:

    $(window).keydown(function (e) {
        if (e.keyCode === 37) { // L E F T
            indexNum--;
        }
    
        if (e.keyCode === 39) { // R I G H T
            indexNum++;
        }
    
        if (e.keyCode === 37 || e.keyCode === 39) {
            $('#instruction').fadeOut();
    
            obj.fadeOut(800);
    
            if (indexNum === -1) {
                indexNum = obj.length-1; //if goes beyond first post, goto the last post
            }
            if (indexNum === obj.length) {
                indexNum = 0; //if goes beyond last post, goto the first post
            }
    
            $(obj[indexNum]).appendTo(".postslide").fadeIn(800);
    
            var width = $(arr[indexNum]).width();
            var marginLeft = width / 2;
            $(obj[indexNum]).css('margin-left', -marginLeft);
        }
    });
    

    它完成了!


    不,当然没有完成。它还远没有完成,还有许多很多需要改进的东西。

    • 就像删除每个按键上的margin-left的丑陋重新计算一样,用几行css解决它。作为一个拇指规则:如果某些东西可以用css而不是javascript来解决它应该是。

    • 或者在infinitescroll(...)而不是$(".postslide")上调用$(".content")并从.appendTo(".postslide")之前删除完全不必要的fadeIn(),因为元素已经附加,重新使用它们是浪费资源。

    • 或移动常数,例如800 ms的淡入淡出长度到代码的开头,给它们一个像var fadeLength = 800;这样的变量并使用它。

    而且我很确定还有很多其他事情可以做得更好,但这就是编程方式:)

    jQuery object is not an array

    编辑:

    因此,如果您位于幻灯片的末尾,您还希望仅显示更多按钮。你写了这个:

    if (indexNum === 14){
      $('.next_page').html('<img src="http://long_url/">');
    }
    

    为什么要将14硬编码到源代码中?为什么你甚至关心加载了多少张图片以及加载多少张图片?代码的给定部分只需知道您是否在最后。如果您有一个关于加载幻灯片数量的变量,您可以轻松检查您是否在最后一个索引。您拥有该变量obj.length

    if (indexNum === obj.length-1){
      $('.next_page').html('<img src="http://long_url/">');
    }
    

    这样,如果是第30个,第45个或第900个,那么最后一张幻灯片上会出现更多按钮而不关心。

    加载新内容后,您还需要此按钮消失。这进入了infinitescroll的回调:

    function () {
        obj = $(".post");
        console.log("Current length is: " + obj.length); //this line is not necessary, just here for debug purposes.
        $('.next_page').html('');
    }
    

    您可以做的另一件事是,不是显示更多按钮,而是可以从代码中触发更多事件。这样,当用户到达最后一张幻灯片时,新幻灯片会自动加载。

    此外,只有在实际需要加载幻灯片时才需要这样做。您可以检查当前状态的isDone属性,该属性告诉您“无限滚动是否完成”,因此不再需要加载元素。

    $('.content').data('infinitescroll').options.state.isDone === false
    

    因此,不是显示更多按钮的部分,而是可以写下:

    if (indexNum === obj.length-1 && !$('.content').data('infinitescroll').options.state.isDone){
      $(document).trigger('retrieve.infscr');
    }
    

答案 1 :(得分:0)

<强>问题:

您在页面加载时设置值,而在滚动发生时或在其他键绑定时不更新

<强>解决方案:

    // I M A G E  S L I D E R
        var obj = $(".post");
        var arr = $.makeArray(obj);
        var lastDiv = $(".post:last");
        var indexNum = arr.length-1;


        $(window).keydown(function (e) {
                        obj = $(".post");
                        arr = $.makeArray(obj);
                        lastDiv = $(".post:last");
                        indexNum = arr.length-1;

                        //other code

        });