overlastic 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +60 -15
- data/app/assets/javascripts/overlastic.js +47 -36
- data/app/assets/javascripts/overlastic.min.js +1 -1
- data/app/assets/javascripts/overlastic.min.js.map +1 -1
- data/app/controllers/overlastic/concerns/overlay_handling.rb +36 -25
- data/app/helpers/overlastic/navigation_helper.rb +11 -7
- data/app/helpers/overlastic/overlays_helper.rb +4 -6
- data/app/javascript/overlastic/clickInterceptor.js +57 -38
- data/app/javascript/overlastic/paneElement.js +1 -1
- data/app/views/overlastic/streams/redirect.turbo_stream.erb +2 -6
- data/lib/overlastic/configuration.rb +8 -0
- data/lib/overlastic/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3ab674f782fbcf5b2a76e0aa8e4d229b87101318c37aba073ce60c648ec3d22
|
4
|
+
data.tar.gz: a61d7ae32a857901b42d2f06c31e04ed16e51d6cf1d79a6e22e8339f5aa64300
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1bd556df73b2f2f3334bf49f6c4925ac7cf436b1b5556931e5aa80033785b15e9a77131383963beb2e91f0073a02f3612e62cbd29000e3667be19640fcf58c2
|
7
|
+
data.tar.gz: dcb9b6a055883ef195d9c393a30d8e34bbd8f5f51a41f43e52d8c9fc56130971814442e223d991ee5895b36df20b00ebfc55af2c55e809ac9bc15d671da37c4d
|
data/README.md
CHANGED
@@ -35,8 +35,8 @@ They work just as `link_to` and accept the same options. You can also pass local
|
|
35
35
|
Nested overlays will stack on top of each other. You can instead replace the last one or the whole stack:
|
36
36
|
|
37
37
|
```erb
|
38
|
-
<%= link_to_dialog "Open dialog", edit_article_path,
|
39
|
-
<%= link_to_dialog "Open dialog", edit_article_path,
|
38
|
+
<%= link_to_dialog "Open dialog", edit_article_path, overlay: :last %>
|
39
|
+
<%= link_to_dialog "Open dialog", edit_article_path, overlay: :first %>
|
40
40
|
```
|
41
41
|
|
42
42
|
By default, links and forms inside an overlay will drive the entire page (target _top). To keep navigation within the overlay you can set its target to _self:
|
@@ -45,6 +45,12 @@ By default, links and forms inside an overlay will drive the entire page (target
|
|
45
45
|
<%= link_to_dialog "Open dialog", edit_article_path, overlay_target: :_self %>
|
46
46
|
```
|
47
47
|
|
48
|
+
To break out of an overlay with target _self you can use:
|
49
|
+
|
50
|
+
```erb
|
51
|
+
<%= link_to "Open whole page", edit_article_path, overlay: false %>
|
52
|
+
```
|
53
|
+
|
48
54
|
A common use case is to render a form inside an overlay. When the form is submitted, you'll validate the data and redirect to a different page if it's successful or render the form again with errors. Overlastic will handle both cases gracefully without any modifications:
|
49
55
|
|
50
56
|
```rb
|
@@ -61,12 +67,13 @@ In case the form overlay was nested inside another overlay, you could prefer to
|
|
61
67
|
redirect_to article_url(@article), overlay: :previous, status: :see_other
|
62
68
|
```
|
63
69
|
|
64
|
-
Sometimes, you may want to alter the content of a view depending on whether it's inside an overlay or not. Overlastic defines a new `:overlay` request variant that you can use to create custom
|
70
|
+
Sometimes, you may want to alter the content of a view depending on whether it's inside an overlay or not. Overlastic defines a new `:overlay` request variant that you can use to create custom views like `new.html+overlay.erb` or inside a controller like so:
|
65
71
|
|
66
72
|
```rb
|
67
73
|
respond_to do |format|
|
68
|
-
format.
|
69
|
-
format.
|
74
|
+
format.turbo_stream.overlay { render :custom_view }
|
75
|
+
format.turbo_stream.any
|
76
|
+
format.html
|
70
77
|
end
|
71
78
|
```
|
72
79
|
|
@@ -83,8 +90,10 @@ else
|
|
83
90
|
end
|
84
91
|
```
|
85
92
|
|
93
|
+
### Advanced features
|
94
|
+
|
86
95
|
<details>
|
87
|
-
<summary>
|
96
|
+
<summary>Rendering an overlay without an initiator</summary><br>
|
88
97
|
|
89
98
|
Overlastic extends the `render` method inside a controller to add all the same options as `link_to_overlay`. This allows you to force an action to render an overlay, even if it wasn't requested:
|
90
99
|
|
@@ -94,6 +103,43 @@ end
|
|
94
103
|
```
|
95
104
|
</details>
|
96
105
|
|
106
|
+
<details>
|
107
|
+
<summary>Appending Turbo Streams to close_overlay</summary><br>
|
108
|
+
|
109
|
+
Sometimes, you may want not only to close an overlay, but also to deliver some other page change using a Turbo Stream:
|
110
|
+
|
111
|
+
```rb
|
112
|
+
close_overlay do
|
113
|
+
turbo_stream.prepend("flash-messages", "Deleted!")
|
114
|
+
end
|
115
|
+
```
|
116
|
+
</details>
|
117
|
+
|
118
|
+
<details>
|
119
|
+
<summary>Appending Turbo Streams to every response</summary><br>
|
120
|
+
|
121
|
+
Overlastic can be configured to append a Turbo Stream to every response that contains an overlay.
|
122
|
+
This can be very useful for rendering flash messages:
|
123
|
+
|
124
|
+
```rb
|
125
|
+
Overlastic.configure do |config|
|
126
|
+
config.append_turbo_stream do
|
127
|
+
turbo_stream.replace("flash-messages", partial: "shared/flash_messages")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
Then you'd only need to specify a flash message when closing an overlay, or redirecting to a different path:
|
133
|
+
|
134
|
+
```rb
|
135
|
+
close_overlay notice: "Deleted!"
|
136
|
+
|
137
|
+
# or
|
138
|
+
|
139
|
+
redirect_to articles_path, notice: "Deleted!", status: :see_other
|
140
|
+
```
|
141
|
+
</details>
|
142
|
+
|
97
143
|
|
98
144
|
## Configuration
|
99
145
|
|
@@ -102,13 +148,18 @@ end
|
|
102
148
|
|
103
149
|
Overlastic.configure do |config|
|
104
150
|
config.overlay_types = %i[dialog pane]
|
105
|
-
config.default_overlay = :dialog
|
106
|
-
config.default_action = :stack
|
107
|
-
config.default_target = :_top
|
151
|
+
config.default_overlay = :dialog # Options: One of the defined overlay types
|
152
|
+
config.default_action = :stack # Options: :stack, :replace_last, :replace_all
|
153
|
+
config.default_target = :_top # Options: :_top, :_self
|
108
154
|
|
109
155
|
# You can define a custom partial for each overlay type
|
110
156
|
config.dialog_overlay_view_path = "overlays/dialog"
|
111
157
|
config.pane_overlay_view_path = "overlays/pane"
|
158
|
+
|
159
|
+
# You can append Turbo Streams to every response containing an overlay
|
160
|
+
config.append_turbo_stream do
|
161
|
+
turbo_stream.replace("flash-messages", partial: "shared/flash_messages")
|
162
|
+
end
|
112
163
|
end
|
113
164
|
```
|
114
165
|
|
@@ -139,12 +190,6 @@ Overlastic comes with default views for both the dialog and pane overlays. It al
|
|
139
190
|
|
140
191
|
## Development
|
141
192
|
|
142
|
-
<details>
|
143
|
-
<summary>Roadmap</summary><br>
|
144
|
-
|
145
|
-
- Toasts?
|
146
|
-
</details>
|
147
|
-
|
148
193
|
<details>
|
149
194
|
<summary>Running the demo application</summary><br>
|
150
195
|
|
@@ -203,7 +203,7 @@ var enableBodyScroll$1 = function enableBodyScroll(targetElement) {
|
|
203
203
|
};
|
204
204
|
|
205
205
|
addEventListener("click", (event => {
|
206
|
-
window._overlasticAnchor = event.target
|
206
|
+
window._overlasticAnchor = event.target;
|
207
207
|
}), true);
|
208
208
|
|
209
209
|
addEventListener("turbo:before-fetch-request", (event => {
|
@@ -211,32 +211,58 @@ addEventListener("turbo:before-fetch-request", (event => {
|
|
211
211
|
}));
|
212
212
|
|
213
213
|
addEventListener("turbo:before-fetch-request", (event => {
|
214
|
-
|
215
|
-
const
|
214
|
+
const anchor = event.target;
|
215
|
+
const name = anchor?.dataset?.overlayName;
|
216
216
|
const type = anchor?.dataset?.overlayType;
|
217
217
|
const target = anchor?.dataset?.overlayTarget;
|
218
218
|
const args = anchor?.dataset?.overlayArgs;
|
219
|
-
|
220
|
-
|
221
|
-
event.detail.fetchOptions.headers["Overlay-
|
222
|
-
|
223
|
-
|
224
|
-
|
219
|
+
if (name?.startsWith("overlay")) {
|
220
|
+
event.detail.fetchOptions.headers["Overlay-Initiator"] = "1";
|
221
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name;
|
222
|
+
if (type) {
|
223
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type;
|
224
|
+
}
|
225
|
+
if (target) {
|
226
|
+
event.detail.fetchOptions.headers["Overlay-Target"] = target;
|
227
|
+
}
|
228
|
+
if (args) {
|
229
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args;
|
230
|
+
}
|
225
231
|
}
|
226
|
-
|
227
|
-
|
232
|
+
}));
|
233
|
+
|
234
|
+
addEventListener("turbo:before-fetch-request", (event => {
|
235
|
+
const script = document.querySelector("script[overlay]");
|
236
|
+
if (script) {
|
237
|
+
const overlay = document.querySelector(`overlastic[id=${script.getAttribute("overlay")}]`);
|
238
|
+
if (overlay) {
|
239
|
+
const name = overlay.id;
|
240
|
+
const target = overlay.dataset.overlayTarget;
|
241
|
+
const type = overlay.dataset?.overlayType;
|
242
|
+
const args = overlay.dataset?.overlayArgs;
|
243
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name;
|
244
|
+
event.detail.fetchOptions.headers["Overlay-Target"] = target;
|
245
|
+
event.detail.fetchOptions.headers["Overlay-Initiator"] = "1";
|
246
|
+
if (type) {
|
247
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type;
|
248
|
+
}
|
249
|
+
if (args) {
|
250
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args;
|
251
|
+
}
|
252
|
+
}
|
228
253
|
}
|
229
|
-
delete window._overlasticTarget;
|
230
254
|
}));
|
231
255
|
|
232
256
|
addEventListener("turbo:before-fetch-request", (event => {
|
233
|
-
|
234
|
-
const
|
235
|
-
if (
|
236
|
-
const
|
237
|
-
const
|
238
|
-
const
|
239
|
-
const
|
257
|
+
const anchor = window._overlasticAnchor;
|
258
|
+
const overlay = anchor.closest("overlastic");
|
259
|
+
if (overlay && !anchor.dataset.overlay && !anchor.dataset.overlayName) {
|
260
|
+
const name = overlay.id;
|
261
|
+
const target = overlay.dataset.overlayTarget;
|
262
|
+
const initiator = overlay.dataset?.overlayInitiator;
|
263
|
+
const type = overlay.dataset?.overlayType;
|
264
|
+
const args = overlay.dataset?.overlayArgs;
|
265
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name;
|
240
266
|
event.detail.fetchOptions.headers["Overlay-Target"] = target;
|
241
267
|
if (initiator) {
|
242
268
|
event.detail.fetchOptions.headers["Overlay-Initiator"] = initiator;
|
@@ -248,22 +274,7 @@ addEventListener("turbo:before-fetch-request", (event => {
|
|
248
274
|
event.detail.fetchOptions.headers["Overlay-Args"] = args;
|
249
275
|
}
|
250
276
|
}
|
251
|
-
|
252
|
-
|
253
|
-
addEventListener("turbo:before-fetch-response", (async event => {
|
254
|
-
const fetchResponse = event.detail.fetchResponse;
|
255
|
-
const visit = fetchResponse.response.headers.get("Overlay-Visit");
|
256
|
-
if (!visit) return;
|
257
|
-
const responseHTML = await fetchResponse.responseHTML;
|
258
|
-
const {redirected: redirected, statusCode: statusCode} = fetchResponse;
|
259
|
-
return Turbo.session.visit(visit, {
|
260
|
-
shouldCacheSnapshot: false,
|
261
|
-
response: {
|
262
|
-
redirected: redirected,
|
263
|
-
statusCode: statusCode,
|
264
|
-
responseHTML: responseHTML
|
265
|
-
}
|
266
|
-
});
|
277
|
+
delete window._overlasticAnchor;
|
267
278
|
}));
|
268
279
|
|
269
280
|
class DialogElement extends HTMLElement {
|
@@ -291,7 +302,7 @@ class PaneElement extends DialogElement {
|
|
291
302
|
window.modalVisitStack = [];
|
292
303
|
}
|
293
304
|
window.modalVisitStack.push(lastVisit);
|
294
|
-
Turbo.navigator.history.push(new URL(this.parentElement.src));
|
305
|
+
Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")));
|
295
306
|
}
|
296
307
|
close(event, self = false) {
|
297
308
|
if (self && event.target !== this) return;
|
@@ -1,2 +1,2 @@
|
|
1
|
-
var e=!1;if("undefined"!=typeof window){var t={get passive(){e=!0}};window.addEventListener("testPassive",null,t),window.removeEventListener("testPassive",null,t)}var o="undefined"!=typeof window&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||"MacIntel"===window.navigator.platform&&window.navigator.maxTouchPoints>1),n=[],
|
1
|
+
var e=!1;if("undefined"!=typeof window){var t={get passive(){e=!0}};window.addEventListener("testPassive",null,t),window.removeEventListener("testPassive",null,t)}var o="undefined"!=typeof window&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||"MacIntel"===window.navigator.platform&&window.navigator.maxTouchPoints>1),n=[],a=!1,i=-1,r=void 0,s=void 0,d=void 0,l=function(e){return n.some((function(t){return!(!t.options.allowTouchMove||!t.options.allowTouchMove(e))}))},c=function(e){var t=e||window.event;return!!l(t.target)||(t.touches.length>1||(t.preventDefault&&t.preventDefault(),!1))};addEventListener("click",(e=>{window._overlasticAnchor=e.target}),!0),addEventListener("turbo:before-fetch-request",(e=>{e.detail.fetchOptions.headers["Overlay-Enabled"]="1"})),addEventListener("turbo:before-fetch-request",(e=>{const t=e.target,o=t?.dataset?.overlayName,n=t?.dataset?.overlayType,a=t?.dataset?.overlayTarget,i=t?.dataset?.overlayArgs;o?.startsWith("overlay")&&(e.detail.fetchOptions.headers["Overlay-Initiator"]="1",e.detail.fetchOptions.headers["Overlay-Name"]=o,n&&(e.detail.fetchOptions.headers["Overlay-Type"]=n),a&&(e.detail.fetchOptions.headers["Overlay-Target"]=a),i&&(e.detail.fetchOptions.headers["Overlay-Args"]=i))})),addEventListener("turbo:before-fetch-request",(e=>{const t=document.querySelector("script[overlay]");if(t){const o=document.querySelector(`overlastic[id=${t.getAttribute("overlay")}]`);if(o){const t=o.id,n=o.dataset.overlayTarget,a=o.dataset?.overlayType,i=o.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Name"]=t,e.detail.fetchOptions.headers["Overlay-Target"]=n,e.detail.fetchOptions.headers["Overlay-Initiator"]="1",a&&(e.detail.fetchOptions.headers["Overlay-Type"]=a),i&&(e.detail.fetchOptions.headers["Overlay-Args"]=i)}}})),addEventListener("turbo:before-fetch-request",(e=>{const t=window._overlasticAnchor,o=t.closest("overlastic");if(o&&!t.dataset.overlay&&!t.dataset.overlayName){const t=o.id,n=o.dataset.overlayTarget,a=o.dataset?.overlayInitiator,i=o.dataset?.overlayType,r=o.dataset?.overlayArgs;e.detail.fetchOptions.headers["Overlay-Name"]=t,e.detail.fetchOptions.headers["Overlay-Target"]=n,a&&(e.detail.fetchOptions.headers["Overlay-Initiator"]=a),i&&(e.detail.fetchOptions.headers["Overlay-Type"]=i),r&&(e.detail.fetchOptions.headers["Overlay-Args"]=r)}delete window._overlasticAnchor}));class v extends HTMLElement{connectedCallback(){disableBodyScroll(this),this.addEventListener("click",(e=>this.close(e,!0))),this.querySelector(".overlastic-close").addEventListener("click",(e=>this.close(e)))}close(e,t=!1){t&&e.target!==this||(enableBodyScroll(this),setTimeout((()=>{this.remove()}),5))}}customElements.define("overlastic-dialog",v);customElements.define("overlastic-pane",class extends v{connectedCallback(){super.connectedCallback();const e=Turbo.navigator.history.location;window.modalVisitStack||(window.modalVisitStack=[]),window.modalVisitStack.push(e),Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")))}close(e,t=!1){t&&e.target!==this||(super.close(e,t),window.modalVisitStack.length>0&&Turbo.navigator.history.replace(window.modalVisitStack.pop()))}}),window.disableBodyScroll=function(t,v){if(t){if(!n.some((function(e){return e.targetElement===t}))){var u={targetElement:t,options:v||{}};n=[].concat(function(e){if(Array.isArray(e)){for(var t=0,o=Array(e.length);t<e.length;t++)o[t]=e[t];return o}return Array.from(e)}(n),[u]),o?window.requestAnimationFrame((function(){if(void 0===s){s={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var e=window,t=e.scrollY,o=e.scrollX,n=e.innerHeight;document.body.style.position="fixed",document.body.style.top=-t,document.body.style.left=-o,setTimeout((function(){return window.requestAnimationFrame((function(){var e=n-window.innerHeight;e&&t>=n&&(document.body.style.top=-(t+e))}))}),300)}})):function(e){if(void 0===d){var t=!!e&&!0===e.reserveScrollBarGap,o=window.innerWidth-document.documentElement.clientWidth;if(t&&o>0){var n=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);d=document.body.style.paddingRight,document.body.style.paddingRight=n+o+"px"}}void 0===r&&(r=document.body.style.overflow,document.body.style.overflow="hidden")}(v),o&&(t.ontouchstart=function(e){1===e.targetTouches.length&&(i=e.targetTouches[0].clientY)},t.ontouchmove=function(e){1===e.targetTouches.length&&function(e,t){var o=e.targetTouches[0].clientY-i;!l(e.target)&&(t&&0===t.scrollTop&&o>0||function(e){return!!e&&e.scrollHeight-e.scrollTop<=e.clientHeight}(t)&&o<0?c(e):e.stopPropagation())}(e,t)},a||(document.addEventListener("touchmove",c,e?{passive:!1}:void 0),a=!0))}}else console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.")},window.enableBodyScroll=function(t){t?(n=n.filter((function(e){return e.targetElement!==t})),o&&(t.ontouchstart=null,t.ontouchmove=null,a&&0===n.length&&(document.removeEventListener("touchmove",c,e?{passive:!1}:void 0),a=!1)),o?function(){if(void 0!==s){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=s.position,document.body.style.top=s.top,document.body.style.left=s.left,window.scrollTo(t,e),s=void 0}}():(void 0!==d&&(document.body.style.paddingRight=d,d=void 0),void 0!==r&&(document.body.style.overflow=r,r=void 0))):console.error("enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.")};
|
2
2
|
//# sourceMappingURL=overlastic.min.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"overlastic.min.js","sources":["../../../node_modules/body-scroll-lock/lib/bodyScrollLock.esm.js","../../javascript/overlastic/clickInterceptor.js","../../javascript/overlastic/dialogElement.js","../../javascript/overlastic/paneElement.js","../../javascript/overlastic/index.js"],"sourcesContent":["function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Older browsers don't support event options, feature detect it.\n\n// Adopted and modified solution from Bohdan Didukh (2017)\n// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi\n\nvar hasPassiveEvents = false;\nif (typeof window !== 'undefined') {\n var passiveTestOptions = {\n get passive() {\n hasPassiveEvents = true;\n return undefined;\n }\n };\n window.addEventListener('testPassive', null, passiveTestOptions);\n window.removeEventListener('testPassive', null, passiveTestOptions);\n}\n\nvar isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);\n\n\nvar locks = [];\nvar documentListenerAdded = false;\nvar initialClientY = -1;\nvar previousBodyOverflowSetting = void 0;\nvar previousBodyPosition = void 0;\nvar previousBodyPaddingRight = void 0;\n\n// returns true if `el` should be allowed to receive touchmove events.\nvar allowTouchMove = function allowTouchMove(el) {\n return locks.some(function (lock) {\n if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {\n return true;\n }\n\n return false;\n });\n};\n\nvar preventDefault = function preventDefault(rawEvent) {\n var e = rawEvent || window.event;\n\n // For the case whereby consumers adds a touchmove event listener to document.\n // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })\n // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then\n // the touchmove event on document will break.\n if (allowTouchMove(e.target)) {\n return true;\n }\n\n // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).\n if (e.touches.length > 1) return true;\n\n if (e.preventDefault) e.preventDefault();\n\n return false;\n};\n\nvar setOverflowHidden = function setOverflowHidden(options) {\n // If previousBodyPaddingRight is already set, don't set it again.\n if (previousBodyPaddingRight === undefined) {\n var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;\n var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;\n\n if (_reserveScrollBarGap && scrollBarGap > 0) {\n var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'), 10);\n previousBodyPaddingRight = document.body.style.paddingRight;\n document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + 'px';\n }\n }\n\n // If previousBodyOverflowSetting is already set, don't set it again.\n if (previousBodyOverflowSetting === undefined) {\n previousBodyOverflowSetting = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n};\n\nvar restoreOverflowSetting = function restoreOverflowSetting() {\n if (previousBodyPaddingRight !== undefined) {\n document.body.style.paddingRight = previousBodyPaddingRight;\n\n // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it\n // can be set again.\n previousBodyPaddingRight = undefined;\n }\n\n if (previousBodyOverflowSetting !== undefined) {\n document.body.style.overflow = previousBodyOverflowSetting;\n\n // Restore previousBodyOverflowSetting to undefined\n // so setOverflowHidden knows it can be set again.\n previousBodyOverflowSetting = undefined;\n }\n};\n\nvar setPositionFixed = function setPositionFixed() {\n return window.requestAnimationFrame(function () {\n // If previousBodyPosition is already set, don't set it again.\n if (previousBodyPosition === undefined) {\n previousBodyPosition = {\n position: document.body.style.position,\n top: document.body.style.top,\n left: document.body.style.left\n };\n\n // Update the dom inside an animation frame \n var _window = window,\n scrollY = _window.scrollY,\n scrollX = _window.scrollX,\n innerHeight = _window.innerHeight;\n\n document.body.style.position = 'fixed';\n document.body.style.top = -scrollY;\n document.body.style.left = -scrollX;\n\n setTimeout(function () {\n return window.requestAnimationFrame(function () {\n // Attempt to check if the bottom bar appeared due to the position change\n var bottomBarHeight = innerHeight - window.innerHeight;\n if (bottomBarHeight && scrollY >= innerHeight) {\n // Move the content further up so that the bottom bar doesn't hide it\n document.body.style.top = -(scrollY + bottomBarHeight);\n }\n });\n }, 300);\n }\n });\n};\n\nvar restorePositionSetting = function restorePositionSetting() {\n if (previousBodyPosition !== undefined) {\n // Convert the position from \"px\" to Int\n var y = -parseInt(document.body.style.top, 10);\n var x = -parseInt(document.body.style.left, 10);\n\n // Restore styles\n document.body.style.position = previousBodyPosition.position;\n document.body.style.top = previousBodyPosition.top;\n document.body.style.left = previousBodyPosition.left;\n\n // Restore scroll\n window.scrollTo(x, y);\n\n previousBodyPosition = undefined;\n }\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\nvar isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {\n return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;\n};\n\nvar handleScroll = function handleScroll(event, targetElement) {\n var clientY = event.targetTouches[0].clientY - initialClientY;\n\n if (allowTouchMove(event.target)) {\n return false;\n }\n\n if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {\n // element is at the top of its scroll.\n return preventDefault(event);\n }\n\n if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {\n // element is at the bottom of its scroll.\n return preventDefault(event);\n }\n\n event.stopPropagation();\n return true;\n};\n\nexport var disableBodyScroll = function disableBodyScroll(targetElement, options) {\n // targetElement must be provided\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');\n return;\n }\n\n // disableBodyScroll must not have been called on this targetElement before\n if (locks.some(function (lock) {\n return lock.targetElement === targetElement;\n })) {\n return;\n }\n\n var lock = {\n targetElement: targetElement,\n options: options || {}\n };\n\n locks = [].concat(_toConsumableArray(locks), [lock]);\n\n if (isIosDevice) {\n setPositionFixed();\n } else {\n setOverflowHidden(options);\n }\n\n if (isIosDevice) {\n targetElement.ontouchstart = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n initialClientY = event.targetTouches[0].clientY;\n }\n };\n targetElement.ontouchmove = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n handleScroll(event, targetElement);\n }\n };\n\n if (!documentListenerAdded) {\n document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = true;\n }\n }\n};\n\nexport var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {\n if (isIosDevice) {\n // Clear all locks ontouchstart/ontouchmove handlers, and the references.\n locks.forEach(function (lock) {\n lock.targetElement.ontouchstart = null;\n lock.targetElement.ontouchmove = null;\n });\n\n if (documentListenerAdded) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n\n // Reset initial clientY.\n initialClientY = -1;\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n\n locks = [];\n};\n\nexport var enableBodyScroll = function enableBodyScroll(targetElement) {\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');\n return;\n }\n\n locks = locks.filter(function (lock) {\n return lock.targetElement !== targetElement;\n });\n\n if (isIosDevice) {\n targetElement.ontouchstart = null;\n targetElement.ontouchmove = null;\n\n if (documentListenerAdded && locks.length === 0) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n};\n\n","// Save the clicked overlay link element for use down the line\naddEventListener(\"click\", event => {\n window._overlasticAnchor = event.target.closest(\"a[data-turbo-frame^=overlay]\")\n}, true)\n\n// Allow progressive enhancement by telling the server if a request is handled by Turbo\naddEventListener(\"turbo:before-fetch-request\", event => {\n event.detail.fetchOptions.headers[\"Overlay-Enabled\"] = \"1\"\n})\n\n// When an overlay anchor is clicked,\n// send its type, target and args along with the frame request\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (!window._overlasticAnchor) return\n\n const anchor = window._overlasticAnchor\n const type = anchor?.dataset?.overlayType\n const target = anchor?.dataset?.overlayTarget\n const args = anchor?.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = \"1\"\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (target) {\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n\n delete window._overlasticTarget\n})\n\n// When any other element triggers a fetch,\n// send the current overlay's target along with the frame request\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (window._overlasticAnchor) return\n\n const frame = event.target.closest(\"turbo-frame[id^=overlay]\")\n\n if (frame) {\n const target = frame.dataset.overlayTarget\n const initiator = frame.dataset?.overlayInitiator\n const type = frame.dataset?.overlayType\n const args = frame.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n\n if (initiator) {\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = initiator\n }\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n})\n\n// Handle frame-to-visit promotions when the server asks for it\naddEventListener(\"turbo:before-fetch-response\", async event => {\n const fetchResponse = event.detail.fetchResponse\n const visit = fetchResponse.response.headers.get(\"Overlay-Visit\")\n\n if (!visit) return\n\n const responseHTML = await fetchResponse.responseHTML\n const { redirected, statusCode } = fetchResponse\n\n return Turbo.session.visit(visit, { shouldCacheSnapshot: false, response: { redirected, statusCode, responseHTML } })\n})\n","export default class DialogElement extends HTMLElement {\n connectedCallback() {\n disableBodyScroll(this)\n\n this.addEventListener(\"click\", event => this.close(event, true))\n this.querySelector(\".overlastic-close\").addEventListener(\"click\", event => this.close(event))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n enableBodyScroll(this)\n\n // Avoid removing before sending dispatching other events (like form submissions)\n setTimeout(() => {\n this.remove()\n }, 5)\n }\n}\n\ncustomElements.define(\"overlastic-dialog\", DialogElement)\n","import DialogElement from \"./dialogElement\"\n\nclass PaneElement extends DialogElement {\n connectedCallback() {\n super.connectedCallback()\n\n const lastVisit = Turbo.navigator.history.location\n\n if (!window.modalVisitStack) {\n window.modalVisitStack = []\n }\n\n window.modalVisitStack.push(lastVisit)\n Turbo.navigator.history.push(new URL(this.parentElement.src))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n super.close(event, self)\n\n if (window.modalVisitStack.length > 0) {\n Turbo.navigator.history.replace(window.modalVisitStack.pop())\n }\n }\n}\n\ncustomElements.define(\"overlastic-pane\", PaneElement)\n","import { disableBodyScroll, enableBodyScroll } from \"body-scroll-lock\"\n\nimport \"./clickInterceptor\"\nimport \"./dialogElement\"\nimport \"./paneElement\"\n\nwindow.disableBodyScroll = disableBodyScroll\nwindow.enableBodyScroll = enableBodyScroll\n"],"names":["hasPassiveEvents","window","passiveTestOptions","passive","addEventListener","removeEventListener","isIosDevice","navigator","platform","test","maxTouchPoints","locks","documentListenerAdded","initialClientY","previousBodyOverflowSetting","previousBodyPosition","previousBodyPaddingRight","allowTouchMove","el","some","lock","options","preventDefault","rawEvent","e","event","target","touches","length","_overlasticAnchor","closest","detail","fetchOptions","headers","anchor","type","dataset","overlayType","overlayTarget","args","overlayArgs","_overlasticTarget","frame","initiator","overlayInitiator","async","fetchResponse","visit","response","get","responseHTML","redirected","statusCode","Turbo","session","shouldCacheSnapshot","DialogElement","HTMLElement","[object Object]","disableBodyScroll","this","close","querySelector","self","enableBodyScroll","setTimeout","remove","customElements","define","super","connectedCallback","lastVisit","history","location","modalVisitStack","push","URL","parentElement","src","replace","pop","targetElement","concat","arr","Array","isArray","i","arr2","from","_toConsumableArray","requestAnimationFrame","undefined","position","document","body","style","top","left","_window","scrollY","scrollX","innerHeight","bottomBarHeight","_reserveScrollBarGap","reserveScrollBarGap","scrollBarGap","innerWidth","documentElement","clientWidth","computedBodyPaddingRight","parseInt","getComputedStyle","getPropertyValue","paddingRight","overflow","setOverflowHidden","ontouchstart","targetTouches","clientY","ontouchmove","scrollTop","scrollHeight","clientHeight","isTargetElementTotallyScrolled","stopPropagation","handleScroll","console","error","filter","y","x","scrollTo","restorePositionSetting"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"overlastic.min.js","sources":["../../../node_modules/body-scroll-lock/lib/bodyScrollLock.esm.js","../../javascript/overlastic/clickInterceptor.js","../../javascript/overlastic/dialogElement.js","../../javascript/overlastic/paneElement.js","../../javascript/overlastic/index.js"],"sourcesContent":["function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n// Older browsers don't support event options, feature detect it.\n\n// Adopted and modified solution from Bohdan Didukh (2017)\n// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi\n\nvar hasPassiveEvents = false;\nif (typeof window !== 'undefined') {\n var passiveTestOptions = {\n get passive() {\n hasPassiveEvents = true;\n return undefined;\n }\n };\n window.addEventListener('testPassive', null, passiveTestOptions);\n window.removeEventListener('testPassive', null, passiveTestOptions);\n}\n\nvar isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);\n\n\nvar locks = [];\nvar documentListenerAdded = false;\nvar initialClientY = -1;\nvar previousBodyOverflowSetting = void 0;\nvar previousBodyPosition = void 0;\nvar previousBodyPaddingRight = void 0;\n\n// returns true if `el` should be allowed to receive touchmove events.\nvar allowTouchMove = function allowTouchMove(el) {\n return locks.some(function (lock) {\n if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {\n return true;\n }\n\n return false;\n });\n};\n\nvar preventDefault = function preventDefault(rawEvent) {\n var e = rawEvent || window.event;\n\n // For the case whereby consumers adds a touchmove event listener to document.\n // Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })\n // in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then\n // the touchmove event on document will break.\n if (allowTouchMove(e.target)) {\n return true;\n }\n\n // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).\n if (e.touches.length > 1) return true;\n\n if (e.preventDefault) e.preventDefault();\n\n return false;\n};\n\nvar setOverflowHidden = function setOverflowHidden(options) {\n // If previousBodyPaddingRight is already set, don't set it again.\n if (previousBodyPaddingRight === undefined) {\n var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;\n var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;\n\n if (_reserveScrollBarGap && scrollBarGap > 0) {\n var computedBodyPaddingRight = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'), 10);\n previousBodyPaddingRight = document.body.style.paddingRight;\n document.body.style.paddingRight = computedBodyPaddingRight + scrollBarGap + 'px';\n }\n }\n\n // If previousBodyOverflowSetting is already set, don't set it again.\n if (previousBodyOverflowSetting === undefined) {\n previousBodyOverflowSetting = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n};\n\nvar restoreOverflowSetting = function restoreOverflowSetting() {\n if (previousBodyPaddingRight !== undefined) {\n document.body.style.paddingRight = previousBodyPaddingRight;\n\n // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it\n // can be set again.\n previousBodyPaddingRight = undefined;\n }\n\n if (previousBodyOverflowSetting !== undefined) {\n document.body.style.overflow = previousBodyOverflowSetting;\n\n // Restore previousBodyOverflowSetting to undefined\n // so setOverflowHidden knows it can be set again.\n previousBodyOverflowSetting = undefined;\n }\n};\n\nvar setPositionFixed = function setPositionFixed() {\n return window.requestAnimationFrame(function () {\n // If previousBodyPosition is already set, don't set it again.\n if (previousBodyPosition === undefined) {\n previousBodyPosition = {\n position: document.body.style.position,\n top: document.body.style.top,\n left: document.body.style.left\n };\n\n // Update the dom inside an animation frame \n var _window = window,\n scrollY = _window.scrollY,\n scrollX = _window.scrollX,\n innerHeight = _window.innerHeight;\n\n document.body.style.position = 'fixed';\n document.body.style.top = -scrollY;\n document.body.style.left = -scrollX;\n\n setTimeout(function () {\n return window.requestAnimationFrame(function () {\n // Attempt to check if the bottom bar appeared due to the position change\n var bottomBarHeight = innerHeight - window.innerHeight;\n if (bottomBarHeight && scrollY >= innerHeight) {\n // Move the content further up so that the bottom bar doesn't hide it\n document.body.style.top = -(scrollY + bottomBarHeight);\n }\n });\n }, 300);\n }\n });\n};\n\nvar restorePositionSetting = function restorePositionSetting() {\n if (previousBodyPosition !== undefined) {\n // Convert the position from \"px\" to Int\n var y = -parseInt(document.body.style.top, 10);\n var x = -parseInt(document.body.style.left, 10);\n\n // Restore styles\n document.body.style.position = previousBodyPosition.position;\n document.body.style.top = previousBodyPosition.top;\n document.body.style.left = previousBodyPosition.left;\n\n // Restore scroll\n window.scrollTo(x, y);\n\n previousBodyPosition = undefined;\n }\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions\nvar isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {\n return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;\n};\n\nvar handleScroll = function handleScroll(event, targetElement) {\n var clientY = event.targetTouches[0].clientY - initialClientY;\n\n if (allowTouchMove(event.target)) {\n return false;\n }\n\n if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {\n // element is at the top of its scroll.\n return preventDefault(event);\n }\n\n if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {\n // element is at the bottom of its scroll.\n return preventDefault(event);\n }\n\n event.stopPropagation();\n return true;\n};\n\nexport var disableBodyScroll = function disableBodyScroll(targetElement, options) {\n // targetElement must be provided\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');\n return;\n }\n\n // disableBodyScroll must not have been called on this targetElement before\n if (locks.some(function (lock) {\n return lock.targetElement === targetElement;\n })) {\n return;\n }\n\n var lock = {\n targetElement: targetElement,\n options: options || {}\n };\n\n locks = [].concat(_toConsumableArray(locks), [lock]);\n\n if (isIosDevice) {\n setPositionFixed();\n } else {\n setOverflowHidden(options);\n }\n\n if (isIosDevice) {\n targetElement.ontouchstart = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n initialClientY = event.targetTouches[0].clientY;\n }\n };\n targetElement.ontouchmove = function (event) {\n if (event.targetTouches.length === 1) {\n // detect single touch.\n handleScroll(event, targetElement);\n }\n };\n\n if (!documentListenerAdded) {\n document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = true;\n }\n }\n};\n\nexport var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {\n if (isIosDevice) {\n // Clear all locks ontouchstart/ontouchmove handlers, and the references.\n locks.forEach(function (lock) {\n lock.targetElement.ontouchstart = null;\n lock.targetElement.ontouchmove = null;\n });\n\n if (documentListenerAdded) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n\n // Reset initial clientY.\n initialClientY = -1;\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n\n locks = [];\n};\n\nexport var enableBodyScroll = function enableBodyScroll(targetElement) {\n if (!targetElement) {\n // eslint-disable-next-line no-console\n console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');\n return;\n }\n\n locks = locks.filter(function (lock) {\n return lock.targetElement !== targetElement;\n });\n\n if (isIosDevice) {\n targetElement.ontouchstart = null;\n targetElement.ontouchmove = null;\n\n if (documentListenerAdded && locks.length === 0) {\n document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined);\n documentListenerAdded = false;\n }\n }\n\n if (isIosDevice) {\n restorePositionSetting();\n } else {\n restoreOverflowSetting();\n }\n};\n\n","// Save the clicked element for use down the line.\naddEventListener(\"click\", event => {\n window._overlasticAnchor = event.target\n}, true)\n\n// Allow progressive enhancement by telling the server if a request is handled by Turbo.\naddEventListener(\"turbo:before-fetch-request\", event => {\n event.detail.fetchOptions.headers[\"Overlay-Enabled\"] = \"1\"\n})\n\n// When an overlay anchor is clicked,\n// send its type, target and args along with the visit request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n const anchor = event.target\n const name = anchor?.dataset?.overlayName\n const type = anchor?.dataset?.overlayType\n const target = anchor?.dataset?.overlayTarget\n const args = anchor?.dataset?.overlayArgs\n\n if (name?.startsWith(\"overlay\")) {\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = \"1\"\n event.detail.fetchOptions.headers[\"Overlay-Name\"] = name\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (target) {\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n})\n\n// When the redirect script triggers a fetch,\n// send the current overlay's target along with the visit request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n const script = document.querySelector(\"script[overlay]\")\n\n if (script) {\n const overlay = document.querySelector(`overlastic[id=${script.getAttribute(\"overlay\")}]`)\n\n if (overlay) {\n const name = overlay.id\n const target = overlay.dataset.overlayTarget\n const type = overlay.dataset?.overlayType\n const args = overlay.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Name\"] = name\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = \"1\"\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n }\n})\n\n// When any other element triggers a fetch,\n// send the current overlay's target along with the visit request.\naddEventListener(\"turbo:before-fetch-request\", event => {\n const anchor = window._overlasticAnchor\n const overlay = anchor.closest(\"overlastic\")\n\n if (overlay && !anchor.dataset.overlay && !anchor.dataset.overlayName) {\n const name = overlay.id\n const target = overlay.dataset.overlayTarget\n const initiator = overlay.dataset?.overlayInitiator\n const type = overlay.dataset?.overlayType\n const args = overlay.dataset?.overlayArgs\n\n event.detail.fetchOptions.headers[\"Overlay-Name\"] = name\n event.detail.fetchOptions.headers[\"Overlay-Target\"] = target\n\n if (initiator) {\n event.detail.fetchOptions.headers[\"Overlay-Initiator\"] = initiator\n }\n\n if (type) {\n event.detail.fetchOptions.headers[\"Overlay-Type\"] = type\n }\n\n if (args) {\n event.detail.fetchOptions.headers[\"Overlay-Args\"] = args\n }\n }\n\n delete window._overlasticAnchor\n})\n","export default class DialogElement extends HTMLElement {\n connectedCallback() {\n disableBodyScroll(this)\n\n this.addEventListener(\"click\", event => this.close(event, true))\n this.querySelector(\".overlastic-close\").addEventListener(\"click\", event => this.close(event))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n enableBodyScroll(this)\n\n // Avoid removing before sending dispatching other events (like form submissions)\n setTimeout(() => {\n this.remove()\n }, 5)\n }\n}\n\ncustomElements.define(\"overlastic-dialog\", DialogElement)\n","import DialogElement from \"./dialogElement\"\n\nclass PaneElement extends DialogElement {\n connectedCallback() {\n super.connectedCallback()\n\n const lastVisit = Turbo.navigator.history.location\n\n if (!window.modalVisitStack) {\n window.modalVisitStack = []\n }\n\n window.modalVisitStack.push(lastVisit)\n Turbo.navigator.history.push(new URL(this.parentElement.getAttribute(\"src\")))\n }\n\n close(event, self = false) {\n if (self && event.target !== this) return\n\n super.close(event, self)\n\n if (window.modalVisitStack.length > 0) {\n Turbo.navigator.history.replace(window.modalVisitStack.pop())\n }\n }\n}\n\ncustomElements.define(\"overlastic-pane\", PaneElement)\n","import { disableBodyScroll, enableBodyScroll } from \"body-scroll-lock\"\n\nimport \"./clickInterceptor\"\nimport \"./dialogElement\"\nimport \"./paneElement\"\n\nwindow.disableBodyScroll = disableBodyScroll\nwindow.enableBodyScroll = enableBodyScroll\n"],"names":["hasPassiveEvents","window","passiveTestOptions","passive","addEventListener","removeEventListener","isIosDevice","navigator","platform","test","maxTouchPoints","locks","documentListenerAdded","initialClientY","previousBodyOverflowSetting","previousBodyPosition","previousBodyPaddingRight","allowTouchMove","el","some","lock","options","preventDefault","rawEvent","e","event","target","touches","length","_overlasticAnchor","detail","fetchOptions","headers","anchor","name","dataset","overlayName","type","overlayType","overlayTarget","args","overlayArgs","startsWith","script","document","querySelector","overlay","getAttribute","id","closest","initiator","overlayInitiator","DialogElement","HTMLElement","[object Object]","disableBodyScroll","this","close","self","enableBodyScroll","setTimeout","remove","customElements","define","super","connectedCallback","lastVisit","Turbo","history","location","modalVisitStack","push","URL","parentElement","replace","pop","targetElement","concat","arr","Array","isArray","i","arr2","from","_toConsumableArray","requestAnimationFrame","undefined","position","body","style","top","left","_window","scrollY","scrollX","innerHeight","bottomBarHeight","_reserveScrollBarGap","reserveScrollBarGap","scrollBarGap","innerWidth","documentElement","clientWidth","computedBodyPaddingRight","parseInt","getComputedStyle","getPropertyValue","paddingRight","overflow","setOverflowHidden","ontouchstart","targetTouches","clientY","ontouchmove","scrollTop","scrollHeight","clientHeight","isTargetElementTotallyScrolled","stopPropagation","handleScroll","console","error","filter","y","x","scrollTo","restorePositionSetting"],"mappings":"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"}
|
@@ -10,22 +10,26 @@ module Overlastic::Concerns::OverlayHandling
|
|
10
10
|
request.variant = :overlay if helpers.current_overlay_name.present?
|
11
11
|
end
|
12
12
|
|
13
|
-
def close_overlay(key = :last)
|
13
|
+
def close_overlay(key = :last, **options)
|
14
14
|
overlay_name = helpers.overlay_name_from key
|
15
15
|
|
16
|
-
|
17
|
-
end
|
16
|
+
options.filter { |key, _| key.in? self.class._flash_types }.each { |key, value| flash.now[key] = value }
|
18
17
|
|
19
|
-
|
20
|
-
|
18
|
+
if block_given?
|
19
|
+
render overlay: overlay_name, html: helpers.overlastic_tag(id: helpers.current_overlay_name), append_turbo_stream: yield
|
20
|
+
else
|
21
|
+
render overlay: overlay_name, html: helpers.overlastic_tag(id: helpers.current_overlay_name)
|
22
|
+
end
|
23
|
+
end
|
21
24
|
|
25
|
+
def render(*args, **options, &block)
|
22
26
|
# Force render of overlays without an initiator
|
23
27
|
request.headers["Overlay-Target"] ||= options.delete(:overlay_target)
|
24
28
|
request.headers["Overlay-Type"] ||= options.delete(:overlay_type)
|
25
29
|
request.headers["Overlay-Args"] ||= options.delete(:overlay_args)&.to_json
|
26
30
|
|
27
|
-
#
|
28
|
-
|
31
|
+
# If renderable content other than HTML is passed we should avoid returning a stream
|
32
|
+
avoid_stream = _renderers.excluding(:html).intersection(options.keys).present?
|
29
33
|
|
30
34
|
# Rendering with an error status should render inside the overlay
|
31
35
|
error = Rack::Utils.status_code(options[:status]).in? 400..499
|
@@ -43,23 +47,32 @@ module Overlastic::Concerns::OverlayHandling
|
|
43
47
|
overlay = options.delete :overlay
|
44
48
|
overlay_name = helpers.overlay_name_from(overlay || helpers.current_overlay_name)
|
45
49
|
|
46
|
-
if
|
47
|
-
|
50
|
+
if overlastic_enabled
|
51
|
+
if overlay
|
52
|
+
options[:layout] = false
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
else
|
58
|
-
request.headers["Turbo-Frame"] = nil
|
59
|
-
response.headers["Overlay-Visit"] = request.fullpath
|
54
|
+
if block_given? || options[:html]
|
55
|
+
stream_response = turbo_stream.replace(overlay_name, html: render_to_string(*args, **options, &block))
|
56
|
+
else
|
57
|
+
stream_response = turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
|
58
|
+
end
|
59
|
+
elsif request.variant.overlay?
|
60
|
+
if initiator || error || target != "_top"
|
61
|
+
options[:layout] = false
|
60
62
|
|
61
|
-
|
63
|
+
stream_response = turbo_stream.replace(overlay_name, html: helpers.render_overlay { render_to_string(*args, **options, &block) })
|
64
|
+
else
|
65
|
+
request.headers["Overlay-Name"] = nil
|
66
|
+
end
|
62
67
|
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if stream_response && !avoid_stream
|
71
|
+
super turbo_stream: [
|
72
|
+
stream_response,
|
73
|
+
*options[:append_turbo_stream],
|
74
|
+
*(instance_eval(&Overlastic.configuration.append_turbo_stream) if Overlastic.configuration.append_turbo_stream)
|
75
|
+
]
|
63
76
|
else
|
64
77
|
super
|
65
78
|
end
|
@@ -74,12 +87,10 @@ module Overlastic::Concerns::OverlayHandling
|
|
74
87
|
|
75
88
|
if request.variant.overlay?
|
76
89
|
if overlay_name.present?
|
77
|
-
unless helpers.valid_overlay_name?
|
78
|
-
return render overlay: helpers.current_overlay_name, redirect: location, html: helpers.overlastic_tag(id: helpers.current_overlay_name)
|
79
|
-
end
|
90
|
+
overlay_name = nil unless helpers.valid_overlay_name?(overlay_name)
|
80
91
|
|
81
92
|
request.variant.delete :overlay
|
82
|
-
flash.merge! response_options.
|
93
|
+
flash.merge! response_options.filter { |key, _| key.in? self.class._flash_types }
|
83
94
|
|
84
95
|
case Rack::Utils.status_code(response_options.fetch(:status, :created))
|
85
96
|
when 300..399 then response_options[:status] = :created
|
@@ -8,12 +8,14 @@ module Overlastic::NavigationHelper
|
|
8
8
|
options = options.stringify_keys
|
9
9
|
options["data"] ||= {}
|
10
10
|
|
11
|
+
options["data"][:turbo_stream] = true
|
12
|
+
|
13
|
+
overlay_name = options.delete("overlay")
|
14
|
+
options["data"][:overlay_name] = overlay_name_from(overlay_name || overlay_name_from_overlastic_action(Overlastic.configuration.default_action))
|
15
|
+
|
11
16
|
type = options.delete("overlay_type") || method_type
|
12
17
|
options["data"][:overlay_type] = type if type.present?
|
13
18
|
|
14
|
-
action = options.delete("overlay_action") || Overlastic.configuration.default_action
|
15
|
-
options["data"][:turbo_frame] = turbo_frame_from_overlastic_action(action)
|
16
|
-
|
17
19
|
target = options.delete("overlay_target")
|
18
20
|
options["data"][:overlay_target] = target if target.present?
|
19
21
|
|
@@ -26,12 +28,14 @@ module Overlastic::NavigationHelper
|
|
26
28
|
html_options = html_options.stringify_keys
|
27
29
|
html_options["data"] ||= {}
|
28
30
|
|
31
|
+
html_options["data"][:turbo_stream] = true
|
32
|
+
|
33
|
+
overlay_name = html_options.delete("overlay")
|
34
|
+
html_options["data"][:overlay_name] = overlay_name_from(overlay_name || overlay_name_from_overlastic_action(Overlastic.configuration.default_action))
|
35
|
+
|
29
36
|
type = html_options.delete("overlay_type") || method_type
|
30
37
|
html_options["data"][:overlay_type] = type if type.present?
|
31
38
|
|
32
|
-
action = html_options.delete("overlay_action") || Overlastic.configuration.default_action
|
33
|
-
html_options["data"][:turbo_frame] = turbo_frame_from_overlastic_action(action)
|
34
|
-
|
35
39
|
target = html_options.delete("overlay_target")
|
36
40
|
html_options["data"][:overlay_target] = target if target.present?
|
37
41
|
|
@@ -48,7 +52,7 @@ module Overlastic::NavigationHelper
|
|
48
52
|
|
49
53
|
private
|
50
54
|
|
51
|
-
def
|
55
|
+
def overlay_name_from_overlastic_action(action)
|
52
56
|
case action
|
53
57
|
when :stack
|
54
58
|
overlay_name_from :next
|
@@ -5,20 +5,18 @@ module Overlastic::OverlaysHelper
|
|
5
5
|
target = request.headers["Overlay-Target"] || Overlastic.configuration.default_target
|
6
6
|
args = request.headers["Overlay-Args"]
|
7
7
|
|
8
|
-
|
8
|
+
tag.overlastic id: current_overlay_name || id, src: request.url, data: { overlay_type: type, overlay_target: target, overlay_args: args } do
|
9
9
|
yield
|
10
10
|
|
11
|
-
concat
|
11
|
+
concat tag.overlastic(id: overlay_name_from(:next), data: { overlay_target: Overlastic.configuration.default_target })
|
12
12
|
end
|
13
13
|
else
|
14
|
-
|
14
|
+
tag.overlastic id: id, data: { overlay_target: Overlastic.configuration.default_target }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def current_overlay_name
|
19
|
-
|
20
|
-
|
21
|
-
request.headers["Turbo-Frame"].to_sym
|
19
|
+
request.headers["Overlay-Name"]&.to_sym
|
22
20
|
end
|
23
21
|
|
24
22
|
def overlay_name_from(key)
|
@@ -1,53 +1,83 @@
|
|
1
|
-
// Save the clicked
|
1
|
+
// Save the clicked element for use down the line.
|
2
2
|
addEventListener("click", event => {
|
3
|
-
window._overlasticAnchor = event.target
|
3
|
+
window._overlasticAnchor = event.target
|
4
4
|
}, true)
|
5
5
|
|
6
|
-
// Allow progressive enhancement by telling the server if a request is handled by Turbo
|
6
|
+
// Allow progressive enhancement by telling the server if a request is handled by Turbo.
|
7
7
|
addEventListener("turbo:before-fetch-request", event => {
|
8
8
|
event.detail.fetchOptions.headers["Overlay-Enabled"] = "1"
|
9
9
|
})
|
10
10
|
|
11
11
|
// When an overlay anchor is clicked,
|
12
|
-
// send its type, target and args along with the
|
12
|
+
// send its type, target and args along with the visit request.
|
13
13
|
addEventListener("turbo:before-fetch-request", event => {
|
14
|
-
|
15
|
-
|
16
|
-
const anchor = window._overlasticAnchor
|
14
|
+
const anchor = event.target
|
15
|
+
const name = anchor?.dataset?.overlayName
|
17
16
|
const type = anchor?.dataset?.overlayType
|
18
17
|
const target = anchor?.dataset?.overlayTarget
|
19
18
|
const args = anchor?.dataset?.overlayArgs
|
20
19
|
|
21
|
-
|
20
|
+
if (name?.startsWith("overlay")) {
|
21
|
+
event.detail.fetchOptions.headers["Overlay-Initiator"] = "1"
|
22
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
if (type) {
|
25
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type
|
26
|
+
}
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
if (target) {
|
29
|
+
event.detail.fetchOptions.headers["Overlay-Target"] = target
|
30
|
+
}
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
if (args) {
|
33
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
34
|
+
}
|
33
35
|
}
|
36
|
+
})
|
34
37
|
|
35
|
-
|
38
|
+
// When the redirect script triggers a fetch,
|
39
|
+
// send the current overlay's target along with the visit request.
|
40
|
+
addEventListener("turbo:before-fetch-request", event => {
|
41
|
+
const script = document.querySelector("script[overlay]")
|
42
|
+
|
43
|
+
if (script) {
|
44
|
+
const overlay = document.querySelector(`overlastic[id=${script.getAttribute("overlay")}]`)
|
45
|
+
|
46
|
+
if (overlay) {
|
47
|
+
const name = overlay.id
|
48
|
+
const target = overlay.dataset.overlayTarget
|
49
|
+
const type = overlay.dataset?.overlayType
|
50
|
+
const args = overlay.dataset?.overlayArgs
|
51
|
+
|
52
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name
|
53
|
+
event.detail.fetchOptions.headers["Overlay-Target"] = target
|
54
|
+
event.detail.fetchOptions.headers["Overlay-Initiator"] = "1"
|
55
|
+
|
56
|
+
if (type) {
|
57
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type
|
58
|
+
}
|
59
|
+
|
60
|
+
if (args) {
|
61
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
36
65
|
})
|
37
66
|
|
38
67
|
// When any other element triggers a fetch,
|
39
|
-
// send the current overlay's target along with the
|
68
|
+
// send the current overlay's target along with the visit request.
|
40
69
|
addEventListener("turbo:before-fetch-request", event => {
|
41
|
-
|
42
|
-
|
43
|
-
const frame = event.target.closest("turbo-frame[id^=overlay]")
|
70
|
+
const anchor = window._overlasticAnchor
|
71
|
+
const overlay = anchor.closest("overlastic")
|
44
72
|
|
45
|
-
if (
|
46
|
-
const
|
47
|
-
const
|
48
|
-
const
|
49
|
-
const
|
73
|
+
if (overlay && !anchor.dataset.overlay && !anchor.dataset.overlayName) {
|
74
|
+
const name = overlay.id
|
75
|
+
const target = overlay.dataset.overlayTarget
|
76
|
+
const initiator = overlay.dataset?.overlayInitiator
|
77
|
+
const type = overlay.dataset?.overlayType
|
78
|
+
const args = overlay.dataset?.overlayArgs
|
50
79
|
|
80
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name
|
51
81
|
event.detail.fetchOptions.headers["Overlay-Target"] = target
|
52
82
|
|
53
83
|
if (initiator) {
|
@@ -62,17 +92,6 @@ addEventListener("turbo:before-fetch-request", event => {
|
|
62
92
|
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
63
93
|
}
|
64
94
|
}
|
65
|
-
})
|
66
|
-
|
67
|
-
// Handle frame-to-visit promotions when the server asks for it
|
68
|
-
addEventListener("turbo:before-fetch-response", async event => {
|
69
|
-
const fetchResponse = event.detail.fetchResponse
|
70
|
-
const visit = fetchResponse.response.headers.get("Overlay-Visit")
|
71
|
-
|
72
|
-
if (!visit) return
|
73
|
-
|
74
|
-
const responseHTML = await fetchResponse.responseHTML
|
75
|
-
const { redirected, statusCode } = fetchResponse
|
76
95
|
|
77
|
-
|
96
|
+
delete window._overlasticAnchor
|
78
97
|
})
|
@@ -11,7 +11,7 @@ class PaneElement extends DialogElement {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
window.modalVisitStack.push(lastVisit)
|
14
|
-
Turbo.navigator.history.push(new URL(this.parentElement.src))
|
14
|
+
Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")))
|
15
15
|
}
|
16
16
|
|
17
17
|
close(event, self = false) {
|
@@ -1,10 +1,6 @@
|
|
1
1
|
<%= turbo_stream.append_all "head" do %>
|
2
|
-
<%= javascript_tag nonce: true do %>
|
3
|
-
|
4
|
-
|
5
|
-
frame.dataset.overlayInitiator = "1"
|
6
|
-
frame.src = "<%= escape_javascript location %>"
|
7
|
-
|
2
|
+
<%= javascript_tag nonce: true, overlay: overlay do %>
|
3
|
+
window.Turbo.visit("<%= escape_javascript location %>")
|
8
4
|
document.currentScript.remove()
|
9
5
|
<% end %>
|
10
6
|
<% end %>
|
@@ -23,5 +23,13 @@ module Overlastic
|
|
23
23
|
public_send :"#{overlay_type}_overlay_view_path=", "overlastic/inline/#{overlay_type}"
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
def append_turbo_stream(&block)
|
28
|
+
if block_given?
|
29
|
+
@append_turbo_stream = block
|
30
|
+
else
|
31
|
+
@append_turbo_stream
|
32
|
+
end
|
33
|
+
end
|
26
34
|
end
|
27
35
|
end
|
data/lib/overlastic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: overlastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Zamuner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|