mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +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()
|
this.ribbons.preventTransitions()
|
||||||
|
|
||||||
// hide the viewer to hide any animation crimes...
|
// hide the viewer to hide any animation crimes...
|
||||||
this.ribbons.viewer[0].style.visibility = 'hidden'
|
this.dom[0].style.visibility = 'hidden'
|
||||||
|
|
||||||
// XXX async...
|
// XXX async...
|
||||||
// ...this complicates things as we need to do the next
|
// ...this complicates things as we need to do the next
|
||||||
@ -146,7 +146,7 @@ var AppControlActions = actions.Actions({
|
|||||||
.ribbons
|
.ribbons
|
||||||
.restoreTransitions()
|
.restoreTransitions()
|
||||||
|
|
||||||
that.ribbons.viewer[0].style.visibility = ''
|
that.dom[0].style.visibility = ''
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ module.AppButtons = core.ImageGridFeatures.Feature({
|
|||||||
['start toggleFullScreen',
|
['start toggleFullScreen',
|
||||||
function(){
|
function(){
|
||||||
var fullscreen = this.toggleFullScreen('?')
|
var fullscreen = this.toggleFullScreen('?')
|
||||||
var buttons = this.ribbons.viewer.find('.app-buttons')
|
var buttons = this.dom.find('.app-buttons')
|
||||||
|
|
||||||
// fullscreen button...
|
// fullscreen button...
|
||||||
buttons.find('.fullscreen.button')
|
buttons.find('.fullscreen.button')
|
||||||
|
|||||||
@ -175,7 +175,7 @@ var ExternalEditorUIActions = actions.Actions({
|
|||||||
var path = e.find('.text').last().text()
|
var path = e.find('.text').last().text()
|
||||||
var txt = e.find('.text').first().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,
|
browseWalk.makeWalk(null, path,
|
||||||
// XXX
|
// XXX
|
||||||
'*+(exe|cmd|ps1|sh)',
|
'*+(exe|cmd|ps1|sh)',
|
||||||
@ -291,7 +291,7 @@ var ExternalEditorUIActions = actions.Actions({
|
|||||||
make(['Add new editor...'])
|
make(['Add new editor...'])
|
||||||
.on('open', function(){
|
.on('open', function(){
|
||||||
closingPrevented = true
|
closingPrevented = true
|
||||||
var b = overlay.Overlay(that.ribbons.viewer,
|
var b = overlay.Overlay(that.dom,
|
||||||
browseWalk.makeWalk(
|
browseWalk.makeWalk(
|
||||||
null, '/',
|
null, '/',
|
||||||
// XXX
|
// XXX
|
||||||
|
|||||||
@ -458,7 +458,7 @@ var KeyboardActions = actions.Actions({
|
|||||||
return that.__keyboard_config
|
return that.__keyboard_config
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(){ return that.ribbons.viewer })
|
function(){ return that.dom })
|
||||||
return kb },
|
return kb },
|
||||||
|
|
||||||
testKeyboardDoc: ['- Interface/',
|
testKeyboardDoc: ['- Interface/',
|
||||||
@ -718,9 +718,9 @@ var KeyboardActions = actions.Actions({
|
|||||||
// NOTE: the target element must be focusable...
|
// NOTE: the target element must be focusable...
|
||||||
var target =
|
var target =
|
||||||
this.__keyboard_event_source =
|
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'] == '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'] == 'document' ? $(document)
|
||||||
: $(this.config['keyboard-event-source'])
|
: $(this.config['keyboard-event-source'])
|
||||||
|
|
||||||
|
|||||||
@ -66,10 +66,14 @@ core.ImageGridFeatures.Feature('viewer-testing', [
|
|||||||
'ui',
|
'ui',
|
||||||
'keyboard',
|
'keyboard',
|
||||||
|
|
||||||
|
// XXX BUG?: should this be indicated as a missing dependency???
|
||||||
|
'missing-feature',
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
'ui-ribbons-render',
|
'ui-ribbons-render',
|
||||||
'ui-vdom-render',
|
'ui-vdom-render',
|
||||||
'ui-react-render',
|
//'ui-react-render',
|
||||||
|
//*/
|
||||||
|
|
||||||
// features...
|
// features...
|
||||||
'ui-cursor',
|
'ui-cursor',
|
||||||
|
|||||||
@ -46,12 +46,12 @@ var BoundsIndicatorsActions = actions.Actions({
|
|||||||
bottom: '.bottom-indicator',
|
bottom: '.bottom-indicator',
|
||||||
}[direction]
|
}[direction]
|
||||||
|
|
||||||
var indicator = this.ribbons.viewer.find(cls)
|
var indicator = this.dom.find(cls)
|
||||||
|
|
||||||
if(indicator.length == 0){
|
if(indicator.length == 0){
|
||||||
indicator = $('<div>')
|
indicator = $('<div>')
|
||||||
.addClass(cls.replace('.', ''))
|
.addClass(cls.replace('.', ''))
|
||||||
.appendTo(this.ribbons.viewer)
|
.appendTo(this.dom)
|
||||||
}
|
}
|
||||||
|
|
||||||
return indicator
|
return indicator
|
||||||
@ -262,7 +262,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
|||||||
function(){
|
function(){
|
||||||
var fadein = this.config['current-image-indicator-fadein']
|
var fadein = this.config['current-image-indicator-fadein']
|
||||||
this.updateCurrentImageIndicator()
|
this.updateCurrentImageIndicator()
|
||||||
this.ribbons.viewer.find('.current-marker')
|
this.dom.find('.current-marker')
|
||||||
.css({
|
.css({
|
||||||
display: 'block',
|
display: 'block',
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
@ -302,7 +302,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
|||||||
&& clearTimeout(this.__current_image_indicator_restore_timeout)
|
&& clearTimeout(this.__current_image_indicator_restore_timeout)
|
||||||
delete this.__current_image_indicator_restore_timeout
|
delete this.__current_image_indicator_restore_timeout
|
||||||
|
|
||||||
this.ribbons.viewer
|
this.dom
|
||||||
.find('.current-marker')
|
.find('.current-marker')
|
||||||
.velocity({opacity: 0}, { duration: 100 })
|
.velocity({opacity: 0}, { duration: 100 })
|
||||||
}],
|
}],
|
||||||
@ -312,7 +312,7 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
|||||||
this.__current_image_indicator_restore_timeout = setTimeout(function(){
|
this.__current_image_indicator_restore_timeout = setTimeout(function(){
|
||||||
that.updateCurrentImageIndicator()
|
that.updateCurrentImageIndicator()
|
||||||
|
|
||||||
that.ribbons.viewer
|
that.dom
|
||||||
.find('.current-marker')
|
.find('.current-marker')
|
||||||
.velocity({opacity: 1}, { duration: 100 })
|
.velocity({opacity: 1}, { duration: 100 })
|
||||||
}, this.config['current-image-indicator-restore-delay'] || 500)
|
}, this.config['current-image-indicator-restore-delay'] || 500)
|
||||||
@ -322,12 +322,12 @@ module.CurrentImageIndicator = core.ImageGridFeatures.Feature({
|
|||||||
['toggleSingleImage',
|
['toggleSingleImage',
|
||||||
function(){
|
function(){
|
||||||
if(this.toggleSingleImage('?') == 'off'){
|
if(this.toggleSingleImage('?') == 'off'){
|
||||||
this.ribbons.viewer.find('.current-marker')
|
this.dom.find('.current-marker')
|
||||||
.delay(150)
|
.delay(150)
|
||||||
.animate({opacity: 1}, 100)
|
.animate({opacity: 1}, 100)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.ribbons.viewer.find('.current-marker')
|
this.dom.find('.current-marker')
|
||||||
.css({ opacity: 0 })
|
.css({ opacity: 0 })
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
@ -343,7 +343,7 @@ var makeIndicatorHiderOnFastAction = function(hide_timeout){
|
|||||||
}
|
}
|
||||||
|
|
||||||
var that = this
|
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 t = this.config[hide_timeout]
|
||||||
|
|
||||||
var cur = this.current
|
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...
|
// NOTE: we use .pre events here to see if we have moved...
|
||||||
['prevScreen.post nextScreen.post',
|
['prevScreen.post nextScreen.post',
|
||||||
function(){
|
function(){
|
||||||
var m = this.ribbons.viewer.find('.current-marker')
|
var m = this.dom.find('.current-marker')
|
||||||
|
|
||||||
m.css({ opacity: 0 })
|
m.css({ opacity: 0 })
|
||||||
}],
|
}],
|
||||||
['focusImage.post',
|
['focusImage.post',
|
||||||
function(){
|
function(){
|
||||||
var m = this.ribbons.viewer.find('.current-marker')
|
var m = this.dom.find('.current-marker')
|
||||||
|
|
||||||
m.css({ opacity: '' })
|
m.css({ opacity: '' })
|
||||||
}],
|
}],
|
||||||
@ -464,7 +464,7 @@ var updateBaseRibbonIndicator = function(img){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(m.length == 0){
|
if(m.length == 0){
|
||||||
m = this.ribbons.viewer.find('.base-ribbon-marker')
|
m = this.dom.find('.base-ribbon-marker')
|
||||||
|
|
||||||
// make the indicator...
|
// make the indicator...
|
||||||
if(m.length == 0){
|
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...
|
// XXX this is wrong -- need to calculate the offset after the move and not now...
|
||||||
if(base.offset().left < 0){
|
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 {
|
} else {
|
||||||
m.css('left', '')
|
m.css('left', '')
|
||||||
@ -530,7 +530,7 @@ module.PassiveBaseRibbonIndicator = core.ImageGridFeatures.Feature({
|
|||||||
actions: actions.Actions({
|
actions: actions.Actions({
|
||||||
togglePassiveBaseRibbonIndicator: ['Interface/Passive base ribbon indicator',
|
togglePassiveBaseRibbonIndicator: ['Interface/Passive base ribbon indicator',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'show-passive-base-ribbon-indicator',
|
'show-passive-base-ribbon-indicator',
|
||||||
function(state){
|
function(state){
|
||||||
this.config['ui-show-passive-base-ribbon-indicator'] = state == 'on' }) ],
|
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...
|
// hide and remove current image indicator...
|
||||||
// NOTE: it will be reconstructed on
|
// NOTE: it will be reconstructed on
|
||||||
// next .focusImage(..)
|
// next .focusImage(..)
|
||||||
var m = that.ribbons.viewer
|
var m = that.dom
|
||||||
.find('.current-marker')
|
.find('.current-marker')
|
||||||
.velocity({opacity: 0}, {
|
.velocity({opacity: 0}, {
|
||||||
duration: 100,
|
duration: 100,
|
||||||
@ -245,14 +245,14 @@ module.IndirectControl = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
if(state == null){
|
if(state == null){
|
||||||
return (this.ribbons
|
return (this.ribbons
|
||||||
&& this.ribbons.viewer
|
&& this.dom
|
||||||
&& this.ribbons.viewer.data('hammer'))
|
&& this.dom.data('hammer'))
|
||||||
|| 'none'
|
|| 'none'
|
||||||
|
|
||||||
// on...
|
// on...
|
||||||
} else if(state == 'handling-swipes'){
|
} else if(state == 'handling-swipes'){
|
||||||
var that = this
|
var that = this
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
|
|
||||||
// prevent multiple handlers...
|
// prevent multiple handlers...
|
||||||
if(viewer.data('hammer') != null){
|
if(viewer.data('hammer') != null){
|
||||||
@ -272,7 +272,7 @@ module.IndirectControl = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
// off...
|
// off...
|
||||||
} else {
|
} else {
|
||||||
this.ribbons.viewer
|
this.dom
|
||||||
.off('swipeleft')
|
.off('swipeleft')
|
||||||
.off('swiperight')
|
.off('swiperight')
|
||||||
.off('swipeup')
|
.off('swipeup')
|
||||||
|
|||||||
@ -435,9 +435,7 @@ var VirtualDOMRibbonsPrototype = {
|
|||||||
// concept, so we build the state on demand...
|
// concept, so we build the state on demand...
|
||||||
// XXX get scale from config on initial load...
|
// XXX get scale from config on initial load...
|
||||||
sync: function(target, size){
|
sync: function(target, size){
|
||||||
var dom = this.dom = this.dom
|
var dom = this.dom
|
||||||
// get/create the ribbon-set...
|
|
||||||
|| this.imagegrid.ribbons.getRibbonSet(true)
|
|
||||||
|
|
||||||
var state = this.state ? Object.create(this.state) : {}
|
var state = this.state ? Object.create(this.state) : {}
|
||||||
target && (state.target = target)
|
target && (state.target = target)
|
||||||
@ -447,7 +445,7 @@ var VirtualDOMRibbonsPrototype = {
|
|||||||
if(this.vdom == null){
|
if(this.vdom == null){
|
||||||
var n = this.vdom = this.makeView(state, true)
|
var n = this.vdom = this.makeView(state, true)
|
||||||
var v = vdom.create(n)
|
var v = vdom.create(n)
|
||||||
dom.replaceWith(v)
|
this.imagegrid.dom.append(v)
|
||||||
this.dom = v
|
this.dom = v
|
||||||
|
|
||||||
// patch state...
|
// patch state...
|
||||||
|
|||||||
@ -48,7 +48,7 @@ var ProgressActions = actions.Actions({
|
|||||||
// XXX revise styles...
|
// XXX revise styles...
|
||||||
showProgress: ['- Interface/Show progress bar...',
|
showProgress: ['- Interface/Show progress bar...',
|
||||||
function(text, value, max){
|
function(text, value, max){
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
var msg = text instanceof Array ? text.slice(1).join(': ') : null
|
var msg = text instanceof Array ? text.slice(1).join(': ') : null
|
||||||
|
|||||||
@ -27,7 +27,7 @@ var RangeActions = actions.Actions({
|
|||||||
makeBrace: ['- Range/',
|
makeBrace: ['- Range/',
|
||||||
function(type, gid){
|
function(type, gid){
|
||||||
var cls = type == 'open' ? 'brace-open' : 'brace-close'
|
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)
|
var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls)
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ var RangeActions = actions.Actions({
|
|||||||
// go but it sure makes things simpler...
|
// go but it sure makes things simpler...
|
||||||
if(range == null){
|
if(range == null){
|
||||||
update = true
|
update = true
|
||||||
this.ribbons.viewer
|
this.dom
|
||||||
.find('.ribbon .mark.brace')
|
.find('.ribbon .mark.brace')
|
||||||
.remove()
|
.remove()
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ var RangeActions = actions.Actions({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(update){
|
if(update){
|
||||||
var r = this.ribbons.viewer.find('.ribbon')
|
var r = this.dom.find('.ribbon')
|
||||||
|
|
||||||
// XXX this does not work for non-current images ...
|
// XXX this does not work for non-current images ...
|
||||||
this.ribbons.preventTransitions(r)
|
this.ribbons.preventTransitions(r)
|
||||||
@ -103,7 +103,7 @@ var RangeActions = actions.Actions({
|
|||||||
// XXX not sure if this is the right way to go...
|
// XXX not sure if this is the right way to go...
|
||||||
{browseMode: function(){ return !this.data.__range && 'disabled' }},
|
{browseMode: function(){ return !this.data.__range && 'disabled' }},
|
||||||
function(image){
|
function(image){
|
||||||
var r = this.ribbons.viewer.find('.ribbon')
|
var r = this.dom.find('.ribbon')
|
||||||
|
|
||||||
delete this.data.__range
|
delete this.data.__range
|
||||||
this.updateRangeIndicators()
|
this.updateRangeIndicators()
|
||||||
@ -246,7 +246,7 @@ module.Range = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
// show/hide off-screen indicators...
|
// show/hide off-screen indicators...
|
||||||
// XXX STUB: should we animate indicators???
|
// XXX STUB: should we animate indicators???
|
||||||
['setScale.pre',
|
['viewScale.pre',
|
||||||
function(scale){
|
function(scale){
|
||||||
var range = this.data.__range
|
var range = this.data.__range
|
||||||
if(!this.ribbons || !range){
|
if(!this.ribbons || !range){
|
||||||
@ -259,7 +259,7 @@ module.Range = core.ImageGridFeatures.Feature({
|
|||||||
}],
|
}],
|
||||||
[[
|
[[
|
||||||
'focusImage',
|
'focusImage',
|
||||||
'setScale',
|
'viewScale',
|
||||||
'updateRangeIndicators',
|
'updateRangeIndicators',
|
||||||
],
|
],
|
||||||
function(_, gid){
|
function(_, gid){
|
||||||
@ -273,7 +273,7 @@ module.Range = core.ImageGridFeatures.Feature({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var Wr = this.ribbons.viewer.width()
|
var Wr = this.dom.width()
|
||||||
var W = (Wr / this.scale) / 2
|
var W = (Wr / this.scale) / 2
|
||||||
|
|
||||||
var a = this.data.getImageOrder(range[0])
|
var a = this.data.getImageOrder(range[0])
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
(function(require){ var module={} // make module AMD/node compatible...
|
(function(require){ var module={} // make module AMD/node compatible...
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
|
var object = require('lib/object')
|
||||||
var actions = require('lib/actions')
|
var actions = require('lib/actions')
|
||||||
var features = require('lib/features')
|
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({
|
var ReactActions = actions.Actions({
|
||||||
|
get viewer(){
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
var React =
|
var React =
|
||||||
|
|||||||
@ -7,18 +7,356 @@
|
|||||||
(function(require){ var module={} // make module AMD/node compatible...
|
(function(require){ var module={} // make module AMD/node compatible...
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
|
var object = require('lib/object')
|
||||||
var actions = require('lib/actions')
|
var actions = require('lib/actions')
|
||||||
var features = require('lib/features')
|
var features = require('lib/features')
|
||||||
|
|
||||||
var core = require('features/core')
|
var core = require('features/core')
|
||||||
|
|
||||||
|
var ribbons = require('imagegrid/ribbons')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
var RibbonsActions = actions.Actions({
|
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 =
|
var Ribbons =
|
||||||
module.Ribbons = core.ImageGridFeatures.Feature({
|
module.Ribbons = core.ImageGridFeatures.Feature({
|
||||||
title: '',
|
title: '',
|
||||||
@ -29,6 +367,9 @@ module.Ribbons = core.ImageGridFeatures.Feature({
|
|||||||
depends: [
|
depends: [
|
||||||
// XXX
|
// XXX
|
||||||
],
|
],
|
||||||
|
suggested: [
|
||||||
|
'ui-ribbons-edit-render',
|
||||||
|
],
|
||||||
|
|
||||||
actions: RibbonsActions,
|
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 })
|
* vim:set ts=4 sw=4 : */ return module })
|
||||||
|
|||||||
@ -127,7 +127,7 @@ var SingleImageActions = actions.Actions({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
|
|
||||||
var ribbon = this.ribbons.getRibbon()
|
var ribbon = this.ribbons.getRibbon()
|
||||||
var images = viewer.find('.ribbon .image')
|
var images = viewer.find('.ribbon .image')
|
||||||
@ -239,7 +239,7 @@ var SingleImageActions = actions.Actions({
|
|||||||
|
|
||||||
toggleSingleImage: ['Interface/Single image view',
|
toggleSingleImage: ['Interface/Single image view',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'single-image-mode',
|
'single-image-mode',
|
||||||
function(state){
|
function(state){
|
||||||
if(state == 'on'){
|
if(state == 'on'){
|
||||||
@ -344,7 +344,7 @@ module.SingleImageView = core.ImageGridFeatures.Feature({
|
|||||||
function(){
|
function(){
|
||||||
// prevent this from doing anything while no viewer...
|
// prevent this from doing anything while no viewer...
|
||||||
if(!this.ribbons
|
if(!this.ribbons
|
||||||
|| !this.ribbons.viewer
|
|| !this.dom
|
||||||
|| this.ribbons.getRibbonSet().length == 0){
|
|| this.ribbons.getRibbonSet().length == 0){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -510,7 +510,7 @@ module.SingleImageViewLocalStorage = core.ImageGridFeatures.Feature({
|
|||||||
return function(){
|
return function(){
|
||||||
// prevent this from doing anything while no viewer...
|
// prevent this from doing anything while no viewer...
|
||||||
if(!this.ribbons
|
if(!this.ribbons
|
||||||
|| !this.ribbons.viewer
|
|| !this.dom
|
||||||
|| this.ribbons.getRibbonSet().length == 0){
|
|| this.ribbons.getRibbonSet().length == 0){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -145,7 +145,7 @@ var SlideshowActions = actions.Actions({
|
|||||||
|
|
||||||
toggleSlideshow: ['Slideshow/Slideshow quick toggle',
|
toggleSlideshow: ['Slideshow/Slideshow quick toggle',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'slideshow-running',
|
'slideshow-running',
|
||||||
function(state){
|
function(state){
|
||||||
// start...
|
// start...
|
||||||
|
|||||||
@ -33,7 +33,7 @@ var makeStateIndicatorItem = function(container, type, text){
|
|||||||
var item = $('<div>')
|
var item = $('<div>')
|
||||||
.addClass('item '+ type || '')
|
.addClass('item '+ type || '')
|
||||||
.attr('text', text)
|
.attr('text', text)
|
||||||
this.ribbons.viewer.find('.state-indicator-container.'+container)
|
this.dom.find('.state-indicator-container.'+container)
|
||||||
.append(item)
|
.append(item)
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
@ -461,11 +461,11 @@ var StatusBarActions = actions.Actions({
|
|||||||
// XXX change class...
|
// XXX change class...
|
||||||
function(){
|
function(){
|
||||||
// no viewer yet...
|
// no viewer yet...
|
||||||
if(!this.ribbons || !this.ribbons.viewer){
|
if(!this.ribbons || !this.dom){
|
||||||
return $()
|
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){
|
if(bar.length == 0){
|
||||||
bar = makeStateIndicator('global-info overlay-info statusbar')
|
bar = makeStateIndicator('global-info overlay-info statusbar')
|
||||||
.addClass(this.config['status-bar-mode']
|
.addClass(this.config['status-bar-mode']
|
||||||
@ -484,7 +484,7 @@ var StatusBarActions = actions.Actions({
|
|||||||
.on('mouseout', function(){
|
.on('mouseout', function(){
|
||||||
bar.find('.info').empty()
|
bar.find('.info').empty()
|
||||||
})
|
})
|
||||||
.appendTo(this.ribbons.viewer)
|
.appendTo(this.dom)
|
||||||
}
|
}
|
||||||
return bar
|
return bar
|
||||||
},
|
},
|
||||||
@ -624,7 +624,7 @@ var StatusBarActions = actions.Actions({
|
|||||||
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
||||||
|
|
||||||
// XXX do this better...
|
// 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',
|
editStatusBarRibbon: ['- Interface/Edit ribbon focus position in statusbar',
|
||||||
@ -632,11 +632,11 @@ var StatusBarActions = actions.Actions({
|
|||||||
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
||||||
|
|
||||||
// XXX do this better...
|
// 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',
|
toggleStatusBarIndexMode: ['Interface/Status bar index mode',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer.find('.global-info .index') },
|
function(){ return this.dom.find('.global-info .index') },
|
||||||
['normal', 'global'],
|
['normal', 'global'],
|
||||||
function(state){
|
function(state){
|
||||||
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
this.toggleStatusBar('?') == 'none' && this.toggleStatusBar()
|
||||||
@ -652,7 +652,7 @@ var StatusBarActions = actions.Actions({
|
|||||||
// XXX revise...
|
// XXX revise...
|
||||||
showStatusBarInfo: ['- Interface/',
|
showStatusBarInfo: ['- Interface/',
|
||||||
function(text){
|
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){
|
if(text){
|
||||||
bar.find('.info').text(text)
|
bar.find('.info').text(text)
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
var vdom = require('ext-lib/virtual-dom')
|
var vdom = require('ext-lib/virtual-dom')
|
||||||
|
|
||||||
|
var object = require('lib/object')
|
||||||
var actions = require('lib/actions')
|
var actions = require('lib/actions')
|
||||||
var features = require('lib/features')
|
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({
|
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 =
|
var VirtualDom =
|
||||||
@ -34,7 +479,55 @@ module.VirtualDom = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
actions: VirtualDomActions,
|
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)
|
cls = cls instanceof Array ? cls : cls.split(/\s+/g)
|
||||||
|
|
||||||
// remove old versions...
|
// remove old versions...
|
||||||
context.ribbons.viewer.find('.'+ cls.join('.')).remove()
|
context.dom.find('.'+ cls.join('.')).remove()
|
||||||
|
|
||||||
// make container...
|
// make container...
|
||||||
var controls = $('<div>')
|
var controls = $('<div>')
|
||||||
@ -103,7 +103,7 @@ function(context, cls, data){
|
|||||||
})
|
})
|
||||||
|
|
||||||
controls
|
controls
|
||||||
.appendTo(context.ribbons.viewer)
|
.appendTo(context.dom)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX write docs:
|
// XXX write docs:
|
||||||
@ -121,7 +121,7 @@ function(cls, cfg, parent){
|
|||||||
|
|
||||||
return toggler.Toggler(null,
|
return toggler.Toggler(null,
|
||||||
function(){
|
function(){
|
||||||
parent = parent == null ? this.ribbons.viewer
|
parent = parent == null ? this.dom
|
||||||
: parent instanceof Function ? parent.call(this)
|
: parent instanceof Function ? parent.call(this)
|
||||||
: parent
|
: parent
|
||||||
return parent.find('.'+ cls.join('.')).length > 0 ? 'on' : 'off'
|
return parent.find('.'+ cls.join('.')).length > 0 ? 'on' : 'off'
|
||||||
@ -135,7 +135,7 @@ function(cls, cfg, parent){
|
|||||||
&& makeButtonControls(this, cls, config)
|
&& makeButtonControls(this, cls, config)
|
||||||
|
|
||||||
} else {
|
} 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 a state where the window
|
||||||
// is in focus but keys are not
|
// is in focus but keys are not
|
||||||
// tracked...
|
// tracked...
|
||||||
: that.ribbons.viewer.focus()
|
: that.dom.focus()
|
||||||
})
|
})
|
||||||
// Compensate for click focusing the parent dialog when
|
// Compensate for click focusing the parent dialog when
|
||||||
// a child is created...
|
// a child is created...
|
||||||
@ -427,7 +427,7 @@ var makeDrawer = function(direction){
|
|||||||
var that = this
|
var that = this
|
||||||
options = options || {}
|
options = options || {}
|
||||||
var parent = options.parentElement
|
var parent = options.parentElement
|
||||||
parent = parent ? $(parent) : this.ribbons.viewer
|
parent = parent ? $(parent) : this.dom
|
||||||
|
|
||||||
options.direction = direction || 'bottom'
|
options.direction = direction || 'bottom'
|
||||||
|
|
||||||
@ -513,7 +513,7 @@ var DialogsActions = actions.Actions({
|
|||||||
// element
|
// element
|
||||||
// null
|
// null
|
||||||
get modal(){
|
get modal(){
|
||||||
var modal = this.ribbons.viewer
|
var modal = this.dom
|
||||||
.find('.modal-widget')
|
.find('.modal-widget')
|
||||||
.last()
|
.last()
|
||||||
return modal.data('widget-controller')
|
return modal.data('widget-controller')
|
||||||
@ -540,7 +540,7 @@ var DialogsActions = actions.Actions({
|
|||||||
Overlay: ['- Interface/',
|
Overlay: ['- Interface/',
|
||||||
makeUIContainer(function(dialog, options){
|
makeUIContainer(function(dialog, options){
|
||||||
var that = this
|
var that = this
|
||||||
return overlay.Overlay(this.ribbons.viewer, dialog, options)
|
return overlay.Overlay(this.dom, dialog, options)
|
||||||
// focus top modal on exit...
|
// focus top modal on exit...
|
||||||
.on('close', function(){
|
.on('close', function(){
|
||||||
var o = that.modal
|
var o = that.modal
|
||||||
@ -575,7 +575,7 @@ var DialogsActions = actions.Actions({
|
|||||||
client: dialog,
|
client: dialog,
|
||||||
dom: $('<div>')
|
dom: $('<div>')
|
||||||
.append(dialog.dom || dialog)
|
.append(dialog.dom || dialog)
|
||||||
.appendTo(this.ribbons.viewer)
|
.appendTo(this.dom)
|
||||||
.draggable(),
|
.draggable(),
|
||||||
close: function(func){
|
close: function(func){
|
||||||
if(func){
|
if(func){
|
||||||
@ -762,7 +762,7 @@ var DialogsActions = actions.Actions({
|
|||||||
|
|
||||||
toggleOverlayBlur: ['Interface/Dialog overlay blur',
|
toggleOverlayBlur: ['Interface/Dialog overlay blur',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'overlay-blur-enabled',
|
'overlay-blur-enabled',
|
||||||
function(state){ this.config['ui-overlay-blur'] = state }) ],
|
function(state){ this.config['ui-overlay-blur'] = state }) ],
|
||||||
})
|
})
|
||||||
@ -1406,7 +1406,7 @@ module.ContextActionMenu = core.ImageGridFeatures.Feature({
|
|||||||
['load',
|
['load',
|
||||||
function(){
|
function(){
|
||||||
var that = this
|
var that = this
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
|
|
||||||
!viewer.data('context-menu')
|
!viewer.data('context-menu')
|
||||||
&& viewer
|
&& viewer
|
||||||
@ -1528,7 +1528,7 @@ module.Buttons = core.ImageGridFeatures.Feature({
|
|||||||
$('.main-buttons.buttons .crop.button sub')
|
$('.main-buttons.buttons .crop.button sub')
|
||||||
.text(this.crop_stack ? this.crop_stack.length : '') }],
|
.text(this.crop_stack ? this.crop_stack.length : '') }],
|
||||||
// update zoom button status...
|
// update zoom button status...
|
||||||
['setScale',
|
['viewScale',
|
||||||
function(){
|
function(){
|
||||||
$('.secondary-buttons.buttons .zoom.button sub')
|
$('.secondary-buttons.buttons .zoom.button sub')
|
||||||
.text(Math.round(this.screenwidth)) }],
|
.text(Math.round(this.screenwidth)) }],
|
||||||
@ -1897,7 +1897,7 @@ var WidgetTestActions = actions.Actions({
|
|||||||
make('c/')
|
make('c/')
|
||||||
}
|
}
|
||||||
|
|
||||||
var o = overlay.Overlay(this.ribbons.viewer,
|
var o = overlay.Overlay(this.dom,
|
||||||
browse.makePathList(null, {
|
browse.makePathList(null, {
|
||||||
'a/*': list,
|
'a/*': list,
|
||||||
'b/*': list,
|
'b/*': list,
|
||||||
@ -1914,8 +1914,8 @@ var WidgetTestActions = actions.Actions({
|
|||||||
|
|
||||||
|
|
||||||
// XXX migrate to the dialog framework...
|
// XXX migrate to the dialog framework...
|
||||||
// XXX use this.ribbons.viewer as base...
|
// XXX use this.dom as base...
|
||||||
// XXX BUG: when using this.ribbons.viewer as base some actions leak
|
// XXX BUG: when using this.dom as base some actions leak
|
||||||
// between the two viewers...
|
// between the two viewers...
|
||||||
showTaggedInDrawer: ['- Test/Show tagged in drawer',
|
showTaggedInDrawer: ['- Test/Show tagged in drawer',
|
||||||
function(tag){
|
function(tag){
|
||||||
@ -1928,7 +1928,7 @@ var WidgetTestActions = actions.Actions({
|
|||||||
height: H,
|
height: H,
|
||||||
background: 'black',
|
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...
|
// XXX when using viewer zoom and other stuff get leaked...
|
||||||
var widget = drawer.Drawer($('body'),
|
var widget = drawer.Drawer($('body'),
|
||||||
$('<div>')
|
$('<div>')
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
* Experimental Features:
|
* Experimental Features:
|
||||||
* - ui-ribbons-placement
|
* - ui-ribbons-placement
|
||||||
* manage different low level ribbon placement mechanics
|
* manage different low level ribbon placement mechanics
|
||||||
* XXX experimental...
|
* XXX EXPERIMENTAL...
|
||||||
* - auto-single-image
|
* - auto-single-image
|
||||||
* - auto-ribbon
|
* - auto-ribbon
|
||||||
*
|
*
|
||||||
@ -234,21 +234,11 @@ module.ViewerActions = actions.Actions({
|
|||||||
'ribbon-align-delay': 50,
|
'ribbon-align-delay': 50,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Ribbons...
|
// Viewer dom...
|
||||||
//
|
dom: null,
|
||||||
// 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
|
|
||||||
},
|
|
||||||
|
|
||||||
// Current image data...
|
// Current image data...
|
||||||
//
|
//
|
||||||
// XXX experimental...
|
|
||||||
get image(){
|
get image(){
|
||||||
return this.images && this.images[this.current] },
|
return this.images && this.images[this.current] },
|
||||||
set image(val){
|
set image(val){
|
||||||
@ -259,28 +249,21 @@ module.ViewerActions = actions.Actions({
|
|||||||
|
|
||||||
// Scaling...
|
// Scaling...
|
||||||
//
|
//
|
||||||
// Normal scale...
|
// NOTE: .screenwidth / .screenheight are measured in square image blocks...
|
||||||
get scale(){
|
get scale(){
|
||||||
return this.ribbons != null ? this.ribbons.scale() : null },
|
return this.viewScale() },
|
||||||
set scale(s){
|
set scale(s){
|
||||||
this.setScale(s) },
|
this.viewScale(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...
|
|
||||||
get screenwidth(){
|
get screenwidth(){
|
||||||
return this.ribbons != null ? this.ribbons.getScreenWidthImages() : null },
|
return this.fitImage('?') },
|
||||||
set screenwidth(n){
|
set screenwidth(n){
|
||||||
this.fitImage(n, false) },
|
this.fitImage(n, false) },
|
||||||
|
|
||||||
// Screen height in image blocks...
|
|
||||||
get screenheight(){
|
get screenheight(){
|
||||||
return this.ribbons != null ? this.ribbons.getScreenHeightRibbons() : null },
|
return this.fitRibbon('?') },
|
||||||
set screenheight(n){
|
set screenheight(n){
|
||||||
this.fitRibbon(n, false) },
|
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.
|
// E.g.
|
||||||
//
|
//
|
||||||
@ -289,10 +272,10 @@ module.ViewerActions = actions.Actions({
|
|||||||
// min(image.width, image.height)
|
// min(image.width, image.height)
|
||||||
//
|
//
|
||||||
get screenfit(){
|
get screenfit(){
|
||||||
if(!this.ribbons || !this.ribbons.viewer){
|
if(!this.ribbons || !this.dom){
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
var W = viewer.width()
|
var W = viewer.width()
|
||||||
var H = viewer.height()
|
var H = viewer.height()
|
||||||
|
|
||||||
@ -301,7 +284,7 @@ module.ViewerActions = actions.Actions({
|
|||||||
: this.screenheight
|
: this.screenheight
|
||||||
},
|
},
|
||||||
set screenfit(n){
|
set screenfit(n){
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
var W = viewer.width()
|
var W = viewer.width()
|
||||||
var H = viewer.height()
|
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...
|
// General UI stuff...
|
||||||
// NOTE: this is applicable to all uses...
|
// NOTE: this is applicable to all uses...
|
||||||
toggleTheme: ['Interface/Theme/Viewer theme',
|
toggleTheme: ['Interface/Theme/Viewer theme',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
function(){ return this.config.themes },
|
function(){ return this.config.themes },
|
||||||
function(state){ this.config.theme = state }) ],
|
function(state){ this.config.theme = state }) ],
|
||||||
lighterTheme: ['Interface/Theme/Lighter theme',
|
lighterTheme: ['Interface/Theme/Lighter theme',
|
||||||
@ -493,17 +318,65 @@ module.ViewerActions = actions.Actions({
|
|||||||
}],
|
}],
|
||||||
toggleRibbonTheme: ['Interface/Theme/Ribbon theme',
|
toggleRibbonTheme: ['Interface/Theme/Ribbon theme',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
function(){ return this.config['ribbon-themes'] },
|
function(){ return this.config['ribbon-themes'] },
|
||||||
function(state){ this.config['ribbon-theme'] = state }) ],
|
function(state){ this.config['ribbon-theme'] = state }) ],
|
||||||
toggleRibbonImageSepators: ['Interface/Theme/Ribbon image separators',
|
toggleRibbonImageSepators: ['Interface/Theme/Ribbon image separators',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'ribbon-image-separators',
|
'ribbon-image-separators',
|
||||||
function(state){ this.config['ribbon-image-separators'] = state }) ],
|
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',
|
alignRibbons: ['Interface/Align ribbons',
|
||||||
function(target, scale, now){
|
function(target, scale, now){
|
||||||
if(target == 'now'){
|
if(target == 'now'){
|
||||||
@ -535,6 +408,7 @@ module.ViewerActions = actions.Actions({
|
|||||||
// order...
|
// order...
|
||||||
// XXX skip off-screen ribbons (???)
|
// XXX skip off-screen ribbons (???)
|
||||||
// XXX should the timeout be configurable???
|
// XXX should the timeout be configurable???
|
||||||
|
// XXX remove dependency on .ribbons
|
||||||
alignByOrder: ['Interface/Align ribbons by image order',
|
alignByOrder: ['Interface/Align ribbons by image order',
|
||||||
function(target, scale, now){
|
function(target, scale, now){
|
||||||
if(target == 'now'){
|
if(target == 'now'){
|
||||||
@ -649,34 +523,8 @@ module.ViewerActions = actions.Actions({
|
|||||||
//}, 0)
|
//}, 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/',
|
resizingWindow: ['- Interface/',
|
||||||
core.doc`This is called by the window resize event handler...
|
core.doc`This is called by the window resize event handler...
|
||||||
|
|
||||||
@ -692,57 +540,13 @@ module.ViewerActions = actions.Actions({
|
|||||||
//
|
//
|
||||||
// Not for direct use.
|
// 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... (???)
|
// Zoom/scale protocol...
|
||||||
// XXX need to check if a transition is running and delay timeout...
|
//
|
||||||
|
// Events...
|
||||||
|
// NOTE: the implementation needs to call .resizingDone(..) when all
|
||||||
|
// animations are done...
|
||||||
resizing: ['- Zoom/Scale root protocol action (not for direct use)',
|
resizing: ['- Zoom/Scale root protocol action (not for direct use)',
|
||||||
core.doc`Zooming/scaling root action...
|
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
|
// This will never be used directly, but will wrap protocol user
|
||||||
// functions.
|
// 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)',
|
resizingDone: ['- Zoom/scale post-transition protocol action (not for direct use)',
|
||||||
core.doc`Zooming/scaling post-transition action...
|
core.doc`Zooming/scaling post-transition action...
|
||||||
|
|
||||||
@ -835,56 +612,6 @@ module.ViewerActions = actions.Actions({
|
|||||||
// be called before the transition is done.
|
// 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']
|
// Zooming is done by multiplying the current scale by .config['zoom-step']
|
||||||
// and rounding to nearest discrete number of images to fit on screen.
|
// and rounding to nearest discrete number of images to fit on screen.
|
||||||
zoomIn: ['Zoom/Zoom in',
|
zoomIn: ['Zoom/Zoom in',
|
||||||
@ -917,24 +644,16 @@ module.ViewerActions = actions.Actions({
|
|||||||
}],
|
}],
|
||||||
|
|
||||||
// Scale presets...
|
// Scale presets...
|
||||||
//
|
fitOrig: ['Zoom/Fit to original scale',
|
||||||
|
function(){ this.viewScale(1) }],
|
||||||
fitMax: ['Zoom/Fit the maximum number of images',
|
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',
|
fitScreen: ['Zoom/Fit image to screen',
|
||||||
function(){ this.screenfit = 1 }],
|
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 CW/CCW...
|
||||||
//
|
//
|
||||||
// Rotate ribbon (default step)
|
// Rotate ribbon (default step)
|
||||||
@ -957,7 +676,7 @@ module.ViewerActions = actions.Actions({
|
|||||||
function(){ this.ribbonRotation(0) }],
|
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...
|
// XXX make this play nice with crops...
|
||||||
// ...should this be a crop???
|
// ...should this be a crop???
|
||||||
toggleRibbonList: ['Interface|Ribbon/Ribbons as images view',
|
toggleRibbonList: ['Interface|Ribbon/Ribbons as images view',
|
||||||
@ -992,6 +711,7 @@ module.Viewer = core.ImageGridFeatures.Feature({
|
|||||||
'base',
|
'base',
|
||||||
'workspace',
|
'workspace',
|
||||||
'introspection',
|
'introspection',
|
||||||
|
'ui-render',
|
||||||
],
|
],
|
||||||
suggested: [
|
suggested: [
|
||||||
// XXX is this the right way???
|
// XXX is this the right way???
|
||||||
@ -1196,7 +916,7 @@ core.ImageGridFeatures.Feature({
|
|||||||
// manage the .crop-mode css class...
|
// manage the .crop-mode css class...
|
||||||
['crop uncrop',
|
['crop uncrop',
|
||||||
function(){
|
function(){
|
||||||
this.ribbons.viewer[this.cropped ?
|
this.dom[this.cropped ?
|
||||||
'addClass'
|
'addClass'
|
||||||
: 'removeClass']('crop-mode')
|
: 'removeClass']('crop-mode')
|
||||||
}],
|
}],
|
||||||
@ -1546,11 +1266,11 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
|||||||
actions: actions.Actions({
|
actions: actions.Actions({
|
||||||
toggleHiddenCursor: ['Interface/Cursor hidden',
|
toggleHiddenCursor: ['Interface/Cursor hidden',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'cursor-hidden',
|
'cursor-hidden',
|
||||||
function(state){
|
function(state){
|
||||||
var that = this
|
var that = this
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
|
|
||||||
if(state == 'on'){
|
if(state == 'on'){
|
||||||
var x, y
|
var x, y
|
||||||
@ -1619,12 +1339,12 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
|||||||
//
|
//
|
||||||
toggleAutoHideCursor: ['Interface/Cursor auto-hide',
|
toggleAutoHideCursor: ['Interface/Cursor auto-hide',
|
||||||
toggler.CSSClassToggler(
|
toggler.CSSClassToggler(
|
||||||
function(){ return this.ribbons.viewer },
|
function(){ return this.dom },
|
||||||
'cursor-autohide',
|
'cursor-autohide',
|
||||||
function(state){
|
function(state){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
// NOTE: this is handled by the keyboard feature...
|
// NOTE: this is handled by the keyboard feature...
|
||||||
var kb_target = this.__keyboard_event_source || $(window)
|
var kb_target = this.__keyboard_event_source || $(window)
|
||||||
|
|
||||||
@ -1654,7 +1374,7 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
|||||||
: -1
|
: -1
|
||||||
if(timeout && timeout > 0){
|
if(timeout && timeout > 0){
|
||||||
m_timer = setTimeout(function(){
|
m_timer = setTimeout(function(){
|
||||||
var viewer = that.ribbons.viewer
|
var viewer = that.dom
|
||||||
|
|
||||||
// auto-hide is off -- restore...
|
// auto-hide is off -- restore...
|
||||||
if(!viewer.hasClass('cursor-autohide')){
|
if(!viewer.hasClass('cursor-autohide')){
|
||||||
@ -1680,7 +1400,7 @@ module.Cursor = core.ImageGridFeatures.Feature({
|
|||||||
// avoid this from delaying the keyboard handler...
|
// avoid this from delaying the keyboard handler...
|
||||||
kb_timer = setTimeout(function(){
|
kb_timer = setTimeout(function(){
|
||||||
kb_timer = null
|
kb_timer = null
|
||||||
var viewer = that.ribbons.viewer
|
var viewer = that.dom
|
||||||
|
|
||||||
// get key...
|
// get key...
|
||||||
var key = keyboard.normalizeKey(
|
var key = keyboard.normalizeKey(
|
||||||
@ -1842,7 +1562,7 @@ var ControlActions = actions.Actions({
|
|||||||
// nothing to do...
|
// nothing to do...
|
||||||
null
|
null
|
||||||
: (this.ribbons
|
: (this.ribbons
|
||||||
&& this.ribbons.viewer
|
&& this.dom
|
||||||
//&& this.ribbons.getRibbon().data('hammer') ? 'handling-click' : 'none' },
|
//&& this.ribbons.getRibbon().data('hammer') ? 'handling-click' : 'none' },
|
||||||
&& this.ribbons.getRibbon().hasClass('clickable')) ?
|
&& this.ribbons.getRibbon().hasClass('clickable')) ?
|
||||||
'handling-click'
|
'handling-click'
|
||||||
@ -1978,7 +1698,7 @@ var ControlActions = actions.Actions({
|
|||||||
|
|
||||||
var cl = central && central.offset().left
|
var cl = central && central.offset().left
|
||||||
var w = central && central.outerWidth(true)
|
var w = central && central.outerWidth(true)
|
||||||
var W = this.ribbons.viewer.width()
|
var W = this.dom.width()
|
||||||
var vmin = Math.min(
|
var vmin = Math.min(
|
||||||
document.body.offsetWidth,
|
document.body.offsetWidth,
|
||||||
document.body.offsetHeight)
|
document.body.offsetHeight)
|
||||||
@ -2044,7 +1764,7 @@ var ControlActions = actions.Actions({
|
|||||||
// nothing to do...
|
// nothing to do...
|
||||||
null
|
null
|
||||||
: (this.ribbons
|
: (this.ribbons
|
||||||
&& this.ribbons.viewer
|
&& this.dom
|
||||||
&& this.ribbons.getRibbon().hasClass('draggable')) ?
|
&& this.ribbons.getRibbon().hasClass('draggable')) ?
|
||||||
'handling-pan'
|
'handling-pan'
|
||||||
: 'none' },
|
: 'none' },
|
||||||
@ -2281,8 +2001,8 @@ var ControlActions = actions.Actions({
|
|||||||
// nothing to do...
|
// nothing to do...
|
||||||
null
|
null
|
||||||
: (this.ribbons
|
: (this.ribbons
|
||||||
&& this.ribbons.viewer
|
&& this.dom
|
||||||
&& this.ribbons.viewer.hasClass('mouse-wheel-scroll')) ?
|
&& this.dom.hasClass('mouse-wheel-scroll')) ?
|
||||||
'handling-mouse-wheel'
|
'handling-mouse-wheel'
|
||||||
: 'none' },
|
: 'none' },
|
||||||
'handling-mouse-wheel',
|
'handling-mouse-wheel',
|
||||||
@ -2318,7 +2038,7 @@ var ControlActions = actions.Actions({
|
|||||||
var rgid = this.ribbons.getElemGID(r)
|
var rgid = this.ribbons.getElemGID(r)
|
||||||
|
|
||||||
// XXX vertical scroll...
|
// XXX vertical scroll...
|
||||||
this.ribbons.viewer
|
this.dom
|
||||||
.on('wheel', function(){
|
.on('wheel', function(){
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2357,7 +2077,7 @@ var ControlActions = actions.Actions({
|
|||||||
|
|
||||||
// on...
|
// on...
|
||||||
if(state == '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
|
// NOTE: we are resetting this to avoid multiple setting
|
||||||
// handlers...
|
// handlers...
|
||||||
this.off('updateRibbon', setup)
|
this.off('updateRibbon', setup)
|
||||||
@ -2368,7 +2088,7 @@ var ControlActions = actions.Actions({
|
|||||||
|
|
||||||
// off...
|
// off...
|
||||||
} else {
|
} else {
|
||||||
this.ribbons.viewer.removeClass('mouse-wheel-scroll')
|
this.dom.removeClass('mouse-wheel-scroll')
|
||||||
this.off('updateRibbon', setup)
|
this.off('updateRibbon', setup)
|
||||||
|
|
||||||
this.data.ribbon_order.forEach(function(gid){
|
this.data.ribbon_order.forEach(function(gid){
|
||||||
@ -2390,13 +2110,13 @@ var ControlActions = actions.Actions({
|
|||||||
return state ?
|
return state ?
|
||||||
null
|
null
|
||||||
: (this.ribbons
|
: (this.ribbons
|
||||||
&& this.ribbons.viewer
|
&& this.dom
|
||||||
&& this.ribbons.viewer.data('hammer')) ?
|
&& this.dom.data('hammer')) ?
|
||||||
'handling-swipes'
|
'handling-swipes'
|
||||||
: 'none' },
|
: 'none' },
|
||||||
'handling-swipes',
|
'handling-swipes',
|
||||||
function(state){
|
function(state){
|
||||||
var viewer = this.ribbons.viewer
|
var viewer = this.dom
|
||||||
|
|
||||||
// on...
|
// on...
|
||||||
if(state == 'on'){
|
if(state == 'on'){
|
||||||
@ -2520,7 +2240,7 @@ module.Control = core.ImageGridFeatures.Feature({
|
|||||||
}],
|
}],
|
||||||
|
|
||||||
// if panned image is off screen, center it...
|
// if panned image is off screen, center it...
|
||||||
['setScale',
|
['viewScale',
|
||||||
function(){
|
function(){
|
||||||
var that = this
|
var that = this
|
||||||
Object.keys(this.data.ribbons).forEach(function(r){
|
Object.keys(this.data.ribbons).forEach(function(r){
|
||||||
@ -2617,7 +2337,7 @@ module.PreviewFilters = core.ImageGridFeatures.Feature({
|
|||||||
var cls = filters[state]
|
var cls = filters[state]
|
||||||
var classes = Object.values(filters)
|
var classes = Object.values(filters)
|
||||||
.filter(function(c){ return c != cls })
|
.filter(function(c){ return c != cls })
|
||||||
this.ribbons.viewer
|
this.dom
|
||||||
.find('.'+ classes.join(', .'))
|
.find('.'+ classes.join(', .'))
|
||||||
.removeClass(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...
|
// ...not sure if this is the right way to go...
|
||||||
// XXX need to get the minimal size and not the width as results will
|
// 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 })
|
m = Object.keys(m).filter(function(e){ return m[e] != null })
|
||||||
console.log('Modules (%d):', m.length, m)
|
console.log('Modules (%d):', m.length, m)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// setup actions...
|
||||||
|
window.ig =
|
||||||
|
window.ImageGrid =
|
||||||
|
viewer.ImageGridFeatures
|
||||||
|
.setup([
|
||||||
|
'viewer-testing',
|
||||||
|
|
||||||
// setup actions...
|
'demo',
|
||||||
window.ig =
|
|
||||||
window.ImageGrid =
|
|
||||||
viewer.ImageGridFeatures
|
|
||||||
.setup([
|
|
||||||
'viewer-testing',
|
|
||||||
|
|
||||||
'demo',
|
// XXX this is not for production...
|
||||||
|
'experiments',
|
||||||
|
|
||||||
// XXX this is not for production...
|
//'-commandline',
|
||||||
'experiments',
|
//'-ui-partial-ribbons',
|
||||||
|
])
|
||||||
|
|
||||||
//'-commandline',
|
} catch(err){
|
||||||
//'-ui-partial-ribbons',
|
console.error(err)
|
||||||
])
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// used to switch experimental actions on (set to true) or off (unset or false)...
|
// used to switch experimental actions on (set to true) or off (unset or false)...
|
||||||
@ -130,6 +135,9 @@ $(function(){
|
|||||||
&& console.warn('Features excluded (%d):',
|
&& console.warn('Features excluded (%d):',
|
||||||
ig.features.excluded.length,
|
ig.features.excluded.length,
|
||||||
ig.features.excluded)
|
ig.features.excluded)
|
||||||
|
Object.keys(ig.features.missing).length > 0
|
||||||
|
&& console.warn('Features disabled (%d):',
|
||||||
|
ig.features.missing)
|
||||||
ig.features.disabled.length > 0
|
ig.features.disabled.length > 0
|
||||||
&& console.log('Features disabled (%d):',
|
&& console.log('Features disabled (%d):',
|
||||||
ig.features.disabled.length,
|
ig.features.disabled.length,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user