From 905b76b7b360029274f833c69c1ce2bdf96beaff Mon Sep 17 00:00:00 2001 From: ishikawa999 Date: Thu, 3 Jul 2025 08:26:55 +0000 Subject: [PATCH 2/5] Replace autocomplete input loading icon with SVG --- app/assets/javascripts/application-legacy.js | 44 ++++++++++++++++--- app/assets/stylesheets/application.css | 10 +---- app/assets/stylesheets/rtl.css | 6 --- app/views/groups/_new_users_form.html.erb | 5 ++- app/views/issue_relations/_form.html.erb | 4 +- app/views/issues/_attributes.html.erb | 7 ++- app/views/issues/bulk_edit.html.erb | 3 +- app/views/issues/destroy.html.erb | 3 ++ app/views/members/_new_form.html.erb | 5 ++- .../repositories/_related_issues.html.erb | 6 ++- app/views/timelog/_form.html.erb | 1 + app/views/timelog/bulk_edit.html.erb | 1 + app/views/users/_form.html.erb | 2 +- app/views/watchers/_new.html.erb | 5 ++- 14 files changed, 73 insertions(+), 29 deletions(-) diff --git a/app/assets/javascripts/application-legacy.js b/app/assets/javascripts/application-legacy.js index f7c1de95c..9c2b49f1e 100644 --- a/app/assets/javascripts/application-legacy.js +++ b/app/assets/javascripts/application-legacy.js @@ -748,13 +748,45 @@ function observeAutocompleteField(fieldId, url, options) { source: url, minLength: 2, position: {collision: "flipfit"}, - search: function(){$('#'+fieldId).addClass('ajax-loading');}, - response: function(){$('#'+fieldId).removeClass('ajax-loading');} + search: function(){showAutocompleteLoadingIcon(fieldId)}, + response: function(){restoreAutocompleteSearchIcon(fieldId)} }, options)); $('#'+fieldId).addClass('autocomplete'); }); } +function showAutocompleteLoadingIcon(fieldId) { + const input = document.getElementById(fieldId); + if (!input) return; + + const container = input.closest('p'); + if (!container) return; + + const svg = container.querySelector('svg.svg-search'); + if (!svg) return; + + updateSVGIcon(svg, 'loader'); + svg.classList.remove('svg-search'); + svg.classList.add('svg-loader'); + input.classList.add('ajax-loading'); +} + +function restoreAutocompleteSearchIcon(fieldId) { + const input = document.getElementById(fieldId); + if (!input) return; + + const container = input.closest('p'); + if (!container) return; + + const svg = container.querySelector('svg.svg-loader'); + if (!svg) return; + + updateSVGIcon(svg, 'search'); + svg.classList.remove('svg-loader'); + svg.classList.add('svg-search'); + input.classList.remove('ajax-loading'); +} + function multipleAutocompleteField(fieldId, url, options) { function split(val) { return val.split(/,\s*/); @@ -774,10 +806,10 @@ function multipleAutocompleteField(fieldId, url, options) { minLength: 2, position: {collision: "flipfit"}, search: function () { - $('#' + fieldId).addClass('ajax-loading'); + showAutocompleteLoadingIcon(fieldId); }, response: function () { - $('#' + fieldId).removeClass('ajax-loading'); + restoreAutocompleteSearchIcon(fieldId); }, select: function (event, ui) { var terms = split(this.value); @@ -809,8 +841,8 @@ function observeSearchfield(fieldId, targetId, url) { type: 'get', data: {q: $this.val()}, success: function(data){ if(targetId) $('#'+targetId).html(data); }, - beforeSend: function(){ $this.addClass('ajax-loading'); }, - complete: function(){ $this.removeClass('ajax-loading'); } + beforeSend: function(){ showAutocompleteLoadingIcon(fieldId); }, + complete: function(){ restoreAutocompleteSearchIcon(fieldId); } }); } }; diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 91217f5b5..dfb3e0c90 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -965,7 +965,8 @@ ul.properties li span {font-style:italic;} .total-hours span.hours-int { font-size: 120%; } .autoscroll {overflow-x: auto; padding:1px; margin-bottom: 1.2em; position: relative;} -#user_login, #user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select { width: 90%; } +#user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select { width: 90%; } +#user_login { width: calc(90% - 18px); } #workflow_copy_form select { width: 200px; } table.transitions td.enabled {background: #bfb;} @@ -1199,13 +1200,6 @@ select.bool_cf {width:auto !important;} input#principal_search, input#user_search {width:90%} .roles-selection label {display:inline-block; width:210px;} -input.autocomplete { - background: #fff url(/search.svg) no-repeat 2px 50%; padding-left:20px !important; -} -input.autocomplete.ajax-loading { - background-image: url(/loading.gif); -} - .role-visibility {padding-left:2em;} .objects-selection { diff --git a/app/assets/stylesheets/rtl.css b/app/assets/stylesheets/rtl.css index 20a2a73dc..55555b2ed 100644 --- a/app/assets/stylesheets/rtl.css +++ b/app/assets/stylesheets/rtl.css @@ -230,8 +230,6 @@ fieldset#notified_events .parent {padding-left:0px; padding-right:20px; } .attachments_fields input.description {margin-left:0px; margin-right:4px;} .attachments_fields input.filename {background:url(/attachment.png) no-repeat right 1px top 50%; padding-left:0px; padding-right:18px;} -.attachments_fields .ajax-waiting input.filename {background:url(/hourglass-empty.svg) no-repeat right top 50%;} -.attachments_fields .ajax-loading input.filename {background:url(/loading.gif) no-repeat right top 50%;} .attachments_fields div.ui-progressbar {margin: 2px 8px -5px 0;} a.remove-upload {background: url(/delete.png) no-repeat right 1px top 50%; padding-left:0px; padding-right:16px;} @@ -247,10 +245,6 @@ em.info.error {padding-left:0; padding-right:20px; background:url(/exclamation.p table.members td.name {padding-right: 20px; padding-left:0; } table.members td.group, table.members td.groupnonmember, table.members td.groupanonymous {background: url(/group.png) no-repeat right 50%;} -input.autocomplete { - background: #fff url(/search.svg) no-repeat right 2px top 50%; padding-left:0px !important; padding-right:20px !important; -} - .role-visibility {padding-right:2em; padding-left:0;} /***** Flash & error messages ****/ diff --git a/app/views/groups/_new_users_form.html.erb b/app/views/groups/_new_users_form.html.erb index 5c33a966c..352e3e321 100644 --- a/app/views/groups/_new_users_form.html.erb +++ b/app/views/groups/_new_users_form.html.erb @@ -1,6 +1,9 @@
<%= label_tag "user_search", l(:label_user_search) %> -

<%= text_field_tag 'user_search', nil %>

+

+ <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> + <%= text_field_tag 'user_search', nil %> +

<%= javascript_tag "observeSearchfield('user_search', null, '#{ escape_javascript autocomplete_for_user_group_path(@group) }')" %>
diff --git a/app/views/issue_relations/_form.html.erb b/app/views/issue_relations/_form.html.erb index b55e93eac..fa2377a54 100644 --- a/app/views/issue_relations/_form.html.erb +++ b/app/views/issue_relations/_form.html.erb @@ -11,7 +11,9 @@
<% end %>

<%= f.select :relation_type, collection_for_relation_type_select, {}, :onchange => "setPredecessorFieldsVisibility();" %> -<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :value => unsaved_relations_ids, :size => 10 %> + +<%= l(:label_issue) %> #<%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %><%= f.text_field :issue_to_id, :value => unsaved_relations_ids, :size => 10 %> + diff --git a/app/views/issues/_attributes.html.erb b/app/views/issues/_attributes.html.erb index 970767460..c2aa4ab34 100644 --- a/app/views/issues/_attributes.html.erb +++ b/app/views/issues/_attributes.html.erb @@ -63,9 +63,12 @@

<% if @issue.safe_attribute? 'parent_issue_id' %> -

<%= f.text_field :parent_issue_id, :size => 10, +

+ <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> + <%= f.text_field :parent_issue_id, :size => 9, :required => @issue.required_attribute?('parent_issue_id'), - :onchange => "updateIssueFrom('#{escape_javascript update_issue_form_path(@project, @issue)}', this)" %>

+ :onchange => "updateIssueFrom('#{escape_javascript update_issue_form_path(@project, @issue)}', this)" %> +

<%= javascript_tag "observeAutocompleteField('issue_parent_issue_id', '#{escape_javascript(auto_complete_issues_path(:project_id => @issue.project, :scope => Setting.cross_project_subtasks, :status => @issue.closed? ? 'c' : 'o', :issue_id => @issue.id))}')" %> <% end %> diff --git a/app/views/issues/bulk_edit.html.erb b/app/views/issues/bulk_edit.html.erb index b8bf87beb..fd057d6f4 100644 --- a/app/views/issues/bulk_edit.html.erb +++ b/app/views/issues/bulk_edit.html.erb @@ -146,7 +146,8 @@ <% if @safe_attributes.include?('parent_issue_id') && @project %>

- <%= text_field_tag 'issue[parent_issue_id]', '', :size => 10, :value => @issue_params[:parent_issue_id] %> + <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> + <%= text_field_tag 'issue[parent_issue_id]', '', :size => 9, :value => @issue_params[:parent_issue_id] %>

<%= javascript_tag "observeAutocompleteField('issue_parent_issue_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project, :scope => Setting.cross_project_subtasks)}')" %> diff --git a/app/views/issues/destroy.html.erb b/app/views/issues/destroy.html.erb index e4f0e66fb..df8d6428e 100644 --- a/app/views/issues/destroy.html.erb +++ b/app/views/issues/destroy.html.erb @@ -10,8 +10,11 @@
<% end %> <% if @project %> + +<%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> <%= text_field_tag 'reassign_to_id', params[:reassign_to_id], :size => 6, :onfocus => '$("#todo_reassign").attr("checked", true);' %> + <%= javascript_tag "observeAutocompleteField('reassign_to_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project)}')" %> <% end %>

diff --git a/app/views/members/_new_form.html.erb b/app/views/members/_new_form.html.erb index 70caa2600..d7eced2ae 100644 --- a/app/views/members/_new_form.html.erb +++ b/app/views/members/_new_form.html.erb @@ -1,6 +1,9 @@
<%= label_tag("principal_search", l(:label_principal_search)) %> -

<%= text_field_tag('principal_search', nil) %>

+

+ <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> + <%= text_field_tag('principal_search', nil) %> +

<%= javascript_tag "observeSearchfield('principal_search', null, '#{ escape_javascript autocomplete_project_memberships_path(@project, :format => 'js') }')" %>
<%= render_principals_for_new_members(@project) %> diff --git a/app/views/repositories/_related_issues.html.erb b/app/views/repositories/_related_issues.html.erb index cac85a001..437991118 100644 --- a/app/views/repositories/_related_issues.html.erb +++ b/app/views/repositories/_related_issues.html.erb @@ -32,7 +32,11 @@ :remote => true, :method => :post, :id => 'new-relation-form', :style => (@issue ? '' : 'display: none;')) do |f| %> - <%= l(:label_issue) %> #<%= text_field_tag 'issue_id', '', :size => 10 %> +

+ <%= l(:label_issue) %> # + <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> + <%= text_field_tag 'issue_id', '', :size => 10 %> +

<%= submit_tag l(:button_add) %> <%= toggle_link l(:button_cancel), 'new-relation-form'%> <% end %> diff --git a/app/views/timelog/_form.html.erb b/app/views/timelog/_form.html.erb index 3a0543e7c..e59ebb5af 100644 --- a/app/views/timelog/_form.html.erb +++ b/app/views/timelog/_form.html.erb @@ -11,6 +11,7 @@ <% end %>

+ <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> <%= f.text_field :issue_id, :size => 6, :required => Setting.timelog_required_fields.include?('issue_id') %> <%= link_to_issue(@time_entry.issue) if @time_entry.issue.try(:visible?) %> diff --git a/app/views/timelog/bulk_edit.html.erb b/app/views/timelog/bulk_edit.html.erb index 4f496470a..c588356b5 100644 --- a/app/views/timelog/bulk_edit.html.erb +++ b/app/views/timelog/bulk_edit.html.erb @@ -40,6 +40,7 @@ :onchange => "updateBulkEditFrom('#{escape_javascript url_for(:action => 'bulk_edit', :format => 'js')}')" ) %>

+ <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %> <%= text_field :time_entry, :issue_id, :size => 6 %> diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb index 6d6058c49..a2005c83e 100644 --- a/app/views/users/_form.html.erb +++ b/app/views/users/_form.html.erb @@ -6,7 +6,7 @@

<%=l(:label_information_plural)%> -

<%= f.text_field :login, :required => true, :size => 25 %>

+

<%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %><%= f.text_field :login, :required => true, :size => 25 %>

<%= f.text_field :firstname, :required => true %>

<%= f.text_field :lastname, :required => true %>

<%= f.text_field :mail, :required => true %>

diff --git a/app/views/watchers/_new.html.erb b/app/views/watchers/_new.html.erb index dfff5516c..28293cff0 100644 --- a/app/views/watchers/_new.html.erb +++ b/app/views/watchers/_new.html.erb @@ -21,7 +21,10 @@ title = <% end %> <%= hidden_field_tag 'project_id', @project.id if @project %> -

<%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

+

+ <%= label_tag 'user_search', l(:label_user_search) %>
+ <%= sprite_icon 'search', icon_only: true, css_class: 'svg-search' %><%= text_field_tag 'user_search', nil %> +

<%= javascript_tag( "observeSearchfield( 'user_search', -- 2.49.0