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.
An option can be to use ResizeObserver:
Observes all width changes, wen when MutationObserver
doesn't as in Useless Code's answer.
Does not have much browser compatibility, however.
JS:
var foo = document.getElementById('foo');
var observer = new window.ResizeObserver(entries =>
console.log(entries[0].contentRect.width));
observer.observe(foo);
}
Stackblitz in Angular
There's no default event provided by browser when the width of your element is changing. However, just like @Leo mentioned, you can register and trigger your own event.
There are 3 steps you have to:
The sample code is here:
<body>
<div class="square"></div>
</body>
$(function() {
var $square = $('.square');
// Register a custom event and bind an event handler on it
$square.on('square.resize', function() {
console.log('Square is resized!');
});
// Trigger that event when you change the square size
function resizeSquare() {
$square.width($square.width() + 10);
$square.height($square.height() + 10);
$square.trigger('square.resize');
}
// Anytime you resize the square, it will trigger 'square.resize' event
// In this example, I am using setInverval() to resize the square, but you could
// change it into any ways you like
setInterval(resizeSquare, 1000);
});
You may check here for CodePen Live Demo
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>