forked from fixin.me/fixin.me
Rewrite stream rendering to avoid client-side expanding
* adding streams in client breaks things (e.g. autofocus) * some tasks need to be performed in one stream action to avoid flickering (e.g. table row substitution)
This commit is contained in:
parent
759a0b31b7
commit
1198add901
@ -103,8 +103,6 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def render_turbo_stream(partial, locals)
|
||||
# TODO: extend with smth like "if outside of rendering, render; otherwise
|
||||
# appendChild() template within current render"
|
||||
"Turbo.renderStreamMessage('#{j(render partial: partial, locals: locals)}'); return false;"
|
||||
end
|
||||
|
||||
|
@ -14,6 +14,7 @@ function beforeStreamRender(event) {
|
||||
document.addEventListener('turbo:before-stream-render', beforeStreamRender)
|
||||
*/
|
||||
|
||||
/*
|
||||
Turbo.session.streamMessageRenderer.appendFragment = async function (fragment) {
|
||||
for (let child of [...fragment.children]) {
|
||||
document.documentElement.appendChild(child)
|
||||
@ -32,6 +33,38 @@ Turbo.session.streamMessageRenderer.appendFragment = async function (fragment) {
|
||||
}
|
||||
}
|
||||
|
||||
window.renderTurboStream = function (message) {
|
||||
// Render if not already rendering, otherwise just append fragment to DOM
|
||||
if (document.documentElement.getElementsByTagName("turbo-stream").length == 0) {
|
||||
Turbo.renderStreamMessage(message)
|
||||
} else {
|
||||
Turbo.session.streamMessageRenderer
|
||||
.appendFragment(Turbo.StreamMessage.wrap(message).fragment)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Turbo.StreamElement.prototype.enableElement = function(element) {
|
||||
element.removeAttribute("disabled")
|
||||
element.removeAttribute("aria-disabled")
|
||||
// 'tabindex' is not used explicitly, so removing it is safe
|
||||
element.removeAttribute("tabindex")
|
||||
}
|
||||
|
||||
Turbo.StreamElement.prototype.removePreviousForm = function(form) {
|
||||
const id = form.id
|
||||
const row = document.getElementById(id + "_cached")
|
||||
form.remove()
|
||||
if (row) {
|
||||
row.id = id
|
||||
row.style.display = "revert"
|
||||
}
|
||||
if (form.hasAttribute("data-link-id")) {
|
||||
const link = document.getElementById(form.getAttribute("data-link-id"))
|
||||
this.enableElement(link)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Turbo.StreamActions.disable = function() {
|
||||
this.targetElements.forEach((e) => {
|
||||
@ -42,12 +75,7 @@ Turbo.StreamActions.disable = function() {
|
||||
}
|
||||
|
||||
Turbo.StreamActions.enable = function() {
|
||||
this.targetElements.forEach((e) => {
|
||||
e.removeAttribute("disabled")
|
||||
e.removeAttribute("aria-disabled")
|
||||
// 'tabindex' is not used explicitly, so removing it is safe
|
||||
e.removeAttribute("tabindex")
|
||||
})
|
||||
this.targetElements.forEach((e) => { this.enableElement(e) })
|
||||
}
|
||||
|
||||
Turbo.StreamActions.blur = function() {
|
||||
@ -59,6 +87,43 @@ Turbo.StreamActions.focus = function() {
|
||||
this.targetElements[0].focus({focusVisible: true})
|
||||
}
|
||||
|
||||
Turbo.StreamActions.prepend_form = function() {
|
||||
this.targetElements.forEach((e) => {
|
||||
[...e.getElementsByClassName("form")].forEach((f) => {
|
||||
this.removePreviousForm(f)
|
||||
})
|
||||
e.prepend(this.templateContent)
|
||||
})
|
||||
}
|
||||
|
||||
Turbo.StreamActions.after_form = function() {
|
||||
this.targetElements.forEach((e) => {
|
||||
[...e.parentElement?.getElementsByClassName("form")].forEach((f) => {
|
||||
this.removePreviousForm(f)
|
||||
})
|
||||
e.parentElement?.insertBefore(this.templateContent, e.nextSibling)
|
||||
})
|
||||
}
|
||||
|
||||
Turbo.StreamActions.replace_form = function() {
|
||||
this.targetElements.forEach((e) => {
|
||||
[...e.parentElement?.getElementsByClassName("form")].forEach((f) => {
|
||||
this.removePreviousForm(f)
|
||||
})
|
||||
e.style.display = "none"
|
||||
e.id = e.id + "_cached"
|
||||
e.parentElement?.insertBefore(this.templateContent, e.nextSibling)
|
||||
})
|
||||
}
|
||||
|
||||
Turbo.StreamActions.close_form = function() {
|
||||
this.targetElements.forEach((e) => {
|
||||
this.removePreviousForm(e.closest(".form"))
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
Turbo.StreamActions.click = function() {
|
||||
this.targetElements.forEach((e) => { e.click() })
|
||||
}
|
||||
*/
|
||||
|
@ -1,5 +1,7 @@
|
||||
<%= fields_for @unit do |form| %>
|
||||
<tr id="<%= dom_id(@unit) %>" onkeydown="processKey(event)">
|
||||
<%= tag.tr id: dom_id(@unit), class: "form", onkeydown: "processKey(event)",
|
||||
data: {link_id: link_id} do %>
|
||||
|
||||
<td class="<%= class_names({subunit: @unit.base}) %>">
|
||||
<%= form.text_field :symbol, form: :unit_form, required: true, autofocus: true, size: 12,
|
||||
maxlength: @unit.class.columns_hash['symbol'].limit, autocomplete: "off" %>
|
||||
@ -19,8 +21,8 @@
|
||||
<td class="actions">
|
||||
<%= form.submit form: :unit_form %>
|
||||
<%= image_link_to t(:cancel), "close-circle-outline", units_path, class: 'dangerous',
|
||||
name: :cancel, onclick: render_turbo_stream('form_close', {id: id}) %>
|
||||
name: :cancel, onclick: render_turbo_stream('form_close', {link_id: link_id}) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<!-- TODO: display error_messages_for unit -->
|
||||
<% end %>
|
||||
|
@ -1,3 +1,2 @@
|
||||
<%= @unit.persisted? ? turbo_stream.replace(@unit) : turbo_stream.remove(@unit) %>
|
||||
<%= turbo_stream.enable id %>
|
||||
<%= turbo_stream.focus id %>
|
||||
<%= turbo_stream.close_form @unit %>
|
||||
<%#= turbo_stream.focus link_id %>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<%# TODO: make sure turbo_stream layout is used in new/edit %>
|
||||
<%= turbo_stream.replace @unit, partial: 'form', locals: {id: dom_id(@unit, :edit)} %>
|
||||
|
||||
<%= turbo_stream.update :unit_form_frame do %>
|
||||
<%= form_with model: @unit, html: {id: :unit_form} do %>
|
||||
<% end %>
|
||||
<% end unless @unit.errors.present? %>
|
||||
<% end %>
|
||||
|
||||
<%= turbo_stream.replace_form @unit, partial: 'form', locals: {link_id: dom_id(@unit, :edit)} %>
|
||||
|
@ -1,20 +1,9 @@
|
||||
<% options = {partial: 'form', locals: {id: dom_id(@unit.base || @unit, :add)}} %>
|
||||
<% link_id = dom_id(@unit.base || @unit, :add) %>
|
||||
<%= turbo_stream.disable link_id -%>
|
||||
|
||||
<% if @unit.errors.present? %>
|
||||
<%= turbo_stream.replace @unit, **options -%>
|
||||
<% else %>
|
||||
<%= turbo_stream.disable options[:locals][:id] -%>
|
||||
<%= turbo_stream.click_all 'tbody a[name=cancel]' -%>
|
||||
<%#= turbo_stream.blur_all %>
|
||||
|
||||
<% if @unit.base.nil? %>
|
||||
<%= turbo_stream.prepend :units, **options -%>
|
||||
<% else %>
|
||||
<%= turbo_stream.after @unit.base, **options -%>
|
||||
<% end %>
|
||||
|
||||
<%= turbo_stream.update :unit_form_frame do %>
|
||||
<%= form_with model: @unit, html: {id: :unit_form} do %>
|
||||
<% end %>
|
||||
<%= turbo_stream.update :unit_form_frame do %>
|
||||
<%= form_with model: @unit, html: {id: :unit_form} do %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= turbo_stream.insert_form (@unit.base || :units), partial: 'form', locals: {link_id: link_id} %>
|
||||
|
@ -23,11 +23,27 @@ ActiveSupport.on_load :turbo_streams_tag_builder do
|
||||
action :focus, target, allow_inferred_rendering: false
|
||||
end
|
||||
|
||||
def click(target)
|
||||
action :click, target, allow_inferred_rendering: false
|
||||
#def click(target)
|
||||
# action :click, target, allow_inferred_rendering: false
|
||||
#end
|
||||
|
||||
#def click_all(targets)
|
||||
# action_all :click, targets, allow_inferred_rendering: false
|
||||
#end
|
||||
|
||||
def insert_form(target, content = nil, **rendering, &block)
|
||||
if target.is_a? Symbol
|
||||
action :prepend_form, target, content, **rendering, &block
|
||||
else
|
||||
action :after_form, target, content, **rendering, &block
|
||||
end
|
||||
end
|
||||
|
||||
def click_all(targets)
|
||||
action_all :click, targets, allow_inferred_rendering: false
|
||||
def replace_form(target, content = nil, **rendering, &block)
|
||||
action :replace_form, target, content, **rendering, &block
|
||||
end
|
||||
|
||||
def close_form(target)
|
||||
action :close_form, target, allow_inferred_rendering: false
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user