diff --git a/src/journal/tests/test_journal_frontend.py b/src/journal/tests/test_journal_frontend.py
index 6b94cbe600..63e3a85041 100644
--- a/src/journal/tests/test_journal_frontend.py
+++ b/src/journal/tests/test_journal_frontend.py
@@ -1,3 +1,8 @@
+import os
+import shutil
+
+from django.conf import settings
+from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils import timezone
@@ -8,6 +13,7 @@
from press.models import Press
from utils.testing import helpers
from utils import setting_handler
+from core import files as core_files
from core import models as core_models
from submission import models as submission_models
@@ -270,3 +276,85 @@ def test_search_excludes_artucle(self):
response,
self.article_title,
)
+
+
+class TestTableModalKeyboardDismiss(TestCase):
+ """
+ Regression tests for #5387: the enlarged-table modal must be keyboard
+ dismissable. Without tabindex="-1" on the modal, Bootstrap cannot move
+ focus into it, so keyboard users can never reach the close button.
+ """
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.press = helpers.create_press()
+ cls.journal_domain = "tablemodal.janeway.systems"
+ cls.journal = make_test_journal(
+ code="tablemodal",
+ domain=cls.journal_domain,
+ )
+ setting_handler.save_setting(
+ "general",
+ "journal_theme",
+ cls.journal,
+ "clean",
+ )
+ helpers.create_roles(["Author"])
+ cls.owner = helpers.create_user(
+ "table_modal_owner@janeway.systems",
+ ["author"],
+ cls.journal,
+ )
+ cls.article = helpers.create_article(
+ journal=cls.journal,
+ title="An article with a table",
+ stage=submission_models.STAGE_PUBLISHED,
+ date_published=timezone.now(),
+ owner=cls.owner,
+ )
+ galley_html = (
+ '
"
+ )
+ uploaded_file = SimpleUploadedFile(
+ "tables.html",
+ galley_html.encode("utf-8"),
+ content_type="text/html",
+ )
+ file_obj = core_files.save_file_to_article(
+ uploaded_file,
+ cls.article,
+ cls.owner,
+ label="HTML",
+ is_galley=True,
+ )
+ cls.galley = helpers.create_galley(
+ cls.article,
+ file_obj=file_obj,
+ label="HTML",
+ type="html",
+ )
+ cls.addClassCleanup(
+ shutil.rmtree,
+ os.path.join(settings.BASE_DIR, "files", "articles", str(cls.article.pk)),
+ ignore_errors=True,
+ )
+
+ def test_table_modal_is_focusable_for_keyboard_dismissal(self):
+ response = self.client.get(
+ reverse(
+ "article_view",
+ kwargs={
+ "identifier_type": "id",
+ "identifier": self.article.pk,
+ },
+ ),
+ SERVER_NAME=self.journal_domain,
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertContains(
+ response,
+ 'id="table-T1" tabindex="-1"',
+ )
diff --git a/src/static/common/js/reversable-links.js b/src/static/common/js/reversable-links.js
index a236897e7b..28bb8cdeae 100644
--- a/src/static/common/js/reversable-links.js
+++ b/src/static/common/js/reversable-links.js
@@ -47,15 +47,26 @@ function drawUserAttention(targetElement){
element.tabIndex = "-1"
element.focus();
+ const restoreTabIndex = () => {
+ if (oldTabIndex === null) {
+ element.removeAttribute('tabIndex');
+ } else {
+ element.tabIndex = oldTabIndex;
+ }
+ };
+
const timeout = setTimeout(() => {
element.classList.remove('draw-attention');
if (element.classList.length === 0) {
element.removeAttribute('class');
}
- if (oldTabIndex === null) {
- element.removeAttribute('tabIndex');
+ if (document.activeElement === element) {
+ // Removing tabindex while the element is focused sends focus
+ // back to , so tabbing would restart from the top of
+ // the page. Wait until focus moves on before restoring.
+ element.addEventListener('blur', restoreTabIndex, { once: true });
} else {
- element.tabIndex = oldTabIndex;
+ restoreTabIndex();
}
attentionTimeouts.delete(element);
}, 2000);
diff --git a/src/templates/common/elements/journal/article_authors_full.html b/src/templates/common/elements/journal/article_authors_full.html
index 02e8d88c66..fd4d103911 100644
--- a/src/templates/common/elements/journal/article_authors_full.html
+++ b/src/templates/common/elements/journal/article_authors_full.html
@@ -1,4 +1,4 @@
-
+
{% for author in article.frozen_authors.all %}
- {% include "common/elements/journal/article_author_display.html" %}
{% endfor %}
diff --git a/src/themes/clean/templates/elements/journal/table_modal.html b/src/themes/clean/templates/elements/journal/table_modal.html
index 5d556521b9..d5423aa334 100644
--- a/src/themes/clean/templates/elements/journal/table_modal.html
+++ b/src/themes/clean/templates/elements/journal/table_modal.html
@@ -1,5 +1,5 @@
-