mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +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:
|
||||
//
|
||||
// Get current state:
|
||||
// state_accessor()
|
||||
// state_accessor(<elem>)
|
||||
// -> <current-state>
|
||||
//
|
||||
// Set new state:
|
||||
// state_accessor(<new-state>)
|
||||
// state_accessor(<elem>, <new-state>)
|
||||
// -> <new-state>
|
||||
//
|
||||
// `this' within <state_accessor> is set to toggler's context.
|
||||
//
|
||||
// NOTE: for single state toggling, 'none' will get passed to
|
||||
// state_accessor to indicate an "empty" state...
|
||||
// NOTE: if elem is a function it will be called in the same context as
|
||||
// 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
|
||||
// later is enough, but as strict mode is not stable enough (sometimes
|
||||
// works and sometimes does not), we can not reliably pass the element
|
||||
// via 'this'.
|
||||
function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
||||
// 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...
|
||||
if(callback_b === undefined){
|
||||
var callback_pre = null
|
||||
@ -120,8 +135,6 @@ function Toggler(elem, state_accessor, states, callback_a, 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
|
||||
// between a method and a root context in a simple manner...
|
||||
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
|
||||
|
||||
// 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???
|
||||
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...
|
||||
if(action == null || action == '?' || action == '!'){
|
||||
// get current state...
|
||||
var cur = state_accessor.call(e)
|
||||
var cur = state_accessor.call(this, e)
|
||||
|
||||
// just asking for info...
|
||||
if(action == '?'){
|
||||
@ -204,7 +228,7 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
||||
}
|
||||
|
||||
// update the element...
|
||||
state_accessor.call(e, state)
|
||||
state_accessor.call(this, e, state)
|
||||
|
||||
// post callback...
|
||||
if(callback_post != null){
|
||||
@ -217,21 +241,48 @@ function Toggler(elem, state_accessor, states, callback_a, callback_b){
|
||||
return action
|
||||
}
|
||||
|
||||
func.states = states
|
||||
if(bool_action){
|
||||
func.doc = '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{
|
||||
func.doc = '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.'
|
||||
}
|
||||
// XXX these are broken...
|
||||
//func.states = states
|
||||
Object.defineProperty(func, 'states', {
|
||||
get: function(){
|
||||
return typeof(states_getter) == typeof(function(){}) ?
|
||||
states_getter.apply(this)
|
||||
: state_set
|
||||
},
|
||||
set: function(value){
|
||||
state_set = states_getter = value
|
||||
},
|
||||
})
|
||||
Object.defineProperty(func, 'doc', {
|
||||
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.constructor = Toggler
|
||||
@ -244,26 +295,46 @@ Toggler.prototype.__proto__ = Function.prototype
|
||||
// XXX this should be drop-in compatible with createCSSClassToggler(..)
|
||||
// test and replace...
|
||||
function CSSClassToggler(elem, classes, callback_a, callback_b){
|
||||
// normalize the states...
|
||||
classes = typeof(classes) == typeof('str') ? ['none', classes] : classes
|
||||
// remove the dot from class names...
|
||||
// NOTE: this is here because I've made the error of including a
|
||||
// leading "." almost every time I use this after I forget
|
||||
// the UI...
|
||||
classes = classes
|
||||
.map(function(e){
|
||||
return e.split(' ')
|
||||
.map(function(c){
|
||||
c = c.trim()
|
||||
return c[0] == '.' ? c.slice(1) : c
|
||||
}).join(' ')
|
||||
})
|
||||
var classes_getter = classes
|
||||
var classes_set = classes
|
||||
|
||||
var getClasses = function(){
|
||||
var classes = typeof(classes_getter) == typeof(function(){}) ?
|
||||
classes_getter.call(this)
|
||||
: classes_set
|
||||
classes = typeof(classes) == typeof('str') ? ['none', classes] : classes
|
||||
|
||||
// remove the dot from class names...
|
||||
// NOTE: this is here because I've made the error of including a
|
||||
// leading "." almost every time I use this after I forget
|
||||
// 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(
|
||||
elem,
|
||||
function(state){
|
||||
function(e, state){
|
||||
'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...
|
||||
if(state == null){
|
||||
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_b)
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
"height": 700,
|
||||
"min_width": 400,
|
||||
"min_height": 400,
|
||||
"frame": false,
|
||||
"frame": true,
|
||||
"toolbar": false,
|
||||
"show": false
|
||||
},
|
||||
|
||||
@ -456,9 +456,9 @@ actions.Actions({
|
||||
function(all){ this.focusImage(all == null ? 'last' : -1) }],
|
||||
// XXX these break if image at first/last position are not loaded (crop, group, ...)
|
||||
// XXX do we actually need these???
|
||||
firstGlobalImage: ['Navigate/First globally image',
|
||||
firstGlobalImage: ['Navigate/First image globally',
|
||||
function(){ this.firstImage(true) }],
|
||||
lastGlobalImage: ['Navigate/Last globally image',
|
||||
lastGlobalImage: ['Navigate/Last image globally',
|
||||
function(){ this.lastImage(true) }],
|
||||
|
||||
// XXX skip unloaded images... (groups?)
|
||||
@ -1160,14 +1160,8 @@ actions.Actions({
|
||||
toggleTheme: ['Interface/Toggle viewer theme',
|
||||
CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
// XXX how do we get this live from config???
|
||||
//this.config.themes,
|
||||
[
|
||||
'gray',
|
||||
'dark',
|
||||
'light',
|
||||
],
|
||||
function(state){ this.config['theme'] = state }) ],
|
||||
function(){ return this.config.themes },
|
||||
function(state){ this.config.theme = state }) ],
|
||||
setEmptyMsg: ['- Interface/Set message to be displayed when nothing is loaded.',
|
||||
function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }],
|
||||
|
||||
@ -1717,7 +1711,11 @@ var ConfigLocalStorageActions = actions.Actions({
|
||||
key = key || this.config['config-local-storage-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
|
||||
// to enable features to load their data...
|
||||
// XXX look inside...
|
||||
loadIndex: ['File/Load index',
|
||||
loadIndex: ['- File/Load index',
|
||||
function(path, logger){
|
||||
var that = this
|
||||
|
||||
@ -3902,7 +3900,7 @@ var FileSystemLoaderActions = actions.Actions({
|
||||
// XXX add a recursive option...
|
||||
// ...might also be nice to add sub-dirs to ribbons...
|
||||
// XXX make image pattern more generic...
|
||||
loadImages: ['File/Load images',
|
||||
loadImages: ['- File/Load images',
|
||||
function(path, logger){
|
||||
if(path == null){
|
||||
return
|
||||
@ -3932,7 +3930,7 @@ var FileSystemLoaderActions = actions.Actions({
|
||||
}],
|
||||
|
||||
// XXX auto-detect format or let the user chose...
|
||||
loadPath: ['File/Load path (STUB)',
|
||||
loadPath: ['- File/Load path (STUB)',
|
||||
function(path, logger){
|
||||
// XXX check if this.config['index-dir'] exists, if yes then
|
||||
// .loadIndex(..) else .loadImages(..)
|
||||
@ -4137,8 +4135,8 @@ var FileSystemLoaderUIActions = actions.Actions({
|
||||
// to start from.
|
||||
// XXX should passing no path to this start browsing from the current
|
||||
// path or from the root?
|
||||
loadIndex: [makeBrowseProxy('loadIndex')],
|
||||
loadImages: [makeBrowseProxy('loadImages')],
|
||||
loadIndex: ['File/Load index', makeBrowseProxy('loadIndex')],
|
||||
loadImages: ['File/Load images', makeBrowseProxy('loadImages')],
|
||||
})
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user