DOM Elements! Y U No Resize Event?

During your coding adventures, you may have run into occasions where you wanted to know when an element in your document changed dimensions – basically the window resize event, but on regular elements. Element size changes can occur for many reasons: modifications to CSS width, height, padding, as a response to changes to a parent element’s size, and many more. Before today, you probably thought this was mere unicorn lore, an impossible feat – well buckle up folks, we’re about to throw down the gauntlet.

Eye of Newt, and Toe of Frog

Before we start adding bits to our hacker’s cauldron, let’s review which browsers this will target…you might have just thought to yourself “well, all of them, right?” – but you’d be wrong. This hack is only needed for WebKit and Firefox. In a twist of fate, IE offers built-in support for resize events on regular DOM elements – I shit you not, see for yourself: http://msdn.microsoft.com/en-us/library/ie/ms536959%28v=vs.85%29.aspx.

Now, for the DOM alchemy! We’ll need to add to our cauldron overflow or underflow events. If you haven’t heard of them, that’s OK, because I have just the post to get you up to speed – go ahead, I’ll wait here –> Back Alley Coder: Overflow and Underflow Events.

Whew, you’re back! Now that you’re in the overflow know, you might think this hack is simply setting overflow and underflow on an element, but that doesn’t provide us with the functionality we’re after. Overflow and underflow events only fire when an element changes flow state, not each time an element changes size. We’re going to need a few DOM elements and some very well-placed overflow and underflow events to create what I refer to as ‘sensors’. Let’s take a look at the code you’ll need to make cross-browser element resize events possible:

Resize Sensor HTML

The following HTML block is auto-appended to any element you attach a resize event to. You can only attach resize events to elements that allow children – basically, no elements declared with self-closing tags.

<div class="resize-sensor">
<div class="resize-overflow"><div></div></div>
<div class="resize-underflow"><div></div></div>
</div>

Resize Sensor CSS

.resize-sensor, .resize-sensor > div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: -1;
}

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. (further details on the addFlowListener method are available in the overflow/underflow event post, as previous mentioned)

function addFlowListener(element, type, fn){
var flow = type == 'over';
element.addEventListener('OverflowEvent' in window ? 'overflowchanged' : type + 'flow', function(e){
if (e.type == (type + 'flow') ||
((e.orient == 0 && e.horizontalOverflow == flow) ||
(e.orient == 1 && e.verticalOverflow == flow) ||
(e.orient == 2 && e.horizontalOverflow == flow && e.verticalOverflow == flow))) {
e.flow = type;
return fn.call(this, e);
}
}, false);
}; function fireEvent(element, type, data, options){
var options = options || {},
event = document.createEvent('Event');
event.initEvent(type, 'bubbles' in options ? options.bubbles : true, 'cancelable' in options ? options.cancelable : true);
for (var z in data) event[z] = data[z];
element.dispatchEvent(event);
}; function addResizeListener(element, fn){
var resize = 'onresize' in element;
if (!resize && !element._resizeSensor) {
var sensor = element._resizeSensor = document.createElement('div');
sensor.className = 'resize-sensor';
sensor.innerHTML = '<div class="resize-overflow"><div></div></div><div class="resize-underflow"><div></div></div>'; var x = 0, y = 0,
first = sensor.firstElementChild.firstChild,
last = sensor.lastElementChild.firstChild,
matchFlow = function(event){
var change = false,
width = element.offsetWidth;
if (x != width) {
first.style.width = width - 1 + 'px';
last.style.width = width + 1 + 'px';
change = true;
x = width;
}
var height = element.offsetHeight;
if (y != height) {
first.style.height = height - 1 + 'px';
last.style.height = height + 1 + 'px';
change = true;
y = height;
}
if (change && event.currentTarget != element) fireEvent(element, 'resize');
}; if (getComputedStyle(element).position == 'static'){
element.style.position = 'relative';
element._resizeSensor._resetPosition = true;
}
addFlowListener(sensor, 'over', matchFlow);
addFlowListener(sensor, 'under', matchFlow);
addFlowListener(sensor.firstElementChild, 'over', matchFlow);
addFlowListener(sensor.lastElementChild, 'under', matchFlow);
element.appendChild(sensor);
matchFlow({});
}
var events = element._flowEvents || (element._flowEvents = []);
if (events.indexOf(fn) == -1) events.push(fn);
if (!resize) element.addEventListener('resize', fn, false);
element.onresize = function(e){
events.forEach(function(fn){
fn.call(element, e);
});
};
}; function removeResizeListener(element, fn){
var index = element._flowEvents.indexOf(fn);
if (index > -1) element._flowEvents.splice(index, 1);
if (!element._flowEvents.length) {
var sensor = element._resizeSensor;
if (sensor) {
element.removeChild(sensor);
if (sensor._resetPosition) element.style.position = 'static';
delete element._resizeSensor;
}
if ('onresize' in element) element.onresize = null;
delete element._flowEvents;
}
element.removeEventListener('resize', fn);
};

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);

Cut to the chase, let’s see this resize thang in action:

Resize ALL The Things!

Now that we’re equipped with a nifty, cross-browser element resize event, what would it be good for? Here’s a few possible uses:

  • Resize-proof Web Component UI development
  • Per-element responsive design
  • Size-based loading of content
  • Anything you can imagine!

Cross-Browser, Event-based, Element Resize Detection(转)的更多相关文章

  1. 基于事件的网关 Event­based Gateway

    基于事件的网关 Event­based Gateway 作者:Jesai 时间:2018年4月21日 21:19:30 什么是事件网关? 基于事件的网关,允许基于事件做选择. 事件网关的执行原理? 网 ...

  2. CVPR 2011 Global contrast based salient region detection

    Two salient region detection methods are proposed in this paper: HC AND RC HC: Histogram based contr ...

  3. Global Contrast based Salient Region Detection (Ming ming Cheng)

    abstract: Automatic estimation of salient object regions across images, without any prior assumption ...

  4. Event based Collections

    https://sourceforge.net/p/happy-guys/wiki/Event%20based%20Collections/

  5. 《Stereo R-CNN based 3D Object Detection for Autonomous Driving》论文解读

    论文链接:https://arxiv.org/pdf/1902.09738v2.pdf 这两个月忙着做实验 博客都有些荒废了,写篇用于3D检测的论文解读吧,有理解错误的地方,烦请有心人指正). 博客原 ...

  6. event based xml parser (SAX) demo

    import java.io.ByteArrayInputStream; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SA ...

  7. js polyfill , to developing the cross browser js

    https://github.com/paulmillr/console-polyfill https://github.com/Modernizr/Modernizr/wiki/HTML5-Cros ...

  8. Automatic Ship Detection in Optical Remote Sensing Images Based on Anomaly Detection and SPP-PCANet

    基于异常检测和 PCANet 的船舶目标检测 船舶检测会遇到三个问题: 1.船低对比度 2.海平面情况复杂 3.云,礁等错误检测 实验步骤: 1.预处理海陆边界,掩膜陆地 2.异常检测获得感兴趣区域, ...

  9. 监测元素resize

    前言 近来有需求要做分页,听起来可能有点Low. 所以我要把Low的事情做得有点逼格. 分页本身没啥,但是数据量起来了,比如十万. 要是不做点处理, 那你的页面估计爽得很,机器也爽得很. 放心,我不会 ...

随机推荐

  1. BZOJ3083 遥远的国度 【树链剖分】

    BZOJ3083 遥远的国度 Description zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcw ...

  2. fpga配置过程(转载)

    fpga 配置时序图如下 1.FPGA器件有三类配置下载方式:主动配置方式(AS)和被动配置方式(PS)和最常用的(JTAG)配置方式.             AS 由FPGA器件引导配置操作过程, ...

  3. simulink中几个bit型操作模型

    bit concat  将两个fix point 数据 结合到一块. bit rotate 循环移位 bit shift 移位 又分逻辑移位和算术移位,逻辑移位不管最高位0或1,统统移0,算术移位会移 ...

  4. Epub格式的电子书——文件组成

    epub格式电子书遵循IDPF推出的OCF规范,OCF规范遵循ZIP压缩技术,即epub电子书本身就是一个ZIP文件,我们将epub格式电子书的后缀.epub修改为.zip后,可以通过解压缩软件(例如 ...

  5. ASP.NET常用标准配置web.config

    在我们的项目开发过程中,我们经常要配置wei.config文件,而大多数的时候配置差不多,下面的是一个简单的配置,其他的配置可以在这个基础上在添加 <?xml version="1.0 ...

  6. Python 函数 -xrange()

    xrange() xrange() 函数用法与 range 完全相同,所不同的是生成的不是一个数组,而是一个生成器. 语法: xrange(stop) xrange(start, stop[, ste ...

  7. Fuel9.0安装openstack过程中所踩过的坑2018最新版

    坑一,安装好后,无法访问Web UI画面 访问https//10.20.0.2:8443无法打开UI画面.首先我们不管以后的步骤,打不开是很不爽的. 解决方法:把下面网卡1,网卡2,网卡3的界面名称都 ...

  8. Liveqrcode活码系统设计

    活码是一种二维码,可以通过后台配置让用户扫码时跳转到不同的网址.除了二维码生成接口,本站还实现了多租户的活码配置接口,以及活码后台jar包,详见二维码接口. 二维码生成使用了zxing三方包实现,活码 ...

  9. (转)Inno Setup入门(十八)——Inno Setup类参考(4)

    本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17251009 编辑框 编辑框也叫文本框,是典型的窗口可视化组件,既可 ...

  10. jmeter数据关联_后置处理器_正则表达式提取器