Merge pull request #4358 from consul/sdg_related_list_fieldest
Improve goals/targets selector accessibility
This commit is contained in:
@@ -30,11 +30,11 @@
|
||||
var keep_goal = $(amsify_suggestags.selector).val().split(",").some(function(selected_value) {
|
||||
return App.SDGRelatedListSelector.goal_code(value) === App.SDGRelatedListSelector.goal_code(selected_value);
|
||||
});
|
||||
App.SDGRelatedListSelector.goal_element(value).attr("aria-checked", keep_goal);
|
||||
App.SDGRelatedListSelector.goal_element(value).prop("checked", keep_goal);
|
||||
App.SDGRelatedListSelector.manage_remove_help(amsify_suggestags, value);
|
||||
},
|
||||
afterAdd: function(value) {
|
||||
App.SDGRelatedListSelector.goal_element(value).attr("aria-checked", true);
|
||||
App.SDGRelatedListSelector.goal_element(value).prop("checked", true);
|
||||
App.SDGRelatedListSelector.manage_add_help(amsify_suggestags, value);
|
||||
},
|
||||
keepLastOnHoverTag: false,
|
||||
@@ -48,23 +48,24 @@
|
||||
}
|
||||
},
|
||||
manage_icons: function(amsify_suggestags) {
|
||||
$("[role='checkbox']").on("click keydown", function(event) {
|
||||
$(".sdg-related-list-selector .goals input").on("change", function() {
|
||||
var goal_id = this.dataset.code;
|
||||
|
||||
if (event.type === "click" || (event.type === "keydown" && [13, 32].indexOf(event.keyCode) >= 0)) {
|
||||
if (amsify_suggestags.isPresent(goal_id)) {
|
||||
amsify_suggestags.removeTag(goal_id, false);
|
||||
} else {
|
||||
amsify_suggestags.addTag(goal_id, false);
|
||||
}
|
||||
|
||||
if (amsify_suggestags.isPresent(goal_id)) {
|
||||
amsify_suggestags.removeTag(goal_id, false);
|
||||
} else {
|
||||
amsify_suggestags.addTag(goal_id, false);
|
||||
}
|
||||
}).on("keydown", function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
$(this).trigger("click");
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
});
|
||||
},
|
||||
goal_element: function(value) {
|
||||
return $("li[data-code=" + App.SDGRelatedListSelector.goal_code(value) + "]");
|
||||
return $(".sdg-related-list-selector .goals [data-code=" + App.SDGRelatedListSelector.goal_code(value) + "]");
|
||||
},
|
||||
goal_code: function(value) {
|
||||
return value.toString().split(".")[0];
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
width: calc(100% + #{$spacing});
|
||||
width: calc(100% + #{$max-spacing});
|
||||
|
||||
li {
|
||||
> * {
|
||||
margin-bottom: 0;
|
||||
margin-left: $spacing;
|
||||
margin-left: $max-spacing;
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
@include grid-column-gutter;
|
||||
clear: both;
|
||||
|
||||
> legend {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.amsify-suggestags-area .amsify-select-tag {
|
||||
color: $white;
|
||||
|
||||
@@ -12,22 +16,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
label + ul {
|
||||
.goals {
|
||||
$spacing: 0.5%;
|
||||
@include sdg-goal-list($spacing);
|
||||
|
||||
li {
|
||||
legend {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
label {
|
||||
min-width: $sdg-icon-min-width;
|
||||
width: calc(100% / 17 - #{$spacing});
|
||||
|
||||
&[aria-checked=true] img {
|
||||
opacity: 0.15;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: $outline-focus;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -36,6 +37,23 @@
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
@include element-invisible;
|
||||
|
||||
&:focus + label {
|
||||
outline: $outline-focus;
|
||||
}
|
||||
|
||||
&:checked + label img {
|
||||
opacity: 0.15;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.input-section {
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
<div class="sdg-related-list-selector">
|
||||
<div class="input-section">
|
||||
<%= f.label :related_sdg_list %>
|
||||
<fieldset class="sdg-related-list-selector">
|
||||
<legend><%= t("sdg.related_list_selector.title") %></legend>
|
||||
|
||||
<ul aria-label="<%= t("sdg.related_list_selector.goal_list") %>">
|
||||
<% goals.each do |goal| %>
|
||||
<li data-code="<%= goal.code %>" role="checkbox" aria-checked="<%= checked?(goal.code) %>" tabindex="0">
|
||||
<%= render SDG::Goals::IconComponent.new(goal) %>
|
||||
</li>
|
||||
<div class="input-section">
|
||||
<fieldset class="goals">
|
||||
<legend><%= t("sdg.related_list_selector.goal_list", record: relatable_name) %></legend>
|
||||
<%= f.collection_check_boxes(:sdg_goal_ids, goals, :id, :code) do |checkbox_form| %>
|
||||
<%= goal_field(checkbox_form) %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
<%= f.text_field :related_sdg_list,
|
||||
class: "input",
|
||||
label: false,
|
||||
placeholder: t("sdg.related_list_selector.placeholder"),
|
||||
hint: t("sdg.related_list_selector.hint"),
|
||||
label: t("sdg.related_list_selector.hint"),
|
||||
data: { "suggestions-list": sdg_related_suggestions,
|
||||
"remove-tag-text": t("sdg.related_list_selector.remove_tag") } %>
|
||||
</div>
|
||||
|
||||
<div class="help-section callout primary hide">
|
||||
<h3><%= t("sdg.related_list_selector.help.title", record: f.object.model_name.human) %></h3>
|
||||
<h3><%= t("sdg.related_list_selector.help.title", record: relatable_name) %></h3>
|
||||
<ul class="selected-info"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -5,10 +5,6 @@ class SDG::RelatedListSelectorComponent < ApplicationComponent
|
||||
@f = form
|
||||
end
|
||||
|
||||
def checked?(code)
|
||||
f.object.sdg_goals.find_by(code: code).present?
|
||||
end
|
||||
|
||||
def sdg_related_suggestions
|
||||
goals_and_targets.map { |goal_or_target| suggestion_tag_for(goal_or_target) }
|
||||
end
|
||||
@@ -39,6 +35,13 @@ class SDG::RelatedListSelectorComponent < ApplicationComponent
|
||||
SDG::Goal.order(:code)
|
||||
end
|
||||
|
||||
def goal_field(checkbox_form)
|
||||
goal = checkbox_form.object
|
||||
|
||||
checkbox_form.check_box(data: { code: goal.code }) +
|
||||
checkbox_form.label { render(SDG::Goals::IconComponent.new(goal)) }
|
||||
end
|
||||
|
||||
def text_for(goal_or_target)
|
||||
if goal_or_target.class.name == "SDG::Goal"
|
||||
t("sdg.related_list_selector.goal_identifier", code: goal_or_target.code)
|
||||
@@ -46,4 +49,8 @@ class SDG::RelatedListSelectorComponent < ApplicationComponent
|
||||
goal_or_target.code
|
||||
end
|
||||
end
|
||||
|
||||
def relatable_name
|
||||
f.object.model_name.human.downcase
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@ en:
|
||||
attributes:
|
||||
geozone_id: "Scope of operation"
|
||||
results_enabled: "Show results"
|
||||
related_sdg_list: "Sustainable Development Goals and Targets"
|
||||
stats_enabled: "Show stats"
|
||||
advanced_stats_enabled: "Show advanced stats"
|
||||
name: Name
|
||||
|
||||
@@ -455,12 +455,13 @@ en:
|
||||
other: "%{count} more goals"
|
||||
related_list_selector:
|
||||
goal_identifier: "SDG%{code}"
|
||||
goal_list: "Goal list"
|
||||
goal_list: "You can choose one or several SDGs aligned with your %{record}"
|
||||
help:
|
||||
title: "Which SDGs and targets are aligned with my %{record}?"
|
||||
hint: "You can introduce the code of a specific goal/target or a text to find one"
|
||||
placeholder: "Write a goal or target code or description"
|
||||
remove_tag: "Remove"
|
||||
title: "Sustainable Development Goals and Targets"
|
||||
targets:
|
||||
filter:
|
||||
link: "See all %{resources} related to target %{code}"
|
||||
|
||||
@@ -2,7 +2,6 @@ es:
|
||||
attributes:
|
||||
geozone_id: "Ámbito de actuación"
|
||||
results_enabled: "Mostrar resultados"
|
||||
related_sdg_list: "Objetivos de Desarrollo Sostenible y Metas"
|
||||
stats_enabled: "Mostrar estadísticas"
|
||||
advanced_stats_enabled: "Mostrar estadísticas avanzadas"
|
||||
name: Nombre
|
||||
|
||||
@@ -455,12 +455,13 @@ es:
|
||||
other: "%{count} objetivos más"
|
||||
related_list_selector:
|
||||
goal_identifier: "ODS%{code}"
|
||||
goal_list: "Listado de objetivos"
|
||||
goal_list: "Puedes seleccionar uno o varios ODS con los que se alinea tu %{record}"
|
||||
help:
|
||||
title: "¿Qué ODS y metas se alinean con mi %{record}?"
|
||||
hint: "Puedes introducir el código de un objetivo/meta específico o un texto para encontrar uno"
|
||||
placeholder: "Escribe las etiquetas que desees"
|
||||
remove_tag: "Eliminar"
|
||||
title: "Objetivos de Desarrollo Sostenible y Metas"
|
||||
targets:
|
||||
filter:
|
||||
link: "Ver %{resources} de la meta %{code}"
|
||||
|
||||
@@ -45,7 +45,9 @@ module CommonActions
|
||||
end
|
||||
|
||||
def click_sdg_goal(code)
|
||||
find("li[data-code='#{code}']").click
|
||||
within(".sdg-related-list-selector .goals") do
|
||||
find("[data-code='#{code}'] + label").click
|
||||
end
|
||||
end
|
||||
|
||||
def remove_sdg_goal_or_target_tag(code)
|
||||
|
||||
@@ -299,17 +299,17 @@ describe "SDG Relations", :js do
|
||||
create(:sdg_local_target, code: "1.1.1")
|
||||
visit sdg_management_edit_legislation_process_path(process)
|
||||
|
||||
fill_in "Sustainable Development Goals and Targets", with: "3"
|
||||
fill_in "You can introduce the code of a specific goal/target or a text to find one", with: "3"
|
||||
within(".amsify-list") { find(:css, "[data-val='3']").click }
|
||||
|
||||
within(".amsify-suggestags-input-area") { expect(page).to have_content "SDG3" }
|
||||
|
||||
fill_in "Sustainable Development Goals and Targets", with: "1.1"
|
||||
fill_in "You can introduce the code of a specific goal/target or a text to find one", with: "1.1"
|
||||
within(".amsify-list") { find(:css, "[data-val='1.1']").click }
|
||||
|
||||
within(".amsify-suggestags-input-area") { expect(page).to have_content "1.1" }
|
||||
|
||||
fill_in "Sustainable Development Goals and Targets", with: "1.1.1"
|
||||
fill_in "You can introduce the code of a specific goal/target or a text to find one", with: "1.1.1"
|
||||
within(".amsify-list") { find(:css, "[data-val='1.1.1']").click }
|
||||
|
||||
within(".amsify-suggestags-input-area") { expect(page).to have_content "1.1.1" }
|
||||
@@ -327,8 +327,8 @@ describe "SDG Relations", :js do
|
||||
process = create(:legislation_process, title: "SDG process")
|
||||
|
||||
visit sdg_management_edit_legislation_process_path(process)
|
||||
fill_in "You can introduce the code of a specific goal/target or a text to find one", with: "tag nonexistent,"
|
||||
|
||||
fill_in "Sustainable Development Goals and Targets", with: "tag nonexistent,"
|
||||
within(".amsify-suggestags-input-area") { expect(page).not_to have_content "tag nonexistent" }
|
||||
end
|
||||
|
||||
@@ -368,7 +368,7 @@ describe "SDG Relations", :js do
|
||||
visit sdg_management_edit_legislation_process_path(process)
|
||||
click_sdg_goal(1)
|
||||
|
||||
expect(find("li[data-code='1']")["aria-checked"]).to eq "true"
|
||||
expect(find("input[data-code='1']")).to be_checked
|
||||
end
|
||||
|
||||
scenario "when remove a last tag related to a Goal, the icon will not be checked" do
|
||||
@@ -380,15 +380,32 @@ describe "SDG Relations", :js do
|
||||
visit sdg_management_edit_legislation_process_path(process)
|
||||
remove_sdg_goal_or_target_tag(1)
|
||||
|
||||
expect(find("li[data-code='1']")["aria-checked"]).to eq "true"
|
||||
expect(find("input[data-code='1']")).to be_checked
|
||||
|
||||
remove_sdg_goal_or_target_tag(1.1)
|
||||
|
||||
expect(find("li[data-code='1']")["aria-checked"]).to eq "true"
|
||||
expect(find("input[data-code='1']")).to be_checked
|
||||
|
||||
remove_sdg_goal_or_target_tag("1.1.1")
|
||||
|
||||
expect(find("li[data-code='1']")["aria-checked"]).to eq "false"
|
||||
expect(find("input[data-code='1']")).not_to be_checked
|
||||
end
|
||||
|
||||
context "when we have a Goal and a related Target selected" do
|
||||
scenario "we can remove and add same Goal always keeping the icon as checked" do
|
||||
process = create(:legislation_process, title: "SDG process")
|
||||
process.sdg_goals = [SDG::Goal[1]]
|
||||
process.sdg_targets = [SDG::Target[1.1]]
|
||||
|
||||
visit sdg_management_edit_legislation_process_path(process)
|
||||
click_sdg_goal(1)
|
||||
|
||||
expect(find("input[data-code='1']")).to be_checked
|
||||
|
||||
click_sdg_goal(1)
|
||||
|
||||
expect(find("input[data-code='1']")).to be_checked
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user