0

I'm pretty new to front-end javascript (in particular DOM manipulation and JQuery), I wanted to achieve an effect where if a user scroll the mouse wheel the image on the page changes, I then found that the best way to this is a wheel event (I got that from this question). I implemented it but nothing happens when I scroll, even alerts aren't working.

I would really appreciate any help, and even additional information if deemed necessary by the author of the answer. Thanks in advance.

Here's what I've done so far:

<!DOCTYPE html>
<html>
    <head>
        <title>NERD</title>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    </head>

    <body>

        <div id="Banner">
            <img id="Bimage" src="./images/Avatar.png" alt="Logo">
        </div>

        <script>
            var pages = ["./images/IMAGE1.png", "./images/IMAGE2.png", "./images/IMAGE3.png"],
            position = 0;

            document.getElementById("image").on('wheel', mouseHandler);

            function mouseHandler() {
                return function(e) {

                    if(e.originalEvent.deltaY < 0) {
                        position -= 1;
                        this.attr("src", pages[position]);
                    } else {
                        position += 1;
                        this.attr("src", pages[position]);
                    }
                }
            }

        </script>

    </body>
</html>

The error message from the console says: Cannot read property 'on' of null at index.html:71

Community
  • 1
  • 1
  • You'd be getting an error in your browser's console, wouldn't you? Something about how `.on()` isn't a function? Because `.on()` is a jQuery function, but you're trying to use it directly on a DOM element. Or something about `null`, because you've got the image's ID wrong. Try `$("#Bimage").on(...)` instead. – nnnnnn Mar 15 '17 at 02:19
  • Thanks for that @nnnnnn, didn't check, I'll update the question with the specified error –  Mar 15 '17 at 02:22

1 Answers1

0

You've got the ID of your element wrong, so document.getElementById() returns null, hence the error you mention in the question.

However, if you fix the ID you will still get an error, because you are trying to call the jQuery .on() method directly on the DOM element. Use $("#Bimage").on(...) instead.

Also, within your event handler don't return a function, just do directly what you want to do. Your function also tries to use this.attr, which has the same problem as above that .attr() is a jQuery method but this is the DOM element, so use $(this).attr() instead.

Next, you don't want to just keep adding or subtracting 1 from position, because then you run past the beginning or end of the array. You probably want to "wrap" around to the other end of the array, so I'll show code for that.

Also, you can move the .attr() line to after the if/else rather than repeating exactly the same thing in each branch.

Finally, you probably don't want the whole page to scroll if the mouse is over the image when the wheel is turned, so call the event.preventDefault() method from within your event handler. (If you move the wheel when the mouse is somewhere else the page will scroll as normal.)

Putting all of that together:

var pages = ["./images/IMAGE1.png", "./images/IMAGE2.png", "./images/IMAGE3.png"],
    position = 0;

$("#Bimage").on('wheel', mouseHandler);

function mouseHandler(e) {
  e.preventDefault();
  if (e.originalEvent.deltaY < 0) {
    position = position === 0 ? pages.length - 1 : position - 1;
  } else {
    position = (position + 1) % pages.length;
  }
  $(this).attr("src", pages[position]);
  // log current image name for demo purposes, because
  // this snippet doesn't have access to the images
  console.log(pages[position]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="Banner">
  <img id="Bimage" src="./images/Avatar.png" alt="Logo">
</div>

Update: In a comment, the OP asked about scrolling with the mouse anywhere in the window rather than just over the image. That is a matter of binding the wheel event to window and then not using this within the event handler (because this refers to the object the event handler was bound to, which was fine when bound to the image, but not right for window).

Expand/run the following snippet to see that in context:

var pages = ["./images/IMAGE1.png", "./images/IMAGE2.png", "./images/IMAGE3.png"],
    position = 0;

// save a reference to the image element, rather than continually
// reselecting it every time the `wheel` event occurs
var theImage = $("#Bimage");

$(window).on('wheel', mouseHandler);

function mouseHandler(e) {
  e.preventDefault();
  if (e.originalEvent.deltaY < 0) {
    position = position === 0 ? pages.length - 1 : position - 1;
  } else {
    position = (position + 1) % pages.length;
  }
  theImage.attr("src", pages[position]);
  // log current image name for demo purposes, because
  // this snippet doesn't have access to the images
  console.log(pages[position]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="Banner">
  <img id="Bimage" src="./images/Avatar.png" alt="Logo">
</div>
nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • Wow that is some magic right there, thanks so much, but how can I make the image change irregardless of the mouse icon position (as long as the wheel is moved) if its not too much to ask for? –  Mar 15 '17 at 02:43
  • Bind the event handler to `window` instead of to the image element. So `$(window).on(...)`. – nnnnnn Mar 15 '17 at 02:46
  • The console logs the change, but the image is not changing (I attached the event on the window as you said) –  Mar 15 '17 at 03:01
  • with $("#Bimage") it worked as long as the mouse icon was on the area of the image, with $(window) it logs the current image but nothing changes on the screen –  Mar 15 '17 at 03:45
  • Sorry, the problem with `$(window)` was that then within the handler `this` refers to `window` and not the image, and we were setting the `src` via `this`. I've updated my answer with a variation that works for `window`. – nnnnnn Mar 15 '17 at 04:23
  • Magic once more @nnnnn, thanks very much for the extra details they will be very helpful in my progression. Cheers –  Mar 15 '17 at 04:29