Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Isotope & javascript - elements aren't clickable anymore after adding a new one

I'm trying to make a table of images loaded from a json (not a real json, more like a javascript array) and every time the json changes (when I append a new image to the json file with some script, I want that my table of images to upload as well.

This is the json format:

[{
    "image": "images/set_1_UTC+03.jpg",
    "weight": 101
}, {
    "image": "images/set_1_UTC+03.jpg",
    "weight": 102
}, {
    "image": "images/set_1_UTC+03.jpg",
    "weight": 103
}, {
    "image": "images/set_1_UTC+03.jpg",
    "weight": 104
}]

For this I use isotope. I managed to achieve everything I mentioned above, the only problem is that I wanted to make the images clickable and whenever I click one of the image, to have it in a bigger size and when I click it again to get back to the small size. Here is the code:

<script>
    var previous = 0;
    var current = 0;
    loadJSON(function(response) {
        // Parse JSON string into object
        current = JSON.parse(response);
    });

    function loadJSON(callback) {
        var xobj = new XMLHttpRequest();
        xobj.overrideMimeType("application/json");
        xobj.open('GET', 'data.json', true); // Replace 'my_data' with the path to your file
        xobj.onreadystatechange = function() {
            if (xobj.readyState == 4 && xobj.status == "200") {
                // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
                callback(xobj.responseText);
            }
        };
        xobj.send(null);
    }

    let lengthOfprevious = previous.length;

    setInterval(function() {
        loadJSON(function(response) {
            // Parse JSON string into object
            current = JSON.parse(response);
        });
        previous = current;
        if (lengthOfprevious != current.length) {
            UpdateBody(lengthOfprevious);
        }
        lengthOfprevious = previous.length;
    }, 5000);

    function UpdateBody(startIndex) {
        var newElements = "";
        for (let i = startIndex; i < previous.length; i++) {
            $(document).ready(function() {
                newElements = "";
                newElements +=
                    '<div class="photo element-item">' +
                    '<a href="' + previous[i].image + '"><img class="small-image" src="' + previous[i].image + '"/></a>' +
                    '<a class="weight">' + previous[i].weight + '</a></div>';
                var $newElems = $(newElements);

                $('#container').append($newElems).imagesLoaded(function() {

                    $('#container').isotope('insert', $newElems);
                });
            });
        }

        // ============//
        $(function() {
            var $container = $('#container'),
                $photos = $container.find('.photo'),
                $loadingIndicator = $('<div class="loading"><span><img src="http://i.imgur.com/IE7iw.gif" /></span></div>');
            // trigger Isotope after images have loaded
            $container.imagesLoaded(function() {
                $container.isotope({
                    itemSelector: '.photo',
                    masonry: {
                        columnWidth: 200
                    }
                });
            });
            // shows the large version of the image
            // shows small version of previously large image
            function enlargeImage($photo) {
                $photos.filter('.large').removeClass('large');
                $photo.addClass('large');
                $container.isotope('reLayout');
            }

            $photos.find('a').click(function() {
                var $this = $(this),
                    $photo = $this.parents('.photo');

                if ($photo.hasClass('large')) {
                    // already large, just remove
                    $photo.removeClass('large');
                    $container.isotope('reLayout');
                } else {
                    if ($photo.hasClass('has-big-image')) {
                        enlargeImage($photo);
                    } else {
                        // add a loading indicator
                        $this.append($loadingIndicator);

                        // create big image
                        var $bigImage = $('<img>', {
                            src: this.href
                        });

                        // give it a wrapper and appended it to element
                        $('<div>', {
                                'class': 'big-image'
                            })
                            .append($bigImage)
                            .appendTo($this)
                            .imagesLoaded(function() {
                                $loadingIndicator.remove()
                                enlargeImage($photo);
                            });
                        // add a class, so we'll know not to do this next time
                        $photo.addClass('has-big-image');
                    }
                }
                return false;
            });
        });
    }
</script>

The problem is that after setInterval runs once, everything works as expected, when it runs again, the images aren't clickable anymore. If I move the part after the // ============// tag in the for, only the last image is clickable.

I cannot figure out the solution for this (I'm a beginner with javascript). Can someone point me in the right direction?

Update : Here you can get an archive of the project so that one can run it locally.

You need to manually copy and pasteduplicate some lines from the data file in order for the demo to work because it searches for the difference of the previous state and the current state of the data file. The problem is that it is clickable at first, and then it's not anymore.

like image 685
AMayer Avatar asked May 20 '18 20:05

AMayer


People also ask

What is an isotope simple definition?

Atoms with the same number of protons but different numbers of neutrons are called isotopes. They share almost the same chemical properties, but differ in mass and therefore in physical properties.

What is an example of isotope?

The atoms belonging to the same element, having same atomic number Z, but different mass number A, are called isotopes. For example, carbon-12, carbon-13 and carbon-14 are three isotopes of the element carbon with mass numbers 12, 13 and 14 respectively.

Why is it called A isotope?

Three nuclei with one proton are known that contain 0, 1, and 2 neutrons, respectively. The three share the place in the periodic table assigned to atomic number 1 and hence are called isotopes (from the Greek isos, meaning “same,” and topos, signifying “place”) of hydrogen.

How do you identify isotopes?

Isotopes are identified by their mass, which is the total number of protons and neutrons. There are two ways that isotopes are generally written. They both use the mass of the atom where mass = (number of protons) + (number of neutrons).


1 Answers

I found a couple of things that need to be modified in your code:

  1. Why is $(document).ready used more than 1 time?
  2. No need to use $(function()
  3. Because I see the photo class is being generated dynamically on run time and container class is already in DOM, I have modified the click event

    $container.on('click', '.photo a', function() {
    

Edit Please note code is not tested; I have just code corrected it.

Final updated code is following:

var previous = 0;
var current = 0;
loadJSON(function(response) {
    // Parse JSON string into object
    current = JSON.parse(response);
});

function loadJSON(callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'data.json', true); // Replace 'my_data' with the path to your file
    xobj.onreadystatechange = function() {
        if (xobj.readyState == 4 && xobj.status == "200") {
            // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
            callback(xobj.responseText);
        }
    };
    xobj.send(null);
}
let lengthOfprevious = previous.length;

setInterval(function() {
    loadJSON(function(response) {
        // Parse JSON string into object
        current = JSON.parse(response);
    });
    previous = current;
    if (lengthOfprevious != current.length) {
        UpdateBody(lengthOfprevious);
    }
    lengthOfprevious = previous.length;
}, 5000);

function UpdateBody(startIndex) {
    var newElements = "",
        $container = $('#container'),
        $photos = $container.find('.photo'),
        $loadingIndicator = $('<div class="loading"><span><img src="http://i.imgur.com/IE7iw.gif" /></span></div>');

    $(document).ready(function() {
        for (let i = startIndex; i < previous.length; i++) {
            newElements = "";
            newElements +=
                '<div class="photo element-item">' +
                '<a href="' + previous[i].image + '"><img class="small-image" src="' + previous[i].image + '"/></a>' +
                '<a class="weight">' + previous[i].weight + '</a></div>';

            var $newElems = $(newElements);

            $container.append($newElems).imagesLoaded(function() {
                $container.isotope('insert', $newElems);
            });
        }
        $container.imagesLoaded(function() {
            $container.isotope({
                itemSelector: '.photo',
                masonry: {
                    columnWidth: 200
                }
            });
        });
        // shows the large version of the image
        // shows small version of previously large image
        function enlargeImage($photo) {
            $photos.filter('.large').removeClass('large');
            $photo.addClass('large');
            $container.isotope('reLayout');
        }

        $container.on('click', '.photo a', function() {
            var $this = $(this),
                $photo = $this.parents('.photo');

            if ($photo.hasClass('large')) {
                // already large, just remove
                $photo.removeClass('large');
                $container.isotope('reLayout');
            } else {
                if ($photo.hasClass('has-big-image')) {
                    enlargeImage($photo);
                } else {
                    // add a loading indicator
                    $this.append($loadingIndicator);

                    // create big image
                    var $bigImage = $('<img>', {
                        src: this.href
                    });

                    // give it a wrapper and appended it to element
                    $('<div>', {
                            'class': 'big-image'
                        })
                        .append($bigImage)
                        .appendTo($this)
                        .imagesLoaded(function() {
                            $loadingIndicator.remove()
                            enlargeImage($photo);
                        });

                    // add a class, so we'll know not to do this next time
                    $photo.addClass('has-big-image');

                }
            }

            return false;
        });

    });
}
like image 74
A. N. SINHA Avatar answered Sep 28 '22 21:09

A. N. SINHA