start on trying to save focus for timeline
feels like this isn't really working because I can't distinguish between blur events because the timeline is being destroyed and blur events because the user clicked and we lost focus... not sure how important this feature is, and it adds a lot of complexity in the form of extra attributes to track the focused element
This commit is contained in:
parent
e6bf344aec
commit
820d77a78f
|
@ -1,7 +1,8 @@
|
|||
<article class="status-article {{getClasses(originalStatus, timelineType, isStatusInOwnThread)}}"
|
||||
tabindex="0"
|
||||
delegate-click-key="{{delegateKey}}"
|
||||
delegate-keydown-key="{{delegateKey}}"
|
||||
delegate-click-key="{{elementKey}}"
|
||||
delegate-keydown-key="{{elementKey}}"
|
||||
focus-key="{{elementKey}}"
|
||||
aria-posinset="{{index}}"
|
||||
aria-setsize="{{length}}"
|
||||
aria-label="Status by {{originalStatus.account.display_name || originalStatus.account.username}}"
|
||||
|
@ -94,15 +95,15 @@
|
|||
|
||||
export default {
|
||||
oncreate() {
|
||||
let delegateKey = this.get('delegateKey')
|
||||
let elementKey = this.get('elementKey')
|
||||
let onClickOrKeydown = this.onClickOrKeydown.bind(this)
|
||||
registerDelegate('click', delegateKey, onClickOrKeydown)
|
||||
registerDelegate('keydown', delegateKey, onClickOrKeydown)
|
||||
registerDelegate('click', elementKey, onClickOrKeydown)
|
||||
registerDelegate('keydown', elementKey, onClickOrKeydown)
|
||||
},
|
||||
ondestroy() {
|
||||
let delegateKey = this.get('delegateKey')
|
||||
unregisterDelegate('click', delegateKey)
|
||||
unregisterDelegate('keydown', delegateKey)
|
||||
let elementKey = this.get('elementKey')
|
||||
unregisterDelegate('click', elementKey)
|
||||
unregisterDelegate('keydown', elementKey)
|
||||
},
|
||||
components: {
|
||||
StatusSidebar,
|
||||
|
@ -147,7 +148,7 @@
|
|||
computed: {
|
||||
originalStatus: (status) => status.reblog ? status.reblog : status,
|
||||
statusId: (originalStatus) => originalStatus.id,
|
||||
delegateKey: (statusId, timelineType, timelineValue) => `status-${timelineType}-${timelineValue}-${statusId}`,
|
||||
elementKey: (statusId, timelineType, timelineValue) => `status-${timelineType}-${timelineValue}-${statusId}`,
|
||||
contextualStatusId: ($currentInstance, timelineType, timelineValue, status, notification) => {
|
||||
return `${$currentInstance}/${timelineType}/${timelineValue}/${notification ? notification.id : ''}/${status.id}`
|
||||
},
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
<div class="timeline" role="feed" aria-label="{{label}}">
|
||||
<div class="timeline"
|
||||
role="feed"
|
||||
aria-label="{{label}}"
|
||||
on:focusWithCapture="saveFocus(event)"
|
||||
on:blurWithCapture="clearFocus(event)"
|
||||
>
|
||||
{{#if !$initialized}}
|
||||
<LoadingPage />
|
||||
{{/if}}
|
||||
|
@ -55,11 +60,19 @@
|
|||
import { database } from '../../_database/database'
|
||||
import { initializeTimeline, fetchTimelineItemsOnScrollToBottom, setupTimeline } from '../../_actions/timeline'
|
||||
import LoadingPage from '../LoadingPage.html'
|
||||
import { focusWithCapture, blurWithCapture } from '../../_utils/events'
|
||||
|
||||
export default {
|
||||
async oncreate() {
|
||||
oncreate() {
|
||||
console.log('timeline oncreate()')
|
||||
setupTimeline()
|
||||
if (this.store.get('initialized')) {
|
||||
console.log('initialized!!!!')
|
||||
this.restoreFocus()
|
||||
}
|
||||
},
|
||||
ondestroy() {
|
||||
console.log('ondestroy')
|
||||
},
|
||||
data: () => ({
|
||||
StatusVirtualListItem,
|
||||
|
@ -109,6 +122,10 @@
|
|||
PseudoVirtualList,
|
||||
LoadingPage
|
||||
},
|
||||
events: {
|
||||
focusWithCapture,
|
||||
blurWithCapture
|
||||
},
|
||||
methods: {
|
||||
initialize() {
|
||||
if (this.store.get('initialized') || !this.store.get('timelineItemIds')) {
|
||||
|
@ -124,7 +141,46 @@
|
|||
return
|
||||
}
|
||||
fetchTimelineItemsOnScrollToBottom()
|
||||
}
|
||||
},
|
||||
saveFocus(e) {
|
||||
let instanceName = this.store.get('currentInstance')
|
||||
let timelineName = this.get('timeline')
|
||||
let lastFocusedElementSelector
|
||||
let activeElement = e.target
|
||||
if (activeElement) {
|
||||
let focusKey = activeElement.getAttribute('focus-key')
|
||||
if (focusKey) {
|
||||
lastFocusedElementSelector = `[focus-key=${focusKey}]`
|
||||
}
|
||||
}
|
||||
console.log('saving focus to ', lastFocusedElementSelector)
|
||||
this.store.setForTimeline(instanceName, timelineName, {
|
||||
lastFocusedElementSelector
|
||||
})
|
||||
},
|
||||
clearFocus() {
|
||||
/*console.log('clearing focus')
|
||||
let instanceName = this.store.get('currentInstance')
|
||||
let timelineName = this.get('timeline')
|
||||
this.store.setForTimeline(instanceName, timelineName, {
|
||||
lastFocusedElementSelector: null
|
||||
})*/
|
||||
},
|
||||
restoreFocus() {
|
||||
let lastFocusedElementSelector = this.store.get('lastFocusedElementSelector')
|
||||
console.log('lastFocused', lastFocusedElementSelector)
|
||||
if (lastFocusedElementSelector) {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
let element = document.querySelector(lastFocusedElementSelector)
|
||||
console.log('el', element)
|
||||
if (element) {
|
||||
element.focus()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,11 +1,19 @@
|
|||
|
||||
function computeForTimeline(store, key) {
|
||||
store.compute(key, ['currentTimelineData'], (currentTimelineData) => currentTimelineData[key])
|
||||
}
|
||||
|
||||
|
||||
export function timelineComputations (store) {
|
||||
store.compute('currentTimelineData', ['currentInstance', 'currentTimeline', 'timelines'],
|
||||
(currentInstance, currentTimeline, timelines) => {
|
||||
return ((timelines && timelines[currentInstance]) || {})[currentTimeline] || {}
|
||||
})
|
||||
|
||||
store.compute('timelineItemIds', ['currentTimelineData'], (currentTimelineData) => currentTimelineData.timelineItemIds)
|
||||
store.compute('runningUpdate', ['currentTimelineData'], (currentTimelineData) => currentTimelineData.runningUpdate)
|
||||
store.compute('initialized', ['currentTimelineData'], (currentTimelineData) => currentTimelineData.initialized)
|
||||
computeForTimeline(store, 'timelineItemIds')
|
||||
computeForTimeline(store, 'runningUpdate')
|
||||
computeForTimeline(store, 'initialized')
|
||||
computeForTimeline(store, 'lastFocusedElementSelector')
|
||||
|
||||
store.compute('lastTimelineItemId', ['timelineItemIds'], (timelineItemIds) => timelineItemIds && timelineItemIds.length && timelineItemIds[timelineItemIds.length - 1])
|
||||
}
|
||||
|
|
|
@ -34,3 +34,21 @@ export function mouseover (node, callback) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function focusWithCapture (node, callback) {
|
||||
node.addEventListener('focus', callback, true)
|
||||
return {
|
||||
teardown () {
|
||||
node.removeEventListener('focus', callback, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function blurWithCapture (node, callback) {
|
||||
node.addEventListener('blur', callback, true)
|
||||
return {
|
||||
teardown () {
|
||||
node.removeEventListener('blur', callback, true)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue