opal-browser 0.1.0.beta1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/build.yml +95 -0
  3. data/.gitignore +3 -0
  4. data/.yardopts +1 -1
  5. data/Gemfile +22 -3
  6. data/LICENSE +20 -0
  7. data/README.md +200 -20
  8. data/Rakefile +29 -1
  9. data/config.ru +20 -2
  10. data/docs/polyfills.md +24 -0
  11. data/examples/2048/Gemfile +6 -0
  12. data/examples/2048/README.md +13 -0
  13. data/examples/2048/app/application.rb +169 -0
  14. data/examples/2048/config.ru +9 -0
  15. data/examples/canvas/Gemfile +6 -0
  16. data/examples/canvas/README.md +9 -0
  17. data/examples/canvas/app/application.rb +55 -0
  18. data/examples/canvas/config.ru +9 -0
  19. data/examples/component/Gemfile +6 -0
  20. data/examples/component/README.md +10 -0
  21. data/examples/component/app/application.rb +66 -0
  22. data/examples/component/config.ru +9 -0
  23. data/examples/integrations/README.md +24 -0
  24. data/examples/integrations/dynamic-rack-opal-sprockets-server/Gemfile +6 -0
  25. data/examples/integrations/dynamic-rack-opal-sprockets-server/README.md +16 -0
  26. data/examples/integrations/dynamic-rack-opal-sprockets-server/app/application.rb +6 -0
  27. data/examples/integrations/dynamic-rack-opal-sprockets-server/config.ru +9 -0
  28. data/examples/integrations/dynamic-roda-roda-sprockets/.gitignore +1 -0
  29. data/examples/integrations/dynamic-roda-roda-sprockets/Gemfile +7 -0
  30. data/examples/integrations/dynamic-roda-roda-sprockets/README.md +22 -0
  31. data/examples/integrations/dynamic-roda-roda-sprockets/Rakefile +4 -0
  32. data/examples/integrations/dynamic-roda-roda-sprockets/app/application.rb +6 -0
  33. data/examples/integrations/dynamic-roda-roda-sprockets/app.rb +32 -0
  34. data/examples/integrations/dynamic-roda-roda-sprockets/config.ru +3 -0
  35. data/examples/integrations/dynamic-roda-tilt/.gitignore +1 -0
  36. data/examples/integrations/dynamic-roda-tilt/Gemfile +8 -0
  37. data/examples/integrations/dynamic-roda-tilt/README.md +17 -0
  38. data/examples/integrations/dynamic-roda-tilt/Rakefile +6 -0
  39. data/examples/integrations/dynamic-roda-tilt/app/application.rb +6 -0
  40. data/examples/integrations/dynamic-roda-tilt/app.rb +50 -0
  41. data/examples/integrations/dynamic-roda-tilt/config.ru +3 -0
  42. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/Gemfile +7 -0
  43. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/README.md +16 -0
  44. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/app/application.rb +6 -0
  45. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/config.ru +29 -0
  46. data/examples/integrations/static-bash/.gitignore +2 -0
  47. data/examples/integrations/static-bash/Gemfile +3 -0
  48. data/examples/integrations/static-bash/README.md +8 -0
  49. data/examples/integrations/static-bash/app/application.rb +6 -0
  50. data/examples/integrations/static-bash/build.sh +4 -0
  51. data/examples/integrations/static-bash/index.html +10 -0
  52. data/examples/integrations/static-bash-opal-parser/.gitignore +3 -0
  53. data/examples/integrations/static-bash-opal-parser/Gemfile +3 -0
  54. data/examples/integrations/static-bash-opal-parser/README.md +10 -0
  55. data/examples/integrations/static-bash-opal-parser/build.sh +4 -0
  56. data/examples/integrations/static-bash-opal-parser/index.html +19 -0
  57. data/examples/integrations/static-rake/.gitignore +1 -0
  58. data/examples/integrations/static-rake/Gemfile +4 -0
  59. data/examples/integrations/static-rake/README.md +7 -0
  60. data/examples/integrations/static-rake/Rakefile +10 -0
  61. data/examples/integrations/static-rake/app/application.rb +6 -0
  62. data/examples/integrations/static-rake/index.html +9 -0
  63. data/examples/integrations/static-rake-guard/.gitignore +1 -0
  64. data/examples/integrations/static-rake-guard/Gemfile +6 -0
  65. data/examples/integrations/static-rake-guard/Guardfile +3 -0
  66. data/examples/integrations/static-rake-guard/README.md +10 -0
  67. data/examples/integrations/static-rake-guard/Rakefile +10 -0
  68. data/examples/integrations/static-rake-guard/app/application.rb +6 -0
  69. data/examples/integrations/static-rake-guard/index.html +9 -0
  70. data/examples/svg/.gitignore +1 -0
  71. data/examples/svg/Gemfile +4 -0
  72. data/examples/svg/README.md +7 -0
  73. data/examples/svg/Rakefile +10 -0
  74. data/examples/svg/app/application.rb +11 -0
  75. data/examples/svg/index.html +17 -0
  76. data/examples/svg/index.svg +6 -0
  77. data/index.html.erb +24 -0
  78. data/lib/opal-browser.rb +1 -0
  79. data/opal/browser/animation_frame.rb +92 -10
  80. data/opal/browser/audio/node.rb +121 -0
  81. data/opal/browser/audio/param_schedule.rb +43 -0
  82. data/opal/browser/audio.rb +66 -0
  83. data/opal/browser/blob.rb +94 -0
  84. data/opal/browser/canvas/data.rb +2 -12
  85. data/opal/browser/canvas/gradient.rb +1 -11
  86. data/opal/browser/canvas/style.rb +3 -11
  87. data/opal/browser/canvas/text.rb +1 -11
  88. data/opal/browser/canvas.rb +86 -28
  89. data/opal/browser/console.rb +6 -38
  90. data/opal/browser/cookies.rb +90 -27
  91. data/opal/browser/crypto.rb +79 -0
  92. data/opal/browser/css/declaration.rb +1 -6
  93. data/opal/browser/css/rule.rb +1 -1
  94. data/opal/browser/css/style_sheet.rb +2 -2
  95. data/opal/browser/css.rb +23 -7
  96. data/opal/browser/database/sql.rb +193 -0
  97. data/opal/browser/delay.rb +94 -0
  98. data/opal/browser/dom/attribute.rb +16 -9
  99. data/opal/browser/dom/builder.rb +35 -25
  100. data/opal/browser/dom/character_data.rb +43 -7
  101. data/opal/browser/dom/document.rb +171 -37
  102. data/opal/browser/dom/document_fragment.rb +18 -0
  103. data/opal/browser/dom/document_or_shadow_root.rb +19 -0
  104. data/opal/browser/dom/element/attributes.rb +111 -0
  105. data/opal/browser/dom/element/button.rb +31 -0
  106. data/opal/browser/dom/element/custom.rb +177 -0
  107. data/opal/browser/dom/element/data.rb +82 -0
  108. data/opal/browser/dom/element/editable.rb +47 -0
  109. data/opal/browser/dom/element/form.rb +38 -0
  110. data/opal/browser/dom/element/iframe.rb +37 -0
  111. data/opal/browser/dom/element/image.rb +25 -0
  112. data/opal/browser/dom/element/input.rb +48 -1
  113. data/opal/browser/dom/element/media.rb +17 -0
  114. data/opal/browser/dom/element/offset.rb +32 -10
  115. data/opal/browser/dom/element/position.rb +11 -2
  116. data/opal/browser/dom/element/scroll.rb +139 -20
  117. data/opal/browser/dom/element/select.rb +42 -0
  118. data/opal/browser/dom/element/size.rb +46 -0
  119. data/opal/browser/dom/element/template.rb +11 -0
  120. data/opal/browser/dom/element/textarea.rb +26 -0
  121. data/opal/browser/dom/element.rb +496 -168
  122. data/opal/browser/dom/mutation_observer.rb +69 -9
  123. data/opal/browser/dom/node.rb +270 -83
  124. data/opal/browser/dom/node_set.rb +74 -41
  125. data/opal/browser/dom/shadow_root.rb +12 -0
  126. data/opal/browser/dom/text.rb +18 -3
  127. data/opal/browser/dom.rb +40 -18
  128. data/opal/browser/effects.rb +180 -3
  129. data/opal/browser/event/all.rb +26 -0
  130. data/opal/browser/event/animation.rb +40 -0
  131. data/opal/browser/{dom/event → event}/audio_processing.rb +10 -6
  132. data/opal/browser/event/base.rb +461 -0
  133. data/opal/browser/event/before_unload.rb +17 -0
  134. data/opal/browser/event/clipboard.rb +37 -0
  135. data/opal/browser/event/close.rb +49 -0
  136. data/opal/browser/event/composition.rb +52 -0
  137. data/opal/browser/event/custom.rb +65 -0
  138. data/opal/browser/event/data_transfer.rb +95 -0
  139. data/opal/browser/event/device_light.rb +25 -0
  140. data/opal/browser/{dom/event → event}/device_motion.rb +21 -6
  141. data/opal/browser/event/device_orientation.rb +50 -0
  142. data/opal/browser/{dom/event → event}/device_proximity.rb +10 -6
  143. data/opal/browser/event/drag.rb +123 -0
  144. data/opal/browser/event/focus.rb +41 -0
  145. data/opal/browser/event/gamepad.rb +62 -0
  146. data/opal/browser/{dom/event → event}/hash_change.rb +10 -6
  147. data/opal/browser/event/keyboard.rb +128 -0
  148. data/opal/browser/event/message.rb +72 -0
  149. data/opal/browser/{dom/event → event}/mouse.rb +37 -32
  150. data/opal/browser/event/page_transition.rb +25 -0
  151. data/opal/browser/event/pop_state.rb +35 -0
  152. data/opal/browser/event/progress.rb +45 -0
  153. data/opal/browser/event/sensor.rb +17 -0
  154. data/opal/browser/{dom/event → event}/storage.rb +10 -6
  155. data/opal/browser/{dom/event → event}/touch.rb +14 -21
  156. data/opal/browser/event/ui.rb +38 -0
  157. data/opal/browser/{dom/event → event}/wheel.rb +6 -4
  158. data/opal/browser/event.rb +163 -0
  159. data/opal/browser/event_source.rb +7 -4
  160. data/opal/browser/form_data.rb +225 -0
  161. data/opal/browser/history.rb +53 -21
  162. data/opal/browser/http/binary.rb +1 -0
  163. data/opal/browser/http/headers.rb +21 -2
  164. data/opal/browser/http/request.rb +83 -55
  165. data/opal/browser/http/response.rb +5 -1
  166. data/opal/browser/http.rb +47 -9
  167. data/opal/browser/immediate.rb +128 -10
  168. data/opal/browser/interval.rb +41 -23
  169. data/opal/browser/location.rb +20 -4
  170. data/opal/browser/navigator.rb +136 -13
  171. data/opal/browser/polyfill/visual_viewport.rb +216 -0
  172. data/opal/browser/screen.rb +34 -8
  173. data/opal/browser/setup/base.rb +6 -0
  174. data/opal/browser/setup/full.rb +13 -0
  175. data/opal/browser/setup/large.rb +17 -0
  176. data/opal/browser/setup/mini.rb +8 -0
  177. data/opal/browser/setup/traditional.rb +10 -0
  178. data/opal/browser/socket.rb +16 -8
  179. data/opal/browser/storage.rb +155 -52
  180. data/opal/browser/support.rb +299 -0
  181. data/opal/browser/utils.rb +116 -18
  182. data/opal/browser/version.rb +1 -1
  183. data/opal/browser/visual_viewport.rb +39 -0
  184. data/opal/browser/window/size.rb +47 -9
  185. data/opal/browser/window/view.rb +37 -4
  186. data/opal/browser/window.rb +46 -26
  187. data/opal/browser.rb +1 -10
  188. data/opal/opal-browser.rb +1 -0
  189. data/opal-browser.gemspec +10 -12
  190. data/spec/database/sql_spec.rb +139 -0
  191. data/spec/delay_spec.rb +41 -0
  192. data/spec/dom/attribute_spec.rb +49 -0
  193. data/spec/dom/builder_spec.rb +36 -19
  194. data/spec/dom/document_spec.rb +28 -6
  195. data/spec/dom/element/attributes_spec.rb +52 -0
  196. data/spec/dom/element/custom_spec.rb +106 -0
  197. data/spec/dom/element/subclass_spec.rb +144 -0
  198. data/spec/dom/element_spec.rb +184 -7
  199. data/spec/dom/mutation_observer_spec.rb +13 -9
  200. data/spec/dom/node_set_spec.rb +44 -0
  201. data/spec/dom/node_spec.rb +87 -27
  202. data/spec/dom_spec.rb +19 -9
  203. data/spec/event_source_spec.rb +18 -15
  204. data/spec/{dom/event_spec.rb → event_spec.rb} +55 -26
  205. data/spec/history_spec.rb +32 -19
  206. data/spec/http_spec.rb +25 -36
  207. data/spec/immediate_spec.rb +10 -7
  208. data/spec/interval_spec.rb +59 -0
  209. data/spec/native_cached_wrapper_spec.rb +46 -0
  210. data/spec/runner.rb +107 -0
  211. data/spec/socket_spec.rb +18 -14
  212. data/spec/spec_helper.rb +2 -4
  213. data/spec/spec_helper_promise.rb.erb +25 -0
  214. data/spec/storage_spec.rb +7 -7
  215. data/spec/wgxpath.install.js +49 -0
  216. data/spec/window_spec.rb +2 -2
  217. metadata +181 -93
  218. data/opal/browser/compatibility/animation_frame.rb +0 -93
  219. data/opal/browser/compatibility/dom/document/window.rb +0 -15
  220. data/opal/browser/compatibility/dom/element/css.rb +0 -15
  221. data/opal/browser/compatibility/dom/element/matches.rb +0 -31
  222. data/opal/browser/compatibility/dom/element/offset.rb +0 -20
  223. data/opal/browser/compatibility/dom/element/scroll.rb +0 -25
  224. data/opal/browser/compatibility/dom/element/style.rb +0 -15
  225. data/opal/browser/compatibility/dom/mutation_observer.rb +0 -47
  226. data/opal/browser/compatibility/http/request.rb +0 -15
  227. data/opal/browser/compatibility/immediate.rb +0 -107
  228. data/opal/browser/compatibility/window/scroll.rb +0 -27
  229. data/opal/browser/compatibility/window/size.rb +0 -13
  230. data/opal/browser/compatibility/window/view.rb +0 -13
  231. data/opal/browser/compatibility.rb +0 -59
  232. data/opal/browser/dom/compatibility.rb +0 -8
  233. data/opal/browser/dom/event/animation.rb +0 -26
  234. data/opal/browser/dom/event/base.rb +0 -207
  235. data/opal/browser/dom/event/before_unload.rb +0 -13
  236. data/opal/browser/dom/event/clipboard.rb +0 -26
  237. data/opal/browser/dom/event/close.rb +0 -35
  238. data/opal/browser/dom/event/composition.rb +0 -38
  239. data/opal/browser/dom/event/custom.rb +0 -30
  240. data/opal/browser/dom/event/device_light.rb +0 -21
  241. data/opal/browser/dom/event/device_orientation.rb +0 -36
  242. data/opal/browser/dom/event/drag.rb +0 -113
  243. data/opal/browser/dom/event/focus.rb +0 -23
  244. data/opal/browser/dom/event/gamepad.rb +0 -47
  245. data/opal/browser/dom/event/keyboard.rb +0 -93
  246. data/opal/browser/dom/event/message.rb +0 -50
  247. data/opal/browser/dom/event/page_transition.rb +0 -21
  248. data/opal/browser/dom/event/pop_state.rb +0 -21
  249. data/opal/browser/dom/event/progress.rb +0 -31
  250. data/opal/browser/dom/event/sensor.rb +0 -13
  251. data/opal/browser/dom/event/ui.rb +0 -22
  252. data/opal/browser/dom/event.rb +0 -240
  253. data/opal/browser/http/compatibility.rb +0 -1
  254. data/opal/browser/http/parameters.rb +0 -8
  255. data/opal/browser/timeout.rb +0 -60
  256. data/opal/browser/window/compatibility.rb +0 -3
  257. data/opal/browser/window/scroll.rb +0 -49
@@ -0,0 +1,216 @@
1
+ # VisualViewport polyfill (mainly for Firefox browsers) taken from:
2
+ # https://github.com/WICG/visual-viewport/blob/gh-pages/polyfill/visualViewport.js
3
+ # Licensed under "W3C 3-clause BSD License".
4
+
5
+ # Let's make sure the functions aren't poluting the global context:
6
+ %x{
7
+ (function(){ "use strict";
8
+
9
+ // This is hacky but necessary in order to get the innerWidth/Height without
10
+ // page scale applied reliably.
11
+ function updateUnscaledDimensions() {
12
+ if (!window.viewPolyfill.iframeDummy) {
13
+ var iframe = document.createElement('iframe');
14
+ iframe.style.position="absolute";
15
+ iframe.style.width="100%";
16
+ iframe.style.height="100%";
17
+ iframe.style.left="0px";
18
+ iframe.style.top="0px";
19
+ iframe.style.border="0";
20
+ iframe.style.visibility="hidden";
21
+ iframe.style.zIndex="-1";
22
+ iframe.srcdoc = "<!DOCTYPE html><html><body style='margin:0px; padding:0px'></body></html>";
23
+
24
+ document.body.appendChild(iframe);
25
+ window.viewPolyfill.iframeDummy = iframe;
26
+ }
27
+
28
+ var iframe = window.viewPolyfill.iframeDummy;
29
+
30
+ var documentRect = document.documentElement.getBoundingClientRect();
31
+ var iframeBody = iframe.contentDocument.body;
32
+ iframeBody.style.width = documentRect.width + 'px';
33
+ iframeBody.style.height = documentRect.height + 'px';
34
+
35
+ // Hide overflow temporarily so that the iframe size isn't shrunk by
36
+ // scrollbars.
37
+ var prevDocumentOverflow = document.documentElement.style.overflow;
38
+ document.documentElement.style.overflow = "hidden";
39
+
40
+ var iframeWindow = window.viewPolyfill.iframeDummy.contentWindow;
41
+ window.viewPolyfill.unscaledInnerWidth = iframeWindow.innerWidth;
42
+ window.viewPolyfill.unscaledInnerHeight = iframeWindow.innerHeight;
43
+
44
+ document.documentElement.style.overflow = prevDocumentOverflow;
45
+ }
46
+
47
+ function fireScrollEvent() {
48
+ var listeners = window.viewPolyfill.scrollEventListeners;
49
+ for (var i = 0; i < listeners.length; i++)
50
+ listeners[i]();
51
+ }
52
+
53
+ function fireResizeEvent() {
54
+ var listeners = window.viewPolyfill.resizeEventListeners;
55
+ for (var i = 0; i < listeners.length; i++)
56
+ listeners[i]();
57
+ }
58
+
59
+ function updateViewportChanged() {
60
+ var scrollChanged =
61
+ window.viewPolyfill.offsetLeftSinceLastChange != window.visualViewport.offsetLeft ||
62
+ window.viewPolyfill.offsetTopSinceLastChange != window.visualViewport.offsetTop;
63
+
64
+ var sizeChanged =
65
+ window.viewPolyfill.widthSinceLastChange != window.visualViewport.width ||
66
+ window.viewPolyfill.heightSinceLastChange != window.visualViewport.height ||
67
+ window.viewPolyfill.scaleSinceLastChange != window.visualViewport.scale;
68
+
69
+ window.viewPolyfill.offsetLeftSinceLastChange = window.visualViewport.offsetLeft;
70
+ window.viewPolyfill.offsetTopSinceLastChange = window.visualViewport.offsetTop;
71
+ window.viewPolyfill.widthSinceLastChange = window.visualViewport.width;
72
+ window.viewPolyfill.heightSinceLastChange = window.visualViewport.height;
73
+ window.viewPolyfill.scaleSinceLastChange = window.visualViewport.scale;
74
+
75
+ if (scrollChanged)
76
+ fireScrollEvent();
77
+
78
+ if (sizeChanged)
79
+ fireResizeEvent();
80
+
81
+ setTimeout(updateViewportChanged, 500);
82
+ }
83
+
84
+ function registerChangeHandlers() {
85
+ window.addEventListener('scroll', updateViewportChanged, {'passive': true});
86
+ window.addEventListener('resize', updateViewportChanged, {'passive': true});
87
+ window.addEventListener('resize', updateUnscaledDimensions, {'passive': true});
88
+ }
89
+
90
+ var isChrome = navigator.userAgent.indexOf('Chrome') > -1;
91
+ var isSafari = navigator.userAgent.indexOf("Safari") > -1;
92
+ var isIEEdge = navigator.userAgent.indexOf('Edge') > -1;
93
+
94
+ if ((isChrome)&&(isSafari))
95
+ isSafari=false;
96
+
97
+ if (window.visualViewport) {
98
+ console.log('Using real visual viewport API');
99
+ } else {
100
+ console.log('Polyfilling Viewport API');
101
+ var layoutDummy = document.createElement('div');
102
+ layoutDummy.style.width = "100%";
103
+ layoutDummy.style.height = "100%";
104
+ if (isSafari) {
105
+ layoutDummy.style.position = "fixed";
106
+ } else {
107
+ layoutDummy.style.position = "absolute";
108
+ }
109
+ layoutDummy.style.left = "0px";
110
+ layoutDummy.style.top = "0px";
111
+ layoutDummy.style.visibility = "hidden";
112
+
113
+ window.viewPolyfill = {
114
+ "offsetLeftSinceLastChange": null,
115
+ "offsetTopSinceLastChange": null,
116
+ "widthSinceLastChange": null,
117
+ "heightSinceLastChange": null,
118
+ "scaleSinceLastChange": null,
119
+ "scrollEventListeners": [],
120
+ "resizeEventListeners": [],
121
+ "layoutDummy": layoutDummy,
122
+ "iframeDummy": null,
123
+ "unscaledInnerWidth": 0,
124
+ "unscaledInnerHeight": 0
125
+ }
126
+
127
+ registerChangeHandlers();
128
+
129
+ // TODO: Need to wait for <body> to be loaded but this is probably
130
+ // later than needed.
131
+ window.addEventListener('load', function() {
132
+ updateUnscaledDimensions();
133
+ document.body.appendChild(layoutDummy);
134
+
135
+ var viewport = {
136
+ get offsetLeft() {
137
+ if (isSafari) {
138
+ // Note: Safari's getBoundingClientRect left/top is wrong when pinch-zoomed requiring this "unscaling".
139
+ return window.scrollX - (layoutDummy.getBoundingClientRect().left * this.scale + window.scrollX * this.scale);
140
+ } else {
141
+ return window.scrollX + layoutDummy.getBoundingClientRect().left;
142
+ }
143
+ },
144
+ get offsetTop() {
145
+ if (isSafari) {
146
+ // Note: Safari's getBoundingClientRect left/top is wrong when pinch-zoomed requiring this "unscaling".
147
+ return window.scrollY - (layoutDummy.getBoundingClientRect().top * this.scale + window.scrollY * this.scale);
148
+ } else {
149
+ return window.scrollY + layoutDummy.getBoundingClientRect().top;
150
+ }
151
+ },
152
+ get width() {
153
+ var clientWidth = document.documentElement.clientWidth;
154
+ if (isIEEdge) {
155
+ // If there's no scrollbar before pinch-zooming, Edge will add
156
+ // a non-layout-affecting overlay scrollbar. This won't be
157
+ // reflected in documentElement.clientWidth so we need to
158
+ // manually subtract it out.
159
+ if (document.documentElement.clientWidth == window.viewPolyfill.unscaledInnerWidth
160
+ && this.scale > 1) {
161
+ var oldWidth = document.documentElement.clientWidth;
162
+ var prevHeight = layoutDummy.style.height;
163
+ // Lengthen the dummy to add a layout vertical scrollbar.
164
+ layoutDummy.style.height = "200%";
165
+ var scrollbarWidth = oldWidth - document.documentElement.clientWidth;
166
+ layoutDummy.style.width = prevHeight;
167
+ clientWidth -= scrollbarWidth;
168
+ }
169
+ }
170
+ return clientWidth / this.scale;
171
+ },
172
+ get height() {
173
+ var clientHeight = document.documentElement.clientHeight;
174
+ if (isIEEdge) {
175
+ // If there's no scrollbar before pinch-zooming, Edge will add
176
+ // a non-layout-affecting overlay scrollbar. This won't be
177
+ // reflected in documentElement.clientHeight so we need to
178
+ // manually subtract it out.
179
+ if (document.documentElement.clientHeight == window.viewPolyfill.unscaledInnerHeight
180
+ && this.scale > 1) {
181
+ var oldHeight = document.documentElement.clientHeight;
182
+ var prevWidth = layoutDummy.style.width;
183
+ // Widen the dummy to add a layout horizontal scrollbar.
184
+ layoutDummy.style.width = "200%";
185
+ var scrollbarHeight = oldHeight - document.documentElement.clientHeight;
186
+ layoutDummy.style.width = prevWidth;
187
+ clientHeight -= scrollbarHeight;
188
+ }
189
+ }
190
+ return clientHeight / this.scale;
191
+ },
192
+ get scale() {
193
+ return window.viewPolyfill.unscaledInnerWidth / window.innerWidth;
194
+ },
195
+ get pageLeft() {
196
+ return window.scrollX;
197
+ },
198
+ get pageTop() {
199
+ return window.scrollY;
200
+ },
201
+ "addEventListener": function(name, func) {
202
+ // TODO: Match event listener semantics. i.e. can't add the same callback twice.
203
+ if (name === 'scroll')
204
+ window.viewPolyfill.scrollEventListeners.push(func);
205
+ else if (name === 'resize')
206
+ window.viewPolyfill.resizeEventListeners.push(func);
207
+ }
208
+ };
209
+
210
+ window.visualViewport = viewport;
211
+ });
212
+ }
213
+
214
+ })();
215
+
216
+ }
@@ -1,39 +1,65 @@
1
1
  module Browser
2
2
 
3
+ # Representation of the screen the window is being rendered on.
4
+ #
5
+ # @see https://developer.mozilla.org/en-US/docs/Web/API/Window.screen
3
6
  class Screen
4
- include Native
5
- include DOM::Event::Target
7
+ include Browser::NativeCachedWrapper
8
+ include Event::Target
6
9
 
7
10
  target {|value|
8
11
  Screen.new(value) if Native.is_a?(value, `window.Screen`)
9
12
  }
10
13
 
14
+ Depth = Struct.new(:color, :pixel)
15
+
16
+ # @!attribute [r] width
17
+ # @return [Integer] the width of the screen in pixels
11
18
  alias_native :width
19
+
20
+ # @!attribute [r] height
21
+ # @return [Integer] the height of the screen in pixels
12
22
  alias_native :height
13
23
 
24
+ # @!attribute [r] size
25
+ # @return [Size] the size in pixels
14
26
  def size
15
27
  Size.new(width, height)
16
28
  end
17
29
 
30
+ # @!attribute [r] x
31
+ # @return [Integer] the offset from the top left corner of the screen in
32
+ # pixels
18
33
  alias_native :x, :top
34
+
35
+ # @!attribute [r] y
36
+ # @return [Integer] the offset from the top left corner of the screen in
37
+ # pixels
19
38
  alias_native :y, :left
20
39
 
40
+ # @!attribute [r] position
41
+ # @return [Position] the offset from the top left corner of the screen in
42
+ # pixels
21
43
  def position
22
44
  Position.new(x, y)
23
45
  end
24
46
 
25
- alias_native :color_depth, :colorDepth
26
- alias_native :pixel_depth, :pixelDepth
47
+ # @!attribute [r] depth
48
+ # @return [Depth] the screen depth
49
+ def depth
50
+ Depth.new(`#@native.colorDepth`, `#@native.pixelDepth`)
51
+ end
27
52
 
53
+ # @!attribute [r] orientation
54
+ # @return [String] the orientation of the screen
28
55
  alias_native :orientation
29
56
  end
30
57
 
31
58
  class Window
32
- # Get the {Screen} for this window.
33
- #
34
- # @return [Screen]
59
+ # @!attribute [r] screen
60
+ # @return [Screen] the screen for the window
35
61
  def screen
36
- Screen.new(`#@native.screen`)
62
+ @screen ||= Screen.new(`#@native.screen`)
37
63
  end
38
64
  end
39
65
 
@@ -0,0 +1,6 @@
1
+ # browser/setup/base: Setup only the base requires
2
+
3
+ require 'browser/version'
4
+ require 'browser/utils'
5
+ require 'browser/form_data'
6
+ require 'browser/support'
@@ -0,0 +1,13 @@
1
+ # browser/setup/full - a full set of requires to provide all features at once
2
+
3
+ require 'paggio'
4
+
5
+ require 'browser/setup/large'
6
+
7
+ require 'browser/event/all'
8
+
9
+ require 'browser/dom/builder'
10
+ require 'browser/dom/mutation_observer'
11
+ require 'browser/dom/element/custom'
12
+
13
+ require 'browser/canvas'
@@ -0,0 +1,17 @@
1
+ # browser/setup/large - a larger set of requires for more complex applications
2
+ #
3
+ # Note - it doesn't include Paggio (or Paggio support) or many events
4
+
5
+ require 'browser/setup/mini'
6
+
7
+ require 'browser/effects'
8
+ require 'browser/http'
9
+ require 'browser/delay'
10
+ require 'browser/interval'
11
+ require 'browser/immediate'
12
+ require 'browser/storage'
13
+ require 'browser/blob'
14
+ require 'browser/animation_frame'
15
+ require 'browser/socket'
16
+ require 'browser/history'
17
+ require 'browser/navigator'
@@ -0,0 +1,8 @@
1
+ # browser/setup/mini - A smaller set of requires, designed for slim codebases
2
+
3
+ require 'browser/setup/base'
4
+
5
+ require 'browser/event'
6
+ require 'browser/window'
7
+ require 'browser/dom'
8
+ require 'browser/css'
@@ -0,0 +1,10 @@
1
+ # browser/setup/traditional, browser, opal-browser
2
+ # ------------------------------------------------
3
+ # A traditional set of requires.
4
+
5
+ require 'native'
6
+ require 'paggio'
7
+
8
+ require 'browser/setup/mini'
9
+ require 'browser/event/all'
10
+ require 'browser/dom/builder'
@@ -1,14 +1,17 @@
1
1
  module Browser
2
2
 
3
- # This class wraps `WebSocket`.
4
- class Socket
3
+ # A {Socket} allows the browser and a server to have a bidirectional data
4
+ # connection.
5
+ #
6
+ # @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
7
+ class Socket < IO
5
8
  def self.supported?
6
- defined? `window.WebSocket`
9
+ Browser.supports? :WebSocket
7
10
  end
8
11
 
9
- include Native
10
- include IO::Writable
11
- include DOM::Event::Target
12
+ include Native::Wrapper
13
+ include IO::Writable if defined? IO::Writable
14
+ include Event::Target
12
15
 
13
16
  target {|value|
14
17
  Socket.new(value) if Native.is_a?(value, `window.WebSocket`)
@@ -18,8 +21,9 @@ class Socket
18
21
  #
19
22
  # @param url [String] the URL to connect to
20
23
  # @param protocol [String] the protocol to use
21
- # @yield if the block has no parameters it's instance_exec'd, otherwise it's
22
- # called with self
24
+ #
25
+ # @yield if the block has no parameters it's `instance_exec`d, otherwise it's
26
+ # called with `self`
23
27
  def initialize(url, protocol = nil, &block)
24
28
  if native?(url)
25
29
  super(url)
@@ -103,6 +107,10 @@ class Socket
103
107
  `#@native.send(#{data.to_n})`
104
108
  end
105
109
 
110
+ alias << write
111
+
112
+ alias send write
113
+
106
114
  # Close the socket.
107
115
  #
108
116
  # @param code [Integer, nil] the error code