mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
refactoring of the ui/render/access -- started split of viewer into a renderer and viewer actions...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
796bd4d8cb
commit
22627468eb
@ -132,7 +132,7 @@ var AppControlActions = actions.Actions({
|
||||
this.ribbons.preventTransitions()
|
||||
|
||||
// hide the viewer to hide any animation crimes...
|
||||
this.ribbons.viewer[0].style.visibility = 'hidden'
|
||||
this.dom[0].style.visibility = 'hidden'
|
||||
|
||||
// XXX async...
|
||||
// ...this complicates things as we need to do the next
|
||||
@ -146,7 +146,7 @@ var AppControlActions = actions.Actions({
|
||||
.ribbons
|
||||
.restoreTransitions()
|
||||
|
||||
that.ribbons.viewer[0].style.visibility = ''
|
||||
that.dom[0].style.visibility = ''
|
||||
}, 100)
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ module.AppButtons = core.ImageGridFeatures.Feature({
|
||||
['start toggleFullScreen',
|
||||
function(){
|
||||
var fullscreen = this.toggleFullScreen('?')
|
||||
var buttons = this.ribbons.viewer.find('.app-buttons')
|
||||
var buttons = this.dom.find('.app-buttons')
|
||||
|
||||
// fullscreen button...
|
||||
buttons.find('.fullscreen.button')
|
||||
|
||||
@ -175,7 +175,7 @@ var ExternalEditorUIActions = actions.Actions({
|
||||
var path = e.find('.text').last().text()
|
||||
var txt = e.find('.text').first().text()
|
||||
|
||||
var b = overlay.Overlay(that.ribbons.viewer,
|
||||
var b = overlay.Overlay(that.dom,
|
||||
browseWalk.makeWalk(null, path,
|
||||
// XXX
|
||||
'*+(exe|cmd|ps1|sh)',
|
||||
@ -291,7 +291,7 @@ var ExternalEditorUIActions = actions.Actions({
|
||||
make(['Add new editor...'])
|
||||
.on('open', function(){
|
||||
closingPrevented = true
|
||||
var b = overlay.Overlay(that.ribbons.viewer,
|
||||
var b = overlay.Overlay(that.dom,
|
||||
browseWalk.makeWalk(
|
||||
null, '/',
|
||||
// XXX
|
||||
|
||||
@ -458,7 +458,7 @@ var KeyboardActions = actions.Actions({
|
||||
return that.__keyboard_config
|
||||
}
|
||||
},
|
||||
function(){ return that.ribbons.viewer })
|
||||
function(){ return that.dom })
|
||||
return kb },
|
||||
|
||||
testKeyboardDoc: ['- Interface/',
|
||||
@ -718,9 +718,9 @@ var KeyboardActions = actions.Actions({
|
||||
// NOTE: the target element must be focusable...
|
||||
var target =
|
||||
this.__keyboard_event_source =
|
||||
this.config['keyboard-event-source'] == null ? this.ribbons.viewer
|
||||
this.config['keyboard-event-source'] == null ? this.dom
|
||||
: this.config['keyboard-event-source'] == 'window' ? $(window)
|
||||
: this.config['keyboard-event-source'] == 'viewer' ? this.ribbons.viewer
|
||||
: this.config['keyboard-event-source'] == 'viewer' ? this.dom
|
||||
: this.config['keyboard-event-source'] == 'document' ? $(document)
|
||||
: $(this.config['keyboard-event-source'])
|
||||
|
||||
|
||||
@ -66,10 +66,14 @@ core.ImageGridFeatures.Feature('viewer-testing', [
|
||||
'ui',
|
||||
'keyboard',
|
||||
|
||||
// XXX BUG?: should this be indicated as a missing dependency???
|
||||
'missing-feature',
|
||||
|
||||
// XXX
|
||||
'ui-ribbons-render',
|
||||
'ui-vdom-render',
|
||||
'ui-react-render',
|
||||
//'ui-react-render',
|
||||
//*/
|
||||
|
||||
// features...
|
||||
'ui-cursor',
|
||||
|
||||
@ -46,12 +46,12 @@ var BoundsIndicatorsActions = actions.Actions({
|
||||
bottom: '.bottom-indicator',
|
||||
}[direction]
|
||||
|
||||
var indicator = this.ribbons.viewer.find(cls)
|
||||
var indicator = this.dom.find(cls)
|
||||
|
||||
if(indicator.length == 0){
|
||||
indicator = $('<div>')
|
||||
.addClass(cls.replace('.', ''))
|
||||
.appendTo(this.ribbons.viewer)
|
||||
.appendTo(this.dom)
|
||||
}
|
||||
|
||||
return indicator
|
||||
@ -262,7 +262,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
||||
function(){
|
||||
var fadein = this.config['current-image-indicator-fadein']
|
||||
this.updateCurrentImageIndicator()
|
||||
this.ribbons.viewer.find('.current-marker')
|
||||
this.dom.find('.current-marker')
|
||||
.css({
|
||||
display: 'block',
|
||||
opacity: 0,
|
||||
@ -302,7 +302,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
||||
&& clearTimeout(this.__current_image_indicator_restore_timeout)
|
||||
delete this.__current_image_indicator_restore_timeout
|
||||
|
||||
this.ribbons.viewer
|
||||
this.dom
|
||||
.find('.current-marker')
|
||||
.velocity({opacity: 0}, { duration: 100 })
|
||||
}],
|
||||
@ -312,7 +312,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
||||
this.__current_image_indicator_restore_timeout = setTimeout(function(){
|
||||
that.updateCurrentImageIndicator()
|
||||
|
||||
that.ribbons.viewer
|
||||
that.dom
|
||||
.find('.current-marker')
|
||||
.velocity({opacity: 1}, { duration: 100 })
|
||||
}, this.config['current-image-indicator-restore-delay'] || 500)
|
||||
@ -322,12 +322,12 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
||||
['toggleSingleImage',
|
||||
function(){
|
||||
if(this.toggleSingleImage('?') == 'off'){
|
||||
this.ribbons.viewer.find('.current-marker')
|
||||
this.dom.find('.current-marker')
|
||||
.delay(150)
|
||||
.animate({opacity: 1}, 100)
|
||||
|
||||
} else {
|
||||
this.ribbons.viewer.find('.current-marker')
|
||||
this.dom.find('.current-marker')
|
||||
.css({ opacity: 0 })
|
||||
}
|
||||
}],
|
||||
@ -343,7 +343,7 @@ var makeIndicatorHiderOnFastAction = function(hide_timeout){
|
||||
}
|
||||
|
||||
var that = this
|
||||
var m = this.ribbons.viewer.find('.current-marker')
|
||||
var m = this.dom.find('.current-marker')
|
||||
var t = this.config[hide_timeout]
|
||||
|
||||
var cur = this.current
|
||||
@ -431,13 +431,13 @@ module.CurrentImageIndicatorHideOnScreenNav = core.ImageGridFeatures.Feature({
|
||||
// NOTE: we use .pre events here to see if we have moved...
|
||||
['prevScreen.post nextScreen.post',
|
||||
function(){
|
||||
var m = this.ribbons.viewer.find('.current-marker')
|
||||
var m = this.dom.find('.current-marker')
|
||||
|
||||
m.css({ opacity: 0 })
|
||||
}],
|
||||
['focusImage.post',
|
||||
function(){
|
||||
var m = this.ribbons.viewer.find('.current-marker')
|
||||
var m = this.dom.find('.current-marker')
|
||||
|
||||
m.css({ opacity: '' })
|
||||
}],
|
||||
@ -464,7 +464,7 @@ var updateBaseRibbonIndicator = function(img){
|
||||
}
|
||||
|
||||
if(m.length == 0){
|
||||
m = this.ribbons.viewer.find('.base-ribbon-marker')
|
||||
m = this.dom.find('.base-ribbon-marker')
|
||||
|
||||
// make the indicator...
|
||||
if(m.length == 0){
|
||||
@ -478,7 +478,7 @@ var updateBaseRibbonIndicator = function(img){
|
||||
|
||||
// XXX this is wrong -- need to calculate the offset after the move and not now...
|
||||
if(base.offset().left < 0){
|
||||
m.css('left', (img.position().left + img.width()/2 - this.ribbons.viewer.width()/2) / scale)
|
||||
m.css('left', (img.position().left + img.width()/2 - this.dom.width()/2) / scale)
|
||||
|
||||
} else {
|
||||
m.css('left', '')
|
||||
@ -530,7 +530,7 @@ module.PassiveBaseRibbonIndicator = core.ImageGridFeatures.Feature({
|
||||
actions: actions.Actions({
|
||||
togglePassiveBaseRibbonIndicator: ['Interface/Passive base ribbon indicator',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'show-passive-base-ribbon-indicator',
|
||||
function(state){
|
||||
this.config['ui-show-passive-base-ribbon-indicator'] = state == 'on' }) ],
|
||||
|
||||
@ -153,7 +153,7 @@ module.DirectControlHammer = core.ImageGridFeatures.Feature({
|
||||
// hide and remove current image indicator...
|
||||
// NOTE: it will be reconstructed on
|
||||
// next .focusImage(..)
|
||||
var m = that.ribbons.viewer
|
||||
var m = that.dom
|
||||
.find('.current-marker')
|
||||
.velocity({opacity: 0}, {
|
||||
duration: 100,
|
||||
@ -245,14 +245,14 @@ module.IndirectControl = core.ImageGridFeatures.Feature({
|
||||
|
||||
if(state == null){
|
||||
return (this.ribbons
|
||||
&& this.ribbons.viewer
|
||||
&& this.ribbons.viewer.data('hammer'))
|
||||
&& this.dom
|
||||
&& this.dom.data('hammer'))
|
||||
|| 'none'
|
||||
|
||||
// on...
|
||||
} else if(state == 'handling-swipes'){
|
||||
var that = this
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
|
||||
// prevent multiple handlers...
|
||||
if(viewer.data('hammer') != null){
|
||||
@ -272,7 +272,7 @@ module.IndirectControl = core.ImageGridFeatures.Feature({
|
||||
|
||||
// off...
|
||||
} else {
|
||||
this.ribbons.viewer
|
||||
this.dom
|
||||
.off('swipeleft')
|
||||
.off('swiperight')
|
||||
.off('swipeup')
|
||||
|
||||
@ -435,9 +435,7 @@ var VirtualDOMRibbonsPrototype = {
|
||||
// concept, so we build the state on demand...
|
||||
// XXX get scale from config on initial load...
|
||||
sync: function(target, size){
|
||||
var dom = this.dom = this.dom
|
||||
// get/create the ribbon-set...
|
||||
|| this.imagegrid.ribbons.getRibbonSet(true)
|
||||
var dom = this.dom
|
||||
|
||||
var state = this.state ? Object.create(this.state) : {}
|
||||
target && (state.target = target)
|
||||
@ -447,7 +445,7 @@ var VirtualDOMRibbonsPrototype = {
|
||||
if(this.vdom == null){
|
||||
var n = this.vdom = this.makeView(state, true)
|
||||
var v = vdom.create(n)
|
||||
dom.replaceWith(v)
|
||||
this.imagegrid.dom.append(v)
|
||||
this.dom = v
|
||||
|
||||
// patch state...
|
||||
|
||||
@ -48,7 +48,7 @@ var ProgressActions = actions.Actions({
|
||||
// XXX revise styles...
|
||||
showProgress: ['- Interface/Show progress bar...',
|
||||
function(text, value, max){
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
var that = this
|
||||
|
||||
var msg = text instanceof Array ? text.slice(1).join(': ') : null
|
||||
|
||||
@ -27,7 +27,7 @@ var RangeActions = actions.Actions({
|
||||
makeBrace: ['- Range/',
|
||||
function(type, gid){
|
||||
var cls = type == 'open' ? 'brace-open' : 'brace-close'
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
var r = this.dom.find('.ribbon')
|
||||
|
||||
var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls)
|
||||
|
||||
@ -61,7 +61,7 @@ var RangeActions = actions.Actions({
|
||||
// go but it sure makes things simpler...
|
||||
if(range == null){
|
||||
update = true
|
||||
this.ribbons.viewer
|
||||
this.dom
|
||||
.find('.ribbon .mark.brace')
|
||||
.remove()
|
||||
|
||||
@ -90,7 +90,7 @@ var RangeActions = actions.Actions({
|
||||
}
|
||||
|
||||
if(update){
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
var r = this.dom.find('.ribbon')
|
||||
|
||||
// XXX this does not work for non-current images ...
|
||||
this.ribbons.preventTransitions(r)
|
||||
@ -103,7 +103,7 @@ var RangeActions = actions.Actions({
|
||||
// XXX not sure if this is the right way to go...
|
||||
{browseMode: function(){ return !this.data.__range && 'disabled' }},
|
||||
function(image){
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
var r = this.dom.find('.ribbon')
|
||||
|
||||
delete this.data.__range
|
||||
this.updateRangeIndicators()
|
||||
@ -246,7 +246,7 @@ module.Range = core.ImageGridFeatures.Feature({
|
||||
|
||||
// show/hide off-screen indicators...
|
||||
// XXX STUB: should we animate indicators???
|
||||
['setScale.pre',
|
||||
['viewScale.pre',
|
||||
function(scale){
|
||||
var range = this.data.__range
|
||||
if(!this.ribbons || !range){
|
||||
@ -259,7 +259,7 @@ module.Range = core.ImageGridFeatures.Feature({
|
||||
}],
|
||||
[[
|
||||
'focusImage',
|
||||
'setScale',
|
||||
'viewScale',
|
||||
'updateRangeIndicators',
|
||||
],
|
||||
function(_, gid){
|
||||
@ -273,7 +273,7 @@ module.Range = core.ImageGridFeatures.Feature({
|
||||
return
|
||||
}
|
||||
|
||||
var Wr = this.ribbons.viewer.width()
|
||||
var Wr = this.dom.width()
|
||||
var W = (Wr / this.scale) / 2
|
||||
|
||||
var a = this.data.getImageOrder(range[0])
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
(function(require){ var module={} // make module AMD/node compatible...
|
||||
/*********************************************************************/
|
||||
|
||||
var object = require('lib/object')
|
||||
var actions = require('lib/actions')
|
||||
var features = require('lib/features')
|
||||
|
||||
@ -14,9 +15,31 @@ var core = require('features/core')
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var ViewerClassPrototype = {
|
||||
}
|
||||
|
||||
|
||||
var ViewerPrototype = {
|
||||
sync: function(){
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var Viewer =
|
||||
module.Viewer =
|
||||
object.makeConstructor('Viewer',
|
||||
ViewerClassPrototype,
|
||||
ViewerPrototype)
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var ReactActions = actions.Actions({
|
||||
get viewer(){
|
||||
},
|
||||
})
|
||||
|
||||
var React =
|
||||
|
||||
@ -7,18 +7,356 @@
|
||||
(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')
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var RibbonsActions = actions.Actions({
|
||||
|
||||
get dom(){
|
||||
return this.ribbons ? this.ribbons.viewer : undefined },
|
||||
|
||||
|
||||
// NOTE: this expects that ribbons will maintain .parent.images...
|
||||
// NOTE: when getting rid of ribbons need to also remove the .parent
|
||||
// reference...
|
||||
// XXX remove...
|
||||
get ribbons(){
|
||||
return this.__ribbons },
|
||||
set ribbons(ribbons){
|
||||
this.__ribbons = ribbons
|
||||
ribbons.parent = this
|
||||
},
|
||||
|
||||
|
||||
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()
|
||||
})
|
||||
*/
|
||||
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.getElemGID(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.getElemGID(target)
|
||||
: target
|
||||
|
||||
// align current ribbon...
|
||||
this.ribbons.centerRibbon(target)
|
||||
}],
|
||||
|
||||
|
||||
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.getElemGID(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
|
||||
}
|
||||
}],
|
||||
|
||||
// XXX move all the stuff from UI that binds actions to ribbons...
|
||||
// XXX
|
||||
})
|
||||
|
||||
|
||||
var Ribbons =
|
||||
module.Ribbons = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
@ -29,6 +367,9 @@ module.Ribbons = core.ImageGridFeatures.Feature({
|
||||
depends: [
|
||||
// XXX
|
||||
],
|
||||
suggested: [
|
||||
'ui-ribbons-edit-render',
|
||||
],
|
||||
|
||||
actions: RibbonsActions,
|
||||
|
||||
@ -37,6 +378,54 @@ module.Ribbons = core.ImageGridFeatures.Feature({
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// XXX
|
||||
|
||||
var PartialRibbonsActions = actions.Actions({
|
||||
})
|
||||
|
||||
var PartialRibbons =
|
||||
module.PartialRibbons = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'ui-partial-ribbons-render',
|
||||
exclusive: ['ui-render'],
|
||||
depends: [
|
||||
// XXX this will need to reuse part of the actions defined in Ribbons...
|
||||
],
|
||||
suggested: [
|
||||
'ui-ribbons-edit-render',
|
||||
],
|
||||
|
||||
actions: PartialRibbonsActions,
|
||||
|
||||
handlers: [],
|
||||
})
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
var RibbonsEditActions = actions.Actions({
|
||||
})
|
||||
|
||||
|
||||
var RibbonsEdit =
|
||||
module.RibbonsEdit = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'ui-ribbons-edit-render',
|
||||
depends: [
|
||||
'edit',
|
||||
],
|
||||
|
||||
actions: RibbonsEditActions,
|
||||
|
||||
handlers: [],
|
||||
})
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* vim:set ts=4 sw=4 : */ return module })
|
||||
|
||||
@ -127,7 +127,7 @@ var SingleImageActions = actions.Actions({
|
||||
return
|
||||
}
|
||||
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
|
||||
var ribbon = this.ribbons.getRibbon()
|
||||
var images = viewer.find('.ribbon .image')
|
||||
@ -239,7 +239,7 @@ var SingleImageActions = actions.Actions({
|
||||
|
||||
toggleSingleImage: ['Interface/Single image view',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'single-image-mode',
|
||||
function(state){
|
||||
if(state == 'on'){
|
||||
@ -344,7 +344,7 @@ module.SingleImageView = core.ImageGridFeatures.Feature({
|
||||
function(){
|
||||
// prevent this from doing anything while no viewer...
|
||||
if(!this.ribbons
|
||||
|| !this.ribbons.viewer
|
||||
|| !this.dom
|
||||
|| this.ribbons.getRibbonSet().length == 0){
|
||||
return
|
||||
}
|
||||
@ -510,7 +510,7 @@ module.SingleImageViewLocalStorage = core.ImageGridFeatures.Feature({
|
||||
return function(){
|
||||
// prevent this from doing anything while no viewer...
|
||||
if(!this.ribbons
|
||||
|| !this.ribbons.viewer
|
||||
|| !this.dom
|
||||
|| this.ribbons.getRibbonSet().length == 0){
|
||||
return
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ var SlideshowActions = actions.Actions({
|
||||
|
||||
toggleSlideshow: ['Slideshow/Slideshow quick toggle',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'slideshow-running',
|
||||
function(state){
|
||||
// start...
|
||||
|
||||
@ -33,7 +33,7 @@ var makeStateIndicatorItem = function(container, type, text){
|
||||
var item = $('<div>')
|
||||
.addClass('item '+ type || '')
|
||||
.attr('text', text)
|
||||
this.ribbons.viewer.find('.state-indicator-container.'+container)
|
||||
this.dom.find('.state-indicator-container.'+container)
|
||||
.append(item)
|
||||
return item
|
||||
}
|
||||
@ -461,11 +461,11 @@ var StatusBarActions = actions.Actions({
|
||||
// XXX change class...
|
||||
function(){
|
||||
// no viewer yet...
|
||||
if(!this.ribbons || !this.ribbons.viewer){
|
||||
if(!this.ribbons || !this.dom){
|
||||
return $()
|
||||
}
|
||||
|
||||
var bar = this.ribbons.viewer.find('.state-indicator-container.global-info')
|
||||
var bar = this.dom.find('.state-indicator-container.global-info')
|
||||
if(bar.length == 0){
|
||||
bar = makeStateIndicator('global-info overlay-info statusbar')
|
||||
.addClass(this.config['status-bar-mode']
|
||||
@ -484,7 +484,7 @@ var StatusBarActions = actions.Actions({
|
||||
.on('mouseout', function(){
|
||||
bar.find('.info').empty()
|
||||
})
|
||||
.appendTo(this.ribbons.viewer)
|
||||
.appendTo(this.dom)
|
||||
}
|
||||
return bar
|
||||
},
|
||||
@ -624,7 +624,7 @@ var StatusBarActions = actions.Actions({
|
||||
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
||||
|
||||
// XXX do this better...
|
||||
this.ribbons.viewer.find('.global-info .index .position').focus().click()
|
||||
this.dom.find('.global-info .index .position').focus().click()
|
||||
}
|
||||
}],
|
||||
editStatusBarRibbon: ['- Interface/Edit ribbon focus position in statusbar',
|
||||
@ -632,11 +632,11 @@ var StatusBarActions = actions.Actions({
|
||||
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
||||
|
||||
// XXX do this better...
|
||||
this.ribbons.viewer.find('.global-info .ribbon-number').focus().click()
|
||||
this.dom.find('.global-info .ribbon-number').focus().click()
|
||||
}],
|
||||
toggleStatusBarIndexMode: ['Interface/Status bar index mode',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer.find('.global-info .index') },
|
||||
function(){ return this.dom.find('.global-info .index') },
|
||||
['normal', 'global'],
|
||||
function(state){
|
||||
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
||||
@ -652,7 +652,7 @@ var StatusBarActions = actions.Actions({
|
||||
// XXX revise...
|
||||
showStatusBarInfo: ['- Interface/',
|
||||
function(text){
|
||||
var bar = this.ribbons.viewer.find('.state-indicator-container.global-info')
|
||||
var bar = this.dom.find('.state-indicator-container.global-info')
|
||||
|
||||
if(text){
|
||||
bar.find('.info').text(text)
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
var vdom = require('ext-lib/virtual-dom')
|
||||
|
||||
var object = require('lib/object')
|
||||
var actions = require('lib/actions')
|
||||
var features = require('lib/features')
|
||||
|
||||
@ -16,9 +17,453 @@ var core = require('features/core')
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
/*/ XXX
|
||||
var ViewerClassPrototype = {
|
||||
}
|
||||
|
||||
|
||||
var ViewerPrototype = {
|
||||
sync: function(){
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var Viewer =
|
||||
module.Viewer =
|
||||
object.makeConstructor('Viewer',
|
||||
ViewerClassPrototype,
|
||||
ViewerPrototype)
|
||||
//*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// - take care of DOM construction and update...
|
||||
// - alignment is done via .centerRibbon(..) / .centerImage(..)
|
||||
// - preview updates (XXX)
|
||||
// - update onload (a-la .ribbons._loadImagePreviewURL(..))
|
||||
|
||||
var VirtualDOMRibbonsClassPrototype = {
|
||||
// XXX ???
|
||||
}
|
||||
|
||||
var VirtualDOMRibbonsPrototype = {
|
||||
// XXX this is a circular ref -- I do not like it...
|
||||
imagegrid: null,
|
||||
|
||||
dom: null,
|
||||
vdom: null,
|
||||
|
||||
// Format:
|
||||
// {
|
||||
// count: <count>,
|
||||
//
|
||||
// scale: <scale>,
|
||||
//
|
||||
// top: <offset>,
|
||||
//
|
||||
// ribbons: {
|
||||
// <gid>: <offset>,
|
||||
// ...
|
||||
// },
|
||||
// }
|
||||
state: null,
|
||||
|
||||
|
||||
// XXX reuse these from ribbons???
|
||||
preventTransitions: function(){
|
||||
},
|
||||
restoreTransitions: function(){
|
||||
},
|
||||
getElemGID: function(){
|
||||
},
|
||||
getImage: function(){
|
||||
},
|
||||
getVisibleImageSize: function(){
|
||||
},
|
||||
focusImage: function(){
|
||||
},
|
||||
px2vmin: function(){
|
||||
},
|
||||
|
||||
|
||||
// constructors...
|
||||
makeView: function(state, initial){
|
||||
state = state || {}
|
||||
var that = this
|
||||
var ig = this.imagegrid
|
||||
|
||||
var target = state.target || ig.current
|
||||
|
||||
this.state = this.state || {}
|
||||
var count = state.count = state.count
|
||||
|| ig.screenwidth * (ig.config['ribbon-size-screens'] || 9)
|
||||
var s = state.scale = state.scale
|
||||
|| ig.scale
|
||||
|
||||
var data = ig.data
|
||||
var images = ig.images
|
||||
|
||||
var ribbons = data.ribbon_order
|
||||
.map(function(gid){
|
||||
return that.makeRibbon(gid, target, count, state, initial) })
|
||||
|
||||
return vdom.h('div.ribbon-set',
|
||||
{
|
||||
//key: 'ribbon-set',
|
||||
style: {
|
||||
transform: 'scale('+ s +', '+ s +')',
|
||||
}
|
||||
}, [
|
||||
// current image indicator...
|
||||
vdom.h('div.current-marker'),
|
||||
|
||||
// ribbon locator...
|
||||
vdom.h('div.ribbon-locator',
|
||||
{
|
||||
//key: 'ribbon-locator',
|
||||
},
|
||||
ribbons),
|
||||
])
|
||||
},
|
||||
// XXX setup handlers (???)
|
||||
// XXX STUB: make aligning more extensible... (???)
|
||||
makeRibbon: function(gid, target, count, state, initial){
|
||||
state = state || {}
|
||||
var that = this
|
||||
var ig = this.imagegrid
|
||||
var current = ig.current
|
||||
target = target || state.target || current
|
||||
var size = this.state.tile_size = state.tile_size
|
||||
|| this.state.tile_size
|
||||
|| this.getVisibleImageSize('max')
|
||||
var scale = state.scale = state.scale
|
||||
|| ig.scale
|
||||
var data = ig.data
|
||||
var images = ig.images
|
||||
// XXX
|
||||
var ribbons = ig.ribbons
|
||||
var base = data.base == gid ? '.base' : ''
|
||||
var imgs = []
|
||||
|
||||
this.state = this.state || {}
|
||||
//this.state.ribbons = this.state.ribbons || {}
|
||||
|
||||
// XXX
|
||||
var size = this.state.tile_size =
|
||||
this.state.tile_size
|
||||
|| this.getVisibleImageSize('max')
|
||||
|
||||
// calculate offset...
|
||||
// XXX this accounts for only one offset mode...
|
||||
// ...make this extensible...
|
||||
// XXX
|
||||
var vsize = this.px2vmin(size / scale)
|
||||
var ref = data.getImage(target, 'before', gid)
|
||||
var offset = ref == target ? vsize / 2
|
||||
: ref != null ? vsize
|
||||
: 0
|
||||
ref = ref || data.getImage(target, 'after', gid)
|
||||
|
||||
// build the images...
|
||||
//var gids = data.getImages(gid, count, 'total')
|
||||
var gids = data.getImages(ref, count, 'total')
|
||||
gids
|
||||
.forEach(function(gid){
|
||||
// image...
|
||||
imgs.push(that.makeImage(gid, size))
|
||||
|
||||
// marks...
|
||||
that.makeImageMarks(gid)
|
||||
.forEach(function(mark){ imgs.push(mark) })
|
||||
})
|
||||
|
||||
// XXX not sure about this...
|
||||
var style = initial ? { transform: 'translate3d(120vw, 0, 0)' } : {}
|
||||
|
||||
return vdom.h('div.ribbon'+base, {
|
||||
//key: 'ribbon-'+gid,
|
||||
|
||||
// XXX events, hammer, ...???
|
||||
|
||||
attributes: {
|
||||
gid: JSON.stringify(gid)
|
||||
.replace(/^"(.*)"$/g, '$1'),
|
||||
},
|
||||
|
||||
style: style,
|
||||
},
|
||||
imgs)
|
||||
},
|
||||
// XXX setup image handlers...
|
||||
// XXX update image previews...
|
||||
// XXX update image proportions for rotated images... (???)
|
||||
makeImage: function(gid, size){
|
||||
var ig = this.imagegrid
|
||||
//size = this.state.tile_size = size
|
||||
size = size
|
||||
|| this.state.tile_size
|
||||
|| this.getVisibleImageSize('max')
|
||||
var data = this.imagegrid.data
|
||||
var images = this.imagegrid.images || {}
|
||||
var current = data.current == gid ? '.current' : ''
|
||||
|
||||
// resolve group preview cover...
|
||||
var image = images[gid] || {}
|
||||
var seen = []
|
||||
while(image.type == 'group'){
|
||||
// error, recursive group...
|
||||
if(seen.indexOf(image.id) >= 0){
|
||||
image = images.IMAGE_DATA
|
||||
console.error('Recursive group:', gid)
|
||||
break
|
||||
}
|
||||
seen.push(image.id)
|
||||
|
||||
image = that.images[image.cover]
|
||||
}
|
||||
var url = ig.images.getBestPreview(gid, size, image, true).url
|
||||
|
||||
return vdom.h('div.image'+current, {
|
||||
// XXX BUG:
|
||||
// - setting this makes the images some times not change previews...
|
||||
// - removing this breaks .current class setting...
|
||||
key: 'image-'+gid,
|
||||
|
||||
attributes: {
|
||||
gid: JSON.stringify(gid)
|
||||
.replace(/^"(.*)"$/g, '$1'),
|
||||
orientation: image.orientation,
|
||||
flipped: image.flipped,
|
||||
|
||||
// XXX preview size -- get this onload from image...
|
||||
//'preview-width': ..,
|
||||
//'preview-height': ..,
|
||||
},
|
||||
style: {
|
||||
// XXX need to update this onload if changing preview
|
||||
// of same image...
|
||||
backgroundImage: 'url("'+ url +'")',
|
||||
}
|
||||
})
|
||||
},
|
||||
// XXX STUB: make marks handling extensible... (???)
|
||||
makeImageMarks: function(gid){
|
||||
var that = this
|
||||
var marks = []
|
||||
var tags = this.imagegrid.data.getTags(gid)
|
||||
|
||||
// XXX STUB: make this extensible...
|
||||
tags.indexOf('bookmark') >= 0
|
||||
&& marks.push('bookmark')
|
||||
tags.indexOf('selected') >= 0
|
||||
&& marks.push('selected')
|
||||
|
||||
return marks
|
||||
.map(function(type){
|
||||
return vdom.h('div.mark.'+(type || ''), {
|
||||
key: 'mark-'+type+'-'+gid,
|
||||
attributes: {
|
||||
gid: JSON.stringify(gid)
|
||||
.replace(/^"(.*)"$/g, '$1'),
|
||||
},
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// XXX add ability to hook in things like current image marker...
|
||||
|
||||
|
||||
// XXX these need .getImage(..) / .getRibbon(..) / .getRibbonLocator(..)
|
||||
centerRibbon: function(target){
|
||||
var ribbon = this.getRibbon(target)
|
||||
var locator = this.getRibbonLocator()
|
||||
|
||||
if(locator.length != 0 && ribbon.length != 0){
|
||||
var t = ribbon[0].offsetTop
|
||||
var h = ribbon[0].offsetHeight
|
||||
|
||||
locator.transform({ x: 0, y: this.px2vh(-(t + h/2)) + 'vh', z: 0 })
|
||||
}
|
||||
return this
|
||||
},
|
||||
centerImage: function(target, mode){
|
||||
target = this.getImage(target)
|
||||
var ribbon = this.getRibbon(target)
|
||||
|
||||
if(ribbon.length != 0){
|
||||
var l = target[0].offsetLeft
|
||||
var w = target[0].offsetWidth
|
||||
|
||||
var image_offset = mode == 'before' ? 0
|
||||
: mode == 'after' ? w
|
||||
: w/2
|
||||
|
||||
ribbon.transform({x: -this.px2vmin(l + image_offset) + 'vmin', y: 0, z: 0})
|
||||
}
|
||||
return this
|
||||
},
|
||||
|
||||
scale: function(scale){
|
||||
if(scale){
|
||||
this.state.scale = scale
|
||||
this.sync()
|
||||
|
||||
} else {
|
||||
return this.imagegrid.scale
|
||||
}
|
||||
},
|
||||
|
||||
// XXX not sure how to proceed with these...
|
||||
setImageHandler: function(evt, handler){
|
||||
},
|
||||
setRibbonHandler: function(evt, handler){
|
||||
},
|
||||
|
||||
|
||||
|
||||
clear: function(){
|
||||
this.dom
|
||||
&& this.dom.remove()
|
||||
|
||||
delete this.state
|
||||
delete this.dom
|
||||
delete this.vdom
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
// NOTE: virtual-dom architecture is designed around a fast-render-on-demand
|
||||
// concept, so we build the state on demand...
|
||||
// XXX get scale from config on initial load...
|
||||
sync: function(target, size){
|
||||
var dom = this.dom
|
||||
|
||||
var state = this.state ? Object.create(this.state) : {}
|
||||
target && (state.target = target)
|
||||
size && (state.count = size)
|
||||
|
||||
// build initial state...
|
||||
if(this.vdom == null){
|
||||
var n = this.vdom = this.makeView(state, true)
|
||||
var v = vdom.create(n)
|
||||
this.imagegrid.dom.append(v)
|
||||
this.dom = v
|
||||
|
||||
// patch state...
|
||||
} else {
|
||||
var n = this.makeView(state)
|
||||
var diff = vdom.diff(this.vdom, n)
|
||||
vdom.patch(dom, diff)
|
||||
this.vdom = n
|
||||
}
|
||||
|
||||
return this
|
||||
},
|
||||
// XXX should this do a full or partial .clear()???
|
||||
// XXX BUG: current image indicator resets but does not get shown...
|
||||
reset: function(){
|
||||
delete this.dom
|
||||
delete this.vdom
|
||||
if(this.state){
|
||||
delete this.state.tile_size
|
||||
}
|
||||
|
||||
return this
|
||||
.sync()
|
||||
},
|
||||
|
||||
__init__: function(imagegrid){
|
||||
this.imagegrid = imagegrid
|
||||
},
|
||||
}
|
||||
|
||||
var VirtualDOMRibbons =
|
||||
module.VirtualDOMRibbons =
|
||||
object.makeConstructor('VirtualDOMRibbons',
|
||||
VirtualDOMRibbonsClassPrototype,
|
||||
VirtualDOMRibbonsPrototype)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var VirtualDomActions = actions.Actions({
|
||||
|
||||
get dom(){
|
||||
return this.__dom },
|
||||
set dom(value){
|
||||
this.__dom = value},
|
||||
get virtualdom(){
|
||||
return (this.__virtual_dom = this.__virtual_dom || VirtualDOMRibbons(this)) },
|
||||
|
||||
|
||||
load: [
|
||||
function(data){
|
||||
return function(){
|
||||
// recycle the viewer if one is not given specifically...
|
||||
var viewer = data.viewer
|
||||
viewer = viewer == null ? this.dom : viewer
|
||||
|
||||
if(this.dom == null){
|
||||
this.dom = viewer
|
||||
|
||||
} else {
|
||||
this.virtualdom.clear()
|
||||
}
|
||||
|
||||
this.reload()
|
||||
}
|
||||
}],
|
||||
reload: ['Interface/Reload viewer',
|
||||
function(){
|
||||
this.virtualdom.reset()
|
||||
this.focusImage()
|
||||
}],
|
||||
// XXX this ignores it's args...
|
||||
refresh: ['Interface/Refresh images without reloading',
|
||||
function(gids, scale){
|
||||
this.virtualdom.sync()
|
||||
this.focusImage()
|
||||
}],
|
||||
|
||||
|
||||
// XXX
|
||||
updateRibbon: ['- Interface/Update partial ribbon size',
|
||||
function(target, w, size, threshold){
|
||||
target = target instanceof jQuery
|
||||
? this.virtualdom.getElemGID(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']
|
||||
|| 9) * w
|
||||
|
||||
// XXX DEBUG
|
||||
//size = 5
|
||||
|
||||
// XXX for some reason this does not set the .current class
|
||||
// on the right image...
|
||||
this.virtualdom.sync(target, size)
|
||||
|
||||
// XXX HACK: this fixes a bug in virtual-dom where .current
|
||||
// is not synced correctly...
|
||||
// ...one theory I have is that we change the class
|
||||
// manually, dom gets diffed and no change is detected
|
||||
// then the object gets recycled and the .current class
|
||||
// ends up on a different element...
|
||||
this.virtualdom.focusImage(target)
|
||||
|
||||
this.centerViewer(target)
|
||||
}],
|
||||
})
|
||||
|
||||
var VirtualDom =
|
||||
@ -34,7 +479,55 @@ module.VirtualDom = core.ImageGridFeatures.Feature({
|
||||
|
||||
actions: VirtualDomActions,
|
||||
|
||||
handlers: [],
|
||||
handlers: [
|
||||
['clear',
|
||||
function(){ this.virtualdom.clear() }],
|
||||
['fitImage toggleSingleImage',
|
||||
function(){ delete this.virtualdom.state.tile_size }],
|
||||
|
||||
// XXX account for fast navigation...
|
||||
['focusImage.pre',
|
||||
function(target){
|
||||
var img = this.virtualdom.getImage(target)
|
||||
|
||||
// in-place update...
|
||||
if(img.length > 0){
|
||||
// XXX need to account for running out of images and
|
||||
// not only on the current ribbon...
|
||||
if(!this.__partial_ribbon_update){
|
||||
this.__partial_ribbon_update = setTimeout((function(){
|
||||
delete this.__partial_ribbon_update
|
||||
this.virtualdom.preventTransitions()
|
||||
|
||||
this
|
||||
.updateRibbon(this.current)
|
||||
// NOTE: we are doing this manually because we
|
||||
// are running after the handler is done
|
||||
// thus missing the base call...
|
||||
.alignRibbons(null, null, true)
|
||||
|
||||
this.virtualdom.restoreTransitions()
|
||||
}).bind(this), 150)
|
||||
}
|
||||
|
||||
// long-jump...
|
||||
} else {
|
||||
if(this.__partial_ribbon_update){
|
||||
clearTimeout(this.__partial_ribbon_update)
|
||||
delete this.__partial_ribbon_update
|
||||
}
|
||||
|
||||
this.updateRibbon(target)
|
||||
}
|
||||
}],
|
||||
|
||||
// marks...
|
||||
[[
|
||||
'toggleMark',
|
||||
'toggleBookmark',
|
||||
//], function(){ this.updateRibbon() }],
|
||||
], function(){ this.virtualdom.sync() }],
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ function(context, cls, data){
|
||||
cls = cls instanceof Array ? cls : cls.split(/\s+/g)
|
||||
|
||||
// remove old versions...
|
||||
context.ribbons.viewer.find('.'+ cls.join('.')).remove()
|
||||
context.dom.find('.'+ cls.join('.')).remove()
|
||||
|
||||
// make container...
|
||||
var controls = $('<div>')
|
||||
@ -103,7 +103,7 @@ function(context, cls, data){
|
||||
})
|
||||
|
||||
controls
|
||||
.appendTo(context.ribbons.viewer)
|
||||
.appendTo(context.dom)
|
||||
}
|
||||
|
||||
// XXX write docs:
|
||||
@ -121,7 +121,7 @@ function(cls, cfg, parent){
|
||||
|
||||
return toggler.Toggler(null,
|
||||
function(){
|
||||
parent = parent == null ? this.ribbons.viewer
|
||||
parent = parent == null ? this.dom
|
||||
: parent instanceof Function ? parent.call(this)
|
||||
: parent
|
||||
return parent.find('.'+ cls.join('.')).length > 0 ? 'on' : 'off'
|
||||
@ -135,7 +135,7 @@ function(cls, cfg, parent){
|
||||
&& makeButtonControls(this, cls, config)
|
||||
|
||||
} else {
|
||||
this.ribbons.viewer.find('.'+ cls.join('.')).remove()
|
||||
this.dom.find('.'+ cls.join('.')).remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -341,7 +341,7 @@ module.makeUIContainer = function(make){
|
||||
// is in a state where the window
|
||||
// is in focus but keys are not
|
||||
// tracked...
|
||||
: that.ribbons.viewer.focus()
|
||||
: that.dom.focus()
|
||||
})
|
||||
// Compensate for click focusing the parent dialog when
|
||||
// a child is created...
|
||||
@ -427,7 +427,7 @@ var makeDrawer = function(direction){
|
||||
var that = this
|
||||
options = options || {}
|
||||
var parent = options.parentElement
|
||||
parent = parent ? $(parent) : this.ribbons.viewer
|
||||
parent = parent ? $(parent) : this.dom
|
||||
|
||||
options.direction = direction || 'bottom'
|
||||
|
||||
@ -513,7 +513,7 @@ var DialogsActions = actions.Actions({
|
||||
// element
|
||||
// null
|
||||
get modal(){
|
||||
var modal = this.ribbons.viewer
|
||||
var modal = this.dom
|
||||
.find('.modal-widget')
|
||||
.last()
|
||||
return modal.data('widget-controller')
|
||||
@ -540,7 +540,7 @@ var DialogsActions = actions.Actions({
|
||||
Overlay: ['- Interface/',
|
||||
makeUIContainer(function(dialog, options){
|
||||
var that = this
|
||||
return overlay.Overlay(this.ribbons.viewer, dialog, options)
|
||||
return overlay.Overlay(this.dom, dialog, options)
|
||||
// focus top modal on exit...
|
||||
.on('close', function(){
|
||||
var o = that.modal
|
||||
@ -575,7 +575,7 @@ var DialogsActions = actions.Actions({
|
||||
client: dialog,
|
||||
dom: $('<div>')
|
||||
.append(dialog.dom || dialog)
|
||||
.appendTo(this.ribbons.viewer)
|
||||
.appendTo(this.dom)
|
||||
.draggable(),
|
||||
close: function(func){
|
||||
if(func){
|
||||
@ -762,7 +762,7 @@ var DialogsActions = actions.Actions({
|
||||
|
||||
toggleOverlayBlur: ['Interface/Dialog overlay blur',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'overlay-blur-enabled',
|
||||
function(state){ this.config['ui-overlay-blur'] = state }) ],
|
||||
})
|
||||
@ -1406,7 +1406,7 @@ module.ContextActionMenu = core.ImageGridFeatures.Feature({
|
||||
['load',
|
||||
function(){
|
||||
var that = this
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
|
||||
!viewer.data('context-menu')
|
||||
&& viewer
|
||||
@ -1528,7 +1528,7 @@ module.Buttons = core.ImageGridFeatures.Feature({
|
||||
$('.main-buttons.buttons .crop.button sub')
|
||||
.text(this.crop_stack ? this.crop_stack.length : '') }],
|
||||
// update zoom button status...
|
||||
['setScale',
|
||||
['viewScale',
|
||||
function(){
|
||||
$('.secondary-buttons.buttons .zoom.button sub')
|
||||
.text(Math.round(this.screenwidth)) }],
|
||||
@ -1897,7 +1897,7 @@ var WidgetTestActions = actions.Actions({
|
||||
make('c/')
|
||||
}
|
||||
|
||||
var o = overlay.Overlay(this.ribbons.viewer,
|
||||
var o = overlay.Overlay(this.dom,
|
||||
browse.makePathList(null, {
|
||||
'a/*': list,
|
||||
'b/*': list,
|
||||
@ -1914,8 +1914,8 @@ var WidgetTestActions = actions.Actions({
|
||||
|
||||
|
||||
// XXX migrate to the dialog framework...
|
||||
// XXX use this.ribbons.viewer as base...
|
||||
// XXX BUG: when using this.ribbons.viewer as base some actions leak
|
||||
// XXX use this.dom as base...
|
||||
// XXX BUG: when using this.dom as base some actions leak
|
||||
// between the two viewers...
|
||||
showTaggedInDrawer: ['- Test/Show tagged in drawer',
|
||||
function(tag){
|
||||
@ -1928,7 +1928,7 @@ var WidgetTestActions = actions.Actions({
|
||||
height: H,
|
||||
background: 'black',
|
||||
})
|
||||
// XXX use this.ribbons.viewer as base...
|
||||
// XXX use this.dom as base...
|
||||
// XXX when using viewer zoom and other stuff get leaked...
|
||||
var widget = drawer.Drawer($('body'),
|
||||
$('<div>')
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
* Experimental Features:
|
||||
* - ui-ribbons-placement
|
||||
* manage different low level ribbon placement mechanics
|
||||
* XXX experimental...
|
||||
* XXX EXPERIMENTAL...
|
||||
* - auto-single-image
|
||||
* - auto-ribbon
|
||||
*
|
||||
@ -234,21 +234,11 @@ module.ViewerActions = actions.Actions({
|
||||
'ribbon-align-delay': 50,
|
||||
},
|
||||
|
||||
// Ribbons...
|
||||
//
|
||||
// NOTE: this expects that ribbons will maintain .parent.images...
|
||||
// NOTE: when getting rid of ribbons need to also remove the .parent
|
||||
// reference...
|
||||
get ribbons(){
|
||||
return this.__ribbons },
|
||||
set ribbons(ribbons){
|
||||
this.__ribbons = ribbons
|
||||
ribbons.parent = this
|
||||
},
|
||||
// Viewer dom...
|
||||
dom: null,
|
||||
|
||||
// Current image data...
|
||||
//
|
||||
// XXX experimental...
|
||||
get image(){
|
||||
return this.images && this.images[this.current] },
|
||||
set image(val){
|
||||
@ -259,28 +249,21 @@ module.ViewerActions = actions.Actions({
|
||||
|
||||
// Scaling...
|
||||
//
|
||||
// Normal scale...
|
||||
// NOTE: .screenwidth / .screenheight are measured in square image blocks...
|
||||
get scale(){
|
||||
return this.ribbons != null ? this.ribbons.scale() : null },
|
||||
return this.viewScale() },
|
||||
set scale(s){
|
||||
this.setScale(s) },
|
||||
|
||||
// Screen width in image blocks...
|
||||
//
|
||||
// NOTE: this will change depending on image block sizing...
|
||||
// NOTE: this not usable for image blocks of different sizes...
|
||||
this.viewScale(s) },
|
||||
get screenwidth(){
|
||||
return this.ribbons != null ? this.ribbons.getScreenWidthImages() : null },
|
||||
return this.fitImage('?') },
|
||||
set screenwidth(n){
|
||||
this.fitImage(n, false) },
|
||||
|
||||
// Screen height in image blocks...
|
||||
get screenheight(){
|
||||
return this.ribbons != null ? this.ribbons.getScreenHeightRibbons() : null },
|
||||
return this.fitRibbon('?') },
|
||||
set screenheight(n){
|
||||
this.fitRibbon(n, false) },
|
||||
|
||||
// Screen size in image radii on the narrow side of the screen...
|
||||
// Screen size in image "radii" on the narrow side of the screen...
|
||||
//
|
||||
// E.g.
|
||||
//
|
||||
@ -289,10 +272,10 @@ module.ViewerActions = actions.Actions({
|
||||
// min(image.width, image.height)
|
||||
//
|
||||
get screenfit(){
|
||||
if(!this.ribbons || !this.ribbons.viewer){
|
||||
if(!this.ribbons || !this.dom){
|
||||
return null
|
||||
}
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
var W = viewer.width()
|
||||
var H = viewer.height()
|
||||
|
||||
@ -301,7 +284,7 @@ module.ViewerActions = actions.Actions({
|
||||
: this.screenheight
|
||||
},
|
||||
set screenfit(n){
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
var W = viewer.width()
|
||||
var H = viewer.height()
|
||||
|
||||
@ -313,170 +296,12 @@ module.ViewerActions = actions.Actions({
|
||||
}
|
||||
},
|
||||
|
||||
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.ribbons.viewer
|
||||
: 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()
|
||||
})
|
||||
*/
|
||||
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() }],
|
||||
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)
|
||||
}],
|
||||
|
||||
|
||||
// General UI stuff...
|
||||
// NOTE: this is applicable to all uses...
|
||||
toggleTheme: ['Interface/Theme/Viewer theme',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
function(){ return this.config.themes },
|
||||
function(state){ this.config.theme = state }) ],
|
||||
lighterTheme: ['Interface/Theme/Lighter theme',
|
||||
@ -493,17 +318,65 @@ module.ViewerActions = actions.Actions({
|
||||
}],
|
||||
toggleRibbonTheme: ['Interface/Theme/Ribbon theme',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
function(){ return this.config['ribbon-themes'] },
|
||||
function(state){ this.config['ribbon-theme'] = state }) ],
|
||||
toggleRibbonImageSepators: ['Interface/Theme/Ribbon image separators',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'ribbon-image-separators',
|
||||
function(state){ this.config['ribbon-image-separators'] = state }) ],
|
||||
|
||||
|
||||
// ribbon aligning...
|
||||
// Navigation...
|
||||
//
|
||||
// NOTE: these prioritize whole images, i.e. each image will at least
|
||||
// once be fully shown.
|
||||
prevScreen: ['Navigate/Screen width back',
|
||||
function(){
|
||||
// NOTE: the 0.2 is added to compensate for alignment/scaling
|
||||
// errors -- 2.99 images wide counts as 3 while 2.5 as 2.
|
||||
var w = Math.floor(this.screenwidth + 0.2)
|
||||
w += (w % 2) - 1
|
||||
this.prevImage(w)
|
||||
}],
|
||||
nextScreen: ['Navigate/Screen width forward',
|
||||
function(){
|
||||
var w = Math.floor(this.screenwidth + 0.2)
|
||||
w += (w % 2) - 1
|
||||
this.nextImage(w)
|
||||
}],
|
||||
|
||||
|
||||
// Renderer API...
|
||||
/*/ XXX do we need these here???
|
||||
centerImage: ['- Interface/Center an image in ribbon horizontally',
|
||||
function(target, align, offset, scale){
|
||||
}],
|
||||
centerRibbon: ['- Interface/Center a ribbon vertically',
|
||||
function(target){
|
||||
}],
|
||||
ribbonRotation: ['- Interface|Ribbon/',
|
||||
function(a){
|
||||
}],
|
||||
viewScale: ['- Zoom/',
|
||||
function(scale){
|
||||
}],
|
||||
fitImage: ['Zoom/Fit image',
|
||||
function(count, overflow){
|
||||
}],
|
||||
fitRibbon: ['Zoom/Fit ribbon vertically',
|
||||
function(count, whole){
|
||||
}],
|
||||
//*/
|
||||
|
||||
|
||||
// ribbon aligning and centering...
|
||||
centerViewer: ['- Interface/Center the viewer',
|
||||
function(target){
|
||||
this
|
||||
.centerImage(target)
|
||||
.centerRibbon(target) }],
|
||||
alignRibbons: ['Interface/Align ribbons',
|
||||
function(target, scale, now){
|
||||
if(target == 'now'){
|
||||
@ -535,6 +408,7 @@ module.ViewerActions = actions.Actions({
|
||||
// order...
|
||||
// XXX skip off-screen ribbons (???)
|
||||
// XXX should the timeout be configurable???
|
||||
// XXX remove dependency on .ribbons
|
||||
alignByOrder: ['Interface/Align ribbons by image order',
|
||||
function(target, scale, now){
|
||||
if(target == 'now'){
|
||||
@ -649,34 +523,8 @@ module.ViewerActions = actions.Actions({
|
||||
//}, 0)
|
||||
}],
|
||||
|
||||
// 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.getElemGID(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.getElemGID(target)
|
||||
: target
|
||||
|
||||
// align current ribbon...
|
||||
this.ribbons.centerRibbon(target)
|
||||
}],
|
||||
|
||||
centerViewer: ['- Interface/Center the viewer',
|
||||
function(target){
|
||||
this
|
||||
.centerImage(target)
|
||||
.centerRibbon(target)
|
||||
}],
|
||||
|
||||
// Viewer/window resize event...
|
||||
resizingWindow: ['- Interface/',
|
||||
core.doc`This is called by the window resize event handler...
|
||||
|
||||
@ -692,57 +540,13 @@ module.ViewerActions = actions.Actions({
|
||||
//
|
||||
// Not for direct use.
|
||||
})],
|
||||
|
||||
|
||||
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.getElemGID(t)
|
||||
|
||||
this.focusImage(t, r)
|
||||
}
|
||||
}],
|
||||
|
||||
// NOTE: these prioritize whole images, i.e. each image will at least
|
||||
// once be fully shown.
|
||||
prevScreen: ['Navigate/Screen width back',
|
||||
function(){
|
||||
// NOTE: the 0.2 is added to compensate for alignment/scaling
|
||||
// errors -- 2.99 images wide counts as 3 while 2.5 as 2.
|
||||
var w = Math.floor(this.screenwidth + 0.2)
|
||||
w += (w % 2) - 1
|
||||
this.prevImage(w)
|
||||
}],
|
||||
nextScreen: ['Navigate/Screen width forward',
|
||||
function(){
|
||||
var w = Math.floor(this.screenwidth + 0.2)
|
||||
w += (w % 2) - 1
|
||||
this.nextImage(w)
|
||||
}],
|
||||
|
||||
|
||||
// XXX hide from user action list... (???)
|
||||
// XXX need to check if a transition is running and delay timeout...
|
||||
// Zoom/scale protocol...
|
||||
//
|
||||
// Events...
|
||||
// NOTE: the implementation needs to call .resizingDone(..) when all
|
||||
// animations are done...
|
||||
resizing: ['- Zoom/Scale root protocol action (not for direct use)',
|
||||
core.doc`Zooming/scaling root action...
|
||||
|
||||
@ -785,34 +589,7 @@ module.ViewerActions = actions.Actions({
|
||||
//
|
||||
// This will never be used directly, but will wrap protocol user
|
||||
// functions.
|
||||
//
|
||||
// As an example see: .setScale(..)
|
||||
|
||||
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)
|
||||
}
|
||||
})],
|
||||
|
||||
resizingDone: ['- Zoom/scale post-transition protocol action (not for direct use)',
|
||||
core.doc`Zooming/scaling post-transition action...
|
||||
|
||||
@ -835,56 +612,6 @@ module.ViewerActions = actions.Actions({
|
||||
// be called before the transition is done.
|
||||
})],
|
||||
|
||||
// Zoom/scale protocol actions...
|
||||
setScale: ['- Zoom/',
|
||||
function(scale){
|
||||
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)
|
||||
}],
|
||||
fitOrig: ['Zoom/Fit to original scale',
|
||||
function(){
|
||||
this.resizing.chainCall(this, function(){
|
||||
this.ribbons.scale(1)
|
||||
// NOTE: we pass explicit scale here to compensate for animation...
|
||||
this.refresh('*', 1)
|
||||
}, 'scale', 1)
|
||||
}],
|
||||
// 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){
|
||||
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
|
||||
}
|
||||
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){
|
||||
this.resizing.chainCall(this, function(){
|
||||
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)
|
||||
}],
|
||||
|
||||
|
||||
// Zooming...
|
||||
//
|
||||
// Zooming is done by multiplying the current scale by .config['zoom-step']
|
||||
// and rounding to nearest discrete number of images to fit on screen.
|
||||
zoomIn: ['Zoom/Zoom in',
|
||||
@ -917,24 +644,16 @@ module.ViewerActions = actions.Actions({
|
||||
}],
|
||||
|
||||
// Scale presets...
|
||||
//
|
||||
fitOrig: ['Zoom/Fit to original scale',
|
||||
function(){ this.viewScale(1) }],
|
||||
fitMax: ['Zoom/Fit the maximum number of images',
|
||||
function(){ this.fitImage(this.config['max-screen-images']) }],
|
||||
function(){ this.screenwidth = this.config['max-screen-images'] }],
|
||||
fitScreen: ['Zoom/Fit image to screen',
|
||||
function(){ this.screenfit = 1 }],
|
||||
|
||||
// ribbon rotation...
|
||||
|
||||
// Ribbon rotation...
|
||||
//
|
||||
ribbonRotation: ['- Interface|Ribbon/',
|
||||
function(a){
|
||||
if(arguments.length > 0){
|
||||
this.ribbons.rotate(a)
|
||||
|
||||
} else {
|
||||
return this.ribbons.rotate() || 0
|
||||
}
|
||||
}],
|
||||
|
||||
// Rotate ribbon CW/CCW...
|
||||
//
|
||||
// Rotate ribbon (default step)
|
||||
@ -957,7 +676,7 @@ module.ViewerActions = actions.Actions({
|
||||
function(){ this.ribbonRotation(0) }],
|
||||
|
||||
|
||||
// XXX experimental: not sure if this is the right way to go...
|
||||
// XXX EXPERIMENTAL: not sure if this is the right way to go...
|
||||
// XXX make this play nice with crops...
|
||||
// ...should this be a crop???
|
||||
toggleRibbonList: ['Interface|Ribbon/Ribbons as images view',
|
||||
@ -992,6 +711,7 @@ module.Viewer = core.ImageGridFeatures.Feature({
|
||||
'base',
|
||||
'workspace',
|
||||
'introspection',
|
||||
'ui-render',
|
||||
],
|
||||
suggested: [
|
||||
// XXX is this the right way???
|
||||
@ -1196,7 +916,7 @@ core.ImageGridFeatures.Feature({
|
||||
// manage the .crop-mode css class...
|
||||
['crop uncrop',
|
||||
function(){
|
||||
this.ribbons.viewer[this.cropped ?
|
||||
this.dom[this.cropped ?
|
||||
'addClass'
|
||||
: 'removeClass']('crop-mode')
|
||||
}],
|
||||
@ -1546,11 +1266,11 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
||||
actions: actions.Actions({
|
||||
toggleHiddenCursor: ['Interface/Cursor hidden',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'cursor-hidden',
|
||||
function(state){
|
||||
var that = this
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
|
||||
if(state == 'on'){
|
||||
var x, y
|
||||
@ -1619,12 +1339,12 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
||||
//
|
||||
toggleAutoHideCursor: ['Interface/Cursor auto-hide',
|
||||
toggler.CSSClassToggler(
|
||||
function(){ return this.ribbons.viewer },
|
||||
function(){ return this.dom },
|
||||
'cursor-autohide',
|
||||
function(state){
|
||||
var that = this
|
||||
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
// NOTE: this is handled by the keyboard feature...
|
||||
var kb_target = this.__keyboard_event_source || $(window)
|
||||
|
||||
@ -1654,7 +1374,7 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
||||
: -1
|
||||
if(timeout && timeout > 0){
|
||||
m_timer = setTimeout(function(){
|
||||
var viewer = that.ribbons.viewer
|
||||
var viewer = that.dom
|
||||
|
||||
// auto-hide is off -- restore...
|
||||
if(!viewer.hasClass('cursor-autohide')){
|
||||
@ -1680,7 +1400,7 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
||||
// avoid this from delaying the keyboard handler...
|
||||
kb_timer = setTimeout(function(){
|
||||
kb_timer = null
|
||||
var viewer = that.ribbons.viewer
|
||||
var viewer = that.dom
|
||||
|
||||
// get key...
|
||||
var key = keyboard.normalizeKey(
|
||||
@ -1842,7 +1562,7 @@ var ControlActions = actions.Actions({
|
||||
// nothing to do...
|
||||
null
|
||||
: (this.ribbons
|
||||
&& this.ribbons.viewer
|
||||
&& this.dom
|
||||
//&& this.ribbons.getRibbon().data('hammer') ? 'handling-click' : 'none' },
|
||||
&& this.ribbons.getRibbon().hasClass('clickable')) ?
|
||||
'handling-click'
|
||||
@ -1978,7 +1698,7 @@ var ControlActions = actions.Actions({
|
||||
|
||||
var cl = central && central.offset().left
|
||||
var w = central && central.outerWidth(true)
|
||||
var W = this.ribbons.viewer.width()
|
||||
var W = this.dom.width()
|
||||
var vmin = Math.min(
|
||||
document.body.offsetWidth,
|
||||
document.body.offsetHeight)
|
||||
@ -2044,7 +1764,7 @@ var ControlActions = actions.Actions({
|
||||
// nothing to do...
|
||||
null
|
||||
: (this.ribbons
|
||||
&& this.ribbons.viewer
|
||||
&& this.dom
|
||||
&& this.ribbons.getRibbon().hasClass('draggable')) ?
|
||||
'handling-pan'
|
||||
: 'none' },
|
||||
@ -2281,8 +2001,8 @@ var ControlActions = actions.Actions({
|
||||
// nothing to do...
|
||||
null
|
||||
: (this.ribbons
|
||||
&& this.ribbons.viewer
|
||||
&& this.ribbons.viewer.hasClass('mouse-wheel-scroll')) ?
|
||||
&& this.dom
|
||||
&& this.dom.hasClass('mouse-wheel-scroll')) ?
|
||||
'handling-mouse-wheel'
|
||||
: 'none' },
|
||||
'handling-mouse-wheel',
|
||||
@ -2318,7 +2038,7 @@ var ControlActions = actions.Actions({
|
||||
var rgid = this.ribbons.getElemGID(r)
|
||||
|
||||
// XXX vertical scroll...
|
||||
this.ribbons.viewer
|
||||
this.dom
|
||||
.on('wheel', function(){
|
||||
})
|
||||
|
||||
@ -2357,7 +2077,7 @@ var ControlActions = actions.Actions({
|
||||
|
||||
// on...
|
||||
if(state == 'on'){
|
||||
this.ribbons.viewer.addClass('mouse-wheel-scroll')
|
||||
this.dom.addClass('mouse-wheel-scroll')
|
||||
// NOTE: we are resetting this to avoid multiple setting
|
||||
// handlers...
|
||||
this.off('updateRibbon', setup)
|
||||
@ -2368,7 +2088,7 @@ var ControlActions = actions.Actions({
|
||||
|
||||
// off...
|
||||
} else {
|
||||
this.ribbons.viewer.removeClass('mouse-wheel-scroll')
|
||||
this.dom.removeClass('mouse-wheel-scroll')
|
||||
this.off('updateRibbon', setup)
|
||||
|
||||
this.data.ribbon_order.forEach(function(gid){
|
||||
@ -2390,13 +2110,13 @@ var ControlActions = actions.Actions({
|
||||
return state ?
|
||||
null
|
||||
: (this.ribbons
|
||||
&& this.ribbons.viewer
|
||||
&& this.ribbons.viewer.data('hammer')) ?
|
||||
&& this.dom
|
||||
&& this.dom.data('hammer')) ?
|
||||
'handling-swipes'
|
||||
: 'none' },
|
||||
'handling-swipes',
|
||||
function(state){
|
||||
var viewer = this.ribbons.viewer
|
||||
var viewer = this.dom
|
||||
|
||||
// on...
|
||||
if(state == 'on'){
|
||||
@ -2520,7 +2240,7 @@ module.Control = core.ImageGridFeatures.Feature({
|
||||
}],
|
||||
|
||||
// if panned image is off screen, center it...
|
||||
['setScale',
|
||||
['viewScale',
|
||||
function(){
|
||||
var that = this
|
||||
Object.keys(this.data.ribbons).forEach(function(r){
|
||||
@ -2617,7 +2337,7 @@ module.PreviewFilters = core.ImageGridFeatures.Feature({
|
||||
var cls = filters[state]
|
||||
var classes = Object.values(filters)
|
||||
.filter(function(c){ return c != cls })
|
||||
this.ribbons.viewer
|
||||
this.dom
|
||||
.find('.'+ classes.join(', .'))
|
||||
.removeClass(classes.join(' '))
|
||||
|
||||
@ -2641,7 +2361,7 @@ module.PreviewFilters = core.ImageGridFeatures.Feature({
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
// XXX experimental...
|
||||
// XXX EXPERIMENTAL...
|
||||
|
||||
// ...not sure if this is the right way to go...
|
||||
// XXX need to get the minimal size and not the width as results will
|
||||
|
||||
@ -102,22 +102,27 @@ $(function(){
|
||||
m = Object.keys(m).filter(function(e){ return m[e] != null })
|
||||
console.log('Modules (%d):', m.length, m)
|
||||
|
||||
try {
|
||||
// setup actions...
|
||||
window.ig =
|
||||
window.ImageGrid =
|
||||
viewer.ImageGridFeatures
|
||||
.setup([
|
||||
'viewer-testing',
|
||||
|
||||
// setup actions...
|
||||
window.ig =
|
||||
window.ImageGrid =
|
||||
viewer.ImageGridFeatures
|
||||
.setup([
|
||||
'viewer-testing',
|
||||
'demo',
|
||||
|
||||
'demo',
|
||||
// XXX this is not for production...
|
||||
'experiments',
|
||||
|
||||
// XXX this is not for production...
|
||||
'experiments',
|
||||
//'-commandline',
|
||||
//'-ui-partial-ribbons',
|
||||
])
|
||||
|
||||
//'-commandline',
|
||||
//'-ui-partial-ribbons',
|
||||
])
|
||||
} catch(err){
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// used to switch experimental actions on (set to true) or off (unset or false)...
|
||||
@ -130,6 +135,9 @@ $(function(){
|
||||
&& console.warn('Features excluded (%d):',
|
||||
ig.features.excluded.length,
|
||||
ig.features.excluded)
|
||||
Object.keys(ig.features.missing).length > 0
|
||||
&& console.warn('Features disabled (%d):',
|
||||
ig.features.missing)
|
||||
ig.features.disabled.length > 0
|
||||
&& console.log('Features disabled (%d):',
|
||||
ig.features.disabled.length,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user