0

In my website I have a calendar, whenever a user hovers over a day of the calendar I want the background to change, but of course I don't want all that loading overhead to happen at page load, but rather only when the user hovers over one of the days.

I tried to do it by following what I found in this question, but it seems to only work the first time. This is what I did after modifying the plugins code as a test:

counter = 0;
  $('.calendar-day').hover(
    function() {
      if (counter == 0) {
        $('body').attr('data-background', template_url + '/images/bg_2.jpg'); 
        counter++;
      } else if (counter == 1) {
        $('body').attr('data-background', template_url + '/images/bg_3.jpg'); 
        counter++;
      } else if (counter == 2) {
        $('body').attr('data-background', template_url + '/images/bg_4.jpg'); 
        counter++;
      } else if (counter == 3) {
        $('body').attr('data-background', template_url + '/images/bg_1.jpg'); 
        counter = 0;
      }  
      $('body').lazyload();
    },
    function() {

    }  
  );

Even though it does trigger all the cases, the lazy loading doesn't happen and the background doesn't change after the first time. Any thoughts on this? Other approaches to managing this are welcome as well.

Community
  • 1
  • 1
8vius
  • 5,566
  • 12
  • 67
  • 133
  • 1
    You don't need lazyload here. If the `background-image` property doesn't appear in your css file then it won't load it until you add it into your html style. If you are adding the background using javascript then it will always be loaded only when needed. Lazyload is meant for images who are loaded initially with the page or added under the fold. + I don't get the logic behind your `counter`, you want it to change on each hover? Just go in a circle no matter what the day is? – iMoses Nov 09 '12 at 12:47
  • The counter was just a test, see how it worked. That's it. I use the lazy load because I don't want to see the image loading but rather just show it when it's fully loaded. It's a matter of aesthetic. – 8vius Nov 09 '12 at 12:52
  • Two questions: 1) How big is the image? 2) What do you want to happen? – iMoses Nov 09 '12 at 12:54
  • If the image is small enough this should be a problem, otherwise I can give you a nice solution for it. – iMoses Nov 09 '12 at 12:55
  • It's the background for the website, it's big 1580x960. And as I said, I have calendar, whenever you hover over a day I want the bg to change to an image related to that day. – 8vius Nov 09 '12 at 12:57

1 Answers1

1

This might do the trick for you. Give it a try:

var counter = -1,
    loadImage = function(onCase) {
        return function(e) {
            if (counter % 4 === onCase) {
                $('body').css('background-image', 'url(' + this.src + ')');
            }
        };
    };

$('body').on('mouseenter', '.calendar-day', function() {
    counter++;
    switch (counter % 4) {
        case 0:
            $('<img>').on('load', loadImage(0))
                .attr('src', template_url + '/images/bg_2.jpg');
            break;
        case 1:
            $('<img>').on('load', loadImage(1))
                .attr('src', template_url + '/images/bg_3.jpg');
            break;
        case 2:
            $('<img>').on('load', loadImage(2))
                .attr('src', template_url + '/images/bg_4.jpg');
            break;
        case 3:
            $('<img>').on('load', loadImage(3))
                .attr('src', template_url + '/images/bg_1.jpg');
            break;
    }
});

onCase is meant to verify we still wanna add "this" background and haven't moved yet to another, in case of a race condition.

EDIT: a cleaner version

var counter = -1,
    loadImage = function(index, backgroundImages) {
        $('<img>').on('load', function(e) {
            if (counter % backgroundImages.length === index) {
                $('body').css('background-image', 'url(' + this.src + ')');
            }
        }).attr('src', backgroundImages[index]);
    },
    backgroundImages = [
        template_url + '/images/bg_2.jpg',
        template_url + '/images/bg_3.jpg',
        template_url + '/images/bg_4.jpg',
        template_url + '/images/bg_1.jpg'
    ];

$('body').on('mouseenter', '.calendar-day', function() {
    counter++;
    loadImage(counter % backgroundImages.length, backgroundImages);
});

When the mouseenter (the first state of an hover, the second being mouseleave) event is triggered by a .calendar-day element, we increase counter and call for loadImage. Using counter % backgroundImages.length will return our current index, a number between 0 - backgroundImages.length (not including the value of backgroundImages.length itself). If you don't know the modulo sign (%) you could read about it here.

loadImage creates an img element which is not attached to the dom, adds an event listener to catch when the image has been loaded, then sets the img element src to our current image. Once the image is loaded we check whether or not we still wanna put that image as background (or have we moved to another image already), if so then we set the body background image, confident it was already loaded. Once the image as been loaded once it should be in our browsers catch, so the next time we attach an event listener to see when an image is loaded, it should fire immediately.

Hope I didn't miss anything, if so please let me know.

iMoses
  • 4,159
  • 1
  • 21
  • 38
  • I think I need some explaining since I don't understand what this code does, and placing it in my site does nothing it seems. – 8vius Nov 09 '12 at 13:32
  • It's not working, no errors or anything, don't know if I'm missing something. – 8vius Nov 09 '12 at 13:58
  • Mind taking this to chat?http://chat.stackoverflow.com/rooms/19344/change-background – 8vius Nov 09 '12 at 14:00