mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 02:40:08 +00:00
toggler now support accessor function on all args and uniformly (backwards incompatible) + some tweaking and cleanup...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
987a3f0ddb
commit
7c7777d745
@ -92,25 +92,40 @@
|
|||||||
// state_accessor signature:
|
// state_accessor signature:
|
||||||
//
|
//
|
||||||
// Get current state:
|
// Get current state:
|
||||||
// state_accessor()
|
// state_accessor(<elem>)
|
||||||
// -> <current-state>
|
// -> <current-state>
|
||||||
//
|
//
|
||||||
// Set new state:
|
// Set new state:
|
||||||
// state_accessor(<new-state>)
|
// state_accessor(<elem>, <new-state>)
|
||||||
// -> <new-state>
|
// -> <new-state>
|
||||||
//
|
//
|
||||||
|
// `this' within <state_accessor> is set to toggler's context.
|
||||||
|
//
|
||||||
// NOTE: for single state toggling, 'none' will get passed to
|
// NOTE: for single state toggling, 'none' will get passed to
|
||||||
// state_accessor to indicate an "empty" state...
|
// state_accessor to indicate an "empty" state...
|
||||||
// NOTE: if elem is a function it will be called in the same context as
|
// NOTE: if elem is a function it will be called in the same context as
|
||||||
// the toggler and is expected to return the element.
|
// the toggler and is expected to return the element.
|
||||||
//
|
//
|
||||||
|
//
|
||||||
|
// states can be:
|
||||||
|
// <state> - state string, equivalent to ['none', <state>]
|
||||||
|
// this will produce a bool toggler that will toggle
|
||||||
|
// a single state on and off.
|
||||||
|
// [<state>, ...] - list of string states that will be toggled
|
||||||
|
// through, one special state 'none' is supported
|
||||||
|
// function(){ ... } - function that will return either a state or
|
||||||
|
// a list of states, `this' will be set to
|
||||||
|
// the toggler's context...
|
||||||
|
//
|
||||||
|
//
|
||||||
// XXX technically we do not need both elem and state_accessor here, the
|
// XXX technically we do not need both elem and state_accessor here, the
|
||||||
// later is enough, but as strict mode is not stable enough (sometimes
|
// later is enough, but as strict mode is not stable enough (sometimes
|
||||||
// works and sometimes does not), we can not reliably pass the element
|
// works and sometimes does not), we can not reliably pass the element
|
||||||
// via 'this'.
|
// via 'this'.
|
||||||
function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
||||||
// normalize states...
|
// normalize states...
|
||||||
states = typeof(states) == typeof('str') ? ['none', states] : states
|
var states_getter = states
|
||||||
|
var state_set = typeof(states) == typeof('str') ? ['none', states] : states
|
||||||
// normalize the callbacks...
|
// normalize the callbacks...
|
||||||
if(callback_b === undefined){
|
if(callback_b === undefined){
|
||||||
var callback_pre = null
|
var callback_pre = null
|
||||||
@ -120,8 +135,6 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
|||||||
var callback_post = callback_b
|
var callback_post = callback_b
|
||||||
}
|
}
|
||||||
|
|
||||||
var bool_action = (states.length == 2 && states[0] == 'none')
|
|
||||||
|
|
||||||
// NOTE: this needs to be strict so as to be able to distinguish
|
// NOTE: this needs to be strict so as to be able to distinguish
|
||||||
// between a method and a root context in a simple manner...
|
// between a method and a root context in a simple manner...
|
||||||
var func = function(a, b){
|
var func = function(a, b){
|
||||||
@ -141,6 +154,17 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
|||||||
|
|
||||||
e = e instanceof Function ? e.call(this) : e
|
e = e instanceof Function ? e.call(this) : e
|
||||||
|
|
||||||
|
// see if we got an explicit state list or need to use a getter...
|
||||||
|
var states = state_set
|
||||||
|
if(typeof(states_getter) == typeof(function(){})){
|
||||||
|
// get the states...
|
||||||
|
var states = states_getter.call(this)
|
||||||
|
var states = typeof(states) == typeof('str') ?
|
||||||
|
['none', states]
|
||||||
|
: states
|
||||||
|
}
|
||||||
|
var bool_action = (state_set.length == 2 && state_set[0] == 'none')
|
||||||
|
|
||||||
// XXX is this correct???
|
// XXX is this correct???
|
||||||
var args = args2array(arguments).slice(2)
|
var args = args2array(arguments).slice(2)
|
||||||
|
|
||||||
@ -160,7 +184,7 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
|||||||
// we need to get the current state...
|
// we need to get the current state...
|
||||||
if(action == null || action == '?' || action == '!'){
|
if(action == null || action == '?' || action == '!'){
|
||||||
// get current state...
|
// get current state...
|
||||||
var cur = state_accessor.call(e)
|
var cur = state_accessor.call(this, e)
|
||||||
|
|
||||||
// just asking for info...
|
// just asking for info...
|
||||||
if(action == '?'){
|
if(action == '?'){
|
||||||
@ -204,7 +228,7 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update the element...
|
// update the element...
|
||||||
state_accessor.call(e, state)
|
state_accessor.call(this, e, state)
|
||||||
|
|
||||||
// post callback...
|
// post callback...
|
||||||
if(callback_post != null){
|
if(callback_post != null){
|
||||||
@ -217,21 +241,48 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
|||||||
return action
|
return action
|
||||||
}
|
}
|
||||||
|
|
||||||
func.states = states
|
// XXX these are broken...
|
||||||
if(bool_action){
|
//func.states = states
|
||||||
func.doc = 'With no arguments this will toggle between "on" and '+
|
Object.defineProperty(func, 'states', {
|
||||||
'"off".\n'+
|
get: function(){
|
||||||
'If either "on" or "off" are given then this will switch '+
|
return typeof(states_getter) == typeof(function(){}) ?
|
||||||
'to that mode.\n'+
|
states_getter.apply(this)
|
||||||
'If "?" is given, this will return either "on" or "off" '+
|
: state_set
|
||||||
'depending on the current state.'
|
},
|
||||||
}else{
|
set: function(value){
|
||||||
func.doc = 'With no arguments this will toggle between '+
|
state_set = states_getter = value
|
||||||
states +' in cycle.\n' +
|
},
|
||||||
'if any of the state names or its number is given then that '+
|
})
|
||||||
'state is switched on.'+
|
Object.defineProperty(func, 'doc', {
|
||||||
'If "?" is given, this will return the current state.'
|
get: function(){
|
||||||
}
|
if(func.__doc != null){
|
||||||
|
return func.__doc
|
||||||
|
}
|
||||||
|
var states = typeof(states_getter) == typeof(function(){}) ?
|
||||||
|
states_getter.apply(this)
|
||||||
|
: state_set
|
||||||
|
|
||||||
|
// bool_action...
|
||||||
|
if(states.length == 2 && states[0] == 'none'){
|
||||||
|
return 'With no arguments this will toggle between "on" and '
|
||||||
|
+'"off".\n'
|
||||||
|
+'If either "on" or "off" are given then this will switch '
|
||||||
|
+'to that mode.\n'
|
||||||
|
+'If "?" is given, this will return either "on" or "off" '
|
||||||
|
+'depending on the current state.'
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return 'With no arguments this will toggle between '
|
||||||
|
+ states +' in cycle.\n'
|
||||||
|
+'if any of the state names or its number is given then that '
|
||||||
|
+'state is switched on.'
|
||||||
|
+'If "?" is given, this will return the current state.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: function(value){
|
||||||
|
func.__doc = value
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
func.__proto__ = Toggler.prototype
|
func.__proto__ = Toggler.prototype
|
||||||
func.constructor = Toggler
|
func.constructor = Toggler
|
||||||
@ -244,26 +295,46 @@ Toggler.prototype.__proto__ = Function.prototype
|
|||||||
// XXX this should be drop-in compatible with createCSSClassToggler(..)
|
// XXX this should be drop-in compatible with createCSSClassToggler(..)
|
||||||
// test and replace...
|
// test and replace...
|
||||||
function CSSClassToggler(elem, classes, callback_a, callback_b){
|
function CSSClassToggler(elem, classes, callback_a, callback_b){
|
||||||
// normalize the states...
|
var classes_getter = classes
|
||||||
classes = typeof(classes) == typeof('str') ? ['none', classes] : classes
|
var classes_set = classes
|
||||||
// remove the dot from class names...
|
|
||||||
// NOTE: this is here because I've made the error of including a
|
var getClasses = function(){
|
||||||
// leading "." almost every time I use this after I forget
|
var classes = typeof(classes_getter) == typeof(function(){}) ?
|
||||||
// the UI...
|
classes_getter.call(this)
|
||||||
classes = classes
|
: classes_set
|
||||||
.map(function(e){
|
classes = typeof(classes) == typeof('str') ? ['none', classes] : classes
|
||||||
return e.split(' ')
|
|
||||||
.map(function(c){
|
// remove the dot from class names...
|
||||||
c = c.trim()
|
// NOTE: this is here because I've made the error of including a
|
||||||
return c[0] == '.' ? c.slice(1) : c
|
// leading "." almost every time I use this after I forget
|
||||||
}).join(' ')
|
// the UI...
|
||||||
})
|
return classes
|
||||||
|
.map(function(e){
|
||||||
|
return e.split(' ')
|
||||||
|
.map(function(c){
|
||||||
|
c = c.trim()
|
||||||
|
return c[0] == '.' ? c.slice(1) : c
|
||||||
|
}).join(' ')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize...
|
||||||
|
// NOTE: this happens here once if we got explicit classes, and on
|
||||||
|
// each access if we get a getter function...
|
||||||
|
classes_set = typeof(classes_getter) != typeof(function(){}) ?
|
||||||
|
getClasses.call(this)
|
||||||
|
: classes_set
|
||||||
|
|
||||||
var toggler = Toggler(
|
var toggler = Toggler(
|
||||||
elem,
|
elem,
|
||||||
function(state){
|
function(e, state){
|
||||||
'use strict'
|
'use strict'
|
||||||
var e = $(this == null ? elem : this)
|
|
||||||
|
var classes = classes_set.constructor === Array ?
|
||||||
|
classes_set
|
||||||
|
: getClasses.call(this)
|
||||||
|
|
||||||
|
e = $(e == null ? elem : e)
|
||||||
// get the state...
|
// get the state...
|
||||||
if(state == null){
|
if(state == null){
|
||||||
var cur = 'none'
|
var cur = 'none'
|
||||||
@ -286,7 +357,7 @@ function CSSClassToggler(elem, classes, callback_a, callback_b){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
classes,
|
typeof(classes_getter) == typeof(function(){}) ? getClasses : classes_set,
|
||||||
callback_a,
|
callback_a,
|
||||||
callback_b)
|
callback_b)
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
"height": 700,
|
"height": 700,
|
||||||
"min_width": 400,
|
"min_width": 400,
|
||||||
"min_height": 400,
|
"min_height": 400,
|
||||||
"frame": false,
|
"frame": true,
|
||||||
"toolbar": false,
|
"toolbar": false,
|
||||||
"show": false
|
"show": false
|
||||||
},
|
},
|
||||||
|
|||||||
@ -456,9 +456,9 @@ actions.Actions({
|
|||||||
function(all){ this.focusImage(all == null ? 'last' : -1) }],
|
function(all){ this.focusImage(all == null ? 'last' : -1) }],
|
||||||
// XXX these break if image at first/last position are not loaded (crop, group, ...)
|
// XXX these break if image at first/last position are not loaded (crop, group, ...)
|
||||||
// XXX do we actually need these???
|
// XXX do we actually need these???
|
||||||
firstGlobalImage: ['Navigate/First globally image',
|
firstGlobalImage: ['Navigate/First image globally',
|
||||||
function(){ this.firstImage(true) }],
|
function(){ this.firstImage(true) }],
|
||||||
lastGlobalImage: ['Navigate/Last globally image',
|
lastGlobalImage: ['Navigate/Last image globally',
|
||||||
function(){ this.lastImage(true) }],
|
function(){ this.lastImage(true) }],
|
||||||
|
|
||||||
// XXX skip unloaded images... (groups?)
|
// XXX skip unloaded images... (groups?)
|
||||||
@ -1160,14 +1160,8 @@ actions.Actions({
|
|||||||
toggleTheme: ['Interface/Toggle viewer theme',
|
toggleTheme: ['Interface/Toggle viewer theme',
|
||||||
CSSClassToggler(
|
CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.ribbons.viewer },
|
||||||
// XXX how do we get this live from config???
|
function(){ return this.config.themes },
|
||||||
//this.config.themes,
|
function(state){ this.config.theme = state }) ],
|
||||||
[
|
|
||||||
'gray',
|
|
||||||
'dark',
|
|
||||||
'light',
|
|
||||||
],
|
|
||||||
function(state){ this.config['theme'] = state }) ],
|
|
||||||
setEmptyMsg: ['- Interface/Set message to be displayed when nothing is loaded.',
|
setEmptyMsg: ['- Interface/Set message to be displayed when nothing is loaded.',
|
||||||
function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }],
|
function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }],
|
||||||
|
|
||||||
@ -1717,7 +1711,11 @@ var ConfigLocalStorageActions = actions.Actions({
|
|||||||
key = key || this.config['config-local-storage-key']
|
key = key || this.config['config-local-storage-key']
|
||||||
|
|
||||||
if(key && localStorage[key]){
|
if(key && localStorage[key]){
|
||||||
this.config = JSON.parse(localStorage[key])
|
var base = this.config
|
||||||
|
var loaded = JSON.parse(localStorage[key])
|
||||||
|
loaded.__proto__ = base
|
||||||
|
|
||||||
|
this.config = loaded
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
|
||||||
@ -3796,7 +3794,7 @@ var FileSystemLoaderActions = actions.Actions({
|
|||||||
// XXX add a symmetric equivalent to .prepareIndexForWrite(..) so as
|
// XXX add a symmetric equivalent to .prepareIndexForWrite(..) so as
|
||||||
// to enable features to load their data...
|
// to enable features to load their data...
|
||||||
// XXX look inside...
|
// XXX look inside...
|
||||||
loadIndex: ['File/Load index',
|
loadIndex: ['- File/Load index',
|
||||||
function(path, logger){
|
function(path, logger){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
@ -3902,7 +3900,7 @@ var FileSystemLoaderActions = actions.Actions({
|
|||||||
// XXX add a recursive option...
|
// XXX add a recursive option...
|
||||||
// ...might also be nice to add sub-dirs to ribbons...
|
// ...might also be nice to add sub-dirs to ribbons...
|
||||||
// XXX make image pattern more generic...
|
// XXX make image pattern more generic...
|
||||||
loadImages: ['File/Load images',
|
loadImages: ['- File/Load images',
|
||||||
function(path, logger){
|
function(path, logger){
|
||||||
if(path == null){
|
if(path == null){
|
||||||
return
|
return
|
||||||
@ -3932,7 +3930,7 @@ var FileSystemLoaderActions = actions.Actions({
|
|||||||
}],
|
}],
|
||||||
|
|
||||||
// XXX auto-detect format or let the user chose...
|
// XXX auto-detect format or let the user chose...
|
||||||
loadPath: ['File/Load path (STUB)',
|
loadPath: ['- File/Load path (STUB)',
|
||||||
function(path, logger){
|
function(path, logger){
|
||||||
// XXX check if this.config['index-dir'] exists, if yes then
|
// XXX check if this.config['index-dir'] exists, if yes then
|
||||||
// .loadIndex(..) else .loadImages(..)
|
// .loadIndex(..) else .loadImages(..)
|
||||||
@ -4137,8 +4135,8 @@ var FileSystemLoaderUIActions = actions.Actions({
|
|||||||
// to start from.
|
// to start from.
|
||||||
// XXX should passing no path to this start browsing from the current
|
// XXX should passing no path to this start browsing from the current
|
||||||
// path or from the root?
|
// path or from the root?
|
||||||
loadIndex: [makeBrowseProxy('loadIndex')],
|
loadIndex: ['File/Load index', makeBrowseProxy('loadIndex')],
|
||||||
loadImages: [makeBrowseProxy('loadImages')],
|
loadImages: ['File/Load images', makeBrowseProxy('loadImages')],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user