added page up/down actions + tweaks and fixes...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2019-06-12 18:20:32 +03:00
parent 29f2639000
commit 877740182b

View File

@ -684,6 +684,10 @@ var BaseBrowserPrototype = {
// count to the path... // count to the path...
// This will also make re-generating the indexes and searching // This will also make re-generating the indexes and searching
// stable... // stable...
//
// XXX for some odd reason this is sorted wrong...
// ...keys that are numbers for some reason are first and sorted
// by value and not by position...
__item_index_cache: null, __item_index_cache: null,
get index(){ get index(){
return (this.__item_index_cache = return (this.__item_index_cache =
@ -2749,6 +2753,25 @@ var getElem = function(elem){
: elem } : elem }
var focusPage = function(direction){
var d = direction == 'up' ?
'pagetop'
: direction == 'down' ?
'pagebottom'
: null
if(d == null){
throw new Error('focusPage(..): unknown direction: '+ direction)
}
return function(){
var target = this.get(d)
return this.focused === target ?
// scroll one page up and focus page top...
this.focus(this.get(d, 1))
// focus top of current page...
: this.focus(target) } }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var BrowserClassPrototype = { var BrowserClassPrototype = {
@ -2770,6 +2793,12 @@ var BrowserPrototype = {
options: { options: {
__proto__: BaseBrowser.prototype.options, __proto__: BaseBrowser.prototype.options,
// for more docs see:
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
//
// XXX 'smooth' value yields odd results...
//scrollBehavior: 'auto',
hideListHeader: false, hideListHeader: false,
renderHidden: false, renderHidden: false,
@ -2853,8 +2882,8 @@ var BrowserPrototype = {
End: 'focus: "last"', End: 'focus: "last"',
// XXX screen navigation... // XXX screen navigation...
PgUp: 'pageUp', PgUp: 'pageUp!',
PgDown: 'pageDown', PgDown: 'pageDown!',
Enter: 'open', Enter: 'open',
@ -2924,28 +2953,70 @@ var BrowserPrototype = {
// XXX currently direct match only... // XXX currently direct match only...
// ...should we add containment search -- match closest item containing obj... // ...should we add containment search -- match closest item containing obj...
// //
//
// .get('pagetop'[, offset] ..)
//
// .get('pagebottom'[, offset] ..)
//
//
// XXX add support for pixel offset... // XXX add support for pixel offset...
// XXX // XXX
get: function(pattern){ get: function(pattern){
var args = [...arguments].slice(1)
var p = pattern var p = pattern
// XXX skip detached elements...
var getAtPagePosition = function(pos, offset){
pos = pos || 'top'
var lst = this.dom.querySelector('.list')
offset = lst.offsetHeight * (offset || 0)
var st = lst.scrollTop
var H = pos == 'bottom' ?
lst.offsetHeight
: 0
return this.search(true,
function(e, i, p, stop){
var edom = getElem(e)
// first below upper border...
pos == 'top'
&& Math.round(edom.offsetTop
- Math.max(0, st - offset)) >= 0
&& stop(e)
// last above lower border...
pos == 'bottom'
&& Math.round(edom.offsetTop + edom.offsetHeight)
- Math.max(0, st + H + offset) <= 0
&& stop(e) },
{ reverse: pos == 'bottom' ?
'flat'
: false })
.run(function(){
return this instanceof Array ?
undefined
: this }) }.bind(this)
pattern = arguments[0] = pattern = arguments[0] =
// DOM element... // DOM element...
// XXX should we also check for content???
pattern instanceof HTMLElement ? pattern instanceof HTMLElement ?
function(e){ return e.dom === p } function(e){ return e.dom === p || getElem(e) === p }
// jQuery object... // jQuery object...
// XXX should we also check for content???
: (typeof(jQuery) != 'undefined' && pattern instanceof jQuery) ? : (typeof(jQuery) != 'undefined' && pattern instanceof jQuery) ?
function(e){ return p.is(e.dom) } function(e){ return p.is(e.dom) || p.is(getElem(e)) }
: pattern // pagetop + offset...
return pattern == 'pagetop' ? : pattern == 'pagetop' ?
// XXX getAtPagePosition('top',
false // page offset...
typeof(args[0]) == typeof(123) ? args.shift() : 0)
// pagebottom + offset...
: pattern == 'pagebottom' ? : pattern == 'pagebottom' ?
// XXX getAtPagePosition('bottom',
false // page offset...
// call parent... typeof(args[0]) == typeof(123) ? args.shift() : 0)
: object.parent(BrowserPrototype.get, this).call(this, ...arguments) }, // other...
: pattern
// call parent...
return object.parent(BrowserPrototype.get, this).call(this, pattern, ...args) },
// Element renderers... // Element renderers...
@ -2991,10 +3062,12 @@ var BrowserPrototype = {
e.stopPropagation() e.stopPropagation()
d.focus() d.focus()
}) })
/* XXX this messes up scrollbar...
d.addEventListener('focus', d.addEventListener('focus',
function(){ function(){
that.focused that.focused
&& getElem(that.focused).focus() }) && getElem(that.focused).focus() })
//*/
this.dom = d this.dom = d
@ -3021,11 +3094,7 @@ var BrowserPrototype = {
// </div> // </div>
// </div> // </div>
// //
// XXX instrument interactions... // XXX the way focus management is done here feels hack-ish...
// XXX register event handlers...
// XXX HANCK: preventing scrollbar from grabbing focus -- there is
// definitely a better solution implemented in browse.js + ImageGrid
// (the effect seems to be originating out of ImageGrid...)
renderList: function(items, context){ renderList: function(items, context){
var that = this var that = this
var options = context.options || this.options var options = context.options || this.options
@ -3034,6 +3103,9 @@ var BrowserPrototype = {
var dialog = document.createElement('div') var dialog = document.createElement('div')
dialog.classList.add('browse-widget') dialog.classList.add('browse-widget')
dialog.setAttribute('tabindex', '0') dialog.setAttribute('tabindex', '0')
// HACK?: prevent dialog from grabbing focus from item...
dialog.addEventListener('mousedown',
function(evt){ evt.stopPropagation() })
// header... // header...
options.hideListHeader options.hideListHeader
@ -3042,13 +3114,9 @@ var BrowserPrototype = {
// list... // list...
var list = document.createElement('div') var list = document.createElement('div')
list.classList.add('list', 'v-block') list.classList.add('list', 'v-block')
// XXX HACK: prevent scrollbar from grabbing focus... // HACK?: prevent scrollbar from grabbing focus...
list.addEventListener('mousedown', list.addEventListener('mousedown',
function(){ function(evt){ evt.stopPropagation() })
setTimeout(function(){
that.focused
&& !list.querySelector(':focus')
&& that.focused.dom.focus() }, 0) })
items items
.forEach(function(item){ .forEach(function(item){
list.appendChild(item instanceof Array ? list.appendChild(item instanceof Array ?
@ -3318,11 +3386,14 @@ var BrowserPrototype = {
// scroll... // scroll...
// XXX add target posotion (top/bottom/center) -- where to place the item... // XXX do we need this???
scrollTo: function(pattern){ scrollTo: function(pattern, position){
}, var target = this.get(pattern)
center: function(pattern){ target
return this.scrollTo(pattern, 'center', ...[...arguments].slice(1)) }, && getElem(target).scrollIntoView({
behavior: (this.options || {}).scrollBehavior || 'auto',
block: position || 'center',
}) },
// Custom events handlers... // Custom events handlers...
@ -3346,7 +3417,7 @@ var BrowserPrototype = {
this.classList.add('focused') this.classList.add('focused')
this.scrollIntoView({ this.scrollIntoView({
behavior: 'auto', behavior: (that.options || {}).scrollBehavior || 'auto',
block: 'nearest', block: 'nearest',
}) })
}) })
@ -3429,17 +3500,10 @@ var BrowserPrototype = {
.expand() .expand()
: this.next() }, : this.next() },
// navigation relative to page... // XXX should these focus the top/bottom element or and element at
pageTop: function(){ // offset from top/bottom???
this.focus(this.get('pagetop')) }, pageUp: focusPage('up'),
pageBottom: function(){ pageDown: focusPage('down'),
this.focus(this.get('pagebottom')) },
// XXX
pageUp: function(){
this.scrollTo(this.get('pagetop'), 'bottom') },
// XXX should we scroll to the bottom elem (current behavior) or to the one after it???
pageDown: function(){
this.scrollTo(this.get('pagebottom'), 'top') },
} }