mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
826 lines
22 KiB
JavaScript
Executable File
826 lines
22 KiB
JavaScript
Executable File
/**********************************************************************
|
|
*
|
|
*
|
|
* Features:
|
|
* - ui-ribbons-render
|
|
* - ui-ribbons-edit-render
|
|
* - ui-partial-ribbons
|
|
* - ui-animation
|
|
* manage UI non-css animations...
|
|
*
|
|
*
|
|
**********************************************************************/
|
|
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
|
|
(function(require){ var module={} // make module AMD/node compatible...
|
|
/*********************************************************************/
|
|
|
|
var object = require('lib/object')
|
|
var actions = require('lib/actions')
|
|
var features = require('lib/features')
|
|
|
|
var core = require('features/core')
|
|
|
|
var ribbons = require('imagegrid/ribbons')
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
// helpers...
|
|
|
|
// XXX make this compatible with multiple images...
|
|
// XXX for muptiple targets this will just do a .reload()...
|
|
var updateImagePosition =
|
|
function updateImagePosition(actions, target){
|
|
var s = actions.ribbons.getRibbonLocator()
|
|
|
|
if(s.length == 0){
|
|
return
|
|
}
|
|
|
|
target = target || actions.current
|
|
target = target instanceof jQuery
|
|
? actions.ribbons.elemGID(target)
|
|
: target
|
|
|
|
var source_ribbon = actions.ribbons.elemGID(actions.ribbons.getRibbon(target))
|
|
var source_order = actions.data.getImageOrder(target)
|
|
|
|
return function(){
|
|
actions.ribbons.preventTransitions(s)
|
|
var end = function(){
|
|
// XXX not sure why this does not work without a setTimeout(..)
|
|
//actions.ribbons.restoreTransitions(s, true)
|
|
setTimeout(function(){
|
|
actions.ribbons.restoreTransitions(s, true) }, 0) }
|
|
|
|
// XXX hack???
|
|
if(target instanceof Array){
|
|
actions.reload(true)
|
|
return end()
|
|
}
|
|
|
|
var target_ribbon = actions.data.getRibbon(target)
|
|
|
|
// nothing changed...
|
|
if(source_ribbon == target_ribbon
|
|
&& actions.data.getImageOrder(target) == source_order){
|
|
return end()
|
|
}
|
|
|
|
// place image at position...
|
|
var to = actions.data.getImage(target, 'next')
|
|
if(to != null){
|
|
actions.ribbons.placeImage(target, to, 'before')
|
|
|
|
} else {
|
|
// place image after position...
|
|
to = actions.data.getImage(target, 'prev')
|
|
if(to != null){
|
|
actions.ribbons.placeImage(target, to, 'after')
|
|
|
|
// new ribbon...
|
|
} else {
|
|
to = actions.data.getRibbon(target)
|
|
|
|
if(actions.ribbons.getRibbon(to).length == 0){
|
|
actions.ribbons
|
|
.placeRibbon(to, actions.data.getRibbonOrder(target))
|
|
}
|
|
|
|
actions.ribbons.placeImage(target, to)
|
|
}
|
|
}
|
|
|
|
if(actions.data.getImages(source_ribbon).length == 0){
|
|
actions.ribbons.getRibbon(source_ribbon).remove()
|
|
}
|
|
|
|
actions.focusImage()
|
|
|
|
return end()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
// Base ribbons viewer...
|
|
|
|
var RibbonsActions =
|
|
actions.Actions({
|
|
|
|
get dom(){
|
|
return this.ribbons ? this.ribbons.viewer : undefined },
|
|
|
|
|
|
load: [
|
|
function(data){
|
|
return function(){
|
|
// recycle the viewer if one is not given specifically...
|
|
var viewer = data.viewer
|
|
viewer = viewer == null && this.ribbons != null
|
|
? this.dom
|
|
: viewer
|
|
|
|
if(this.ribbons == null){
|
|
this.ribbons = ribbons.Ribbons(viewer, this.images)
|
|
// XXX is this correct???
|
|
this.ribbons.__image_updaters = [this.updateImage.bind(this)]
|
|
|
|
} else {
|
|
this.ribbons.clear()
|
|
this.ribbons.images = this.images
|
|
}
|
|
|
|
this.reload()
|
|
}
|
|
}],
|
|
// NOTE: this will pass the .ribbons.updateData(..) a custom ribbon
|
|
// updater if one is defined here as .updateRibbon(target) action
|
|
//
|
|
// XXX HACK: two sins:
|
|
// - actions.updateRibbon(..) and ribbons.updateRibbon(..)
|
|
// are NOT signature compatible...
|
|
// - we depend on the internals of a custom add-on feature
|
|
reload: ['Interface/Reload viewer',
|
|
function(force){
|
|
// full reload...
|
|
if(force == 'full'){
|
|
//this.stop()
|
|
/*
|
|
killAllWorkers()
|
|
.done(function(){
|
|
reload()
|
|
})
|
|
*/
|
|
return location.reload()
|
|
}
|
|
|
|
this.ribbons.preventTransitions()
|
|
|
|
// NOTE: this essentially sets the update threshold to 0...
|
|
// XXX this should be a custom arg...
|
|
force = force ? 0 : null
|
|
|
|
return function(){
|
|
// see if we've got a custom ribbon updater...
|
|
var that = this
|
|
var settings = this.updateRibbon != null
|
|
// XXX this should be: { updateRibbon: this.updateRibbon.bind(this) }
|
|
? { updateRibbon: function(_, ribbon){
|
|
return that.updateRibbon(ribbon, null, null, force)
|
|
} }
|
|
: null
|
|
|
|
this.ribbons.updateData(this.data, settings)
|
|
|
|
this
|
|
// XXX should this be here???
|
|
.refresh()
|
|
.focusImage()
|
|
|
|
// XXX HACK to make browser redraw images...
|
|
this.scale = this.scale
|
|
|
|
this.ribbons.restoreTransitions()
|
|
}
|
|
}],
|
|
// NOTE: this will trigger .updateImage hooks...
|
|
refresh: ['Interface/Refresh images without reloading',
|
|
function(gids, scale){
|
|
gids = gids || '*'
|
|
var size = scale != null ?
|
|
this.ribbons.getVisibleImageSize('min', scale)
|
|
: null
|
|
|
|
this.ribbons.updateImage(gids, null, size)
|
|
}],
|
|
clear: [
|
|
function(){ this.ribbons && this.ribbons.clear() }],
|
|
// XXX do we need clone???
|
|
clone: [function(full){
|
|
return function(res){
|
|
if(this.ribbons){
|
|
// NOTE: this is a bit wasteful as .ribbons will clone
|
|
// their ref to .images that we will throw away...
|
|
res.ribbons = this.ribbons.clone()
|
|
res.ribbons.images = res.images
|
|
}
|
|
}
|
|
}],
|
|
|
|
|
|
replaceGid: [
|
|
function(from, to){
|
|
return function(res){
|
|
res && this.ribbons.replaceGid(from, to)
|
|
}
|
|
}],
|
|
|
|
|
|
// This is called by .ribbons, the goal is to use it to hook into
|
|
// image updating from features and extensions...
|
|
//
|
|
// NOTE: not intended for calling manually, use .refresh(..) instead...
|
|
//
|
|
// XXX EXPERIMENTAL...
|
|
// ...need this to get triggered by .ribbons
|
|
// at this point manually triggering this will not do anything...
|
|
// XXX problem: need to either redesign this or distinguish from
|
|
// other actions as I keep calling it expecting results...
|
|
// XXX hide from user action list... (???)
|
|
updateImage: ['- Interface/Update image (do not use directly)',
|
|
'This is called by .refresh(..) and intended for use as an '
|
|
+'trigger for handlers, and not as a user-callable acation.',
|
|
core.notUserCallable(function(gid, image){
|
|
// This is the image update protocol root function
|
|
//
|
|
// Not for direct use.
|
|
})],
|
|
|
|
// NOTE: this not used directly, mainly designed as a utility to be
|
|
// used for various partial ribbon implementations...
|
|
// XXX do we handle off-screen ribbons here???
|
|
resizeRibbon: ['- Interface/Resize ribbon to n images',
|
|
function(target, size){
|
|
size = size
|
|
|| (this.config['ribbon-size-screens'] * this.screenwidth)
|
|
|| (5 * this.screenwidth)
|
|
var data = this.data
|
|
var ribbons = this.ribbons
|
|
|
|
// localize transition prevention...
|
|
// NOTE: we can't get ribbon via target directly here as
|
|
// the target might not be loaded...
|
|
var r_gid = data.getRibbon(target)
|
|
if(r_gid == null){
|
|
return
|
|
}
|
|
// NOTE: for the initial load this may be empty...
|
|
var r = ribbons.getRibbon(r_gid)
|
|
|
|
// XXX do we need to for example ignore unloaded (r.length == 0)
|
|
// ribbons here, for example not load ribbons too far off
|
|
// screen??
|
|
|
|
ribbons
|
|
.preventTransitions(r)
|
|
.updateRibbon(
|
|
data.getImages(target, size, 'total'),
|
|
r_gid,
|
|
target)
|
|
.restoreTransitions(r, true)
|
|
}],
|
|
|
|
|
|
// NOTE: this will align only a single image...
|
|
// XXX do we need these low level primitives here???
|
|
centerImage: ['- Interface/Center an image in ribbon horizontally',
|
|
function(target, align, offset, scale){
|
|
target = target instanceof jQuery
|
|
? this.ribbons.elemGID(target)
|
|
: target
|
|
|
|
// align current ribbon...
|
|
this.ribbons.centerImage(target, align, offset, scale)
|
|
}],
|
|
centerRibbon: ['- Interface/Center a ribbon vertically',
|
|
function(target){
|
|
target = target instanceof jQuery
|
|
? this.ribbons.elemGID(target)
|
|
: target
|
|
|
|
// align current ribbon...
|
|
this.ribbons.centerRibbon(target)
|
|
}],
|
|
|
|
|
|
// XXX should these be here, in ui or in ribbons???
|
|
// XXX these are identical to features/ui-preact-render.js
|
|
focusImage: [
|
|
function(target, list){
|
|
return function(){
|
|
this.ribbons.focusImage(this.data != null ? this.current : target) } }],
|
|
focusRibbon: [
|
|
function(target, mode){
|
|
mode = mode || this.config['ribbon-focus-mode']
|
|
|
|
var c = this.data.getRibbonOrder()
|
|
var i = this.data.getRibbonOrder(target)
|
|
// NOTE: we are not changing the direction here based on
|
|
// this.direction as swap will confuse the user...
|
|
var direction = c < i ? 'before' : 'after'
|
|
|
|
if(mode == 'visual'){
|
|
var ribbons = this.ribbons
|
|
var r = this.data.getRibbon(target)
|
|
var t = ribbons.getImageByPosition('current', r)
|
|
|
|
if(t.length > 1){
|
|
t = t.eq(direction == 'before' ? 0 : 1)
|
|
}
|
|
|
|
t = ribbons.elemGID(t)
|
|
|
|
this.focusImage(t, r)
|
|
}
|
|
}],
|
|
|
|
|
|
// Zoom/scale protocol...
|
|
resizing: [
|
|
core.notUserCallable(function(unit, size, overflow){
|
|
// This is a resizing protocol root function.
|
|
//
|
|
// This will never be used directly, but will wrap protocol user
|
|
// functions.
|
|
//
|
|
// As an example see: .viewScale(..)
|
|
|
|
var that = this
|
|
// stop currently running transition...
|
|
this.ribbons.scale(this.ribbons.scale())
|
|
|
|
// transitionend handler...
|
|
if(!this.__resize_handler){
|
|
this.__resize_handler = function(){
|
|
that.__post_resize
|
|
&& that.resizingDone()
|
|
delete that.__post_resize
|
|
}
|
|
}
|
|
this.ribbons.getRibbonSet()
|
|
.off('transitionend', this.__resize_handler)
|
|
.on('transitionend', this.__resize_handler)
|
|
|
|
// timeout handler...
|
|
this.__post_resize && clearTimeout(this.__post_resize)
|
|
return function(){
|
|
this.__post_resize = setTimeout(
|
|
this.__resize_handler,
|
|
this.config['resize-done-timeout'] || 300)
|
|
}
|
|
})],
|
|
|
|
viewScale: ['- Zoom/',
|
|
function(scale){
|
|
if(scale == null || scale == '?'){
|
|
return this.ribbons != null ? this.ribbons.scale() : null
|
|
}
|
|
|
|
this.resizing.chainCall(this, function(){
|
|
this.ribbons
|
|
&& scale
|
|
&& this.ribbons.scale(scale)
|
|
// NOTE: we pass explicit scale here to compensate for animation...
|
|
this.refresh('*', scale)
|
|
}, 'scale', scale)
|
|
}],
|
|
// NOTE: if this gets a count argument it will fit count images,
|
|
// default is one.
|
|
// NOTE: this will add .config['fit-overflow'] to odd counts if no
|
|
// overflow if passed.
|
|
// ...this is done to add ability to control scroll indication.
|
|
fitImage: ['Zoom/Fit image',
|
|
function(count, overflow){
|
|
if(count == '?'){
|
|
return this.ribbons != null ?
|
|
this.ribbons.getScreenWidthImages()
|
|
: null
|
|
}
|
|
|
|
this.resizing.chainCall(this, function(){
|
|
if(count != null){
|
|
overflow = overflow == false ? 0 : overflow
|
|
var o = overflow != null ? overflow
|
|
: count % 2 != 1 ? 0
|
|
: (this.config['fit-overflow'] || 0)
|
|
count += o
|
|
}
|
|
// XXX .ribbons...
|
|
this.ribbons.fitImage(count)
|
|
// NOTE: we pass explicit scale here to compensate for animation...
|
|
this.refresh('*', this.ribbons.getScreenWidthImages(1) / count)
|
|
}, 'screenwidth', count, overflow)
|
|
}],
|
|
// NOTE: this does not account for ribbon spacing...
|
|
fitRibbon: ['Zoom/Fit ribbon vertically',
|
|
function(count, whole){
|
|
if(count == '?'){
|
|
return this.ribbons != null ?
|
|
this.ribbons.getScreenHeightRibbons()
|
|
: null
|
|
}
|
|
|
|
this.resizing.chainCall(this, function(){
|
|
// XXX .ribbons...
|
|
this.ribbons.fitRibbon(count, whole)
|
|
// NOTE: we pass explicit scale here to compensate for animation...
|
|
this.refresh('*', this.ribbons.getScreenHeightRibbons(1, whole) / count)
|
|
}, 'screenheight', count, whole)
|
|
}],
|
|
|
|
|
|
ribbonRotation: ['- Interface|Ribbon/',
|
|
function(a){
|
|
if(arguments.length > 0){
|
|
this.ribbons.rotate(a)
|
|
|
|
} else {
|
|
return this.ribbons.rotate() || 0
|
|
}
|
|
}],
|
|
})
|
|
|
|
|
|
var Ribbons =
|
|
module.Ribbons =
|
|
core.ImageGridFeatures.Feature({
|
|
title: '',
|
|
doc: '',
|
|
|
|
tag: 'ui-ribbons-render',
|
|
exclusive: ['ui-render'],
|
|
depends: [
|
|
// XXX BUG: for some reason this causes a dependency conflict...
|
|
//'ui',
|
|
'base',
|
|
],
|
|
suggested: [
|
|
'ui-animation',
|
|
'ui-ribbons-edit-render',
|
|
'ui-partial-ribbons',
|
|
],
|
|
|
|
actions: RibbonsActions,
|
|
|
|
handlers: [],
|
|
})
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// Edit...
|
|
|
|
var RibbonsEditActions =
|
|
actions.Actions({
|
|
setBaseRibbon: [
|
|
function(target){
|
|
var r = this.data.getRibbon(target)
|
|
r = r == null ? this.ribbons.getRibbon(target) : r
|
|
this.ribbons.setBaseRibbon(r)
|
|
}],
|
|
shiftImageLeft: [
|
|
function(target){ this.ribbons.placeImage(target, -1) }],
|
|
shiftImageRight: [
|
|
function(target){ this.ribbons.placeImage(target, 1) }],
|
|
shiftRibbonUp: [
|
|
function(target){
|
|
target = this.ribbons.getRibbon(target)
|
|
var i = this.ribbons.getRibbonOrder(target)
|
|
if(i > 0){
|
|
this.ribbons.placeRibbon(target, i-1)
|
|
}
|
|
}],
|
|
shiftRibbonDown: [
|
|
function(target){
|
|
target = this.ribbons.getRibbon(target)
|
|
var i = this.ribbons.getRibbonOrder(target)
|
|
if(i < this.data.ribbon_order.length-1){
|
|
this.ribbons.placeRibbon(target, i+1)
|
|
}
|
|
}],
|
|
|
|
// basic image editing...
|
|
//
|
|
// XXX should we have .rotate(..) and .flip(..) generic actions???
|
|
rotateCW: [
|
|
function(target){ this.ribbons.rotateCW(target) }],
|
|
rotateCCW: [
|
|
function(target){ this.ribbons.rotateCCW(target) }],
|
|
flipVertical: [
|
|
function(target){ this.ribbons.flipVertical(target, 'view') }],
|
|
flipHorizontal: [
|
|
function(target){ this.ribbons.flipHorizontal(target, 'view') }],
|
|
|
|
// tags...
|
|
tag: [
|
|
function(tags, gids){
|
|
gids = gids != null && gids.constructor !== Array ? [gids] : gids
|
|
return function(){
|
|
//this.ribbons.updateImage(gids)
|
|
this.refresh(gids)
|
|
}
|
|
}],
|
|
untag: [
|
|
function(tags, gids){
|
|
gids = gids != null && gids.constructor !== Array ? [gids] : gids
|
|
return function(){
|
|
//this.ribbons.updateImage(gids)
|
|
this.refresh(gids)
|
|
}
|
|
}],
|
|
})
|
|
|
|
var RibbonsEdit =
|
|
module.RibbonsEdit =
|
|
core.ImageGridFeatures.Feature({
|
|
title: '',
|
|
doc: '',
|
|
|
|
tag: 'ui-ribbons-edit-render',
|
|
depends: [
|
|
'edit',
|
|
'tags',
|
|
'sort',
|
|
'crop',
|
|
'image-group',
|
|
'ui-ribbons-render',
|
|
],
|
|
|
|
actions: RibbonsEditActions,
|
|
|
|
handlers: [
|
|
[[
|
|
'shiftImageTo.pre',
|
|
'shiftImageUp.pre',
|
|
'shiftImageDown.pre',
|
|
],
|
|
function(target){
|
|
return updateImagePosition(this, target) }],
|
|
|
|
|
|
// manage the .crop-mode css class...
|
|
['crop uncrop',
|
|
function(){
|
|
this.dom[this.cropped ?
|
|
'addClass'
|
|
: 'removeClass']('crop-mode')
|
|
}],
|
|
|
|
// reloading and updating...
|
|
[[
|
|
'sortImages',
|
|
'alignToRibbon',
|
|
'group',
|
|
'ungroup',
|
|
'groupTo',
|
|
'groupMarked',
|
|
'expandGroup',
|
|
'collapseGroup',
|
|
'crop',
|
|
'uncrop',
|
|
],
|
|
function(target){ return this.reload(true) }],
|
|
[[
|
|
'reverseImages',
|
|
'reverseRibbons',
|
|
'cropGroup',
|
|
],
|
|
function(target){ return this.reload() }],
|
|
],
|
|
})
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
// Partial ribbons...
|
|
|
|
// XXX try using .ribbons.resizeRibbon(..) for basic tasks...
|
|
// XXX try a strategy: load more in the direction of movement by an offset...
|
|
// XXX .updateRibbon(..) is not signature compatible with data.updateRibbon(..)
|
|
var PartialRibbonsActions =
|
|
actions.Actions({
|
|
config: {
|
|
// Number of screen widths to load...
|
|
'ribbon-size-screens': 7,
|
|
|
|
// Number of screen widths to edge to trigger reload...
|
|
'ribbon-resize-threshold': 1.5,
|
|
|
|
// Timeout before a non-forced ribbon size update happens after
|
|
// the action...
|
|
// NOTE: if set to null, the update will be sync...
|
|
'ribbon-update-timeout': 120,
|
|
},
|
|
|
|
// NOTE: this will force sync resize if one of the following is true:
|
|
// - the target is not loaded
|
|
// - we are less than screen width from the edge
|
|
// - threshold is set to 0
|
|
// XXX this is not signature compatible with data.updateRibbon(..)
|
|
// XXX do not do anything for off-screen ribbons...
|
|
updateRibbon: ['- Interface/Update partial ribbon size',
|
|
function(target, w, size, threshold){
|
|
target = target instanceof jQuery
|
|
? this.ribbons.elemGID(target)
|
|
// NOTE: data.getImage(..) can return null at start or end
|
|
// of ribbon, thus we need to account for this...
|
|
: (this.data.getImage(target)
|
|
|| this.data.getImage(target, 'after'))
|
|
|
|
w = w || this.screenwidth
|
|
|
|
// get config data and normalize...
|
|
size = (size
|
|
|| this.config['ribbon-size-screens']
|
|
|| 5) * w
|
|
threshold = threshold == 0 ? threshold
|
|
: (threshold
|
|
|| this.config['ribbon-resize-threshold']
|
|
|| 1) * w
|
|
|
|
var timeout = this.config['ribbon-update-timeout']
|
|
|
|
// next/prev loaded...
|
|
var img = this.ribbons.getImage(target)
|
|
var nl = img.nextAll('.image:not(.clone)').length
|
|
var pl = img.prevAll('.image:not(.clone)').length
|
|
|
|
// next/prev available...
|
|
// NOTE: we subtract 1 to remove the current and make these
|
|
// compatible with: nl, pl
|
|
var na = this.data.getImages(target, size, 'after').length - 1
|
|
var pa = this.data.getImages(target, size, 'before').length - 1
|
|
|
|
// do the update...
|
|
// no threshold means force load...
|
|
if(threshold == 0
|
|
// the target is not loaded...
|
|
|| img.length == 0
|
|
// passed hard threshold on the right...
|
|
|| (nl < w && na > nl)
|
|
// passed hard threshold on the left...
|
|
|| (pl < w && pa > pl)){
|
|
|
|
this.resizeRibbon(target, size)
|
|
|
|
// do a late resize...
|
|
// loaded more than we need (crop?)...
|
|
} else if(na + pa < nl + pl
|
|
// passed threshold on the right...
|
|
|| (nl < threshold && na > nl)
|
|
// passed threshold on the left...
|
|
|| (pl < threshold && pa > pl)
|
|
// loaded more than we need by threshold...
|
|
|| nl + pl + 1 > size + threshold){
|
|
|
|
return function(){
|
|
// sync update...
|
|
if(timeout == null){
|
|
this.resizeRibbon(target, size)
|
|
|
|
// async update...
|
|
} else {
|
|
// XXX need to check if we are too close to the edge...
|
|
var that = this
|
|
//setTimeout(function(){ that.resizeRibbon(target, size) }, 0)
|
|
if(this.__update_timeout){
|
|
clearTimeout(this.__update_timeout)
|
|
}
|
|
this.__update_timeout = setTimeout(function(){
|
|
delete that.__update_timeout
|
|
that.resizeRibbon(target, size)
|
|
}, timeout)
|
|
}
|
|
}
|
|
}
|
|
}],
|
|
})
|
|
|
|
var PartialRibbons =
|
|
module.PartialRibbons =
|
|
core.ImageGridFeatures.Feature({
|
|
title: 'Partial Ribbons',
|
|
doc: core.doc`Maintains partially loaded ribbons, this enables very large
|
|
image sets to be handled efficiently.`,
|
|
|
|
// NOTE: partial ribbons needs to be setup first...
|
|
// ...the reasons why things break otherwise is not too clear.
|
|
priority: 'high',
|
|
|
|
tag: 'ui-partial-ribbons',
|
|
exclusive: ['ui-partial-ribbons'],
|
|
depends: [
|
|
//'ui',
|
|
'ui-ribbons-render',
|
|
],
|
|
suggested: [
|
|
'ui-partial-ribbons-precache',
|
|
],
|
|
|
|
|
|
actions: PartialRibbonsActions,
|
|
|
|
handlers: [
|
|
['focusImage.pre centerImage.pre',
|
|
function(target, list){
|
|
// NOTE: we have to do this as we are called BEFORE the
|
|
// actual focus change happens...
|
|
// XXX is there a better way to do this???
|
|
target = list != null ? target = this.data.getImage(target, list) : target
|
|
|
|
this.updateRibbon(target)
|
|
}],
|
|
['resizing.pre',
|
|
function(unit, size){
|
|
// keep constant size in single image...
|
|
if(this.toggleSingleImage && this.toggleSingleImage('?') == 'on'){
|
|
this.updateRibbon(
|
|
'current',
|
|
this.config['ribbons-resize-single-image'] || 13)
|
|
|
|
} else if(unit == 'scale'){
|
|
this.updateRibbon('current', this.screenwidth / size || 1)
|
|
|
|
} else if(unit == 'screenwidth'){
|
|
this.updateRibbon('current', size || 1)
|
|
|
|
} else if(unit == 'screenheight'){
|
|
size = size || 1
|
|
|
|
// convert target height in ribbons to width in images...
|
|
// NOTE: this does not account for compensation that
|
|
// .updateRibbon(..) makes for fitting whole image
|
|
// counts, this is a small enough error so as not
|
|
// to waste time on...
|
|
var s = this.ribbons.scale()
|
|
var h = this.ribbons.getScreenHeightRibbons()
|
|
var w = this.ribbons.getScreenWidthImages()
|
|
var nw = w / (h/size)
|
|
|
|
this.updateRibbon('current', nw)
|
|
}
|
|
}],
|
|
],
|
|
})
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
// Animation...
|
|
|
|
// XXX at this point this does not support target lists...
|
|
// XXX shift up/down to new ribbon is not too correct...
|
|
// XXX depends on .ribbons.makeShadow(..)...
|
|
var ShiftAnimation =
|
|
module.ShiftAnimation = core.ImageGridFeatures.Feature({
|
|
title: '',
|
|
doc: '',
|
|
|
|
tag: 'ui-animation',
|
|
depends: [
|
|
'ui-ribbons-render',
|
|
],
|
|
// NOTE: this will allow the animations to start as early as possible
|
|
// in the action call...
|
|
priority: 'high',
|
|
|
|
config: {
|
|
// XXX make this duration...
|
|
'shadow-animation-delay': 200,
|
|
'shadow-animation-start-delay': 0,
|
|
},
|
|
|
|
handlers: [
|
|
//['shiftImageUp.pre shiftImageDown.pre '
|
|
// +'travelImageUp.pre travelImageDown.pre',
|
|
['shiftImageUp.pre shiftImageDown.pre',
|
|
function(target){
|
|
// XXX do not do target lists...
|
|
if(target != null && target.constructor === Array
|
|
// do not animate in single image mode...
|
|
&& this.toggleSingleImage('?') == 'on'){
|
|
return
|
|
}
|
|
var s = this.ribbons.makeShadow(target, true,
|
|
// XXX make this duration...
|
|
this.config['shadow-animation-delay'],
|
|
this.config['shadow-animation-start-delay'])
|
|
return function(){ s() }
|
|
}],
|
|
// NOTE: this will keep the shadow in place -- the shadow will not
|
|
// go to the mountain, the mountain will come to the shadow ;)
|
|
['shiftImageLeft.pre shiftImageRight.pre',
|
|
function(target){
|
|
// XXX do not do target lists...
|
|
if(target != null && target.constructor === Array
|
|
// do not animate in single image mode...
|
|
&& this.toggleSingleImage('?') == 'on'){
|
|
return
|
|
}
|
|
var s = this.ribbons.makeShadow(target, undefined,
|
|
// XXX make this duration...
|
|
this.config['shadow-animation-delay'],
|
|
this.config['shadow-animation-start-delay'])
|
|
return function(){ s() }
|
|
}],
|
|
],
|
|
})
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* vim:set ts=4 sw=4 : */ return module })
|