Skip to content

Commit d96e173

Browse files
author
Marc J. Schmidt
committed
Implemented better resize detection, added a test file and added ElementQuery.update method.
1 parent c35a240 commit d96e173

File tree

4 files changed

+514
-98
lines changed

4 files changed

+514
-98
lines changed

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Features:
1313
- no interval/timeout detection. Truly event-based
1414
- no CSS modifications. Valid CSS Syntax
1515
- all CSS selectors available. Uses regular attribute selector
16-
- supports and tested in webkit, gecko and IE(8/9/10).
16+
- supports and tested in webkit, gecko and IE(7/8/9/10/11).
1717
- `min-width`, `min-height`, `max-width` and `max-height` are supported so far
1818
- works with any layout modifications: HTML (innerHTML etc), inline styles, DOM mutation, CSS3 transitions, fluid layout changes (also percent changes), pseudo classes (:hover etc.), window resizes and more
1919
- no Javascript-Framework dependency (works with jQuery, Mootools, etc.)
@@ -63,12 +63,9 @@ Issues
6363
------
6464
6565
- So far does not work on `img` tags. Wrapping with a `div` works fine though (See demo).
66-
- [only non-IE]: Adds additional hidden element into selected target element and forces target element to be relative or absolute.
66+
- Adds additional hidden element into selected target element and forces target element to be relative or absolute.
6767
6868
69-
Event-Based resize detection inspired by [backalleycoder.com](http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/) <3
70-
71-
7269
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/marcj/css-element-queries/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
7370
7471

src/ElementQueries.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,16 @@
7070
*/
7171
function SetupInformation(element) {
7272
this.element = element;
73-
this.options = [];
74-
var i, j, option, width = 0, height = 0, value, actualValue, attrValues, attrValue, attrName;
73+
this.options = {};
74+
var key, option, width = 0, height = 0, value, actualValue, attrValues, attrValue, attrName;
7575

7676
/**
77-
* @param option {mode: 'min|max', property: 'width|height', value: '123px'}
77+
* @param {Object} option {mode: 'min|max', property: 'width|height', value: '123px'}
7878
*/
7979
this.addOption = function(option) {
80-
this.options.push(option);
81-
}
80+
var idx = [option.mode, option.property, option.value].join(',');
81+
this.options[idx] = option;
82+
};
8283

8384
var attributes = ['min-width', 'min-height', 'max-width', 'max-height'];
8485

@@ -92,8 +93,12 @@
9293

9394
attrValues = {};
9495

95-
for (i = 0, j = this.options.length; i < j; i++) {
96-
option = this.options[i];
96+
for (key in this.options) {
97+
if (!this.options.hasOwnProperty(key)){
98+
continue;
99+
}
100+
option = this.options[key];
101+
97102
value = convertToPx(this.element, option.value);
98103

99104
actualValue = option.property == 'width' ? width : height;
@@ -218,11 +223,18 @@
218223
for (var i = 0, j = document.styleSheets.length; i < j; i++) {
219224
readRules(document.styleSheets[i].cssText || document.styleSheets[i].cssRules || document.styleSheets[i].rules);
220225
}
221-
}
222-
}
226+
};
227+
228+
this.update = function() {
229+
this.init();
230+
};
231+
};
223232

224233
function init() {
225-
new ElementQueries().init();
234+
ElementQueries.instance = new ElementQueries().init();
235+
ElementQueries.update = function() {
236+
ElementQueries.instance.update();
237+
}
226238
}
227239

228240
if (window.addEventListener) {

src/ResizeSensor.js

Lines changed: 60 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,6 @@
1515
* @constructor
1616
*/
1717
this.ResizeSensor = function(element, callback) {
18-
/**
19-
* Adds a listener to the over/under-flow event.
20-
*
21-
* @param {HTMLElement} element
22-
* @param {Function} callback
23-
*/
24-
function addResizeListener(element, callback) {
25-
if (window.OverflowEvent) {
26-
//webkit
27-
element.addEventListener('overflowchanged', function(e) {
28-
callback.call(this, e);
29-
});
30-
} else {
31-
element.addEventListener('overflow', function(e) {
32-
callback.call(this, e);
33-
});
34-
element.addEventListener('underflow', function(e) {
35-
callback.call(this, e);
36-
});
37-
}
38-
}
39-
4018
/**
4119
*
4220
* @constructor
@@ -84,71 +62,70 @@
8462
return;
8563
}
8664

87-
if ('onresize' in element && 11 > document.documentMode) {
88-
//internet explorer up to 10
89-
if (element.attachEvent) {
90-
element.attachEvent('onresize', function() {
91-
element.resizedAttached.call();
92-
});
93-
} else if (element.addEventListener) {
94-
element.addEventListener('resize', function(){
95-
element.resizedAttached.call();
96-
});
97-
}
98-
} else {
99-
var myResized = function() {
100-
if (setupSensor()) {
101-
element.resizedAttached.call();
102-
}
103-
};
104-
element.resizeSensor = document.createElement('div');
105-
element.resizeSensor.className = 'resize-sensor';
106-
var style =
107-
'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1;';
108-
element.resizeSensor.style.cssText = style;
109-
element.resizeSensor.innerHTML =
110-
'<div class="resize-sensor-overflow" style="' + style + '">' +
111-
'<div></div>' +
112-
'</div>' +
113-
'<div class="resize-sensor-underflow" style="' + style + '">' +
114-
'<div></div>' +
115-
'</div>';
116-
element.appendChild(element.resizeSensor);
117-
118-
if ('absolute' !== getComputedStyle(element, 'position')) {
119-
element.style.position = 'relative';
65+
element.resizeSensor = document.createElement('div');
66+
element.resizeSensor.className = 'resize-sensor';
67+
var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;';
68+
var styleChild = 'position: absolute; left: 0; top: 0;';
69+
70+
element.resizeSensor.style.cssText = style;
71+
element.resizeSensor.innerHTML =
72+
'<div class="resize-sensor-expand" style="' + style + '">' +
73+
'<div style="' + styleChild + '"></div>' +
74+
'</div>' +
75+
'<div class="resize-sensor-shrink" style="' + style + '">' +
76+
'<div style="' + styleChild + ' width: 200%; height: 200%"></div>' +
77+
'</div>';
78+
element.appendChild(element.resizeSensor);
79+
80+
if ('absolute' !== getComputedStyle(element, 'position')) {
81+
element.style.position = 'relative';
82+
}
83+
84+
var expand = element.resizeSensor.childNodes[0];
85+
var expandChild = expand.childNodes[0];
86+
var shrink = element.resizeSensor.childNodes[1];
87+
var shrinkChild = shrink.childNodes[0];
88+
89+
var lastWidth, lastHeight;
90+
91+
var reset = function() {
92+
expandChild.style.width = expand.offsetWidth + 10 + 'px';
93+
expandChild.style.height = expand.offsetHeight + 10 + 'px';
94+
expand.scrollLeft = expand.scrollWidth;
95+
expand.scrollTop = expand.scrollHeight;
96+
shrink.scrollLeft = shrink.scrollWidth;
97+
shrink.scrollTop = shrink.scrollHeight;
98+
lastWidth = element.offsetWidth;
99+
lastHeight = element.offsetHeight;
100+
};
101+
102+
reset();
103+
104+
var changed = function() {
105+
element.resizedAttached.call();
106+
};
107+
108+
var addEvent = function(el, name, cb) {
109+
if (el.attachEvent) {
110+
el.attachEvent('on' + name, cb);
111+
} else {
112+
el.addEventListener(name, cb);
120113
}
114+
};
121115

122-
var x = -1,
123-
y = -1,
124-
firstStyle = element.resizeSensor.firstElementChild.firstChild.style,
125-
lastStyle = element.resizeSensor.lastElementChild.firstChild.style;
126-
127-
function setupSensor() {
128-
var change = false,
129-
width = element.resizeSensor.offsetWidth,
130-
height = element.resizeSensor.offsetHeight;
131-
132-
if (x != width) {
133-
firstStyle.width = (width - 1) + 'px';
134-
lastStyle.width = (width + 1) + 'px';
135-
change = true;
136-
x = width;
137-
}
138-
if (y != height) {
139-
firstStyle.height = (height - 1) + 'px';
140-
lastStyle.height = (height + 1) + 'px';
141-
change = true;
142-
y = height;
143-
}
144-
return change;
116+
addEvent(expand, 'scroll', function() {
117+
if (element.offsetWidth > lastWidth || element.offsetHeight > lastHeight) {
118+
changed();
145119
}
120+
reset();
121+
});
146122

147-
setupSensor();
148-
addResizeListener(element.resizeSensor, myResized);
149-
addResizeListener(element.resizeSensor.firstElementChild, myResized);
150-
addResizeListener(element.resizeSensor.lastElementChild, myResized);
151-
}
123+
addEvent(shrink, 'scroll',function() {
124+
if (element.offsetWidth < lastWidth || element.offsetHeight < lastHeight) {
125+
changed();
126+
}
127+
reset();
128+
});
152129
}
153130

154131
if ('array' === typeof element

0 commit comments

Comments
 (0)