简体   繁体   中英

jQuery variable globally defined but logging as undefined

I am making a product image viewer similar to what is on sites like Amazon (you hover over an image, it appears larger -- click the image thumbnail and it sets the main image as what was clicked).

Background info aside, I set two global variables outside the functions that control the main image. Something strange is happening where the variables are only defined up to a certain point in the code execution, then they become "undefined".

Here is my markup:

<div id="product-image-gallery">
   <div id="product-image-holder" style="background-image: url('http://example.com/images/main-image.jpg');">My Main Image
   </div>

   <ul>
     <li class="product-thumb">
       <img src="http://example.com/images/image-1.jpg"/>
     </li>
     <li class="product-thumb">
       <img src="http://example.com/images/image-2.jpg"/>
     </li>
   </ul>
</div>

In jQuery, I am storing the original image and image background path in two global variables, then defining the functions that alter the main image container to show the proper image. Here is my jQuery:

var $originalImage = $('#product-image-holder');
var $originalImageSrc = $originalImage.css('background-image');

$('#product-image-gallery ul li.product-thumb').click(function () {
    $('li.product-thumb.active').removeClass('active');
    $(this).addClass('active');
});

$('#product-image-gallery ul li.product-thumb').hover(
//mouseenter event
    function () {
        var $imageChange = $(this).find('img');
        var $imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';
        $originalImage.css("background-image", $imageChangeSrc);
},
//mouseleave event
function () {
    var $activeImage = $('#product-image-gallery ul li.product-thumb.active img');
    var $activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

    if($(this).hasClass('active')){
        return;
    }
    else if ($activeImage != '') {
        $originalImage.css("background-image", $activeImageSrc);
    }
    else {
        $originalImage.css("background-image", $originalImageSrc);
    }
});

When I view the page, all works as expected on mouse hover, except the original image path resets itself to undefined (I can witness this behavior in the console). I am completely stumped as to what could cause this to happen.

Any suggestion as to what would make this variable unset itself is greatly appreciated.

[EDIT] Here is a jsfiddle with my example, showing the exact same behavior: https://jsfiddle.net/htxxnfuy/

You check if .active image found incorrectly. Result is a collection of elements with 0 length if nothing matches selector.

if ($activeImage.length) { // <-- this line
    $originalImage.css("background-image", $activeImageSrc);
}

 var $originalImage = $('#product-image-holder'); var $originalImageSrc = $originalImage.css('background-image'); $('#product-image-gallery ul li.product-thumb').click(function () { $('li.product-thumb.active').removeClass('active'); $(this).addClass('active'); }); $('.product-thumb').hover( //mouseenter event function () { var $imageChange = $(this).find('img'); var $imageChangeSrc = 'url(\\'' + $imageChange.attr('src') + '\\')'; $originalImage.css("background-image", $imageChangeSrc); }, //mouseleave event function () { var $activeImage = $('li.active img'); var $activeImageSrc = 'url(\\'' + $activeImage.attr('src') + '\\')'; if($(this).hasClass('active')){ return; } else if ($activeImage.length) { // <-- this line $originalImage.css("background-image", $activeImageSrc); } else { $originalImage.css("background-image", $originalImageSrc); } }); 
 #product-image-holder { height: 50px; width: 50px; } 
 <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <div id="product-image-gallery"> <div id="product-image-holder" style="background-image: url('http://placehold.it/50x50');"> My Main Image </div> <ul> <li class="product-thumb"> <img src="http://placehold.it/52x52"/> </li> <li class="product-thumb"> <img src="http://placehold.it/51x51g"/> </li> </ul> </div> 

You are checking a possible collection of elements against an empty string. When trying to find out if a jQuery selector returns any item (or many), you can test it's length property.

I've also reduced your code a bit:

$(function () {
    // To make your code a bit easier to understand, use $ to prefix
    // only variables that represent a jQuery selector.
    var $originalImage = $('#product-image-holder');
    var originalImageSrc = $originalImage.css('background-image');
    var containerSelector = '#product-image-gallery ul li.product-thumb';
    var $container = $(containerSelector);

    // You can attach as many event handlers as you need in just
    // one go. Also, it's better to use mouseenter and mouseleave
    // instead of hover.
    $container.on({ click: function () {
            $('li.product-thumb.active').removeClass('active');

            $(this).addClass('active');
    }, mouseenter: function () {
        var $imageChange = $(this).find('img');
        var imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';

        $originalImage.css('background-image', imageChangeSrc);
    }, mouseleave: function () {
        var $activeImage = $(containerSelector + '.active img');
        var activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

        // I would review the necessity of this entire check.
        if ($(this).hasClass('active')) {            
        } else if ($activeImage.length > 0) { 
            // If there's at least one element coming
            // from the selector above.           
            $originalImage.css('background-image', activeImageSrc);
        } else {           
            $originalImage.css('background-image', originalImageSrc); 
        }
    }});
});

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM