skip to Main Content

I am using an image for an input (button) within a form on my website, and would like to swap the image on hover.

The following code works fine in a stand alone demo. The images swap nicely.

However… when I integrate this code into the rest of the form code, it fails.

I am guessing it is because the script calls for getElementsByTagName('input') with the tag name being input.

Therefore… perhaps because the form contains other ‘inputs’, the function targets the other inputs as well, and simply dies??????

Is there a way to execute this same function, and target the specific input without using the getElementsByTagName('input'), or by tweaking it some way?

var inputs = document.getElementsByTagName('input');
for (var i = 0, len = inputs.length; i < len; i++) {
  input = inputs[i];
  input.onmouseover = function() {
    this.setAttribute('data-orig-image', this.getAttribute('src'));
    this.src = this.getAttribute('data-alt-image');
  };
  input.onmouseout = function() {
    this.src = this.getAttribute('data-orig-image');
  };
}
<input type="image" src="/images/image1.png" data-alt-image="/images/image2.png" />

3

Answers


  1. If you use querySelectorAll, then you can use CSS selectors – this way, you can narrow down your list however you like (limit is CSS selectors only).

    In the snippet below I broke up your code a bit, but the main point (regarding your question) is that with querySelectorAll I could narrow down the input list with a type. This way, if really a clash is the problem in your context, the problem should be solved (of course, you could be adding a class, or just "filter" for the data-alt-image).

    Also, by updating the iterator function (for...i++ -> inputs.forEach), it works nicely with multiple inputs.

    const ORIG_URL_ATTR = 'src'
    const ALT_URL_ATTR = 'data-alt-image'
    
    const switchImageUrls = ([curr, alt]) => [alt, curr]
    
    const getImageUrls = (input) => [input.getAttribute(ORIG_URL_ATTR), input.getAttribute(ALT_URL_ATTR)]
    
    const setImageUrls = (input) => ([curr, alt]) => {
      input.setAttribute(ORIG_URL_ATTR, curr)
      input.setAttribute(ALT_URL_ATTR, alt)
    }
    
    const handleMouseEvent = (input) => {
      setImageUrls(input)(switchImageUrls(getImageUrls(input)))
    }
    
    const setEventHandlers = (input) => {
      input.onmouseover = () => handleMouseEvent(input);
      input.onmouseout = () => handleMouseEvent(input);
    }
    
    const inputs = document.querySelectorAll('input[type="image"]');
    
    inputs.forEach(setEventHandlers)
    <input type="image" src="https://via.placeholder.com/150/0000FF/808080?text=orig1" data-alt-image="https://via.placeholder.com/150?text=alt1" />
    <input type="image" src="https://via.placeholder.com/150/0000FF/808080?text=orig2" data-alt-image="https://via.placeholder.com/150?text=alt2" />
    Login or Signup to reply.
  2. You specified JavaScript and jQuery, so here is a short & sweet jQuery solution:

    function swapImage(elem) {
      let src = elem.attr('src');
      let alt = elem.data('alt');
      elem.attr('src', alt);
      elem.data('alt', src);
    }
    
    $('document').ready(function() {
      $('input[type="image"]').hover(function () {
        swapImage($(this));
      }, function () {
        swapImage($(this));
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input type="image" src="https://via.placeholder.com/150/0000FF/808080?text=orig1" data-alt="https://via.placeholder.com/150?text=alt1" />
    <input type="image" src="https://via.placeholder.com/150/0000FF/808080?text=orig2" data-alt="https://via.placeholder.com/150?text=alt2" />

    Explanation:

    • the image has src and data-alt attributes
    • the jQuery .hover() function has two callbacks, one for entering, one for leaving
    • on both hover callbacks we call the swapImage() function, which swaps the values of the src and a data-alt attributes
    Login or Signup to reply.
  3. This is fairly simple if you use data attributes; set up the original with swapper.dataset.origImage = swapper.getAttribute('src'); (or put that in the HTML originally as data attributes) then just swap them on the mouse events

    let swappers = document.querySelectorAll('.image-swapper');
    swappers.forEach((swapper) => {
      swapper.dataset.origImage = swapper.getAttribute('src');
      swapper.addEventListener('mouseenter', (event) => {
        event.currentTarget.src = event.currentTarget.dataset.altImage;
      });
      swapper.addEventListener('mouseleave', (event) => {
        event.currentTarget.src = event.currentTarget.dataset.origImage;
      });
    });
    .image-swapper {
      width: 15rem;
      height: 10rem;
    }
    <input class="image-swapper" type="image" src="https://i.stack.imgur.com/7bI1Y.jpg" data-alt-image="https://i.stack.imgur.com/XZ4V5.jpg" />
    <input class="image-swapper" type="image" src="https://i.stack.imgur.com/OVOg3.jpg" data-alt-image="https://i.stack.imgur.com/lxthA.jpg" />
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search