Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 38 additions & 30 deletions ckanext/unfold/assets/js/unfold-init-jstree.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,6 @@ ckan.module("unfold-init-jstree", function ($, _) {
});
},

_setupKeyboardNavigation: function () {
// Handle TAB, SHIFT+TAB navigation
this.tree.on("keydown.jstree", ".jstree-anchor", (e) => {
if (e.key === "Tab") {
e.preventDefault();
this._handleTabNavigation(e.shiftKey, $(e.currentTarget));
}
});
},

_handleTabNavigation: function (isShiftTab, currentAnchor) {
// Get all visible anchors in the tree
const allAnchors = this.tree.find(".jstree-anchor:visible");
const currentIndex = allAnchors.index(currentAnchor);

let targetIndex;
if (isShiftTab) {
// Move to previous anchor, or stay at first if already there
targetIndex = currentIndex > 0 ? currentIndex - 1 : 0;
} else {
// Move to next anchor, or stay at last if already there
targetIndex = currentIndex < allAnchors.length - 1 ? currentIndex + 1 : allAnchors.length - 1;
}

const targetAnchor = allAnchors.eq(targetIndex);
targetAnchor.focus();
},

_onSuccessRequest: function (data) {
if (data.result.error) {
this._displayErrorReason(data.result.error);
Expand All @@ -89,21 +61,57 @@ ckan.module("unfold-init-jstree", function ($, _) {
plugins.push("sort");
}

// Function to move focus out of the tree on Tab / Shift+Tab
const focusableSelector = "a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex='-1'])";
function moveTab(instance, forward) {
// Get all focusable elements on the page
const focusable = Array.from(document.querySelectorAll(focusableSelector)).filter(function (el) {
return (el.offsetWidth > 0 || el.offsetHeight > 0) && !el.hasAttribute("disabled");
});
// Get focusable elements within the tree
const treeFocusable = Array.from(instance.element[0].querySelectorAll(focusableSelector)).filter(function (el) {
return focusable.indexOf(el) !== -1;
});

if (!treeFocusable.length) return;

if (forward) {
const last = treeFocusable[treeFocusable.length - 1];
const idx = focusable.indexOf(last);
const next = focusable[idx + 1];
if (next) { next.focus(); } else { document.activeElement.blur(); }
} else {
const first = treeFocusable[0];
const idx = focusable.indexOf(first);
const prev = focusable[idx - 1];
if (prev) { prev.focus(); } else { document.activeElement.blur(); }
}
};

this.tree = $(this.el)
.on("ready.jstree", () => {
this.loadState.hide();
this._setupKeyboardNavigation();
})
.on("loading.jstree", () => this.loadState.show())
.on("activate_node.jstree", (_, data) => {
this.tree.jstree('toggle_node', data.node);
this.tree.jstree("toggle_node", data.node);
})
.jstree({
core: {
data: data,
themes: { dots: false },
animation: withAnimation ? 200 : 0,
multiple: false,
keyboard: {
"tab": function (e) {
e.preventDefault();
moveTab(this, true);
},
"shift+tab": function (e) {
e.preventDefault();
moveTab(this, false);
}
},
},
search: {
show_only_matches: this.options.searchShowOnlyMatches,
Expand Down
5 changes: 3 additions & 2 deletions ckanext/unfold/templates/unfold_preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
placeholder="{{ _('Search') }}" aria-label="{{ _('Search') }}" />
</div>

<button class="btn btn-sm" type="submit" aria-label="{{ _('Search icon') }}"><i
class="fa fa-search"></i>
<button class="btn btn-sm" type="submit" title="{{ _('Search') }}" aria-label="{{ _('Search icon') }}">
<i class="fa fa-search"></i>
</button>

<button class="btn btn-sm" id="jstree-search-clear" title="{{ _('Clear search') }}" aria-label="{{ _('Clear search') }}">
Expand All @@ -17,6 +17,7 @@
<button class="btn btn-sm" id="jstree-expand-all" title="{{ _('Expand all folders') }}" aria-label="{{ _('Expand all folders') }}">
<i class="fa fa-folder-open"></i>
</button>

<button class="btn btn-sm" id="jstree-collapse-all" title="{{ _('Collapse all folders') }}" aria-label="{{ _('Collapse all folders') }}">
<i class="fa fa-folder"></i>
</button>
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ckanext-unfold"
version = "2.1.6"
version = "2.1.7"
description = "Provides previews for multiple archive formats"
authors = [
{name = "DataShades", email = "datashades@linkdigital.com.au"},
Expand Down