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. 20179223《Linux内核原理与分析》第十二周学习笔记

    Return-to-libc 攻击实验 一.实验描述 缓冲区溢出的常用攻击方法是用 shellcode 的地址来覆盖漏洞程序的返回地址,使得漏洞程序去执行存放在栈中 shellcode.为了阻止这种类 ...

  2. iOS Webview打开不受信的URL

    在我们开发过程中经常会碰到直接访问开发人员的私有地址, 这样在app 上是无法打开指定的网页的. 在iOS中需要对WKWebView 进行如下设置: 1.在工程的Plist 文件中添加一下选项 App ...

  3. Django的MultipleChoiceField处理小技巧

    1.如果遇到多选择的,在收到数据时一般需要做处理 tag_id = fields.MultipleChoiceField( choices=[], widget=widgets.CheckboxSel ...

  4. 定义文档兼容性、让IE按指定版本解析我们的页面

    http://blog.useasp.net/archive/2013/05/29/x-UA-compatible-defining-document-compatibility-emulate-ie ...

  5. matlab中卷积编码参数的理解

    poly2trellis(7, [171 133])代表什么意思呢?首先是7,他是1*k的vector,此处k为1,[171 133]是k*n的vector,此处n就是2,那么这个编码就是1/2码率的 ...

  6. textArea中的maxlength是无效的 解决办法

    --------------------------------------------------------------------------------------   <s:texta ...

  7. fileupload页面跳转找不到原页面的解决方法

    做了个上传图片的功能,之前做的全都对,完全可以实现,但是后来再弄的时候,只要FileUpload控件里面有字(选择了图片),再按button.它尽然不执行button1_click事件,直接页面跳转, ...

  8. xunsearch安装及环境检测(一)

    1.运行执行下载解压安装包wget http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2解压到指定目录 tar -xjf xu ...

  9. jQuery给控件赋值....

    1.jQuery给span取值:$("#id").html(); 2.jQuery给input取值:$("#id").val(); 3.jQuery给texta ...

  10. linux下thinkphp取消调试模式后找不到网页解决方案

    1.最大嫌疑是Runtime目录权限不足,导致common~runtime.php文件无法生成, 解决:1.整个Runtime目录删除,让系统重新生成; 2.给Runtime及以下的所有文件足够权限0 ...