forked from ibm-js/delite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Viewport.js
129 lines (116 loc) · 4.53 KB
/
Viewport.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* Utility singleton to watch for viewport resizes, avoiding duplicate notifications
* which can lead to infinite loops.
*
* Usage:
* ```
* Viewport.on("resize", myCallback)
* Viewport.on("scroll", myOtherCallback)
* ```
*
* myCallback() is called without arguments in case it's Widget.resize(),
* which would interpret the argument as the size to make the widget.
*
* @module delite/Viewport
*/
define([
"decor/Evented",
"decor/sniff", // has("ios")
"requirejs-domready/domReady!"
], function (Evented, has) {
var Viewport = new Evented();
// Get the size of the viewport without size adjustment needed for iOS soft keyboard.
// On android though, this returns the size of the visible area not including the keyboard.
function getBox() {
return {
w: window.innerWidth,
h: window.innerHeight,
t: window.pageYOffset,
l: window.pageXOffset
};
}
/**
* Get the size of the viewport, or on mobile devices, the part of the viewport not obscured by the
* virtual keyboard.
* @function module:delite/Viewport.getEffectiveBox
*/
Viewport.getEffectiveBox = function () {
/* jshint maxcomplexity:11 */
var box = getBox();
// Account for iOS virtual keyboard, if it's being shown. Unfortunately no direct way to check or measure.
var focusedNode = document.activeElement,
tag = focusedNode && focusedNode.tagName && focusedNode.tagName.toLowerCase();
if (has("ios") && focusedNode && !focusedNode.readOnly && (tag === "textarea" || (tag === "input" &&
/^(color|email|number|password|search|tel|text|url)$/.test(focusedNode.type)))) {
var portrait = (window.orientation === 0 || window.orientation === 180);
// "box" represents the size of the viewport. Some of the viewport is likely covered by the virtual
// keyboard, but we don't know how much, so window.innerHeight doesn't help us. Instead,
// estimate effective viewport size based on screen.height (in portrait mode) or screen.width
// (in landscape mode).
// Measurements of various iOS devices and how much of the screen size is available between
// the address bar and the virtual keyboard, including the row for auto-suggest.
// Note that iPhone hides the address bar in landscape mode.
//
// iPhone5, 5s, 5c, SE:
// * landscape screen.width = 320, available height = 115/640 = 17.9%
// * portrait screen.height = 568, available height = 405/1136 = 35.6%
// iPhone 6, 7, 8:
// * landscape screen.width = 375, available height = 263/750 = 35%
// * portrait screen.height = 667, available height = 596/1325 = 44.9%
// iPhone 6+, 6s+, 7+, 8+
// * landscape screen.width = 414, available height = 507/1242 = 40%
// * portrait screen.height = 736, available height = 1060/2208 = 48%
// iPhone X:
// * landscape screen.width = 375, available height = 364/1122 = 32.4%
// * portrait screen.height = 812, available height = 1033/2436 = 42.4%
// iPad mini, iPad Air, iPad Pro 9.7”
// * landscape screen.width = 768, available height = 603 / 1535 = 39.2%
// * portrait screen.height = 1024, available height = 1284 / 2047 = 62.7%
// iPad Pro 12.9”, first and second gen
// * landscape screen.width = 1024, available height = 970 / 2044 = 47.4%
// * portrait screen.height = 1366, available height = 1846 / 2729 = 67.6%
var multiplier;
if (portrait) {
multiplier = screen.height >= 1366 ? 0.67 : screen.height >= 1024 ? 0.62 :
screen.height >= 667 ? 0.42 : 0.35;
box.h = screen.height * multiplier;
} else {
multiplier = screen.width >= 1024 ? 0.47 : screen.width >= 414 ? 0.39 :
screen.width >= 375 ? 0.32 : 0.18;
box.h = screen.width * multiplier;
}
}
return box;
};
var oldEffectiveSize = Viewport.getEffectiveBox(),
oldEffectiveScroll = oldEffectiveSize;
function checkForResize() {
var newBox = Viewport.getEffectiveBox();
if (newBox.h !== oldEffectiveSize.h || newBox.w !== oldEffectiveSize.w) {
oldEffectiveSize = newBox;
Viewport.emit("resize", newBox);
return true;
} else {
return false;
}
}
function checkForScroll() {
var newBox = Viewport.getEffectiveBox();
if (newBox.t !== oldEffectiveScroll.t || newBox.l !== oldEffectiveScroll.l) {
oldEffectiveScroll = newBox;
Viewport.emit("scroll", newBox);
return true;
} else {
return false;
}
}
// Poll for viewport resizes due to rotation, browser window size change, or the virtual keyboard
// popping up/down.
function poll() {
var resized = checkForResize(),
scrolled = checkForScroll();
setTimeout(poll, resized || scrolled ? 10 : 50);
}
poll();
return Viewport;
});