cleanup and refactoring...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-05-20 03:59:11 +03:00
parent 055775fc2b
commit ab7f0a77e6
6 changed files with 313 additions and 324 deletions

View File

@ -78,7 +78,6 @@ core.ImageGridFeatures.Feature('viewer-testing', [
// features...
'ui-cursor',
'ui-animation',
'ui-single-image',
'ui-partial-ribbons',
@ -112,7 +111,6 @@ core.ImageGridFeatures.Feature('viewer-testing', [
'ui-progress',
'ui-status-log',
'ui-scale',
'ui-animation',
'ui-bounds-indicators',
'ui-current-image-indicator',
// NOTE: only one of these can be set...

View File

@ -1,6 +1,13 @@
/**********************************************************************
*
*
* Features:
* - ui-ribbons-render
* - ui-ribbons-edit-render
* - ui-partial-ribbons
* - ui-animation
* manage UI non-css animations...
*
*
**********************************************************************/
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
@ -433,9 +440,10 @@ core.ImageGridFeatures.Feature({
tag: 'ui-ribbons-render',
exclusive: ['ui-render'],
depends: [
// XXX
'base',
],
suggested: [
'ui-animation',
'ui-ribbons-edit-render',
],
@ -743,6 +751,66 @@ core.ImageGridFeatures.Feature({
/*********************************************************************/
// Animation...
// XXX at this point this does not support target lists...
// XXX shift up/down to new ribbon is not too correct...
// XXX depends on .ribbons.makeShadow(..)...
var ShiftAnimation =
module.ShiftAnimation = core.ImageGridFeatures.Feature({
title: '',
doc: '',
tag: 'ui-animation',
depends: [
'ui-ribbons-render',
],
config: {
// XXX make this duration...
'shadow-animation-delay': 200,
'shadow-animation-start-delay': 0,
},
handlers: [
//['shiftImageUp.pre shiftImageDown.pre '
// +'travelImageUp.pre travelImageDown.pre',
['shiftImageUp.pre shiftImageDown.pre',
function(target){
// XXX do not do target lists...
if(target != null && target.constructor === Array
// do not animate in single image mode...
&& this.toggleSingleImage('?') == 'on'){
return
}
var s = this.ribbons.makeShadow(target, true,
// XXX make this duration...
this.config['shadow-animation-delay'],
this.config['shadow-animation-start-delay'])
return function(){ s() }
}],
// NOTE: this will keep the shadow in place -- the shadow will not
// go to the mountain, the mountain will come to the shadow ;)
['shiftImageLeft.pre shiftImageRight.pre',
function(target){
// XXX do not do target lists...
if(target != null && target.constructor === Array
// do not animate in single image mode...
&& this.toggleSingleImage('?') == 'on'){
return
}
var s = this.ribbons.makeShadow(target, undefined,
// XXX make this duration...
this.config['shadow-animation-delay'],
this.config['shadow-animation-start-delay'])
return function(){ s() }
}],
],
})
/**********************************************************************
* vim:set ts=4 sw=4 : */ return module })

View File

@ -15,6 +15,8 @@ var features = require('lib/features')
var core = require('features/core')
var ribbons = require('imagegrid/ribbons')
/*********************************************************************/
@ -26,7 +28,9 @@ var core = require('features/core')
var VirtualDOMRibbonsClassPrototype = {
// XXX ???
}
VirtualDOMRibbonsClassPrototype.__proto__ = ribbons.BaseRibbons.prototype.__proto__
// XXX make this ribbons.BaseRibbons compatible....
var VirtualDOMRibbonsPrototype = {
// XXX this is a circular ref -- I do not like it...
parent: null,
@ -49,29 +53,6 @@ var VirtualDOMRibbonsPrototype = {
// }
state: null,
// XXX reuse these from ribbons???
preventTransitions: function(){
},
restoreTransitions: function(){
},
elemGID: function(){
},
getImage: function(){
},
getImageByPosition: function(){
},
getRibbon: function(){
},
getVisibleImageSize: function(){
},
focusImage: function(){
},
px2vmin: function(){
},
// ...
// constructors...
makeView: function(state, initial){
state = state || {}
@ -362,6 +343,8 @@ var VirtualDOMRibbonsPrototype = {
this.parent = parent || this.parent
},
}
VirtualDOMRibbonsPrototype.__proto__ = ribbons.BaseRibbons.prototype
var VirtualDOMRibbons =
module.VirtualDOMRibbons =

View File

@ -9,8 +9,6 @@
* maintain configuration state in local storage
* - ui-url-hash
* handle .location.hash
* - ui-animation
* manage UI non-css animations...
* - ui-cursor
* - ui-control
* touch/mouse control mechanics
@ -48,9 +46,11 @@ var base = require('features/base')
/*********************************************************************/
// Viewer (widget/interface)...
//
//
// This requires a 'ui-render' family feature to be present
//
// Expected render API is:
// XXX do we actually need this or should we directly use .ribbons.scale()???
// Get/set view scale...
// .viewScale()
// .viewScale('?')
@ -93,7 +93,7 @@ var base = require('features/base')
// .updateRibbon(target)
// -> this
//
// Generic .ribbons API (introspection):
// Base .ribbons API (see: ribbons.BaseRibbons):
// .ribbons.getImage(..)
// -> image
//
@ -231,6 +231,7 @@ module.ViewerActions = actions.Actions({
// Scaling...
//
// NOTE: .screenwidth / .screenheight are measured in square image blocks...
// XXX do we actually need this or should we directly use .ribbons.scale()???
get scale(){
return this.viewScale() },
set scale(s){
@ -748,15 +749,6 @@ module.Viewer = core.ImageGridFeatures.Feature({
/*********************************************************************/
// User interfaces for different base features...
// XXX tag dialogs...
// XXX
/*********************************************************************/
// Utilities and Services...
@ -992,64 +984,6 @@ module.URLHash = core.ImageGridFeatures.Feature({
/*********************************************************************/
// Animation...
// XXX at this point this does not support target lists...
// XXX shift up/down to new ribbon is not too correct...
// XXX depends on .ribbons...
var ShiftAnimation =
module.ShiftAnimation = core.ImageGridFeatures.Feature({
title: '',
doc: '',
tag: 'ui-animation',
depends: ['ui'],
config: {
// XXX make this duration...
'shadow-animation-delay': 200,
'shadow-animation-start-delay': 0,
},
handlers: [
//['shiftImageUp.pre shiftImageDown.pre '
// +'travelImageUp.pre travelImageDown.pre',
['shiftImageUp.pre shiftImageDown.pre',
function(target){
// XXX do not do target lists...
if(target != null && target.constructor === Array
// do not animate in single image mode...
&& this.toggleSingleImage('?') == 'on'){
return
}
var s = this.ribbons.makeShadow(target, true,
// XXX make this duration...
this.config['shadow-animation-delay'],
this.config['shadow-animation-start-delay'])
return function(){ s() }
}],
// NOTE: this will keep the shadow in place -- the shadow will not
// go to the mountain, the mountain will come to the shadow ;)
['shiftImageLeft.pre shiftImageRight.pre',
function(target){
// XXX do not do target lists...
if(target != null && target.constructor === Array
// do not animate in single image mode...
&& this.toggleSingleImage('?') == 'on'){
return
}
var s = this.ribbons.makeShadow(target, undefined,
// XXX make this duration...
this.config['shadow-animation-delay'],
this.config['shadow-animation-start-delay'])
return function(){ s() }
}],
],
})
/*********************************************************************/
// Mouse...
//
@ -1310,6 +1244,7 @@ module.Cursor = core.ImageGridFeatures.Feature({
// XXX how should multiple long interactions be handled??
// XXX revise...
//
// NOTE: modifies .ribbons -- event handlers, attrs, classes... (XXX)
// NOTE: for legacy stuff see: features/ui-legacy.js
//
// XXX add option to block click actions on focus...
@ -1317,7 +1252,6 @@ module.Cursor = core.ImageGridFeatures.Feature({
// system-wide...
// XXX STUB: needs more thought....
// XXX depends on .ribbons...
var ControlActions = actions.Actions({
config: {
'control-mode': 'indirect',
@ -2109,7 +2043,7 @@ module.FailsafeDevTools = core.ImageGridFeatures.Feature({
/*********************************************************************/
// XXX depends on .ribbons...
// NOTE: this updates the current image block CSS...
var PreviewFilters
module.PreviewFilters = core.ImageGridFeatures.Feature({
title: '',

View File

@ -33,7 +33,7 @@ var RIBBON = '.ribbon:not(.clone)'
/*********************************************************************/
//
// This expects the following HTML structure...
// This expects/builds the following HTML structure...
//
// Unpopulated:
//
@ -45,37 +45,43 @@ var RIBBON = '.ribbon:not(.clone)'
//
// <div class="viewer">
// <div class="ribbon-set">
// <div class="ribbon">
// <div class="image" gid="a"></div>
// <div class="image" gid="b"></div>
// <div class="ribbon-locator">
// <div class="ribbon">
// <div class="image" gid="a"></div>
// <div class="image" gid="b"></div>
// ...
// </div>
// <div class="ribbon">
// <div class="image" gid="c"></div>
//
// <!-- current image -->
// <div class="current image" gid="d"></div>
//
// <!-- image with mark... -->
// <div class="image" gid="e"></div>
// <div class="mark selected" gid="f"></div>
//
// <div class="image" gid="g"></div>
//
// ...
// </div>
// ...
// </div>
// <div class="ribbon">
// <div class="image" gid="c"></div>
//
// <!-- current image -->
// <div class="current image" gid="d"></div>
//
// <!-- image with mark... -->
// <div class="image" gid="e"></div>
// <div class="mark selected" gid="f"></div>
//
// <div class="image" gid="g"></div>
//
// ...
// </div>
// ...
// </div>
// </div>
//
//
// NOTE: there can be only one .ribbon-set element.
// NOTE: other elements can exist in the structure, but as long as they
// use different CSS classes they are ignored by the system, note
// that such elements may affect alignment and placement though this
// should be obvious ;)
//
//
//
/*********************************************************************/
var RibbonsClassPrototype = {
var BaseRibbonsClassPrototype = {
// utils...
px2v: function(px, mode){
var ref = mode == 'vw' ?
@ -116,55 +122,9 @@ var RibbonsClassPrototype = {
// this removes the extra quots...
.replace(/^"(.*)"$/g, '$1'))
},
// DOM Constructors...
// NOTE: these will return unattached objects...
createViewer: function(){
return $('<div>')
.addClass('viewer')
.attr('tabindex', 0)
//.append($('<div>')
// .addClass('ribbon-set'))
},
// XXX NOTE: quots removal might render this incompatible with older data formats...
createRibbon: function(gids){
gids = gids || []
gids = gids.constructor !== Array ? [gids] : gids
var that = this
return $(gids.map(function(gid){
gid = gid != null ? gid+'' : gid
return that.elemGID($('<div>')
.addClass('ribbon'), gid)[0]
//return $('<div>')
// .addClass('ribbon-container')
// .append(that.elemGID($('<div>')
// .addClass('ribbon'), gid))[0]
}))
},
// XXX NOTE: quots removal might render this incompatible with older data formats...
createImage: function(gids){
gids = gids || []
gids = gids.constructor !== Array ? [gids] : gids
var that = this
return $(gids.map(function(gid){
gid = gid != null ? gid+'' : gid
return that.elemGID($('<div>')
.addClass('image'), gid)[0]
}))
},
createMark: function(cls, gid){
gid = gid != null ? gid+'' : gid
return this.elemGID($('<div class="mark">')
.addClass(cls), gid)
},
}
//---------------------------------------------------------------------
var IntrospectiveRibbonsPrototype = {
var BaseRibbonsPrototype = {
//
// .viewer (jQuery object)
//
@ -178,15 +138,15 @@ var IntrospectiveRibbonsPrototype = {
},
// utils...
px2v: RibbonsClassPrototype.px2v,
px2vw: RibbonsClassPrototype.px2vw,
px2vh: RibbonsClassPrototype.px2vh,
px2vmin: RibbonsClassPrototype.px2vmin,
px2vmax: RibbonsClassPrototype.px2vmax,
px2v: BaseRibbonsClassPrototype.px2v,
px2vw: BaseRibbonsClassPrototype.px2vw,
px2vh: BaseRibbonsClassPrototype.px2vh,
px2vmin: BaseRibbonsClassPrototype.px2vmin,
px2vmax: BaseRibbonsClassPrototype.px2vmax,
// Generic getters...
elemGID: RibbonsClassPrototype.elemGID,
elemGID: BaseRibbonsClassPrototype.elemGID,
get parent(){
@ -668,28 +628,216 @@ var IntrospectiveRibbonsPrototype = {
return this.viewer.find(RIBBON).index(this.getRibbon(target)) },
// Image info...
//
// NOTE: these are simply shorthands to image attr access...
getImageRotation: function(target){
return (this.getImage(target).attr('orientation') || 0)*1 },
getImageFlip: function(target){
return (this.getImage(target).attr('flipped') || '')
.split(',')
.map(function(e){ return e.trim() })
.filter(function(e){ return e != '' })
.filter(function(e){ return e != '' }) },
// UI manipulation...
// Compensate for viewer proportioned and rotated images.
//
// This will set the margins so as to make the rotated image offset the
// same space as it is occupying visually...
//
// NOTE: this is not needed for square image blocks.
// NOTE: if an image block is square, this will remove the margins.
//
// XXX this does the same job as features/ui-single-image.js' .updateImageProportions(..)
_calcImageProportions: function(image, W, H, w, h, o){
image = image instanceof jQuery ? image[0] : image
//var s = (!w || !h) ? getComputedStyle(image) : null
//w = w || parseFloat(s.width)
//h = h || parseFloat(s.height)
//w = this.px2vmin(w || image.offsetWidth)
//h = this.px2vmin(h || image.offsetHeight)
w = w || image.offsetWidth
h = h || image.offsetHeight
// non-square image...
if(w != h){
W = W || this.viewer.innerWidth()
H = H || this.viewer.innerHeight()
o = o || image.getAttribute('orientation') || 0
var viewer_p = W > H ? 'landscape' : 'portrait'
// NOTE: we need to use the default (CSS) value when
// possible, to avoid sizing issues...
var dfl_w = image.style.width == ''
var dfl_h = image.style.height == ''
var image_p = w > h ? 'landscape' : 'portrait'
// when the image is turned 90deg/270deg and its
// proportions are the same as the screen...
if((o == 90 || o == 270) && image_p == viewer_p){
return {
width: dfl_h ? '' : (this.px2vmin(h) + 'vmin'),
height: dfl_w ? '' : (this.px2vmin(w) + 'vmin'),
margin: this.px2vmin(-((w - h)/2)) +'vmin '+ this.px2vmin((w - h)/2) + 'vmin',
}
} else if((o == 0 || o == 180) && image_p != viewer_p){
return {
width: dfl_h ? '' : (this.px2vmin(h) + 'vmin'),
height: dfl_w ? '' : (this.px2vmin(w) + 'vmin'),
margin: '',
}
}
// square image...
} else {
return {
width: '',
height: '',
margin: '',
}
}
},
correctImageProportionsForRotation: function(images, W, H){
var that = this
W = W || this.viewer.innerWidth()
H = H || this.viewer.innerHeight()
var images = images || this.viewer.find(IMAGE)
return $(images).each(function(i, e){
var data = that._calcImageProportions(this, W, H)
data
&& $(this).css(data)
})
},
// center a ribbon vertically...
//
// Center current ribbon...
// .centerRibbon()
// -> Ribbons
//
// Center specific ribbon...
// .centerRibbon(image)
// .centerRibbon(ribbon)
// -> Ribbons
//
centerRibbon: function(target){
var ribbon = this.getRibbon(target)
var locator = this.getRibbonLocator()
if(locator.length == 0 || ribbon.length == 0){
return this
}
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
},
// center an image horizontally...
//
// Center current ribbon/image...
// .centerImage()
// -> Ribbons
//
// Center specific image...
// .centerImage(image)
// .centerImage(image, 'center')
// -> Ribbons
//
// Center ribbon before/after an image...
// .centerImage(image, 'before')
// .centerImage(image, 'after')
// -> Ribbons
//
centerImage: function(target, mode){
target = this.getImage(target)
var ribbon = this.getRibbon(target)
if(ribbon.length == 0){
return this
}
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
},
}
var IntrospectiveRibbons =
module.IntrospectiveRibbons =
object.makeConstructor('IntrospectiveRibbons',
RibbonsClassPrototype,
IntrospectiveRibbonsPrototype)
var BaseRibbons =
module.BaseRibbons =
object.makeConstructor('BaseRibbons',
BaseRibbonsClassPrototype,
BaseRibbonsPrototype)
//---------------------------------------------------------------------
// NOTE: this is a low level interface, not a set of actions...
var RibbonsClassPrototype = {
// DOM Constructors...
// NOTE: these will return unattached objects...
createViewer: function(){
return $('<div>')
.addClass('viewer')
.attr('tabindex', 0)
//.append($('<div>')
// .addClass('ribbon-set'))
},
// XXX NOTE: quots removal might render this incompatible with older data formats...
createRibbon: function(gids){
gids = gids || []
gids = gids.constructor !== Array ? [gids] : gids
var that = this
return $(gids.map(function(gid){
gid = gid != null ? gid+'' : gid
return that.elemGID($('<div>')
.addClass('ribbon'), gid)[0]
//return $('<div>')
// .addClass('ribbon-container')
// .append(that.elemGID($('<div>')
// .addClass('ribbon'), gid))[0]
}))
},
// XXX NOTE: quots removal might render this incompatible with older data formats...
createImage: function(gids){
gids = gids || []
gids = gids.constructor !== Array ? [gids] : gids
var that = this
return $(gids.map(function(gid){
gid = gid != null ? gid+'' : gid
return that.elemGID($('<div>')
.addClass('image'), gid)[0]
}))
},
createMark: function(cls, gid){
gid = gid != null ? gid+'' : gid
return this.elemGID($('<div class="mark">')
.addClass(cls), gid)
},
}
RibbonsClassPrototype.__proto__ = BaseRibbonsClassPrototype
var RibbonsPrototype = {
// XXX
clone: function(){
@ -2337,147 +2485,6 @@ var RibbonsPrototype = {
return this.flipImage(target, 'horizontal', reference) },
// UI manipulation...
// Compensate for viewer proportioned and rotated images.
//
// This will set the margins so as to make the rotated image offset the
// same space as it is occupying visually...
//
// NOTE: this is not needed for square image blocks.
// NOTE: if an image block is square, this will remove the margins.
//
// XXX this does the same job as features/ui-single-image.js' .updateImageProportions(..)
_calcImageProportions: function(image, W, H, w, h, o){
image = image instanceof jQuery ? image[0] : image
//var s = (!w || !h) ? getComputedStyle(image) : null
//w = w || parseFloat(s.width)
//h = h || parseFloat(s.height)
//w = this.px2vmin(w || image.offsetWidth)
//h = this.px2vmin(h || image.offsetHeight)
w = w || image.offsetWidth
h = h || image.offsetHeight
// non-square image...
if(w != h){
W = W || this.viewer.innerWidth()
H = H || this.viewer.innerHeight()
o = o || image.getAttribute('orientation') || 0
var viewer_p = W > H ? 'landscape' : 'portrait'
// NOTE: we need to use the default (CSS) value when
// possible, to avoid sizing issues...
var dfl_w = image.style.width == ''
var dfl_h = image.style.height == ''
var image_p = w > h ? 'landscape' : 'portrait'
// when the image is turned 90deg/270deg and its
// proportions are the same as the screen...
if((o == 90 || o == 270) && image_p == viewer_p){
return {
width: dfl_h ? '' : (this.px2vmin(h) + 'vmin'),
height: dfl_w ? '' : (this.px2vmin(w) + 'vmin'),
margin: this.px2vmin(-((w - h)/2)) +'vmin '+ this.px2vmin((w - h)/2) + 'vmin',
}
} else if((o == 0 || o == 180) && image_p != viewer_p){
return {
width: dfl_h ? '' : (this.px2vmin(h) + 'vmin'),
height: dfl_w ? '' : (this.px2vmin(w) + 'vmin'),
margin: '',
}
}
// square image...
} else {
return {
width: '',
height: '',
margin: '',
}
}
},
correctImageProportionsForRotation: function(images, W, H){
var that = this
W = W || this.viewer.innerWidth()
H = H || this.viewer.innerHeight()
var images = images || this.viewer.find(IMAGE)
return $(images).each(function(i, e){
var data = that._calcImageProportions(this, W, H)
data
&& $(this).css(data)
})
},
// center a ribbon vertically...
//
// Center current ribbon...
// .centerRibbon()
// -> Ribbons
//
// Center specific ribbon...
// .centerRibbon(image)
// .centerRibbon(ribbon)
// -> Ribbons
//
centerRibbon: function(target){
var ribbon = this.getRibbon(target)
var locator = this.getRibbonLocator()
if(locator.length == 0 || ribbon.length == 0){
return this
}
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
},
// center an image horizontally...
//
// Center current ribbon/image...
// .centerImage()
// -> Ribbons
//
// Center specific image...
// .centerImage(image)
// .centerImage(image, 'center')
// -> Ribbons
//
// Center ribbon before/after an image...
// .centerImage(image, 'before')
// .centerImage(image, 'after')
// -> Ribbons
//
centerImage: function(target, mode){
target = this.getImage(target)
var ribbon = this.getRibbon(target)
if(ribbon.length == 0){
return this
}
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
},
// Fit image to view...
//
// If n is given this will fit n images (default: 1)
@ -2539,15 +2546,13 @@ var RibbonsPrototype = {
return this
},
}
RibbonsPrototype.__proto__ = IntrospectiveRibbonsPrototype
RibbonsPrototype.__proto__ = BaseRibbonsPrototype
var Ribbons =
module.Ribbons =
object.makeConstructor('Ribbons',
RibbonsClassPrototype,
RibbonsPrototype)
RibbonsClassPrototype,
RibbonsPrototype)

View File

@ -26,6 +26,7 @@
"ig-features": "^2.0.0",
"ig-object": "^1.0.1",
"openseadragon": "^2.1.0",
"preact": "^8.1.0",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"requirejs": "^2.1.23",