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. iPhone4s 9.2.1安装cydia(越狱)

    依据网上资料而来 主要就是上图视频中的6步骤选项,不要选错. 1.prepare for jailbreak 2.选择Accept 3. proceed with jailbreak 4.begin ...

  2. __getitem__ 专用方法

    (1)  __getitem__ 专用方法很简单.像普通的方法 clear,keys 和 values 一样,它只是重定向到字典,返回字典的值.但是怎么调用它呢?哦,你可以直接调用 __getitem ...

  3. 阿里云视频点播 php开发

    先购买开通阿里云的<视频点播>服务,视频点播 可以购买套餐 ,我在项目中使用的是299套餐 开发前在<用户信息管理>生成Access Key Secret,开发密钥使用 阿里云 ...

  4. DS04--树

    一.学习总结 1.树结构思维导图 2.树结构学习体会 树这一节遇到最大的困难就是递归不能灵活的运用,总是想用链表那里的知识解决,做了一大堆,程序崩溃也找不到问题出在哪里. 二.PTA实验作业 题目1: ...

  5. DS03--栈和队列

    一.学习总结 1 关键词: 逻辑结构,存储结构,抽象数据类型,顺序存储类型,链式存储类型,线性表应用 栈和队列 2 使用思维导图将这些关键词组织起来. 二.PTA实验作业 2.1题目1:符号配对 请编 ...

  6. Spring security 如何设置才能避免拦截到静态资源

    问题:继承FilterSecurityInterceptor自定义Spring security拦截器,但是每次都拦截了css等静态资源,应该如何设置? @Override protected voi ...

  7. sys模块的问题,深浅COPY的应用场景,元祖与购物车程序练习-打印彩色\033[31;1m--------\033[0m

    打印彩色:%s为变量,格式化 print("Added %s into shopping cart,your current balance is \033[31;1m%s\033[0m&q ...

  8. Fiddler过滤操作

    Fidller,不做过多的简介,其中的过滤操作肯定是绕不过去的.直接上图.

  9. Hadoop Map/Reduce的工作流

    问题描述 我们的数据分析平台是单一的Map/Reduce过程,由于半年来不断地增加需求,导致了问题已经不是那么地简单,特别是在Reduce阶段,一些大对象会常驻内存.因此越来越顶不住压力了,当前内存问 ...

  10. htm标签的语意

    标签名 英文全拼 标签语意 div division 分割 span span 范围 ol ordered list 排序列表 ul unordered list 不排序列表 li list item ...