【问题标题】:jQuery Gallery, click event not firing after page changejQuery Gallery,页面更改后单击事件未触发
【发布时间】:2015-01-07 11:24:20
【问题描述】:

我正在开发一个 jQuery Gallery,我最近向它添加了一个分页,发现虽然我的 on('click') 事件在最初调用显示函数时工作正常,但一旦您更改页面(重新加载显示函数以显示数组数据使用新的开始和结束变量)我的on('click') 事件停止工作。切换回原来的页面并不能让它再次工作。

我尝试将.on("click") 换成.click(),还删除了.empty() 命令,以便页面继续向列表中添加新项目,以及一些其他更改,但我仍然无法弄清楚什么问题是。

小提琴:http://jsfiddle.net/fw37y69h/

HTML

<div id="jGalContainer">
    <ul id="jGalImageList"></ul>

    <div id="jGalOverlay"></div>
    <div id="jGalDisplayOverlay"></div>
</div>

<button id="next">Next</button>
<button id="previous">Previous</button>

JS

$(document).ready(function(){

// Function that generates the display
var displayGal = function(start,stop) {
    // For each item between the passed start and stop variables, increment through the imgListArr array
    // And create the HTML dynamically within the jGalImageList div.
    for(var i = start; i < stop; i++) {
        $('#jGalImageList').append('<li id="image' + i + '"><div class="imgCont"><img id="' + imgListArr[i].id + '" src="' + imgListArr[i].thumbUrl + '" /></div><br /><span class="imageTitle">' + imgListArr[i].name + '</span>');
        console.log(imgListArr[i]);
   }
}

// Array of object items
var imgListArr = [
    {
        id: "image1",
        name: "Cute Puppy",
        url: "img/puppies.jpg",
        thumbUrl: "img/puppies-sm.jpg",
        description: "A lovely picture of a puppy."
    },
    {
        id: "image2",
        name: "Hungry Kitty",
        url: "img/kittens.jpg",
        thumbUrl: "img/kittens-sm.jpg",
        description: "Cats are okay I guess."
    },
    {
        id: "image3",
        name: "Mr Turtle",
        url: "img/turtles.jpg",
        thumbUrl: "img/turtles-sm.jpg",
        description: "All hail our new turtle overlords."
    },
    {
        id: "image4",
        name: "Magestic Deer",
        url: "img/deer.jpg",
        thumbUrl: "img/deer-sm.jpg",
        description: "Cats are okay I guess."
    },
    {
        id: "image5",
        name: "Duck Army",
        url: "img/ducks.jpg",
        thumbUrl: "img/ducks-sm.jpg",
        description: "All hail our new turtle overlords."
    },
    {
        id: "image6",
        name: "Sleepy Pelicans",
        url: "img/pelicans.jpg",
        thumbUrl: "img/pelicans-sm.jpg",
        description: "Cats are okay I guess."
    },
    {
        id: "image7",
        name: "Monkey Family",
        url: "img/monkeys.jpg",
        thumbUrl: "img/monkeys-sm.jpg",
        description: "All hail our new turtle overlords."
    },
    {
        id: "image8",
        name: "Sheeple",
        url: "img/sheep.jpg",
        thumbUrl: "img/sheep-sm.jpg",
        description: "Cats are okay I guess."
    },
    {
        id: "image9",
        name: "Monkey Family",
        url: "img/monkeys.jpg",
        thumbUrl: "img/monkeys-sm.jpg",
        description: "All hail our new turtle overlords."
    },
    {
        id: "image10",
        name: "Sheeple",
        url: "img/sheep.jpg",
        thumbUrl: "img/sheep-sm.jpg",
        description: "Cats are okay I guess."
    }
];

// Set number of items per page
var pageLength = 4;

// Calculate number of pages
var numPages = Math.ceil(imgListArr.length / pageLength);

// Check if the last page will be filled, and determine how many items will be
// displayed on the last page.
// If there is a remained when the array length is divided by number of items per page
// then grab how many items are to be left over and safe as lastPageItems.
// Else set the lastPageItems variable to be however many items are on a page because
// it should fit perfectly.
if(imgListArr.length % pageLength !=0) {
    lastPageItems = imgListArr.length % pageLength;
}
else {
    lastPageItems = pageLength;
}

// Check if there are multiple pages to set what is to be displayed, and set visibility
// of Next and Previous Buttons.
// If there is only one page, the start and stop variebles for the displayGal function
// are set to 0 and whatever the array length is because it will be 4 or less. If this
// the case then we hide the previous and next buttons because they are not needed.
// Otherwise we set the page variable to 0 to indicate we are starting on page 0 and
// then hide only the previous button, as we need the next button to progress through
// pages.
if(numPages === 1) {
    displayGal(0,imgListArr.length);
    $('#next').hide();
    $('#previous').hide();
}
else {
    var page = 0;
    displayGal(0,pageLength);
    $('#previous').hide();
}

// Event handler for clicking on an image to open up the image modal and the overlay
// When an image is clicked on then the we create a details variable to hold the
// array created by the populateModal variable. The function is passed the image ID
// for reference.
// The jGalOverlay (gray overlay) is set to be visible.
// HTML is added to the jGalDisplayOverlay (modal), which is an image and print out
// of the details, this will fade in over the top of the modal in 800ms.
// We grab the height of the window (viewport) and assign the jGalOverlay (gray
// overlay) to take up the whole length.
$('#jGalImageList>li>.imgCont>img').on('click',function(e){
    console.log("click");
    var details = populateModal(this.id);

    $('#jGalOverlay').show();

    $('#jGalDisplayOverlay').html('<img src="' + details[1] + '" id="' + this.id + 'id" alt="' + this.id + '" /><br /><p>' + details[3] + '</p>').fadeIn(800);

    var windowHeight = $(document).height() + "px";
    $('#jGalOverlay').css('height',windowHeight);
});

// Event handler for closing the image modal, if the background overlay is clickied on
// then hide the image modal and the overlay.
// We also use this opportunity to empty the jGalDisplayOverlay (modal) for next image
// click, not sure if this is neccessary for html() method, I was using apprend.
$('#jGalOverlay').on('click',function(e){
    $('#jGalDisplayOverlay').empty().hide();
    $('#jGalOverlay').hide();
});

// Event handler for when the next button is clicked to refresh what is being displayed
// When the next button is clicked, we increment the page variable.
// We test if the page is now 1, if it is we show the previous button, as page 1 can't
// be skipped, this means the show request is only called once rather than on each
// subsequent page load.
// We empty the jGalImageList div, this isn't neccessary if you want to grow a list of
// images but to achieve pages, we empty and then refresh the page.
// By grabbing the page number and multiplying it by page length we find what image
// we are up to viewing as a start point, then we test if we are on the last page, to
// determine if we need to use the lastPageItems variable yet, if we are on the last
// page then our new end variable is set to the number of items on the last page plus
// our new starting variable, and we hide the next button. Otherwise we just add the
// page length variable to the new starting variable to get our end point.
// We then call our display function to populate the jGalImageList.
$('#next').on('click',function(e) {
    page = page + 1;

    if(page == 1) {
        $('#previous').show();
    }

    $('#jGalImageList').empty();
    var newStart = page * pageLength;

    if(page == numPages - 1) {
        var newEnd = newStart + lastPageItems;
        $('#next').hide();
    }
    else {
        var newEnd = newStart + pageLength;
    }

    displayGal(newStart,newEnd);
});

// Event handler for when the previous button is clicked to refresh what is being
// displayed.
// First step is to decrement the page number we are on.
// We check if we are on the first page, if we are we rehide the previous button as
// we can't go back any further.
// We empty the jGalImageList so we can throw in our new image list.
// Our start point is calculated by multiplying page number by page length.
// We check if we are on a page other than the last one, if so we show the next
// button, this is so it is only called once, rather than every page decrement.
// A new end point is calculated by adding page length to our new start point, we
// don't need to worry about lastPageItems because you can't move backwards to the
// last page.
// We finish by calling our display function
$('#previous').on('click',function(e){
    page = page - 1;

    if(page == 0) {
        $('#previous').hide();
    }

    $('#jGalImageList').empty();
    var newStart = page * pageLength;

    if(page == numPages - 2) {
        $('#next').show();
    }

    var newEnd = newStart + pageLength;

    displayGal(newStart,newEnd);
});

// Function to populate the image modal that is displayed.
// We initialise a variable to determine if the image ID is found to false, and
// initialise an emtpy details array.
// We loop through the array, comparing IDs till we find a match.
// If we find a match, we set found to true, populate a details array with all the info
// from the imgListArray, and return details array.
// If no match is found, we return "Error", this will likely break the page, but should
// never actually be able to occur.
var populateModal = function(id) {
    var found = false;
    var details = [];
    for(var i=0; i < imgListArr.length; i++) {
        if(imgListArr[i].id === id) {
            var found = true;
            details = [imgListArr[i].name, imgListArr[i].url, imgListArr[i].thumbUrl,imgListArr[i].description]
            return details;
        }
    }
    if(found === false) {
        return "Error";
    }
}


});

CSS

#jGalContainer {
    width: 800px;
    border: 1px solid #ddd;
    background: #FAFAFA;
    margin: 0 auto;
}

#jGalImageList{
    width: 100%;
    list-style-type: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
}

#jGalImageList li {
    width: calc(49% - 20px);
    display: inline-block;
    *display: inline;
    zoom: 1;
    text-align: center;
    padding: 10px;
}

#jGalImageList li .imgCont {
    width: 100%;
    height: 180px;
    overflow: hidden;
}

#jGalImageList li img {
    width: 100%;
    overflow: hidden;
    margin-bottom: 5px;
    box-shadow: 1px 1px 1px #DEDEDE;
    -webkit-box-shadow: 1px 1px 1px #DEDEDE;
}

#jGalImageList li span.imageTitle {
    font-family: 'Source Sans Pro', sans-serif;
    font-size: 14px;

}

#jGalDisplayOverlay {
    width: 800px;
    height: auto;
    border: 1px solid #777;
    background-color: #FAFAFA;
    display: none;
    position: fixed;
    top: 40px;
    left: calc(50% - 400px);
    z-index: 100;
}

#jGalDisplayOverlay img {
    width: 100%;
    border-bottom: 1px solid #777;
}

#jGalDisplayOverlay p {
    font-family: 'Source Sans Pro', sans-serif;
    font-size: 14px;
    padding: 10px;
}

#jGalOverlay {
    width: 100%;
    height: 100%;
    background: #333;
    opacity: 0.5;
    filter: (Opacity: 50);
    position: absolute;
    top: 0;
    left: 0;
    display: none;
    z-index: 1;
}

【问题讨论】:

    标签: javascript jquery css pagination click


    【解决方案1】:

    你目前做的是直接将事件点击绑定到'#jGalImageList&gt;li&gt;.imgCont&gt;img'

    $('#jGalImageList>li>.imgCont>img').on('click',function(e){
        console.log("click");
        var details = populateModal(this.id);
    
        $('#jGalOverlay').show();
    
        $('#jGalDisplayOverlay').html('<img src="' + details[1] + '" id="' + this.id + 'id" alt="' + this.id + '" /><br /><p>' + details[3] + '</p>').fadeIn(800);
    
        var windowHeight = $(document).height() + "px";
        $('#jGalOverlay').css('height',windowHeight);
    });
    

    上面的事件处理程序只会附加到所有#jGalImageList&gt;li&gt;.imgCont&gt;img 元素在上面的代码被调用时。由于您在单击 Next 或 Previous 按钮时清空 #jGalImageList 并重新填充其内容,因此在单击 Next 或 Previous 按钮后,上面的事件处理程序将不起作用。

    您还需要使用事件委托将点击事件绑定到新创建的#jGalImageList&gt;li&gt;.imgCont&gt;img 元素。以下是来自jQuery documentation 的简介

    事件委托允许我们将单个事件侦听器附加到父元素,该事件侦听器将为匹配选择器的所有后代触发,无论这些后代现在存在还是将来添加。

    下面是修改后的代码

    $('#jGalImageList').on('click','li>.imgCont>img',function(e){
        console.log("click");
        var details = populateModal(this.id);
    
        $('#jGalOverlay').show();
    
        $('#jGalDisplayOverlay').html('<img src="' + details[1] + '" id="' + this.id + 'id" alt="' + this.id + '" /><br /><p>' + details[3] + '</p>').fadeIn(800);
    
        var windowHeight = $(document).height() + "px";
        $('#jGalOverlay').css('height',windowHeight);
    });
    

    这是更新后的小提琴:http://jsfiddle.net/fw37y69h/21/

    【讨论】:

    • 太好了,非常感谢您的帮助!快速提问,是否有原因导致重新填充 #jGalImageList 后它不再开始工作?
    • 那是因为.on('click', function (e) { ... }) 只对现有元素起作用。将点击事件也绑定到新创建的元素的正确方法是.on('click','selector', function (e) { ... })。查看更新后的答案,希望您能理解其中的区别。
    • 谢谢你的补充解释,我现在明白了!
    猜你喜欢
    • 2011-12-01
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    相关资源
    最近更新 更多