Skip to content

Commit ab04aed

Browse files
author
marcj
committed
Fixes marcj#2. Extracted the resize sensor stuff to own class.
1 parent 2cd5bbc commit ab04aed

File tree

3 files changed

+193
-155
lines changed

3 files changed

+193
-155
lines changed

demo.html renamed to index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ <h2>Widget #1</h2>
7070
<img src="demo/image-400px.jpg" />
7171
</div>
7272

73+
<script src="src/ResizeSensor.js"></script>
7374
<script src="src/ElementQueries.js"></script>
7475
</body>
7576
</html>

src/ElementQueries.js

Lines changed: 34 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,11 @@
1-
;(function(){
1+
;
2+
(function() {
23
/**
34
*
45
* @type {Function}
56
* @constructor
67
*/
7-
var ElementQueries = this.ElementQueries = function(){
8-
/**
9-
* Adds a listener to the over/under-flow event.
10-
*
11-
* @param {HTMLElement} element
12-
* @param {Function} callback
13-
*/
14-
function addResizeListener(element, callback) {
15-
if (window.OverflowEvent){
16-
//webkit
17-
element.addEventListener('overflowchanged', function (e) {
18-
callback.call(this, e);
19-
});
20-
} else {
21-
element.addEventListener('overflow', function (e) {
22-
callback.call(this, e);
23-
});
24-
element.addEventListener('underflow', function (e) {
25-
callback.call(this, e);
26-
});
27-
}
28-
}
29-
30-
/**
31-
*
32-
* @constructor
33-
*/
34-
function EventQueue(){
35-
this.q = [];
36-
this.add = function(ev) {
37-
this.q.push(ev);
38-
};
39-
40-
var i, j;
41-
this.call = function() {
42-
for (i=0, j=this.q.length; i < j; i++) {
43-
this.q[i].call();
44-
}
45-
};
46-
}
47-
48-
/**
49-
* @param {HTMLElement} element
50-
* @param {String} prop
51-
* @returns {String|Integer}
52-
*/
53-
function getComputedStyle(element, prop) {
54-
if (element.currentStyle) {
55-
return element.currentStyle(prop);
56-
} else if (window.getComputedStyle) {
57-
return window.getComputedStyle(element, null).getPropertyValue(prop);
58-
} else {
59-
return element.style[prop];
60-
}
61-
62-
}
63-
/**
64-
*
65-
* @param {HTMLElement} element
66-
* @param {Function} resized
67-
*/
68-
function attachResizeEvent(element, resized) {
69-
if (!element.resizedAttached) {
70-
element.resizedAttached = new EventQueue();
71-
element.resizedAttached.add(resized);
72-
} else if (element.resizedAttached) {
73-
element.resizedAttached.add(resized);
74-
return;
75-
}
76-
77-
if (element.onresize) {
78-
//internet explorer
79-
if (element.attachEvent) {
80-
element.attachEvent('onresize', element.resizedAttached.call);
81-
} else if (element.addEventListener) {
82-
element.addEventListener('resize', element.resizedAttached.call);
83-
}
84-
} else {
85-
var myResized = function(){
86-
if (setupSensor()) {
87-
element.resizedAttached.call();
88-
}
89-
}
90-
element.resizeSensor = document.createElement('div');
91-
element.resizeSensor.className = 'resize-sensor';
92-
var style =
93-
'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1;';
94-
element.resizeSensor.style.cssText = style;
95-
element.resizeSensor.innerHTML =
96-
'<div class="resize-sensor-overflow" style="'+style+'">' +
97-
'<div></div>' +
98-
'</div>' +
99-
'<div class="resize-sensor-underflow" style="'+style+'">' +
100-
'<div></div>' +
101-
'</div>';
102-
element.appendChild(element.resizeSensor);
103-
104-
if ('absolute' !== getComputedStyle(element, 'position')) {
105-
element.style.position = 'relative';
106-
}
107-
108-
var x = 0,
109-
y = 0,
110-
firstStyle = element.resizeSensor.firstElementChild.firstChild.style,
111-
lastStyle = element.resizeSensor.lastElementChild.firstChild.style;
112-
113-
function setupSensor() {
114-
var change = false,
115-
width = element.resizeSensor.offsetWidth,
116-
height = element.resizeSensor.offsetHeight;
117-
118-
if (x != width) {
119-
firstStyle.width = width - 1 + 'px';
120-
lastStyle.width = width + 1 + 'px';
121-
change = true;
122-
x = width;
123-
}
124-
if (y != height) {
125-
firstStyle.height = height - 1 + 'px';
126-
lastStyle.height = height + 1 + 'px';
127-
change = true;
128-
y = height;
129-
}
130-
return change;
131-
}
132-
setupSensor();
133-
addResizeListener(element.resizeSensor, myResized);
134-
addResizeListener(element.resizeSensor.firstElementChild, myResized);
135-
addResizeListener(element.resizeSensor.lastElementChild, myResized);
136-
}
137-
}
138-
8+
var ElementQueries = this.ElementQueries = function() {
1399
/**
14010
*
14111
* @param element
@@ -162,21 +32,27 @@
16232
var units = value.replace(/[0-9]*/, '');
16333
value = parseFloat(value);
16434
switch (units) {
165-
case "px": return value;
166-
case "em": return value * getEmSize(element);
167-
case "rem": return value * getEmSize();
35+
case "px":
36+
return value;
37+
case "em":
38+
return value * getEmSize(element);
39+
case "rem":
40+
return value * getEmSize();
16841
// Viewport units!
16942
// According to http://quirksmode.org/mobile/tableViewport.html
17043
// documentElement.clientWidth/Height gets us the most reliable info
171-
case "vw": return value * document.documentElement.clientWidth / 100;
172-
case "vh": return value * document.documentElement.clientHeight / 100;
44+
case "vw":
45+
return value * document.documentElement.clientWidth / 100;
46+
case "vh":
47+
return value * document.documentElement.clientHeight / 100;
17348
case "vmin":
17449
case "vmax":
17550
var vw = document.documentElement.clientWidth / 100;
17651
var vh = document.documentElement.clientHeight / 100;
17752
var chooser = Math[units === "vmin" ? "min" : "max"];
17853
return value * chooser(vw, vh);
179-
default: return value;
54+
default:
55+
return value;
18056
// for now, not supporting physical units (since they are just a set number of px)
18157
// or ex/ch (getting accurate measurements is hard)
18258
}
@@ -187,7 +63,7 @@
18763
* @param {HTMLElement} element
18864
* @constructor
18965
*/
190-
function SetupInformation(element){
66+
function SetupInformation(element) {
19167
this.element = element;
19268
this.options = [];
19369
var i, j, option, width = 0, height = 0, value, actualValue, attrValues, attrValue, attrName;
@@ -206,18 +82,18 @@
20682
*/
20783
this.call = function() {
20884
// extract current dimensions
209-
width = this.element.offsetWidth;
85+
width = this.element.offsetWidth;
21086
height = this.element.offsetHeight;
21187

21288
attrValues = {};
21389

214-
for (i=0, j=this.options.length; i < j; i++) {
90+
for (i = 0, j = this.options.length; i < j; i++) {
21591
option = this.options[i];
216-
value = convertToPx(this.element, option.value);
92+
value = convertToPx(this.element, option.value);
21793

21894
actualValue = option.property == 'width' ? width : height;
219-
attrName = option.mode + '-' + option.property;
220-
attrValue = '';
95+
attrName = option.mode + '-' + option.property;
96+
attrValue = '';
22197

22298
if (option.mode == 'min' && actualValue >= value) {
22399
attrValue += ' ' + option.value;
@@ -251,7 +127,7 @@
251127
} else {
252128
element.elementQueriesSetupInformation = new SetupInformation(element);
253129
element.elementQueriesSetupInformation.addOption(options);
254-
attachResizeEvent(element, function(){
130+
new ResizeSensor(element, function() {
255131
element.elementQueriesSetupInformation.call();
256132
});
257133
}
@@ -276,6 +152,7 @@
276152
}
277153

278154
var regex = /,*([^,]*)\[[\s\t]*(min|max)-(width|height)[\s\t]*[~$\^]?=[\s\t]*"([^"]*)"[\s\t]*]/;
155+
279156
/**
280157
* @param {CssRule} rule
281158
*/
@@ -292,32 +169,34 @@
292169
function readRules(rules) {
293170
var selector = '';
294171
for (var i = 0, j = rules.length; i < j; i++) {
295-
selector = rules[i].selectorText;
296-
if (-1 !== selector.indexOf('min-width') || -1 !== selector.indexOf('max-width')) {
297-
extractQuery(rules[i]);
298-
//todo, ie7-8 includes @imports in a rule, so extract it
172+
if (1 === rules[i].type) {
173+
selector = rules[i].selectorText;
174+
if (-1 !== selector.indexOf('min-width') || -1 !== selector.indexOf('max-width')) {
175+
extractQuery(rules[i]);
176+
//todo, ie7-8 includes @imports in a rule, so extract it
177+
}
299178
}
300179
}
301180
}
302181

303182
/**
304183
* Searches all css rules and setups the event listener to all elements with element query rules..
305184
*/
306-
this.init = function(){
185+
this.init = function() {
307186
for (var i = 0, j = document.styleSheets.length; i < j; i++) {
308187
readRules(document.styleSheets[i].cssRules || document.styleSheets[i].rules);
309188
}
310189
}
311190
}
312191

313-
function init(){
192+
function init() {
314193
new ElementQueries().init();
315194
}
316195

317-
if (window.addEventListener){
318-
window.addEventListener('load',init,false);
196+
if (window.addEventListener) {
197+
window.addEventListener('load', init, false);
319198
} else {
320-
window.attachEvent('onload',init);
199+
window.attachEvent('onload', init);
321200
}
322201

323202
})();

0 commit comments

Comments
 (0)