Visual Studio highlighted my onresize
attribute of my div
tag, and says that it isn\'t a valid attribute for HTML5. Is this true? What should I use
Microsoft's Internet Explorer supports onresize
on all HTML elements.
In all other Browsers the onresize
is only available at the window
object.
https://developer.mozilla.org/en-US/docs/Web/API/Window.onresize
If you wanna have onresize at a div
in all browsers check this:
http://marcj.github.io/css-element-queries/
This library has a class ResizeSensor
which can be used for resize
detection.
Add the following CSS and JavaScript to your page, and use the addResizeListener
and removeResizeListener
methods to listen for element size changes (blog post for further details: http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/):
Resize Sensor CSS
.resize-triggers {
visibility: hidden;
}
.resize-triggers, .resize-triggers > div, .contract-trigger:before {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
.resize-triggers > div {
background: #eee;
overflow: auto;
}
.contract-trigger:before {
width: 200%;
height: 200%;
}
Resize Event Methods
The following is the JavaScript you’ll need to enable resize event listening. The first two functions are prerequisites that are used in the main addResizeListener and removeResizeListener methods.
(function(){
var attachEvent = document.attachEvent;
if (!attachEvent) {
var requestFrame = (function(){
var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
function(fn){ return window.setTimeout(fn, 20); };
return function(fn){ return raf(fn); };
})();
var cancelFrame = (function(){
var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
window.clearTimeout;
return function(id){ return cancel(id); };
})();
function resetTriggers(element){
var triggers = element.__resizeTriggers__,
expand = triggers.firstElementChild,
contract = triggers.lastElementChild,
expandChild = expand.firstElementChild;
contract.scrollLeft = contract.scrollWidth;
contract.scrollTop = contract.scrollHeight;
expandChild.style.width = expand.offsetWidth + 1 + 'px';
expandChild.style.height = expand.offsetHeight + 1 + 'px';
expand.scrollLeft = expand.scrollWidth;
expand.scrollTop = expand.scrollHeight;
};
function checkTriggers(element){
return element.offsetWidth != element.__resizeLast__.width ||
element.offsetHeight != element.__resizeLast__.height;
}
function scrollListener(e){
var element = this;
resetTriggers(this);
if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
this.__resizeRAF__ = requestFrame(function(){
if (checkTriggers(element)) {
element.__resizeLast__.width = element.offsetWidth;
element.__resizeLast__.height = element.offsetHeight;
element.__resizeListeners__.forEach(function(fn){
fn.call(element, e);
});
}
});
};
}
window.addResizeListener = function(element, fn){
if (attachEvent) element.attachEvent('resize', fn);
else {
if (!element.__resizeTriggers__) {
if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
element.__resizeLast__ = {};
element.__resizeListeners__ = [];
(element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
'<div class="contract-trigger"></div>';
element.appendChild(element.__resizeTriggers__);
resetTriggers(element);
element.addEventListener('scroll', scrollListener, true);
}
element.__resizeListeners__.push(fn);
}
};
window.removeResizeListener = function(element, fn){
if (attachEvent) element.detachEvent('resize', fn);
else {
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
if (!element.__resizeListeners__.length) {
element.removeEventListener('scroll', scrollListener);
element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
}
}
}
})();
Demo-licious!
Here’s a pseudo code usage of the method.
var myElement = document.getElementById('my_element'),
myResizeFn = function(){
/* do something on resize */
};
addResizeListener(myElement, myResizeFn);
removeResizeListener(myElement, myResizeFn);
Currently all major browser doesn't support a resize event for html-element's, just for the window object.
What you can to is to intercept the user interaction to build your own listener, like this:
function detectResize(_element)
{
let promise = {};
let _listener = [];
promise.addResizeListener = function(listener)
{
if(typeof(listener) != "function") { return; }
if(_listener.includes(listener)) { return; };
_listener.push(listener);
};
promise.removeResizeListener = function(listener)
{
let index = _listener.indexOf(listener);
if(index >= 0) { _listener.splice(index, 1); }
};
let _size = { width: _element.clientWidth, height: _element.clientHeight };
function checkDimensionChanged()
{
let _currentSize = { width: _element.clientWidth, height: _element.clientHeight };
if(_currentSize.width != _size.width || _currentSize.height != _size.height)
{
let previousSize = _size;
_size = _currentSize;
let diff = { width: _size.width - previousSize.width, height: _size.height - previousSize.height };
fire({ width: _size.width, height: _size.height, previousWidth: previousSize.width, previousHeight: previousSize.height, _element: _element, diff: diff });
}
_size = _currentSize;
}
function fire(info)
{
if(!_element.parentNode) { return; }
_listener.forEach(listener => { listener(info); });
}
let mouseDownListener = event =>
{
let mouseUpListener = event =>
{
window.removeEventListener("mouseup", mouseUpListener);
window.removeEventListener("mousemove", mouseMoveListener);
};
let mouseMoveListener = event =>
{
checkDimensionChanged();
};
window.addEventListener("mouseup", mouseUpListener);
window.addEventListener("mousemove", mouseMoveListener);
};
_element.addEventListener("mousedown", mouseDownListener);
window.addEventListener("resize", event =>
{
checkDimensionChanged();
});
return promise;
}
How to use it:
document.addEventListener("DOMContentLoaded", event =>
{
let textarea = document.querySelector("textarea");
let detector = detectResize(textarea);
let listener = info => { console.log("new width: ", info.width, " new height: ", info.height); };
detector.addResizeListener(listener);
});
html:
<textarea></textarea>
css:
html, body
{
height: 100%;
box-sizing: border-box;
overflow: hidden;
margin: 0px;
}
textarea
{
resize: both;
width: 96px;
height: 112px;
width: 100%;
height: 100%;
border: 1px solid black;
}
Only Window.onResize
exists in the specification. Please remember that every IFrame
element creates new Window
object which supports onResize
. Therefore IMO the most reliable method to detect changes to the element's size is to append hidden iframes to the element.
If you are interested in a neat and portable solution, please check this plugin. It takes 1 line of code to listen the event of changing width or height of your div.
<!-- (1) include plugin script in a page -->
<script src="/src/jquery-element-onresize.js"></script>
// (2) use the detectResizing plugin to monitor changes to the element's size:
$monitoredElement.detectResizing({ onResize: monitoredElement_onResize });
// (3) write a function to react on changes:
function monitoredElement_onResize() {
// logic here...
}