Cross-Browser, Event-based, Element Resize Detection(转)
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(转)的更多相关文章
- 基于事件的网关 Eventbased Gateway
基于事件的网关 Eventbased Gateway 作者:Jesai 时间:2018年4月21日 21:19:30 什么是事件网关? 基于事件的网关,允许基于事件做选择. 事件网关的执行原理? 网 ...
- 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 ...
- Global Contrast based Salient Region Detection (Ming ming Cheng)
abstract: Automatic estimation of salient object regions across images, without any prior assumption ...
- Event based Collections
https://sourceforge.net/p/happy-guys/wiki/Event%20based%20Collections/
- 《Stereo R-CNN based 3D Object Detection for Autonomous Driving》论文解读
论文链接:https://arxiv.org/pdf/1902.09738v2.pdf 这两个月忙着做实验 博客都有些荒废了,写篇用于3D检测的论文解读吧,有理解错误的地方,烦请有心人指正). 博客原 ...
- event based xml parser (SAX) demo
import java.io.ByteArrayInputStream; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SA ...
- js polyfill , to developing the cross browser js
https://github.com/paulmillr/console-polyfill https://github.com/Modernizr/Modernizr/wiki/HTML5-Cros ...
- Automatic Ship Detection in Optical Remote Sensing Images Based on Anomaly Detection and SPP-PCANet
基于异常检测和 PCANet 的船舶目标检测 船舶检测会遇到三个问题: 1.船低对比度 2.海平面情况复杂 3.云,礁等错误检测 实验步骤: 1.预处理海陆边界,掩膜陆地 2.异常检测获得感兴趣区域, ...
- 监测元素resize
前言 近来有需求要做分页,听起来可能有点Low. 所以我要把Low的事情做得有点逼格. 分页本身没啥,但是数据量起来了,比如十万. 要是不做点处理, 那你的页面估计爽得很,机器也爽得很. 放心,我不会 ...
随机推荐
- BZOJ2824 AHOI2012 铁盘整理 【IDA*】
BZOJ2824 AHOI2012 铁盘整理 Description 在训练中,一些臂力训练器材是少不了的,小龙在练习的时候发现举重器械上的铁盘放置的非常混乱,并没有按照从轻到重的顺序摆放,这样非常不 ...
- 使用 ExceptionDispatchInfo 捕捉并重新抛出异常
当你跑起了一个异步线程,并用 await 异步等待时,有没有好奇为什么能够在主线程 catch 到异步线程的异常? 当你希望在代码中提前收集好异常,最后一并把收集到的异常抛出的时候,能不能做到就像在原 ...
- JavaScript 定时任务多事件冲突问题
var iCount = setInterval(ChangeTime, 3500);//3.5秒请求一次函数 function ChangeTime() { $.ajax({ type: " ...
- js中对数字进行正则判断
<script type="text/javascript"> function SubmitCk(num) { var reg = /^([a-zA-Z0-9]+[_ ...
- JDBC查询实例
作为Java与数据库交互最古老的.最基础的规范,JDBC提供了访问底层数据库的接口,其他ORM框架都是在JDBC这块基石上构建的.下面我们看一个基本的JDBC查询例子: package com.ins ...
- golang的beego框架开发时出现的问题纪录
golang的beego框架开发时出现的问题纪录1.数据库并发时问题:[ORM]2017/02/20 23:44:05 -[Queries/default] - [FAIL / db.Query / ...
- Vim下的Web开发之html,CSS,javascript插件
Vim下的Web开发之html,CSS,javascript插件 HTML 下载HTML.zip 解压HTML.zip,然后将里面的所有文件copy到C:\Program Files\Vim\vi ...
- java代码---I/O文件内容复制
总结:主要是弄清输入流,输出流 输入流和输出流都是针对程序而言,把文件内容读取到程序是输入流 从程序把内容写入文件是输出流 package com.a.b; import java.io.*; imp ...
- mybatis MySQL返回插入的主键ID,oracle不行
<insertid=“doSomething"parameterType="map"useGeneratedKeys="true"keyProp ...
- @import '/template/door-info/door-info.wxss';
小程序css样式引入时,首次要用“”双引号,否则报错