mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +00:00
375 lines
10 KiB
JavaScript
Executable File
375 lines
10 KiB
JavaScript
Executable File
/**********************************************************************
|
|
*
|
|
*
|
|
*
|
|
**********************************************************************/
|
|
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)(
|
|
function(require){ var module={} // makes module AMD/node compatible...
|
|
/*********************************************************************/
|
|
|
|
var actions = require('lib/actions')
|
|
var features = require('lib/features')
|
|
|
|
var core = require('features/core')
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
var ProgressActions = actions.Actions({
|
|
config: {
|
|
'progress-pre-delay': 1000,
|
|
'progress-done-delay': 1000,
|
|
'progress-fade-duration': 200,
|
|
|
|
'progress-update-min': 200,
|
|
|
|
// Logger keywords / aliases that trigger progress actions...
|
|
//
|
|
// The builtin keywords / aliases are:
|
|
// add / added - add one or more item to progress bar
|
|
// done - move the progress bar by 1
|
|
// skip / skipped - move the progress bar by 1
|
|
// close / closed - close the progress bar
|
|
// error - report error
|
|
//
|
|
// The progress bar will be created on first 'add' call.
|
|
//
|
|
// The progress bar will be closed when the number of added items
|
|
// is less or equal to the number of done or skipped items.
|
|
//
|
|
//
|
|
// For example:
|
|
// var log = logger.push('Example') // - define a logger...
|
|
// log.emit('add', 'some item...') // - creates a progress bar
|
|
// // with one item...
|
|
// log.emit('add', [ ... ]) // - adds multiple items to
|
|
// // progress bar...
|
|
// ...
|
|
// log.emit('done', 'some item...') // - close the progress bar
|
|
// ...
|
|
//
|
|
//
|
|
// Format:
|
|
// {
|
|
// <keyword>: [
|
|
// <alias>,
|
|
// ...
|
|
// ],
|
|
// ...
|
|
// }
|
|
//
|
|
//
|
|
// NOTE: the builtin aliases will work even if this is empty.
|
|
// NOTE: each root key is also is also usable as a keyword.
|
|
'progress-logger-keywords': {
|
|
add: [
|
|
'queued',
|
|
'found',
|
|
],
|
|
done: [
|
|
'loaded',
|
|
'written',
|
|
'index',
|
|
],
|
|
skip: [
|
|
'skipping',
|
|
'removed',
|
|
],
|
|
reset: [
|
|
'clear',
|
|
],
|
|
close: [
|
|
'end',
|
|
'abort',
|
|
],
|
|
error: [
|
|
],
|
|
},
|
|
},
|
|
|
|
|
|
// XXX add message to be shown...
|
|
// XXX should we report errors and stoppages??? (error state??)
|
|
// XXX multiple containers...
|
|
// XXX shorten the nested css class names...
|
|
// XXX revise styles...
|
|
// XXX make the "X" bigger -- finger usable...
|
|
__progress_cache: null,
|
|
showProgress: ['- Interface/Show progress bar...',
|
|
core.doc`Progress bar widget...
|
|
|
|
Create progress bar...
|
|
.showProgress('text')
|
|
|
|
Update progress bar (value, max, msg)...
|
|
.showProgress('text', 0, 10)
|
|
.showProgress('text', 10, 50, 'message')
|
|
|
|
Update progress bar value (has no effect if max is not set)...
|
|
.showProgress('text', 10)
|
|
|
|
Close progress bar...
|
|
.showProgress('text', 'close')
|
|
|
|
Relative progress modification...
|
|
.showProgress('text', '+1')
|
|
.showProgress('text', '+0', '+1')
|
|
|
|
.showProgress(logger)
|
|
|
|
|
|
The progress bar is going to be shown to the user if:
|
|
- max is greater than 1, or
|
|
- it did not close before .config['progress-pre-delay'] ms of start
|
|
This is done to avoid spamming the user with single point progress bars.
|
|
|
|
|
|
NOTE: to force show the progress bar set attrs.forceShow to true.
|
|
`,
|
|
function(text, value, max, attrs){
|
|
var that = this
|
|
var viewer = this.dom
|
|
|
|
// get attrs...
|
|
var args = [...arguments]
|
|
attrs = args.last() instanceof Object ?
|
|
args.pop()
|
|
: null
|
|
var forceShow = !!(attrs || {}).forceShow
|
|
;[text, value, max] = args
|
|
|
|
var msg = text instanceof Array ? text.slice(1).join(': ') : null
|
|
text = text instanceof Array ? text[0] : text
|
|
|
|
// reset -- clear cache and set everything to 0...
|
|
// NOTE: we will later draw the progress bar full...
|
|
var reset = value == 'reset'
|
|
if(reset){
|
|
delete (this.__progress_cache || {})[text]
|
|
value = 0
|
|
max = 0 }
|
|
|
|
// cache -- make sure we do not update too often...
|
|
if(value != 'close'){
|
|
var cache = (this.__progress_cache = this.__progress_cache || {})
|
|
cache = cache[text] =
|
|
Object.assign(
|
|
cache[text] || {},
|
|
attrs || {})
|
|
|
|
var updateValue = function(name, value){
|
|
var v = cache[name] || 0
|
|
return (cache[name] =
|
|
value != null ?
|
|
((typeof(value) == typeof('str')
|
|
&& /[+-][0-9]+/.test(value)) ?
|
|
v + parseInt(value)
|
|
: parseInt(value))
|
|
: v) }
|
|
|
|
value = updateValue('value', value)
|
|
max = updateValue('max', max)
|
|
|
|
// update not due yet...
|
|
if('timeout' in cache){
|
|
cache.update = true
|
|
return }
|
|
|
|
// set next update point and continue...
|
|
delete cache.update
|
|
cache.timeout = setTimeout(
|
|
function(){
|
|
var cache = that.__progress_cache[text] || {}
|
|
delete cache.timeout
|
|
cache.update
|
|
&& that.showProgress(text) },
|
|
this.config['progress-update-min'] || 200) }
|
|
|
|
// container...
|
|
var container = viewer.find('.progress-container')
|
|
container = container.length == 0 ?
|
|
$('<div/>')
|
|
.addClass('progress-container')
|
|
.appendTo(viewer)
|
|
: container
|
|
|
|
// widget...
|
|
var widget = container.find('.progress-bar[name="'+text+'"]')
|
|
|
|
// close action...
|
|
if(value == 'close'){
|
|
widget.trigger('progressClose')
|
|
return }
|
|
|
|
// create if not done yet...
|
|
widget = widget.length == 0 ?
|
|
$('<div/>')
|
|
.addClass('progress-bar')
|
|
.css({
|
|
display: 'none',
|
|
})
|
|
.attr('name', text)
|
|
.text(text)
|
|
// close button...
|
|
.append($('<span class="close">×</span>')
|
|
.on('click', function(){
|
|
var cache = (that.__progress_cache || {})[text]
|
|
cache.onclose
|
|
&& cache.onclose()
|
|
widget.trigger('progressClose') }))
|
|
// state...
|
|
.append($('<span/>')
|
|
.addClass('progress-details'))
|
|
// bar...
|
|
.append($('<progress/>'))
|
|
// events...
|
|
.on('progressClose', function(){
|
|
var elem = $(this)
|
|
|
|
var clear = function(){
|
|
var cache = (that.__progress_cache || {})[text]
|
|
cache.timeout
|
|
&& clearTimeout(cache.timeout)
|
|
cache.ondone
|
|
&& cache.ondone()
|
|
// clear cache...
|
|
delete (that.__progress_cache || {})[text]
|
|
elem.remove() }
|
|
|
|
// widget was not shown...
|
|
if(elem.attr('closing') == null
|
|
|| elem.css('display') == 'none'){
|
|
clear()
|
|
// fade...
|
|
} else {
|
|
elem[0].setAttribute('closing', '')
|
|
elem
|
|
.fadeOut(
|
|
that.config['progress-fade-duration'] || 200,
|
|
clear) }
|
|
widget = null })
|
|
.appendTo(container)
|
|
: widget
|
|
.removeAttr('closing')
|
|
|
|
// reset closing timeout...
|
|
var timeout = widget.attr('close-timeout')
|
|
timeout
|
|
&& clearTimeout(JSON.parse(timeout))
|
|
|
|
// format the message...
|
|
msg = msg ? ': '+msg : ''
|
|
msg = ' '+ msg
|
|
+ (value && value >= (max || 0) ?
|
|
' (done)'
|
|
: max && value != max ?
|
|
' ('+ (value || 0) +' of '+ max +')'
|
|
: '...')
|
|
|
|
// update widget...
|
|
reset ?
|
|
// NOTE: on reset we show the progress bar full...
|
|
widget.find('progress')
|
|
.attr({ value: 1, max: 1 })
|
|
: widget.find('progress')
|
|
.attr({
|
|
value: (value || ''),
|
|
max: (max || ''),
|
|
})
|
|
widget.find('.progress-details')
|
|
.text(msg)
|
|
|
|
// auto-show...
|
|
if(forceShow
|
|
|| max > 1
|
|
|| !this.config['progress-pre-delay']){
|
|
widget.css({display: ''})
|
|
} else {
|
|
setTimeout(
|
|
function(){
|
|
widget
|
|
&& widget.attr('closing') == undefined
|
|
&& widget.css({display: ''}) },
|
|
this.config['progress-pre-delay'] || 1000) }
|
|
|
|
// auto-close...
|
|
if(value != null && value >= (max || 0)){
|
|
widget.attr('close-timeout',
|
|
JSON.stringify(setTimeout(
|
|
function(){
|
|
if(widget){
|
|
widget.trigger('progressClose') } },
|
|
this.config['progress-done-delay'] || 1000))) } }],
|
|
|
|
// handle logger progress...
|
|
// XXX show progress after a timeout if still not finished...
|
|
handleLogItem: ['- System/',
|
|
function(logger, path, status, ...rest){
|
|
var msg = path.join(': ')
|
|
var l = (rest.length == 1 && rest[0] instanceof Array) ?
|
|
rest[0].length
|
|
: rest.length
|
|
|
|
// only pass the relevant stuff...
|
|
var attrs = {}
|
|
logger.ondone
|
|
&& (attrs.ondone = logger.ondone)
|
|
logger.onclose
|
|
&& (attrs.onclose = logger.onclose)
|
|
|
|
// get keywords...
|
|
var {add, done, skip, reset, close, error} =
|
|
this.config['progress-logger-keywords']
|
|
|| {}
|
|
// setup default aliases...
|
|
add = new Set([...(add || []), 'added'])
|
|
done = new Set([...(done || [])])
|
|
skip = new Set([...(skip || []), 'skipped'])
|
|
reset = new Set([...(reset || [])])
|
|
close = new Set([...(close || []), 'closed'])
|
|
error = new Set([...(error || [])])
|
|
|
|
// close...
|
|
if(status == 'close' || close.has(status)){
|
|
this.showProgress(path, 'close', attrs)
|
|
// reset...
|
|
} else if(status == 'reset' || reset.has(status)){
|
|
this.showProgress(path, 'reset', attrs)
|
|
// added new item -- increase max...
|
|
// XXX show msg in the progress bar???
|
|
} else if(status == 'add' || add.has(status)){
|
|
this.showProgress(path, '+0', '+'+l, attrs)
|
|
// resolved item -- increase done...
|
|
} else if(status == 'done' || done.has(status)){
|
|
this.showProgress(path, '+'+l, attrs)
|
|
// skipped item -- increase done...
|
|
// XXX should we instead decrease max here???
|
|
// ...if not this is the same as done -- merge...
|
|
} else if(status == 'skip' || skip.has(status)){
|
|
this.showProgress(path, '+'+l, attrs)
|
|
// error...
|
|
// XXX STUB...
|
|
} else if(status == 'error' || error.has(status)){
|
|
this.showProgress(['Error'].concat(msg), '+0', '+'+l, attrs) }
|
|
}],
|
|
})
|
|
|
|
var Progress =
|
|
module.Progress = core.ImageGridFeatures.Feature({
|
|
title: '',
|
|
doc: '',
|
|
|
|
tag: 'ui-progress',
|
|
depends: [
|
|
'ui',
|
|
],
|
|
|
|
actions: ProgressActions,
|
|
})
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* vim:set ts=4 sw=4 : */ return module })
|