Multiple instances of Javascript function with resize function

Viewed 1521

I created a quick library to help me position text absolutely over a background image. It works great with one instance. As soon as I add multiple instances, the resize function inside the library function only works on the last instance.

Here is my library code -

function overlay(params) {
  function resizeOverlay(params) {
    //get the overlay container
    var layContainer = document.getElementsByClassName(params.element)[0];

    //user sets height and width of bg image used so we can calculate ratio
    var bgHeight = params.height;
    var bgWidth = params.width;

    var w = window,
    d = document,
    e = d.documentElement,
    g = d.getElementsByTagName('body')[0],
    x = w.innerWidth || e.clientWidth || g.clientWidth,
    y = w.innerHeight|| e.clientHeight|| g.clientHeight;

    var newSize = getFinalMeasurements(x, y, bgWidth, bgHeight);

    var newPos = getNewPosition(x, y, newSize);

    function getFinalMeasurements(x, y, natWidth, natHeight) {
      var finalSize = {};

      var originalRatios = {
        width: x / natWidth,
        height: y / natHeight
      };

      var coverRatio = Math.max(originalRatios.width, originalRatios.height); 

      finalSize = {
        height: natHeight * coverRatio,
        width: natWidth * coverRatio
      }

      return finalSize;
    }

    function getNewPosition(x, y, finalSize) {
      var left = finalSize.width - x;
      var top = finalSize.height - y;
      var leftPos;
      var topPos;
      var finalPos = {};

      if(left > 0) {
        leftPos = left/2;
      } else {
        leftPos = left;
      }

      if(top > 0) {
        topPos = top/2;
      } else {
        topPos = top;
      }

      finalPos = {
        left: leftPos,
        top: topPos
      }

      return finalPos;
    }

    layContainer.setAttribute('style', 'height:' + newSize.height + 'px; width:' + newSize.width + 'px; left: -' + newPos.left + 'px; top:-' + newPos.top + 'px');
  }

  resizeOverlay(params);

  window.onresize = function() {
    resizeOverlay(params);
    console.log('resizing');
  }
}

And then my instances -

var compassTextContainer = new overlay({
    width: 2364,
    height: 1314,
    element: 'compass-overlay'
});

var liveFeedContainer = new overlay({
    width: 2364,
    height: 1314,
    element: 'livefeed-overlay'
});

var rocketContainer = new overlay({
    width: 2364,
    height: 1314,
    element: 'rocket-overlay'
});

All of them work on initial load but when I resize the window, the rocket-overlay element is the only one working.

2 Answers

It's because you're using onresize that overrides the previous event listener. So each time you set up an instance, that instance's resize event listener will override the previous one, hence only the last one works.

To fix that use addEventListener which adds the new event listener without removing the previous ones:

window.addEventListener("resize", function() {
  resizeOverlay(params);
  console.log('resizing');
});

Note: Since the logic is repeated among all the instances, you could refactor your code to use event delegation which only sets one event listener. Also, try not to redefine the functions resizeOverlay and getNewPosition each time you call overlay, an IIFE is ideal for this:

var overlay = (function() {
  function resizeOverlay(params) {
    // ...
  }

  function getNewPosition(x, y, finalSize) {
    // ...
  }

  return function(params) {
    resizeOverlay(params);
    window.addEventListener("resize", function() {
      resizeOverlay(params);
    });
  }
})();

Replace window.onresize with window.addEventListener('resize', () => { resizeOverlay(params) } )

Related