Search code examples
jqueryimageonclicktoggleclass

onclick replaces all images with lower number in src (jQuery)


I have a thermometer built out of 10 images. I would like to change each section (image) of the thermometer onclick, e.g. if you click on the 3rd image (which equals 30 degrees), the images below it (thermo2 and thermo1) also change. This works with the following (admittedly cumbersome) code:

<img src="thermo01_off.png" id="thermo1" class="img-swap" alt="10°" width="157" height="33" />
<img src="thermo01_off.png" id="thermo2" class="img-swap" alt="20°" width="157" height="33" />
<img src="thermo03_off.png" id="thermo3" class="img-swap" alt="30°" width="157" height="33" />
... and so on

$(function(){
    $(".img-swap").on('click', function() {
       if ($(this).attr("id") == "thermo1") {
           thermo1.src = thermo1.src.replace("_off","_on");
       } else if ($(this).attr("id") == "thermo2") {
           thermo1.src = thermo1.src.replace("_off","_on");
           thermo2.src = thermo2.src.replace("_off","_on");
       } else if ($(this).attr("id") == "thermo3") {
           thermo1.src = thermo1.src.replace("_off","_on");
           thermo2.src = thermo2.src.replace("_off","_on");
           thermo3.src = thermo3.src.replace("_off","_on");
       }
 });

Problem 1 Currently the images don't toggle back off. I know you can use "toggleClass", but I am not sure how to implement in the above code.

Problem 2 If I implement the above code for all 10 thermometer images, it will get pretty long. There must be a much more efficient way of writing the above. Any suggestions.

Solution This code worked in the end, thanks also to Gregg.

$(function() {
  $("[id^=thermo]").click(function() {
    var notid, thisid, new_url, not_url = "";
    var $this = $(this);

    //Get the ID without the "thermo" part
    thisid = $this.attr('id').replace('thermo', '');

    //swap image that was clicked
    new_url = $this.attr('src').replace("_off", "_on");
    $(".img-swap" + thisid).attr("src", new_url);

    //replaces all images that were NOT clicked
    $("[id^=thermo]").not(this).attr('id', function(i, idx) {

        //get ids of those not clicked
        notid = idx.replace('thermo', '');

        //change src of images with lower ids than the clicked one
        if (notid < thisid) {
            not_url = $(".img-swap" + notid).attr('src').replace("_off", "_on");
            console.log(notid);
            $(".img-swap" + notid).attr("src", not_url);
        } else {
            not_url = $(".img-swap" + notid).attr('src').replace("_on", "_off");
            $(".img-swap" + notid).attr("src", not_url);
        }
    });
});

});


Solution

  • Something like this should work:

    $(function(){
    // add click event listener to all imgs with id starting with 'thermo'
    $('img[id^="thermo"]').click(function(){
        // get the index of the clicked element in the array of all matching elements
        var idx = $(this).index();
        // edit the src of the elements with an index less than the clicked element
        $.each($('img[id^="thermo"]'), function(i, img){
            if($(img).index() <= idx){
                $(img).attr('src', $(img).attr('id') + '_on');
            }else{
                $(img).attr('src', $(img).attr('id') + '_off');
            }
        });
    });
    

    });

    EDIT: As long as the id of the image is the same as the name of the image files like your sample html shows. this will work. I Changed it to a loop and using the IDs to set the image src.