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的事情做得有点逼格. 分页本身没啥,但是数据量起来了,比如十万. 要是不做点处理, 那你的页面估计爽得很,机器也爽得很. 放心,我不会 ...
随机推荐
- shell编程--遍历目录下的文件
假定目录text下有如下文件 目录:dir_1.dir_2.dir_3 文件:text_1.text_2 遍历目录下所有的文件是目录还是文件 if -- if类型: #!bin/sh for ...
- {Emgu}{C#}保存图片、视频等
一.簡介 以前研究所的時候,有使用VC.NET 配合 OpenCV 做影像處理,這東西相當讚,可以省去不少開發時間,今天嘗試看看如何在Visual C# 2008 上使用 OpenCV. 以下引用 O ...
- Elixir's keyword lists as option parameters
备注: 文章转自:https://www.djm.org.uk/posts/writing-extensible-elixir-with-behaviours-adapters-pluggable-b ...
- Spring核心机制:依赖注入
转载:http://www.cnblogs.com/chenssy/ Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因 ...
- 腾讯加入QQ群,代码生成地址
腾讯加入QQ群,代码生成地址 http://qun.qq.com/join.html
- How to install cacti on centos 6
Cacti – Network and performance monitoring tool Cacti is one of best monitoring tool used to monit ...
- Falcon
1. JE falcon还需要安装je用来处理jdbc,否则打不开falcon的页面,爆内部错误503,然后看异常信息:Caused by: org.apache.falcon.FalconExcep ...
- c# winform委托的使用
可参考http://bbs.csdn.net/topics/390377875中使用new Action<>的使用方式,替代delegate的申明. public delegate voi ...
- Linux命令之hostname - 显示或设置主机名
我使用过的Linux命令之hostname - 显示或设置主机名 本文链接:http://codingstandards.iteye.com/blog/804648 (转载请注明出处) 用途说明 ...
- Mac运维安装软件
Maccrt软件 sudo spctl --master-disable 打开软件,复制到app,按照sn.txt输入即可 sudo spctl --master-enable crt快捷键crtl ...