Module: TurboOverlay::Controller
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/turbo_overlay/controller.rb
Overview
Controller concern. Include in ApplicationController (or any
controller you want overlay-aware):
class ApplicationController < ActionController::Base
include TurboOverlay::Controller
end
The concern auto-installs a layout proc that swaps in the
matching overlay layout for overlay requests and preserves
"turbo_rails/frame" for plain turbo-frame requests (so including
this concern does not regress Turbo's frame-layout optimization).
For apps with a custom layout method, call turbo_overlay_layout
from your method — see the README "A note on custom layouts"
section.
Constant Summary collapse
- OVERLAY_FRAME_PREFIX =
"turbo_overlay_".freeze
- OVERLAY_TYPE_HEADER =
"X-Turbo-Overlay".freeze
- OVERLAY_ID_HEADER =
"X-Turbo-Overlay-Id".freeze
- OVERLAY_POSITION_HEADER =
"X-Turbo-Overlay-Position".freeze
- OVERLAY_ALIGN_HEADER =
"X-Turbo-Overlay-Align".freeze
- OVERLAY_OFFSET_HEADER =
"X-Turbo-Overlay-Offset".freeze
- OVERLAY_BACKDROP_HEADER =
"X-Turbo-Overlay-Backdrop".freeze
- OVERLAY_CLOSE_HEADER =
"X-Turbo-Overlay-Close".freeze
- OVERLAY_KEEP_OPEN_HEADER =
"X-Turbo-Overlay-Keep-Open".freeze
- ALLOWED_POSITIONS =
Whitelists for values that originate from request headers and get reflected into rendered chrome (CSS class tokens, DOM ids, frame names). Constraining them at the resolver protects every downstream consumer — gem partials, generator templates, JS data attributes — without each having to re-validate.
%i[left right top bottom].freeze
- ALLOWED_ALIGNS =
%i[start center end].freeze
- OVERLAY_ID_FORMAT =
/\A[A-Za-z0-9_-]{1,64}\z/.freeze
- OFFSET_RANGE =
(-10_000..10_000).freeze
Instance Method Summary collapse
-
#drawer_request? ⇒ Boolean
----- drawer -----.
-
#hint_request? ⇒ Boolean
----- hint -----.
-
#modal_request? ⇒ Boolean
----- modal -----.
-
#overlay_hintable_request? ⇒ Boolean
True if the current request will use the hint template — either a hover prefetch (which the gem's JS extracts the template from) or an explicit
:hintvariant fetch. -
#overlay_prefetch_request? ⇒ Boolean
True if the current request is a Turbo hover prefetch.
-
#overlay_request? ⇒ Boolean
True if the current request targets any configured overlay (initial open or in-overlay form re-render).
-
#popover_request? ⇒ Boolean
----- popover -----.
-
#turbo_overlay_align ⇒ Object
The per-link cross-axis alignment for popovers, parsed from the
X-Turbo-Overlay-Alignheader. -
#turbo_overlay_backdrop? ⇒ Boolean
Whether the current overlay request should render with a backdrop.
-
#turbo_overlay_close? ⇒ Boolean
Whether the current overlay request should render the chrome's default close ("×") button.
-
#turbo_overlay_frame_re_render? ⇒ Boolean
True when this is a form/link response targeting an existing overlay's turbo-frame (form re-render in place).
-
#turbo_overlay_id ⇒ Object
The overlay id for the current request.
-
#turbo_overlay_initial_open? ⇒ Boolean
True for the initial open of an overlay (an
X-Turbo-Overlayrequest that is not a form re-render inside an existing overlay frame). -
#turbo_overlay_keep_open_on_redirect? ⇒ Boolean
Whether the overlay should stay open when a form descendant submits and the response is a redirect.
-
#turbo_overlay_layout ⇒ Object
Layout name for the current request.
-
#turbo_overlay_offset ⇒ Object
The per-link pixel offset between trigger and popover, parsed from the
X-Turbo-Overlay-Offsetheader. -
#turbo_overlay_position ⇒ Object
The per-link position override for the current overlay request, parsed from the
X-Turbo-Overlay-Positionheader. -
#turbo_overlay_type ⇒ Object
Returns
:modal,:drawer,:popover, ornil.
Instance Method Details
#drawer_request? ⇒ Boolean
----- drawer -----
68 69 70 |
# File 'lib/turbo_overlay/controller.rb', line 68 def drawer_request? == :drawer end |
#hint_request? ⇒ Boolean
----- hint -----
80 81 82 |
# File 'lib/turbo_overlay/controller.rb', line 80 def hint_request? == :hint end |
#modal_request? ⇒ Boolean
----- modal -----
62 63 64 |
# File 'lib/turbo_overlay/controller.rb', line 62 def modal_request? == :modal end |
#overlay_hintable_request? ⇒ Boolean
True if the current request will use the hint template — either
a hover prefetch (which the gem's JS extracts the template from)
or an explicit :hint variant fetch. Gates the +hint variant
auto-render in overlay_stack_tag.
132 133 134 |
# File 'lib/turbo_overlay/controller.rb', line 132 def hint_request? || end |
#overlay_prefetch_request? ⇒ Boolean
True if the current request is a Turbo hover prefetch. Detected
via the X-Sec-Purpose: prefetch request header that Turbo
sends — the W3C Sec-Purpose is a Forbidden Header for
JS-initiated fetch() requests, so Turbo prepends X-. Used
by overlay_stack_tag to decide whether to render the action's
+hint variant template inline.
123 124 125 126 |
# File 'lib/turbo_overlay/controller.rb', line 123 def return false unless respond_to?(:request) && request request.headers["X-Sec-Purpose"].to_s.include?("prefetch") end |
#overlay_request? ⇒ Boolean
True if the current request targets any configured overlay (initial open or in-overlay form re-render). Useful in shared partials.
113 114 115 |
# File 'lib/turbo_overlay/controller.rb', line 113 def !.nil? end |
#popover_request? ⇒ Boolean
----- popover -----
74 75 76 |
# File 'lib/turbo_overlay/controller.rb', line 74 def popover_request? == :popover end |
#turbo_overlay_align ⇒ Object
The per-link cross-axis alignment for popovers, parsed from the
X-Turbo-Overlay-Align header. Returns a Symbol (:start,
:center, :end) or nil. Popover partials fall back to
TurboOverlay.configuration.popover.align.
177 178 179 180 |
# File 'lib/turbo_overlay/controller.rb', line 177 def return @_turbo_overlay_align if defined?(@_turbo_overlay_align) @_turbo_overlay_align = end |
#turbo_overlay_backdrop? ⇒ Boolean
Whether the current overlay request should render with a
backdrop. Defaults to true; only false when the link helper
explicitly passed backdrop: false (carried in the
X-Turbo-Overlay-Backdrop header). Drawer partials switch the
<dialog> open mode and CSS based on this.
196 197 198 199 |
# File 'lib/turbo_overlay/controller.rb', line 196 def return @_turbo_overlay_backdrop if defined?(@_turbo_overlay_backdrop) @_turbo_overlay_backdrop = end |
#turbo_overlay_close? ⇒ Boolean
Whether the current overlay request should render the chrome's
default close ("×") button. Defaults to true; only false
when the link helper explicitly passed close: false (carried in
the X-Turbo-Overlay-Close header). Chrome partials consult
overlay_close? (view helper) which folds this into the full
opt-out precedence chain.
207 208 209 210 |
# File 'lib/turbo_overlay/controller.rb', line 207 def return @_turbo_overlay_close if defined?(@_turbo_overlay_close) @_turbo_overlay_close = end |
#turbo_overlay_frame_re_render? ⇒ Boolean
True when this is a form/link response targeting an existing
overlay's turbo-frame (form re-render in place). Mirrors the
same prefetch guard as _resolve_overlay_type: a hover prefetch
carries the enclosing frame's id in Turbo-Frame but is NOT a
re-render — treating it as one would flip the response
Content-Type to text/vnd.turbo-stream.html (via
_turbo_overlay_set_stream_content_type) for a body that's a
plain <turbo-frame>, an incoherent mismatch.
241 242 243 244 245 |
# File 'lib/turbo_overlay/controller.rb', line 241 def return false unless respond_to?(:request) && request return false if request.headers["Turbo-Frame"].to_s.start_with?(OVERLAY_FRAME_PREFIX) end |
#turbo_overlay_id ⇒ Object
The overlay id for the current request. Resolution order:
X-Turbo-Overlay-Idrequest header (caller suppliedoverlay_id:on the link helper)- The
<id>segment parsed from aTurbo-Frame: turbo_overlay_<type>_<id>header (form re-render) - A freshly generated
SecureRandom.alphanumeric(8)id, memoized for the duration of the request
Available in the controller and in views (e.g. for
turbo_stream.overlay(:close, id: turbo_overlay_id)).
156 157 158 159 |
# File 'lib/turbo_overlay/controller.rb', line 156 def return @_turbo_overlay_id if defined?(@_turbo_overlay_id) @_turbo_overlay_id = end |
#turbo_overlay_initial_open? ⇒ Boolean
True for the initial open of an overlay (an X-Turbo-Overlay
request that is not a form re-render inside an existing
overlay frame). Used internally to decide between turbo-stream
append wrapping and turbo-frame replace wrapping.
228 229 230 231 |
# File 'lib/turbo_overlay/controller.rb', line 228 def return false unless ! end |
#turbo_overlay_keep_open_on_redirect? ⇒ Boolean
Whether the overlay should stay open when a form descendant
submits and the response is a redirect. Defaults to false
(close-on-redirect is the gem's default); becomes true when
the trigger link passed keep_overlay_open_on_redirect: true
(carried in the X-Turbo-Overlay-Keep-Open header). The chrome
partials reflect this onto the <dialog> as a data attribute
the per-dialog submit-end listener reads.
219 220 221 222 |
# File 'lib/turbo_overlay/controller.rb', line 219 def return @_turbo_overlay_keep_open if defined?(@_turbo_overlay_keep_open) @_turbo_overlay_keep_open = end |
#turbo_overlay_layout ⇒ Object
Layout name for the current request. Returns the matching overlay
layout for overlay requests, "turbo_rails/frame" for plain
turbo-frame requests (preserving Turbo's optimization, since our
auto-installed layout proc replaces Turbo's), or nil
otherwise so Rails picks the default layout.
Apps with a custom layout method should call this first:
def custom_layout
|| "my_app_layout"
end
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/turbo_overlay/controller.rb', line 97 def case when :modal then "turbo_overlay/modal" when :drawer then "turbo_overlay/drawer" when :popover then "turbo_overlay/popover" when :hint then "turbo_overlay/hint" else "turbo_rails/frame" if respond_to?(:turbo_frame_request?) && turbo_frame_request? end end |
#turbo_overlay_offset ⇒ Object
The per-link pixel offset between trigger and popover, parsed
from the X-Turbo-Overlay-Offset header. Returns an Integer or
nil. Popover partials fall back to
TurboOverlay.configuration.popover.offset.
186 187 188 189 |
# File 'lib/turbo_overlay/controller.rb', line 186 def return @_turbo_overlay_offset if defined?(@_turbo_overlay_offset) @_turbo_overlay_offset = end |
#turbo_overlay_position ⇒ Object
The per-link position override for the current overlay request,
parsed from the X-Turbo-Overlay-Position header. Returns a
Symbol (:left, :right, :top, :bottom) or nil when the
link didn't supply one. Drawer partials use this with a
fallback to TurboOverlay.configuration.drawer.position;
popover partials use it with a fallback to
TurboOverlay.configuration.popover.position.
168 169 170 171 |
# File 'lib/turbo_overlay/controller.rb', line 168 def return @_turbo_overlay_position if defined?(@_turbo_overlay_position) @_turbo_overlay_position = end |
#turbo_overlay_type ⇒ Object
Returns :modal, :drawer, :popover, or nil. Detected from
the X-Turbo-Overlay request header (initial open) or the
Turbo-Frame: turbo_overlay_<type>_<id> header (form re-render
inside an open overlay).
140 141 142 143 |
# File 'lib/turbo_overlay/controller.rb', line 140 def return @_turbo_overlay_type if defined?(@_turbo_overlay_type) @_turbo_overlay_type = end |