overlastic 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +60 -15
- data/app/assets/javascripts/overlastic.js +47 -42
- 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 +56 -48
- 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 +1 -1
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,13 +203,7 @@ var enableBodyScroll$1 = function enableBodyScroll(targetElement) {
|
|
203
203
|
};
|
204
204
|
|
205
205
|
addEventListener("click", (event => {
|
206
|
-
window._overlasticAnchor = event.target
|
207
|
-
}), true);
|
208
|
-
|
209
|
-
addEventListener("turbo:before-fetch-request", (event => {
|
210
|
-
if (!event.target.hasAttribute("cancel")) return;
|
211
|
-
event.preventDefault();
|
212
|
-
event.target.removeAttribute("cancel");
|
206
|
+
window._overlasticAnchor = event.target;
|
213
207
|
}), true);
|
214
208
|
|
215
209
|
addEventListener("turbo:before-fetch-request", (event => {
|
@@ -217,32 +211,58 @@ addEventListener("turbo:before-fetch-request", (event => {
|
|
217
211
|
}));
|
218
212
|
|
219
213
|
addEventListener("turbo:before-fetch-request", (event => {
|
220
|
-
|
221
|
-
const
|
214
|
+
const anchor = event.target;
|
215
|
+
const name = anchor?.dataset?.overlayName;
|
222
216
|
const type = anchor?.dataset?.overlayType;
|
223
217
|
const target = anchor?.dataset?.overlayTarget;
|
224
218
|
const args = anchor?.dataset?.overlayArgs;
|
225
|
-
|
226
|
-
|
227
|
-
event.detail.fetchOptions.headers["Overlay-
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
+
}
|
231
231
|
}
|
232
|
-
|
233
|
-
|
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
|
+
}
|
234
253
|
}
|
235
|
-
delete window._overlasticTarget;
|
236
254
|
}));
|
237
255
|
|
238
256
|
addEventListener("turbo:before-fetch-request", (event => {
|
239
|
-
|
240
|
-
const
|
241
|
-
if (
|
242
|
-
const
|
243
|
-
const
|
244
|
-
const
|
245
|
-
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;
|
246
266
|
event.detail.fetchOptions.headers["Overlay-Target"] = target;
|
247
267
|
if (initiator) {
|
248
268
|
event.detail.fetchOptions.headers["Overlay-Initiator"] = initiator;
|
@@ -254,22 +274,7 @@ addEventListener("turbo:before-fetch-request", (event => {
|
|
254
274
|
event.detail.fetchOptions.headers["Overlay-Args"] = args;
|
255
275
|
}
|
256
276
|
}
|
257
|
-
|
258
|
-
|
259
|
-
addEventListener("turbo:before-fetch-response", (async event => {
|
260
|
-
const fetchResponse = event.detail.fetchResponse;
|
261
|
-
const visit = fetchResponse.response.headers.get("Overlay-Visit");
|
262
|
-
if (!visit) return;
|
263
|
-
const responseHTML = await fetchResponse.responseHTML;
|
264
|
-
const {redirected: redirected, statusCode: statusCode} = fetchResponse;
|
265
|
-
return Turbo.session.visit(visit, {
|
266
|
-
shouldCacheSnapshot: false,
|
267
|
-
response: {
|
268
|
-
redirected: redirected,
|
269
|
-
statusCode: statusCode,
|
270
|
-
responseHTML: responseHTML
|
271
|
-
}
|
272
|
-
});
|
277
|
+
delete window._overlasticAnchor;
|
273
278
|
}));
|
274
279
|
|
275
280
|
class DialogElement extends HTMLElement {
|
@@ -297,7 +302,7 @@ class PaneElement extends DialogElement {
|
|
297
302
|
window.modalVisitStack = [];
|
298
303
|
}
|
299
304
|
window.modalVisitStack.push(lastVisit);
|
300
|
-
Turbo.navigator.history.push(new URL(this.parentElement.src));
|
305
|
+
Turbo.navigator.history.push(new URL(this.parentElement.getAttribute("src")));
|
301
306
|
}
|
302
307
|
close(event, self = false) {
|
303
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// In order to respect frame behavior, overlay stream responses replace whole frames and\n// come with the correct src. This triggers the frame controller to attempt an eager load.\n// We don't want that for overlays, so we cancel those requests.\naddEventListener(\"turbo:before-fetch-request\", event => {\n if (!event.target.hasAttribute(\"cancel\")) return\n\n event.preventDefault()\n\n event.target.removeAttribute(\"cancel\")\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","hasAttribute","removeAttribute","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,17 +1,6 @@
|
|
1
|
-
// Save the clicked
|
1
|
+
// Save the clicked element for use down the line.
|
2
2
|
addEventListener("click", event => {
|
3
|
-
window._overlasticAnchor = event.target
|
4
|
-
}, true)
|
5
|
-
|
6
|
-
// In order to respect frame behavior, overlay stream responses replace whole frames and
|
7
|
-
// come with the correct src. This triggers the frame controller to attempt an eager load.
|
8
|
-
// We don't want that for overlays, so we cancel those requests.
|
9
|
-
addEventListener("turbo:before-fetch-request", event => {
|
10
|
-
if (!event.target.hasAttribute("cancel")) return
|
11
|
-
|
12
|
-
event.preventDefault()
|
13
|
-
|
14
|
-
event.target.removeAttribute("cancel")
|
3
|
+
window._overlasticAnchor = event.target
|
15
4
|
}, true)
|
16
5
|
|
17
6
|
// Allow progressive enhancement by telling the server if a request is handled by Turbo.
|
@@ -20,45 +9,75 @@ addEventListener("turbo:before-fetch-request", event => {
|
|
20
9
|
})
|
21
10
|
|
22
11
|
// When an overlay anchor is clicked,
|
23
|
-
// send its type, target and args along with the
|
12
|
+
// send its type, target and args along with the visit request.
|
24
13
|
addEventListener("turbo:before-fetch-request", event => {
|
25
|
-
|
26
|
-
|
27
|
-
const anchor = window._overlasticAnchor
|
14
|
+
const anchor = event.target
|
15
|
+
const name = anchor?.dataset?.overlayName
|
28
16
|
const type = anchor?.dataset?.overlayType
|
29
17
|
const target = anchor?.dataset?.overlayTarget
|
30
18
|
const args = anchor?.dataset?.overlayArgs
|
31
19
|
|
32
|
-
|
20
|
+
if (name?.startsWith("overlay")) {
|
21
|
+
event.detail.fetchOptions.headers["Overlay-Initiator"] = "1"
|
22
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name
|
33
23
|
|
34
|
-
|
35
|
-
|
36
|
-
|
24
|
+
if (type) {
|
25
|
+
event.detail.fetchOptions.headers["Overlay-Type"] = type
|
26
|
+
}
|
37
27
|
|
38
|
-
|
39
|
-
|
40
|
-
|
28
|
+
if (target) {
|
29
|
+
event.detail.fetchOptions.headers["Overlay-Target"] = target
|
30
|
+
}
|
41
31
|
|
42
|
-
|
43
|
-
|
32
|
+
if (args) {
|
33
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
34
|
+
}
|
44
35
|
}
|
36
|
+
})
|
37
|
+
|
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
|
+
}
|
45
59
|
|
46
|
-
|
60
|
+
if (args) {
|
61
|
+
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
47
65
|
})
|
48
66
|
|
49
67
|
// When any other element triggers a fetch,
|
50
|
-
// send the current overlay's target along with the
|
68
|
+
// send the current overlay's target along with the visit request.
|
51
69
|
addEventListener("turbo:before-fetch-request", event => {
|
52
|
-
|
53
|
-
|
54
|
-
const frame = event.target.closest("turbo-frame[id^=overlay]")
|
70
|
+
const anchor = window._overlasticAnchor
|
71
|
+
const overlay = anchor.closest("overlastic")
|
55
72
|
|
56
|
-
if (
|
57
|
-
const
|
58
|
-
const
|
59
|
-
const
|
60
|
-
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
|
61
79
|
|
80
|
+
event.detail.fetchOptions.headers["Overlay-Name"] = name
|
62
81
|
event.detail.fetchOptions.headers["Overlay-Target"] = target
|
63
82
|
|
64
83
|
if (initiator) {
|
@@ -73,17 +92,6 @@ addEventListener("turbo:before-fetch-request", event => {
|
|
73
92
|
event.detail.fetchOptions.headers["Overlay-Args"] = args
|
74
93
|
}
|
75
94
|
}
|
76
|
-
})
|
77
|
-
|
78
|
-
// Handle frame-to-visit promotions when the server asks for it.
|
79
|
-
addEventListener("turbo:before-fetch-response", async event => {
|
80
|
-
const fetchResponse = event.detail.fetchResponse
|
81
|
-
const visit = fetchResponse.response.headers.get("Overlay-Visit")
|
82
|
-
|
83
|
-
if (!visit) return
|
84
|
-
|
85
|
-
const responseHTML = await fetchResponse.responseHTML
|
86
|
-
const { redirected, statusCode } = fetchResponse
|
87
95
|
|
88
|
-
|
96
|
+
delete window._overlasticAnchor
|
89
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