简体   繁体   中英

Create onmouseover/onmouseout functions dynamically with javascript?

So here is an example of the function I need to replicate:

document.getElementById('img1').onmouseover = function() {
    document.getElementById('img1').style.width = expandTo + '%';

    expandCompensate(1);
}

document.getElementById('img1').onmouseout = function() {
    expandReset();
}

The situation is that I have a for loop creating some div elements, and the number of them is dynamic. As of right now, I have it creating 4 div elements, so I created 4 iterations of the above functions for img1 , img2 , img3 and img4 . But what I would like to do is to have the onmouseover and onmouseout functions created dynamically based on how many div elements I've decided to create (based on a variable).

Is there any way to do this? Here is all the code for context (it's not much), there are comments in the JS with explanations for everything. The part I'm trying to automate is at the bottom:

https://jsfiddle.net/4w0714su/3/

And here is the working example for context of what I'm trying to achieve:

http://www.ericsartor.ca/imgwide

FYI: The image is I picked were random, I just needed high res images. Just doing this for practice! Thanks to anyone that can help me figure this out!

I can't understand your code very well, but I'll answer particularly what you're asking.

You can achieve what you want by doing a loop:

for (var i = 0; i < 4; i++) {
  document.getElementById('img' + i).onmouseover = function() {
    this.style.width = expandTo + '%';
    expandCompensate(Number(this.id.replace('img', '')));
  };

  document.getElementById('img' + i).onmouseout = function() {
    expandReset();
  }
}

Note: you can't use the i variable inside the event handlers' functions, because it will always be 4 , since it will finish the loop, and will never be changed again.


Another way of doing that is by using an IIFE (Immediately-invoked function expression) , eg:

for (var i = 0; i < 4; i++) {
  (function(n) {
    document.getElementById('img' + n).onmouseover = function() {
      this.style.width = expandTo + '%';
      expandCompensate(n);
    };

    document.getElementById('img' + n).onmouseout = function() {
      expandReset();
    }
  })(i);
}

Doing that, you're passing to a function the current i value, so in that scope, the value of n will be a different one for each execution, eg 0 , 1 , 2 and 3 .

An immediately-invoked function expression (or IIFE, pronounced "iffy") is a JavaScript design pattern which produces a lexical scope using JavaScript's function scoping.

This could be achieved by iterating all those DOM elements and binding events in a loop .

As we bind events in loop , and event callback is being executed later when loop would be iterated completely, we need to maintaing the value of current iteration using CLOSURE .

Try this snippet:

 var pageHeight = document.getElementById('findBottom').getBoundingClientRect().bottom, numOfPics = 4; //the number of div elements to create //creates the div elements within a container div in the HTML document for (var i = 1; i <= numOfPics; i++) { document.getElementById('imgContain').innerHTML += '<div id="img' + i + '" class="imgPane"></div>'; } //used to resize all divs if the window changes size window.onresize = function() { pageHeight = document.getElementById('findBottom').getBoundingClientRect().bottom; for (var i = 1; i <= imgClasses.length; i++) { document.getElementById('img' + i).style.height = pageHeight + 'px'; } for (var i = 1; i <= imgClasses.length; i++) { document.getElementById('img' + i).style.width = 100 / imgClasses.length + '%'; } }; //sets the height of each div to be the mximum height of the page (without scrolling) for (var i = 1; i <= numOfPics; i++) { document.getElementById('img' + i).style.height = pageHeight + 'px'; } //makes all the divs equal percentage widths for (var i = 1; i <= numOfPics; i++) { document.getElementById('img' + i).style.width = 100 / numOfPics + '%'; } //the percentage of the page the hovered image will expand to var expandTo = 40; //function for when an image is hovered over function expandCompensate(whichImg) { for (var i = 1; i <= numOfPics; i++) { if (i != whichImg) document.getElementById('img' + i).style.width = (100 - expandTo) / (numOfPics - 1) + '%'; } } //function for when the hovered image is left to reset the widths function expandReset() { for (var i = 1; i <= numOfPics; i++) { document.getElementById('img' + i).style.width = 100 / numOfPics + '%'; } } (function bindEvents() { for (var i = 1; i <= numOfPics; i++) { document.getElementById('img' + i).onmouseover = (function(i) { return function() { document.getElementById('img' + i).style.width = expandTo + '%'; expandCompensate(i); } })(i); document.getElementById('img' + i).onmouseout = function() { expandReset(); }; } })(); 
 body, p, div { margin: 0; padding: 0; } body {} #findBottom { position: absolute; bottom: 0; } .imgPane { float: left; background-position: center; transition: width 0.25s; } #img1 { background-image: url('http://www.ericsartor.ca/imgwide/img//1.jpg'); } #img2 { background-image: url('http://www.ericsartor.ca/imgwide/img//2.jpg'); } #img3 { background-image: url('http://www.ericsartor.ca/imgwide/img//3.jpg'); } #img4 { background-image: url('http://www.ericsartor.ca/imgwide/img//4.jpg'); } 
 <div id="imgContain"></div> <!-- ABSOLUTE ELEMENTS --> <div id="findBottom"></div> <!-- ABSOLUTE ELEMENTS --> 

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