Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a event invoked when a block's width changes?

I want to call my code when the width of the block I listen to changes. How to?

onresize is invoked only when the size of the window changes.

like image 224
木士羽 Avatar asked Apr 28 '15 02:04

木士羽


2 Answers

An option can be to use ResizeObserver:

Observes all width changes.

JS:

var foo = document.getElementById('foo');

var observer = new window.ResizeObserver(entries => 
   console.log(entries[0].contentRect.width));

   observer.observe(foo);
}

Stackblitz in Angular

like image 113
ttugates Avatar answered Oct 21 '22 09:10

ttugates


As you mentioned, there is no resize event for elements on the page, just for window.

You can however use Mutation Observers to detect changes in an element:

const foo = document.querySelector('#foo');

let oldWidth =  window.getComputedStyle(foo).getPropertyValue('width');
const observer = new MutationObserver(function(mutations) {
  mutations.forEach(mutation => {
    if (mutation.target === foo &&
      mutation.attributeName === 'style' &&
      oldWidth !== foo.style.width) {
        foo.textContent = 'Width changed from ' +
          oldWidth + ' to ' + foo.style.width;
        oldWidth = foo.style.width;
    }
  });
});

// configure the observer, just look for attribute changes:
const config = {
  attributes: true
};

// start observing
observer.observe(foo, config);

// change the width after a second so we can detect it
setTimeout(() => {
  foo.style.width = '150px';
}, 1000);
#foo {
  border: 2px solid #f30;
  width: 100px;
  height: 100px;
  transition: width 1s;
}
<div id="foo">foo</div>

With a little more work you can create a function that will add a custom event to the element you want to detect width changes on:

const addWidthChangeEvent = function(element) {
  let oldWidth =  window.getComputedStyle(element).getPropertyValue('width');
  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
      if (mutation.target === element &&
        mutation.attributeName === 'style' &&
        oldWidth !== element.style.width) {
          oldWidth = element.style.width;
          element.dispatchEvent(new Event('widthChange'));
      }
    });
  });

  // configure the observer, just look for attribute changes:
  const config = {
    attributes: true
  };

  observer.observe(element, config);
};

const foo = document.getElementById('foo');

// add the new widthChange event to foo
addWidthChangeEvent(foo);

// add a listener for the new event
foo.addEventListener('widthChange', event => {
  foo.textContent = foo.style.width;
}, false);


const randomInt = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1)) + min;
};

// change the width every 2 seconds
setInterval(() => {
  let newWidth = randomInt(4, 30) * 10;
  foo.style.width = newWidth + 'px';
}, 2000);
#foo {
  border: 2px solid #f30;
  width: 100px;
  height: 100px;
  transition: width 1s;
}
<div id="foo">foo</div>
like image 26
Useless Code Avatar answered Oct 21 '22 07:10

Useless Code