Merge branch 'master' of github.com:flynx/ImageGrid

This commit is contained in:
Alex A. Naanou 2019-10-02 02:55:55 +03:00
commit c09b055ee5
8 changed files with 441 additions and 93 deletions

View File

@ -1,5 +1,18 @@
sync-flash.sh
Syncs a camera flash card to an archive folder.
Dependencies:
- process-archive.sh
- compress-archive.sh (optional)
- bash
For more info see:
sync-flash.sh --help
process-archive.sh process-archive.sh
Processes and prepares the archive folder for viewing. Processes and prepares the archive folder for viewing via
ImageGrid.Viewer.
Dependencies: Dependencies:
- exiftool - exiftool
@ -9,16 +22,18 @@ process-archive.sh
XXX add self dependency check... XXX add self dependency check...
For more info see:
process-archive.bat -- windows version of process-archive.sh (partial) process-archive.sh --help
sync-flash.sh compress-archive.sh
Syncs a camera flash card to an archive folder. compresses raw files.
Dependencies: By default this will NTFS compress sony ARW files, but other
- process-archive.sh compression methods and raw formats are supported...
- bash
For more info see:
compress-archive.sh --help
update-exif.sh update-exif.sh
@ -27,6 +42,12 @@ update-exif.sh
Dependencies: Dependencies:
- exiv2 (to be deprecated) - exiv2 (to be deprecated)
For more info see:
update-exif.sh --help
---
flatten.sh flatten.sh
Flatten flickr/instagram favorite folder structure created by Flatten flickr/instagram favorite folder structure created by
@ -34,11 +55,13 @@ flatten.sh
./<author>/<filename> -> ./ALL/<author> - <filename> ./<author>/<filename> -> ./ALL/<author> - <filename>
vips-tn.sh vips-tn.sh
cleannwcache.bat cleannwcache.bat
extract-metadata.sh extract-metadata.sh
process-archive.bat -- windows version of process-archive.sh (partial)

View File

@ -29,11 +29,11 @@ printhelp(){
echo "Arguments:" echo "Arguments:"
echo " -h --help - print this help and exit." echo " -h --help - print this help and exit."
echo echo
echo " -bz -bzip2 - use bzip2 to compress (default)." echo " -bz -bzip2 - use bzip2 to compress`[[ $ARCH == $ARCH_BZIP2 ]] && echo " (default)" || echo ""`."
echo " -gz -gzip - use gzip to compress." echo " -gz -gzip - use gzip to compress`[[ $ARCH == $ARCH_GZIP ]] && echo " (default)" || echo ""`."
echo " -c -compact - use ntfs compression." echo " -c -compact - use ntfs compression`[[ $ARCH == $ARCH_NTFS ]] && echo " (default)" || echo ""`."
echo echo
echo " -ext EXT - set file extension to compress (default: ARW)" echo " -ext EXT - set file extension to compress (default: ${EXT})"
echo " NOTE: only one -ext is supported now". echo " NOTE: only one -ext is supported now".
echo echo
} }

View File

@ -5,7 +5,8 @@ COUNT=1
TITLE="" TITLE=""
RSYNC=rsync RSYNC=rsync
RSYNCFLAGS="-arptgoA --info=progress2,flist --human-readable" #RSYNCFLAGS="-arptgoA --info=progress2,flist --human-readable"
RSYNCFLAGS="-arpt --info=progress2,flist --human-readable"
CP=cp CP=cp
CPFLAGS=-Rpfv CPFLAGS=-Rpfv
@ -14,6 +15,10 @@ CPFLAGS=-Rpfv
COPY=$RSYNC COPY=$RSYNC
COPYFLAGS=$RSYNCFLAGS COPYFLAGS=$RSYNCFLAGS
COMPRESSOR=./compress-archive.sh
COMPRESS=1
# base mount dir... # base mount dir...
# systems with /mnt # systems with /mnt
if [ -d /mnt ] ; then if [ -d /mnt ] ; then
@ -40,10 +45,20 @@ while true ; do
echo " single shoot." echo " single shoot."
echo " -l|-last last flash card in set, run" echo " -l|-last last flash card in set, run"
echo " process-archive.sh after copying." echo " process-archive.sh after copying."
echo " -b|-base the base dir to look for drives in" echo " -b|-base BASE the base dir to look for drives in"
echo " default: $BASE" echo " default: $BASE"
echo " --rsync use rsync (default)" echo " --rsync use rsync (default)"
echo " --cp use cp" echo " --cp use cp"
if ! [ -z $COMPRESSOR ] ; then
echo " --compress toggle archive compression"
echo " default: `[[ $COMPRESS ]] && echo "on" || echo "off"`"
fi
# notes...
echo
if ! [ -z $COMPRESSOR ] ; then
echo "NOTE: the index is fully usable during the compression stage"
fi
echo "NOTE: cp under Cygwin may messup permissions, use rsync."
echo echo
exit exit
;; ;;
@ -61,17 +76,24 @@ while true ; do
shift shift
;; ;;
-b|-base|--base) -b|-base|--base)
BASE=1 BASE=$2
shift shift 2
;; ;;
-cp|--cp) -cp|--cp)
COPY=cp COPY=cp
COPYFLAGS=-Rpfv COPYFLAGS=-Rpfv
shift
break break
;; ;;
-rsync|--rsync) -rsync|--rsync)
COPY=$RSYNC COPY=$RSYNC
COPYFLAGS=$RSYNCFLAGS COPYFLAGS=$RSYNCFLAGS
shift
break
;;
-compress|--compress)
COMPRESS=`[[ $COMPRESS ]] && echo "" || echo 1`
shift
break break
;; ;;
*) *)
@ -99,7 +121,12 @@ while true ; do
echo "Enter) copy drive ${DRIVE}" echo "Enter) copy drive ${DRIVE}"
fi fi
echo "2) build." echo "2) build."
echo "3) quit." if ! [ -z $COMPRESSOR ] ; then
echo "3) compresion is `[[ $COMPRESS ]] && echo "on" || echo "off"`"
echo "4) quit."
else
echo "3) quit."
fi
read -p ": " RES read -p ": " RES
case $RES in case $RES in
@ -126,8 +153,15 @@ while true ; do
LAST=1 LAST=1
break break
;; ;;
3) 3)
if ! [ -z $COMPRESSOR ] ; then
COMPRESS=`[[ ! $COMPRESS ]] && echo 1 || echo ""`
else
exit
fi
continue
;;
4)
exit exit
;; ;;
@ -138,6 +172,17 @@ while true ; do
esac esac
fi fi
# sanity check...
if ! [ -e "${BASE}/${DRIVE}" ] ; then
echo
echo "ERR: ${BASE}/${DRIVE}: does not exist, nothing to copy."
echo
if [[ $INTERACTIVE || ! $DRIVE ]] ; then
continue
fi
exit
fi
# XXX do a real three digit count... # XXX do a real three digit count...
# single flash card... # single flash card...
SCOUNT=`printf "%03d" $COUNT` SCOUNT=`printf "%03d" $COUNT`
@ -166,7 +211,7 @@ while true ; do
mkdir -vp "$DIR" mkdir -vp "$DIR"
echo "Copying files from ${BASE}/${DRIVE}..." echo "Copying files from ${BASE}/${DRIVE} (`du -hs "${BASE}/${DRIVE}" | cut -f 1`)..."
$COPY $COPYFLAGS ${BASE}/${DRIVE}/* "$DIR" $COPY $COPYFLAGS ${BASE}/${DRIVE}/* "$DIR"
echo "Copying files: done." echo "Copying files: done."
@ -187,4 +232,13 @@ if [[ ! $MULTI || $LAST ]] ; then
echo "Building archive: done." echo "Building archive: done."
fi fi
if [[ $COMPRESS ]] ; then
echo "Compressing archive..."
${COMPRESSOR} "$BASE_DIR"
echo "Compressing archive: done."
fi
echo "`basename "$0"`: done."
# vim:set nowrap :

View File

@ -1,7 +1,32 @@
#!/bin/bash #!/bin/bash
DIR=`pwd` DIR=`pwd`
printhelp(){
echo "Usage: `basename $0` [ARGUMENTS] [PATH]"
echo
echo "Arguments:"
echo " -h --help - print this help and exit."
echo
}
while true ; do
case $1 in
-h|--help)
printhelp
exit
;;
*)
break
;;
esac
done
exifup(){ exifup(){
PREVIEW_DIR=$1 PREVIEW_DIR=$1

View File

@ -0,0 +1,92 @@
#!/bin/bash
# TODO make this runnable from anywhere...
# - prepend paths with './' only if local/relative
BASE_PATH=.
ARCH_BZIP2='bzip2 -v {}'
ARCH_GZIP='gzip -v {}'
# XXX should we cygpath -w all the inputs???
ARCH_NTFS='compact /c /exe:lzx {}'
# default...
ARCH=$ARCH_NTFS
EXT=ARW
# HACK: this is here to avoid using windows find...
PATH=/bin:$PATH
printhelp(){
echo "Usage: `basename $0` [ARGUMENTS] [PATH]"
echo
echo "Arguments:"
echo " -h --help - print this help and exit."
echo
echo " -bz -bzip2 - use bzip2 to compress`[[ $ARCH == $ARCH_BZIP2 ]] && echo " (default)" || echo ""`."
echo " -gz -gzip - use gzip to compress`[[ $ARCH == $ARCH_GZIP ]] && echo " (default)" || echo ""`."
echo " -c -compact - use ntfs compression`[[ $ARCH == $ARCH_NTFS ]] && echo " (default)" || echo ""`."
echo
echo " -ext EXT - set file extension to compress (default: ${EXT})"
echo " NOTE: only one -ext is supported now".
echo
}
# process args...
while true ; do
case $1 in
-h|--help)
printhelp
exit
;;
# archivers...
-bz|--bzip2)
ARCH=$ARCH_BZIP2
shift
;;
-gz|--gzip)
ARCH=$ARCH_GZIP
shift
;;
-c|--compact)
ARCH=$ARCH_NTFS
shift
;;
# extension to compress...
--ext)
EXT=$2
shift
shift
;;
*)
break
;;
esac
done
# get path...
if [ "$1" ] ; then
BASE_PATH=$1
fi
# do the work...
find "$BASE_PATH" -name \*.${EXT} -exec ${ARCH} \;
echo done.
# vim:set nowrap nospell :

View File

@ -5,7 +5,8 @@ COUNT=1
TITLE="" TITLE=""
RSYNC=rsync RSYNC=rsync
RSYNCFLAGS="-arptgoA --info=progress2,flist --human-readable" #RSYNCFLAGS="-arptgoA --info=progress2,flist --human-readable"
RSYNCFLAGS="-arpt --info=progress2,flist --human-readable"
CP=cp CP=cp
CPFLAGS=-Rpfv CPFLAGS=-Rpfv
@ -14,6 +15,10 @@ CPFLAGS=-Rpfv
COPY=$RSYNC COPY=$RSYNC
COPYFLAGS=$RSYNCFLAGS COPYFLAGS=$RSYNCFLAGS
COMPRESSOR=./compress-archive.sh
COMPRESS=1
# base mount dir... # base mount dir...
# systems with /mnt # systems with /mnt
if [ -d /mnt ] ; then if [ -d /mnt ] ; then
@ -40,10 +45,20 @@ while true ; do
echo " single shoot." echo " single shoot."
echo " -l|-last last flash card in set, run" echo " -l|-last last flash card in set, run"
echo " process-archive.sh after copying." echo " process-archive.sh after copying."
echo " -b|-base the base dir to look for drives in" echo " -b|-base BASE the base dir to look for drives in"
echo " default: $BASE" echo " default: $BASE"
echo " --rsync use rsync (default)" echo " --rsync use rsync (default)"
echo " --cp use cp" echo " --cp use cp"
if ! [ -z $COMPRESSOR ] ; then
echo " --compress toggle archive compression"
echo " default: `[[ $COMPRESS ]] && echo "on" || echo "off"`"
fi
# notes...
echo
if ! [ -z $COMPRESSOR ] ; then
echo "NOTE: the index is fully usable during the compression stage"
fi
echo "NOTE: cp under Cygwin may messup permissions, use rsync."
echo echo
exit exit
;; ;;
@ -61,17 +76,24 @@ while true ; do
shift shift
;; ;;
-b|-base|--base) -b|-base|--base)
BASE=1 BASE=$2
shift shift 2
;; ;;
-cp|--cp) -cp|--cp)
COPY=cp COPY=cp
COPYFLAGS=-Rpfv COPYFLAGS=-Rpfv
shift
break break
;; ;;
-rsync|--rsync) -rsync|--rsync)
COPY=$RSYNC COPY=$RSYNC
COPYFLAGS=$RSYNCFLAGS COPYFLAGS=$RSYNCFLAGS
shift
break
;;
-compress|--compress)
COMPRESS=`[[ $COMPRESS ]] && echo "" || echo 1`
shift
break break
;; ;;
*) *)
@ -99,7 +121,12 @@ while true ; do
echo "Enter) copy drive ${DRIVE}" echo "Enter) copy drive ${DRIVE}"
fi fi
echo "2) build." echo "2) build."
echo "3) quit." if ! [ -z $COMPRESSOR ] ; then
echo "3) compresion is `[[ $COMPRESS ]] && echo "on" || echo "off"`"
echo "4) quit."
else
echo "3) quit."
fi
read -p ": " RES read -p ": " RES
case $RES in case $RES in
@ -126,8 +153,15 @@ while true ; do
LAST=1 LAST=1
break break
;; ;;
3) 3)
if ! [ -z $COMPRESSOR ] ; then
COMPRESS=`[[ ! $COMPRESS ]] && echo 1 || echo ""`
else
exit
fi
continue
;;
4)
exit exit
;; ;;
@ -138,6 +172,17 @@ while true ; do
esac esac
fi fi
# sanity check...
if ! [ -e "${BASE}/${DRIVE}" ] ; then
echo
echo "ERR: ${BASE}/${DRIVE}: does not exist, nothing to copy."
echo
if [[ $INTERACTIVE || ! $DRIVE ]] ; then
continue
fi
exit
fi
# XXX do a real three digit count... # XXX do a real three digit count...
# single flash card... # single flash card...
SCOUNT=`printf "%03d" $COUNT` SCOUNT=`printf "%03d" $COUNT`
@ -166,7 +211,7 @@ while true ; do
mkdir -vp "$DIR" mkdir -vp "$DIR"
echo "Copying files from ${BASE}/${DRIVE}..." echo "Copying files from ${BASE}/${DRIVE} (`du -hs "${BASE}/${DRIVE}" | cut -f 1`)..."
$COPY $COPYFLAGS ${BASE}/${DRIVE}/* "$DIR" $COPY $COPYFLAGS ${BASE}/${DRIVE}/* "$DIR"
echo "Copying files: done." echo "Copying files: done."
@ -187,4 +232,13 @@ if [[ ! $MULTI || $LAST ]] ; then
echo "Building archive: done." echo "Building archive: done."
fi fi
if [[ $COMPRESS ]] ; then
echo "Compressing archive..."
${COMPRESSOR} "$BASE_DIR"
echo "Compressing archive: done."
fi
echo "`basename "$0"`: done."
# vim:set nowrap :

View File

@ -1,7 +1,32 @@
#!/bin/bash #!/bin/bash
DIR=`pwd` DIR=`pwd`
printhelp(){
echo "Usage: `basename $0` [ARGUMENTS] [PATH]"
echo
echo "Arguments:"
echo " -h --help - print this help and exit."
echo
}
while true ; do
case $1 in
-h|--help)
printhelp
exit
;;
*)
break
;;
esac
done
exifup(){ exifup(){
PREVIEW_DIR=$1 PREVIEW_DIR=$1

View File

@ -524,17 +524,52 @@ var BaseItemPrototype = {
: undefined }, : undefined },
// XXX BUG: this does not work for nested header elements... // NOTE: these should not clash with user-supplied handlers ('update' does not)...
//
// XXX BUG: calling this on a nested/inlined browser will mess things up...
// ...the issue seems to be with root options not being available
// for partial render in a nested context...
// ...one way to fix this would be to make the options inheritance
// protocol more strict:
// - if no options given use defaults (i.e. this.options)
// - if options given use as-is
// - defaults are taken from this.options if not present
//
// to reproduce: // to reproduce:
// dialog // dialog.disable('2')
// .get({children: true}) // or:
// .update() // dialog.disable('B/C/D/a')
// ...for some reason the affected element is removed from dom... //
// ...in both cases the whole nested browser disappears...
//
// but this works OK:
// dialog.disable('nested/2')
//
// This might also be a side effect of the .dom / .elem set of
// issues...
//
// This issue seems to go away after expanding/collapsing the
// nested item several times, the buttons are gone but the
// subtrees stop vanishing on update -- could this be related
// to .dom/.elem again???
update: function(options){ update: function(options){
this.parent this.parent
&& this.parent.render(this, options) && this.parent.render(this, options)
return this return this },
}, /* XXX this is disabled to avoid user confusion when a user item
// event handler would not call/replicate the top-level (this)
// functionality and this break code relying on it...
// ...for this to work well need to either:
// - separate item options form the item object,
// - force the user to follow strict protocols,
// - use a proxy when accessing items (reverse of #1)
// XXX this also applies to .update(..) above...
focus: function(){
arguments.length == 0
&& this.parent
&& this.parent.focus(this)
return this },
//*/
__init__(...state){ __init__(...state){
@ -785,6 +820,9 @@ object.Constructor('BaseRenderer', {
// placeholders... // placeholders...
root: null, root: null,
isRendered: function(){
throw new Error('.isRendered(..): Not implemented.') },
// component renderers... // component renderers...
elem: function(item, index, path, options){ elem: function(item, index, path, options){
throw new Error('.elem(..): Not implemented.') }, throw new Error('.elem(..): Not implemented.') },
@ -810,6 +848,9 @@ module.TextRenderer =
object.Constructor('TextRenderer', { object.Constructor('TextRenderer', {
__proto__: BaseRenderer.prototype, __proto__: BaseRenderer.prototype,
// always render...
isRendered: function(){ return false },
elem: function(item, index, path, options){ elem: function(item, index, path, options){
return path return path
.slice(0, -1) .slice(0, -1)
@ -840,6 +881,9 @@ module.PathRenderer =
object.Constructor('PathRenderer', { object.Constructor('PathRenderer', {
__proto__: TextRenderer.prototype, __proto__: TextRenderer.prototype,
// always render...
isRendered: function(){ return false },
elem: function(item, index, path, options){ elem: function(item, index, path, options){
return path.join('/') }, return path.join('/') },
inline: function(item, lst, index, path, options){ inline: function(item, lst, index, path, options){
@ -2654,10 +2698,14 @@ var BaseBrowserPrototype = {
return r && typeof(e) != typeof({}) }, true))){ return r && typeof(e) != typeof({}) }, true))){
// reverse index... // reverse index...
index = this index = this
.reduce(function(res, e, i, p){ .reduce(
res.set(e, [i, p]) function(res, e, i, p){
return res res.set(e, [i, p])
}, new Map(), {iterateAll: true}) return res },
new Map(),
Object.assign(
Object.flatCopy(options || {}),
{iterateAll: true}))
var res var res
var Stop = new Error('Stop iteration') var Stop = new Error('Stop iteration')
try { try {
@ -2676,7 +2724,10 @@ var BaseBrowserPrototype = {
throw Stop }) throw Stop })
: pattern ] : pattern ]
// search... // search...
: that.search(pattern, ...args.slice(1)) }) : !(pattern instanceof BaseItem) ?
that.search(pattern, ...args.slice(1))
// not found...
: [] })
.flat() .flat()
.unique() .unique()
} catch(e){ } catch(e){
@ -2946,6 +2997,13 @@ var BaseBrowserPrototype = {
__renderer__: TextRenderer, __renderer__: TextRenderer,
isRendered: function(renderer){
var render = renderer || this.__renderer__
render = render.root == null ?
new render(this, this.options)
: render
return render.isRendered() },
// //
// Render browser... // Render browser...
// .render([options]) // .render([options])
@ -3594,19 +3652,39 @@ var BaseBrowserPrototype = {
// XXX should we force calling update if options are given??? // XXX should we force calling update if options are given???
// ...and should full get passed if at least one call in sequence // ...and should full get passed if at least one call in sequence
// got a full=true??? // got a full=true???
__update_full: undefined, // XXX supported mdoes:
// 'full' | true - make - render - post-render
// 'normal' - render - post-render
// 'partial' - post-render
__update_mode: undefined,
__update_args: undefined, __update_args: undefined,
__update_timeout: undefined, __update_timeout: undefined,
__update_max_timeout: undefined, __update_max_timeout: undefined,
update: makeEventMethod('update', update: makeEventMethod('update',
function(evt, full, options){ function(evt, mode, options){
options = var modes = [
(full && full !== true && full !== false) ? 'full',
full 'normal',
: options 'partial',
full = full === options ? ]
false
: full options = mode instanceof Object ?
mode
: options
mode = mode === options ?
'normal'
: mode === true ?
'full'
: mode
// sanity check...
if(!modes.includes(mode)){
throw new Error(`.update(..): unsupported mode: ${mode}`) }
var m = this.__update_mode
// if the queued mode is deeper than the requested, ignore the requested...
if(m != null && modes.indexOf(mode) > modes.indexOf(m)){
return this }
// queue update...
// NOTE: we can't simply use _update(..) closure for this as // NOTE: we can't simply use _update(..) closure for this as
// it can be called out of two contexts (timeout and // it can be called out of two contexts (timeout and
// max_timeout), one (timeout) is renewed on each call // max_timeout), one (timeout) is renewed on each call
@ -3616,14 +3694,14 @@ var BaseBrowserPrototype = {
// its setTimeout(..)... // its setTimeout(..)...
// storing the arguments in .__update_args would remove // storing the arguments in .__update_args would remove
// this inconsistency... // this inconsistency...
this.__update_mode = mode
var args = this.__update_args = [ var args = this.__update_args = [
[evt, full, [evt, mode,
...(options ? ...(options ?
[options] [options]
: [])], : [])],
options] options]
this.__update_full = (full && args)
|| this.__update_full
var timeout = (options || {}).updateTimeout var timeout = (options || {}).updateTimeout
|| this.options.updateTimeout || this.options.updateTimeout
var max_timeout = (options || {}).updateMaxDelay var max_timeout = (options || {}).updateMaxDelay
@ -3637,20 +3715,22 @@ var BaseBrowserPrototype = {
delete this.__update_timeout }.bind(this) delete this.__update_timeout }.bind(this)
var _update = function(){ var _update = function(){
_clear_timers() _clear_timers()
var full = !!this.__update_full var mode = this.__update_mode
var [args, opts] = this.__update_full var [args, opts] = this.__update_args
|| this.__update_args
delete this.__update_full delete this.__update_mode
delete this.__update_args delete this.__update_args
full // make...
modes.indexOf(mode) <= modes.indexOf('full')
&& this.make(opts) && this.make(opts)
var context = {} // render...
this ;(!this.isRendered((opts || {}).renderer)
// XXX this needs access to render context.... || modes.indexOf(mode) <= modes.indexOf('normal'))
.preRender(opts, (opts || {}).renderer, context) && this
.render(opts, (opts || {}).renderer, context) .preRender(opts, (opts || {}).renderer)
.render(opts, (opts || {}).renderer)
// update...
this.trigger(...args) }.bind(this) this.trigger(...args) }.bind(this)
var _update_n_delay = function(){ var _update_n_delay = function(){
// call... // call...
@ -3771,6 +3851,7 @@ object.Constructor('BaseBrowser',
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// HTML-specific UI...
var KEYBOARD_CONFIG = var KEYBOARD_CONFIG =
module.KEYBOARD_CONFIG = { module.KEYBOARD_CONFIG = {
@ -4034,17 +4115,17 @@ var updateElemClass = function(action, cls, handler){
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Renderer... // HTML Renderer...
// XXX needs testing...
// - partial rendering...
// - local re-rendering...
// XXX HACK: see .nest(..) // XXX HACK: see .nest(..)
var HTMLRenderer = var HTMLRenderer =
module.HTMLRenderer = module.HTMLRenderer =
object.Constructor('HTMLRenderer', { object.Constructor('HTMLRenderer', {
__proto__: BaseRenderer.prototype, __proto__: BaseRenderer.prototype,
isRendered: function(){
return !!this.root.dom },
// secondary renderers... // secondary renderers...
// //
// base dialog... // base dialog...
@ -4654,7 +4735,6 @@ var HTMLBrowserPrototype = {
__item__: HTMLItem, __item__: HTMLItem,
__renderer__: HTMLRenderer, __renderer__: HTMLRenderer,
options: { options: {
__proto__: BaseBrowser.prototype.options, __proto__: BaseBrowser.prototype.options,
@ -5045,29 +5125,28 @@ var HTMLBrowserPrototype = {
__copy: function(text){ __copy: function(text){
navigator.clipboard.writeText(text || this.path) }, navigator.clipboard.writeText(text || this.path) },
// XXX need a better name...
_updateDOMItems: function(){ // Events extensions...
//
// XXX should tweaking DOM be done here or in the renderer???
__update__: function(){
var c = 0 var c = 0
this.forEach(function(e){ this.forEach(function(e){
// shortcut number hint... // shortcut number hint...
if(c < 10 && !e.disabled && !e.hidden){ if(c < 10 && !e.disabled && !e.hidden){
var a = e.attrs = e.attrs || {} var a = e.attrs = e.attrs || {}
c = a['shortcut-number'] = (++c) % 10
e.elem e.elem
&& e.elem.setAttribute('shortcut-number', c) && e.elem.setAttribute('shortcut-number',
a['shortcut-number'] = (c+1) % 10)
// cleanup... // cleanup...
} else { } else {
delete (e.attrs || {})['shortcut-number'] delete (e.attrs || {})['shortcut-number']
e.elem e.elem
&& e.elem.removeAttribute('shortcut-number') && e.elem.removeAttribute('shortcut-number')
} }
c++
}) }, }) },
// Events extensions...
//
// NOTE: this will also kill any user-set keys for disabled/hidden items... // NOTE: this will also kill any user-set keys for disabled/hidden items...
//
// XXX also handle global button keys... // XXX also handle global button keys...
__preRender__: function(evt, options, renderer, context){ __preRender__: function(evt, options, renderer, context){
var that = this var that = this
@ -5079,18 +5158,6 @@ var HTMLBrowserPrototype = {
var i = 0 var i = 0
this.map(function(e){ this.map(function(e){
// shortcut number hint...
// NOTE: these are just hints, the actual keys are handled
// in .keybindings...
// XXX move this to the renderer...
if(i < 10 && !e.disabled && !e.hidden){
var attrs = e.attrs = e.attrs || {}
attrs['shortcut-number'] = (++i) % 10
// cleanup...
} else {
delete (e.attrs || {})['shortcut-number']
}
// handle item keys... // handle item keys...
if(!e.disabled && !e.hidden){ if(!e.disabled && !e.hidden){
;((e.value instanceof Array ? ;((e.value instanceof Array ?
@ -5140,7 +5207,7 @@ var HTMLBrowserPrototype = {
block: 'nearest', block: 'nearest',
}) })
}) })
// set focus... // XXX do we need this???
.focus() }, .focus() },
__blur__: function(evt, elem){ __blur__: function(evt, elem){
var that = this var that = this
@ -5157,14 +5224,22 @@ var HTMLBrowserPrototype = {
// element up to reveal the expanded subtree... // element up to reveal the expanded subtree...
// ...would also be logical to "show" the expanded tree but // ...would also be logical to "show" the expanded tree but
// keeping the focused elem in view... // keeping the focused elem in view...
__expand__: function(evt, elem){ elem.update() }, __expand__: function(evt, elem){
__collapse__: function(evt, elem){ elem.update() }, elem.update()
this.update('partial') },
__collapse__: function(evt, elem){
elem.update()
this.update('partial') },
__select__: updateElemClass('add', 'selected'), __select__: updateElemClass('add', 'selected'),
__deselect__: updateElemClass('remove', 'selected'), __deselect__: updateElemClass('remove', 'selected'),
__disable__: updateElemClass('add', 'disabled', __disable__: updateElemClass('add', 'disabled',
function(evt, elem){ elem.update() }), function(evt, elem){
elem.update()
this.update('partial') }),
__enable__: updateElemClass('remove', 'disabled', __enable__: updateElemClass('remove', 'disabled',
function(evt, elem){ elem.update() }), function(evt, elem){
elem.update()
this.update('partial') }),
__hide__: updateElemClass('add', 'hidden'), __hide__: updateElemClass('add', 'hidden'),
__show__: updateElemClass('remove', 'hidden'), __show__: updateElemClass('remove', 'hidden'),