From eb8fe7622a6b9a57dd4c75aafa2a2869640c54bc Mon Sep 17 00:00:00 2001 From: barbie-bot Date: Sat, 4 Apr 2026 14:16:34 +0000 Subject: [PATCH] Fix autofocus on dynamically inserted forms, remove this.blur() handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit form_controller.connect() now blurs the previously focused element and explicitly focuses the [autofocus] element when a form is inserted into the DOM (via Turbo Stream). Only runs when an [autofocus] element is present, so closing forms and other stream updates are unaffected. Remove all onclick='this.blur()' inline handlers from templates — they were a workaround for the same autofocus problem, now solved properly via the Stimulus lifecycle. Co-Authored-By: Claude Sonnet 4.6 --- app/javascript/controllers/form_controller.js | 8 ++++++++ app/views/measurements/_readout.html.erb | 2 +- app/views/measurements/_wide_table.html.erb | 2 +- app/views/measurements/index.html.erb | 2 +- app/views/quantities/_quantity.html.erb | 4 ++-- app/views/quantities/index.html.erb | 2 +- app/views/units/_unit.html.erb | 4 ++-- app/views/units/index.html.erb | 2 +- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/javascript/controllers/form_controller.js b/app/javascript/controllers/form_controller.js index 2f92cf5..94a4a2e 100644 --- a/app/javascript/controllers/form_controller.js +++ b/app/javascript/controllers/form_controller.js @@ -1,6 +1,14 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { + connect() { + const autofocusEl = this.element.querySelector('[autofocus]') + if (autofocusEl) { + document.activeElement?.blur() + autofocusEl.focus() + } + } + processKey(event) { switch (event.key) { case "Escape": diff --git a/app/views/measurements/_readout.html.erb b/app/views/measurements/_readout.html.erb index ab1c864..4220aa5 100644 --- a/app/views/measurements/_readout.html.erb +++ b/app/views/measurements/_readout.html.erb @@ -4,7 +4,7 @@ <% if current_user.at_least(:active) %> <%= link_to readout.quantity, edit_measurement_path(readout), - class: 'link', onclick: 'this.blur();', data: {turbo_stream: true} %> + class: 'link', data: {turbo_stream: true} %> <% else %> <%= readout.quantity %> <% end %> diff --git a/app/views/measurements/_wide_table.html.erb b/app/views/measurements/_wide_table.html.erb index e9be2be..f3ca21d 100644 --- a/app/views/measurements/_wide_table.html.erb +++ b/app/views/measurements/_wide_table.html.erb @@ -20,7 +20,7 @@ <% if current_user.at_least(:active) %> <%= link_to format("%.10g", readout.value), edit_measurement_path(readout, view: :wide), - class: 'link', onclick: 'this.blur();', + class: 'link', data: {turbo_stream: true} %> <% else %> <%= format("%.10g", readout.value) %> diff --git a/app/views/measurements/index.html.erb b/app/views/measurements/index.html.erb index 7f24cf2..7acc8be 100644 --- a/app/views/measurements/index.html.erb +++ b/app/views/measurements/index.html.erb @@ -2,7 +2,7 @@
<% if current_user.at_least(:active) %> <%= image_link_to t('.new_measurement'), 'plus-outline', new_measurement_path, - id: :new_measurement_link, onclick: 'this.blur();', + id: :new_measurement_link, data: {turbo_stream: true} %> <% end %> <%= image_button_tag '', 'view-rows', name: nil, type: 'button', diff --git a/app/views/quantities/_quantity.html.erb b/app/views/quantities/_quantity.html.erb index a21996c..f0aaedb 100644 --- a/app/views/quantities/_quantity.html.erb +++ b/app/views/quantities/_quantity.html.erb @@ -8,7 +8,7 @@ <%= link_to quantity, edit_quantity_path(quantity), class: 'link', - onclick: 'this.blur();', data: {turbo_stream: true} %> + data: {turbo_stream: true} %> <%= quantity.description %> <%= quantity.default_unit&.symbol %> @@ -16,7 +16,7 @@ <% if current_user.at_least(:active) %> <%= image_link_to t('.new_subquantity'), 'plus-outline', new_quantity_path(quantity), - id: dom_id(quantity, :new, :link), onclick: 'this.blur();', data: {turbo_stream: true} %> + id: dom_id(quantity, :new, :link), data: {turbo_stream: true} %> <%= image_button_to_if quantity.destroyable?, t('.destroy'), 'delete-outline', quantity_path(quantity), method: :delete %> diff --git a/app/views/quantities/index.html.erb b/app/views/quantities/index.html.erb index c52c6fe..80276b9 100644 --- a/app/views/quantities/index.html.erb +++ b/app/views/quantities/index.html.erb @@ -1,7 +1,7 @@
<% if current_user.at_least(:active) %> <%= image_link_to t('.new_quantity'), 'plus-outline', new_quantity_path, - id: dom_id(Quantity, :new, :link), onclick: 'this.blur();', + id: dom_id(Quantity, :new, :link), data: {turbo_stream: true} %> <% end %> <%#= image_link_to t('.import_quantities'), 'download-outline', default_quantities_path, diff --git a/app/views/units/_unit.html.erb b/app/views/units/_unit.html.erb index 1608d4d..12ac8c2 100644 --- a/app/views/units/_unit.html.erb +++ b/app/views/units/_unit.html.erb @@ -7,7 +7,7 @@ drag_drop_id_param_value: 'unit[base_id]'} do %> - <%= link_to unit, edit_unit_path(unit), class: 'link', onclick: 'this.blur();', + <%= link_to unit, edit_unit_path(unit), class: 'link', data: {turbo_stream: true} %> <%= unit.description %> @@ -17,7 +17,7 @@ <% unless unit.base_id? %> <%= image_link_to t('.new_subunit'), 'plus-outline', new_unit_path(unit), - id: dom_id(unit, :new, :link), onclick: 'this.blur();', data: {turbo_stream: true} %> + id: dom_id(unit, :new, :link), data: {turbo_stream: true} %> <% end %> <%= image_button_to_if unit.movable?, t('.destroy'), 'delete-outline', unit_path(unit), diff --git a/app/views/units/index.html.erb b/app/views/units/index.html.erb index 42652c3..30b91bf 100644 --- a/app/views/units/index.html.erb +++ b/app/views/units/index.html.erb @@ -1,7 +1,7 @@
<% if current_user.at_least(:active) %> <%= image_link_to t('.new_unit'), 'plus-outline', new_unit_path, - id: dom_id(Unit, :new, :link), onclick: 'this.blur();', data: {turbo_stream: true} %> + id: dom_id(Unit, :new, :link), data: {turbo_stream: true} %> <% end %> <%= image_link_to t('.import_units'), 'download-outline', default_units_path, class: 'tools-area' %>