Skip to content

Commit

Permalink
Add bookmark list keyboard navigation (#320)
Browse files Browse the repository at this point in the history
* Add bookmark list keyboard navigation

* Fix focus outline for title link

* Combine bookmark list scripts
  • Loading branch information
sissbruecker authored Aug 14, 2022
1 parent 5af4d41 commit 1308370
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 90 deletions.
127 changes: 127 additions & 0 deletions bookmarks/static/bookmark_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
(function () {
function setupBulkEdit() {
const bulkEditToggle = document.getElementById('bulk-edit-mode')
const bulkEditBar = document.querySelector('.bulk-edit-bar')
const singleToggles = document.querySelectorAll('.bulk-edit-toggle input')
const allToggle = document.querySelector('.bulk-edit-all-toggle input')

function isAllSelected() {
let result = true

singleToggles.forEach(function (toggle) {
result = result && toggle.checked
})

return result
}

function selectAll() {
singleToggles.forEach(function (toggle) {
toggle.checked = true
})
}

function deselectAll() {
singleToggles.forEach(function (toggle) {
toggle.checked = false
})
}

// Toggle all
allToggle.addEventListener('change', function (e) {
if (e.target.checked) {
selectAll()
} else {
deselectAll()
}
})

// Toggle single
singleToggles.forEach(function (toggle) {
toggle.addEventListener('change', function () {
allToggle.checked = isAllSelected()
})
})

// Allow overflow when bulk edit mode is active to be able to display tag auto complete menu
let bulkEditToggleTimeout
if (bulkEditToggle.checked) {
bulkEditBar.style.overflow = 'visible';
}
bulkEditToggle.addEventListener('change', function (e) {
if (bulkEditToggleTimeout) {
clearTimeout(bulkEditToggleTimeout);
bulkEditToggleTimeout = null;
}
if (e.target.checked) {
bulkEditToggleTimeout = setTimeout(function () {
bulkEditBar.style.overflow = 'visible';
}, 500);
} else {
bulkEditBar.style.overflow = 'hidden';
}
});
}

function setupBulkEditTagAutoComplete() {
const wrapper = document.createElement('div');
const tagInput = document.getElementById('bulk-edit-tags-input');
const apiBaseUrl = document.documentElement.dataset.apiBaseUrl || '';
const apiClient = new linkding.ApiClient(apiBaseUrl)

new linkding.TagAutoComplete({
target: wrapper,
props: {
id: 'bulk-edit-tags-input',
name: tagInput.name,
value: tagInput.value,
apiClient: apiClient,
variant: 'small'
}
});

tagInput.parentElement.replaceChild(wrapper, tagInput);
}

function setupListNavigation() {
// Add logic for navigating bookmarks with arrow keys
document.addEventListener('keydown', event => {
// Skip if event occurred within an input element
// or does not use arrow keys
const targetNodeName = event.target.nodeName;
const isInputTarget = targetNodeName === 'INPUT'
|| targetNodeName === 'SELECT'
|| targetNodeName === 'TEXTAREA';
const isArrowUp = event.key === 'ArrowUp';
const isArrowDown = event.key === 'ArrowDown';

if (isInputTarget || !(isArrowUp || isArrowDown)) {
return;
}
event.preventDefault();

// Detect current bookmark list item
const path = event.composedPath();
const currentItem = path.find(item => item.hasAttribute && item.hasAttribute('data-is-bookmark-item'));

// Find next item
let nextItem;
if (currentItem) {
nextItem = isArrowUp
? currentItem.previousElementSibling
: currentItem.nextElementSibling;
} else {
// Select first item
nextItem = document.querySelector('li[data-is-bookmark-item]');
}
// Focus first link
if (nextItem) {
nextItem.querySelector('a').focus();
}
});
}

setupBulkEdit();
setupBulkEditTagAutoComplete();
setupListNavigation();
})()
86 changes: 0 additions & 86 deletions bookmarks/static/bulk_edit.js

This file was deleted.

9 changes: 9 additions & 0 deletions bookmarks/styles/bookmarks.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ ul.bookmark-list {
margin: 0;
padding: 0;

.title a {
display: inline-block;
vertical-align: top;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.description {
color: $gray-color-dark;

Expand Down
2 changes: 1 addition & 1 deletion bookmarks/templates/bookmarks/archive.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ <h2>Tags</h2>

<script src="{% static "bundle.js" %}"></script>
<script src="{% static "shared.js" %}"></script>
<script src="{% static "bulk_edit.js" %}"></script>
<script src="{% static "bookmark_list.js" %}"></script>
{% endblock %}
7 changes: 5 additions & 2 deletions bookmarks/templates/bookmarks/bookmark_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
<input type="checkbox" name="bookmark_id" value="{{ bookmark.id }}">
<i class="form-icon"></i>
</label>
<div class="title truncate">
<a href="{{ bookmark.url }}" target="{{ link_target }}" rel="noopener" class="{% if bookmark.unread %}text-italic{% endif %}">{{ bookmark.resolved_title }}</a>
<div class="title">
<a href="{{ bookmark.url }}" target="{{ link_target }}" rel="noopener"
class="{% if bookmark.unread %}text-italic{% endif %}">
{{ bookmark.resolved_title }}
</a>
</div>
<div class="description truncate">
{% if bookmark.tag_names %}
Expand Down
2 changes: 1 addition & 1 deletion bookmarks/templates/bookmarks/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ <h2>Tags</h2>

<script src="{% static "bundle.js" %}"></script>
<script src="{% static "shared.js" %}"></script>
<script src="{% static "bulk_edit.js" %}"></script>
<script src="{% static "bookmark_list.js" %}"></script>
{% endblock %}

0 comments on commit 1308370

Please sign in to comment.