diff --git a/ui (gen4)/data.js b/ui (gen4)/data.js
index 62ff8c8a..ecd21e64 100755
--- a/ui (gen4)/data.js
+++ b/ui (gen4)/data.js
@@ -379,7 +379,7 @@ module.DataPrototype = {
}
// normalize target...
- if(target in this.ribbons || target.constructor.name == 'Array'){
+ if(target in this.ribbons || target.constructor === Array){
list = target
target = this.current
} else if(['before', 'after', 'next', 'prev'].indexOf(target) >= 0){
@@ -885,6 +885,7 @@ module.DataPrototype = {
// NOTE: this depends on setting length of an array, it works in
// Chrome but will it work the same in other systems???
reverseImages: function(){
+ var ribbons = this.ribbons
this.order.reverse()
var l = this.order.length
for(k in ribbons){
@@ -1004,7 +1005,17 @@ module.DataPrototype = {
// update ribbons...
for(k in ribbons){
- ribbons[k].splice(t+i, 0, ribbons[k].splice(f, 1)[0])
+ var e = ribbons[k].splice(f, 1)[0]
+ ribbons[k].splice(t+i, 0, e)
+ // remove the null/undefined if it was just inserted...
+ // NOTE: this needs to be done as splice inserts the 3'rd
+ // argument explicitly regardless of it's value,
+ // this if not done we'll end up with undefined
+ // inserted into a sparse ribbon which will be
+ // considered as an element...
+ if(e == null){
+ delete ribbons[k][t+i]
+ }
}
}
}
diff --git a/ui (gen4)/index.html b/ui (gen4)/index.html
index 2883b352..a6ef8d77 100755
--- a/ui (gen4)/index.html
+++ b/ui (gen4)/index.html
@@ -5,6 +5,49 @@
+
+
+
diff --git a/ui (gen4)/lib/actions.js b/ui (gen4)/lib/actions.js
index aa0591ff..1504c91e 100755
--- a/ui (gen4)/lib/actions.js
+++ b/ui (gen4)/lib/actions.js
@@ -101,8 +101,10 @@ define(function(require){ var module = {}
// helpers...
// XXX
-function args2array(args){
- return Array.apply(null, args)
+if(typeof(args2array) != 'function'){
+ function args2array(args){
+ return [].slice.call(args)
+ }
}
@@ -209,7 +211,7 @@ function Action(name, doc, ldoc, func){
.map(function(h){ return h.apply(that, args) })
// NOTE: this action will get included and called by the code
- // above and below...
+ // above and below, so no need to explicitly call func...
// call handlers -- post phase...
// NOTE: post handlers need to get called last run pre first run post...
@@ -519,12 +521,18 @@ function test(){
// NOTE: this looks like an action and feels like an action but
// actually this is a callback as an action with this name
// already exists...
- testActionGen1: [function(){
- console.log(' pre callback!')
- return function(){
- console.log(' post callback!')
- }
- }],
+ testActionGen1: [
+ function(){
+ console.log(' pre callback!')
+ return function(){
+ console.log(' post callback!')
+ }
+ }],
+
+ testAction2: ['this is an action',
+ function(){
+ console.log('testAction2 args:', arguments)
+ }],
})
diff --git a/ui (gen4)/lib/jli.js b/ui (gen4)/lib/jli.js
index 84e6a6c7..b3104555 100755
--- a/ui (gen4)/lib/jli.js
+++ b/ui (gen4)/lib/jli.js
@@ -1325,7 +1325,8 @@ Array.prototype.len = function(){
// convert JS arguments to Array...
function args2array(args){
- return Array.apply(null, args)
+ //return Array.apply(null, args)
+ return [].slice.call(args)
}
diff --git a/ui (gen4)/ribbons.js b/ui (gen4)/ribbons.js
index 07d48740..40197249 100755
--- a/ui (gen4)/ribbons.js
+++ b/ui (gen4)/ribbons.js
@@ -169,6 +169,30 @@ module.RibbonsPrototype = {
// Helpers...
+ // XXX
+ preventTransitions: function(){
+ this.viewer.addClass('no-transitions')
+ },
+ restoreTransitions: function(now){
+ // sync...
+ if(now){
+ this.viewer.removeClass('no-transitions')
+
+ // on next exec frame...
+ } else {
+ var that = this
+ setTimeout(function(){
+ that.viewer.removeClass('no-transitions')}, 0)
+ }
+ },
+
+ noTransitions: function(func){
+ this.preventTransitions()
+ func.apply(this, args2array(arguments).slice(1))
+ this.restoreTransitions()
+ },
+
+
// Get visible image tile size...
//
// .getVisibleImageSize()
@@ -187,11 +211,10 @@ module.RibbonsPrototype = {
//
// XXX try and make image size the product of vmin and scale...
// XXX is this the right place for this???
- // XXX uses jli.js getElementScale(..)
getVisibleImageSize: function(dim){
dim = dim == null ? 'width' : dim
var img = this.viewer.find('.image')
- var scale = getElementScale(this.viewer.find('.ribbon-set'))
+ var scale = this.getScale()
if(dim == 'height'){
return img.outerHeight(true) * scale
} else if(dim == 'width'){
@@ -203,6 +226,24 @@ module.RibbonsPrototype = {
}
},
+ getScreenWidthImages: function(scale){
+ var scale = scale == null ? 1 : scale/this.getScale()
+
+ var W = this.viewer.width()
+ var w = this.getVisibleImageSize('width')*scale
+
+ return W/w
+ },
+
+ // XXX uses jli.js getElementScale(..) / setElementScale(..)
+ getScale: function(){
+ return getElementScale(this.viewer.find('.ribbon-set'))
+ },
+ setScale: function(scale){
+ setElementScale(this.viewer.find('.ribbon-set'), scale)
+ return this
+ },
+
// Contextual getters...
@@ -1202,10 +1243,13 @@ module.RibbonsPrototype = {
// NOTE: image_offset is applicable ONLY when both vertical and
// horizontal are set to 'center', either explicitly or
// implicitly (i.e. the default)
- _getOffset: function(target, vertical, horizontal, image_offset){
+ // NOTE: this will get absolute results relative to screen, view
+ // scaling will have no effect...
+ _getOffset: function(target, vertical, horizontal, image_offset, scale){
vertical = vertical == null ? 'center' : vertical
horizontal = horizontal == null ? 'center' : horizontal
image_offset = image_offset == null ? 'center' : image_offset
+ scale = scale == null ? this.getScale() : scale
if(vertical == 'before' || vertical == 'after'){
image_offset = vertical
@@ -1227,8 +1271,8 @@ module.RibbonsPrototype = {
var W = viewer.width()
var H = viewer.height()
- var w = image.width()
- var h = image.height()
+ var w = image.width() * scale
+ var h = image.height() * scale
image_offset = image_offset == 'before' ? w/2
: image_offset == 'after' ? -w/2
@@ -1258,9 +1302,11 @@ module.RibbonsPrototype = {
}
},
// center a ribbon vertically...
- // XXX
- centerRibbon: function(target, offset){
- offset = offset == null ? this._getOffset(target) : offset
+ //
+ centerRibbon: function(target, offset, scale){
+ offset = offset == null
+ ? this._getOffset(target, null, null, null, scale)
+ : offset
// vertical offset...
this.viewer.find('.ribbon-set')
@@ -1271,22 +1317,34 @@ module.RibbonsPrototype = {
return this
},
// center an image horizontally...
- // XXX
- centerImage: function(target, mode, offset){
- offset = offset == null ? this._getOffset(target, 'center', 'center', mode) : offset
+ //
+ centerImage: function(target, mode, offset, scale){
+ scale = scale == null ? this.getScale() : scale
+ offset = offset == null
+ ? this._getOffset(target, 'center', 'center', mode, scale)
+ : offset
// horizontal offset, current ribbon...
this.getRibbon(target)
.css({
- left: offset.left
+ left: offset.left / scale,
})
return this
},
// XXX
- fitNImages: function(n){
- // XXX
+ fitImage: function(n){
+ n = n == null ? 1 : n
+
+ var scale = this.getScreenWidthImages(1) / n
+
+ this
+ .setScale(scale)
+ //.centerRibbon(null, null, scale)
+ //.centerImage(null, null, null, scale)
+
+ return this
},
diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js
index 06a2ce66..848a52bc 100755
--- a/ui (gen4)/ui.js
+++ b/ui (gen4)/ui.js
@@ -88,6 +88,12 @@ module.GLOBAL_KEYBOARD = {
}),
*/
'ctrl+shift': 'F5',
+
+ // XXX testing...
+ ctrl: function(){
+ event.preventDefault()
+ a.reverseImages()
+ },
},
P: {
'ctrl+shift': 'F12',
@@ -104,20 +110,33 @@ module.GLOBAL_KEYBOARD = {
},
// XXX testing...
- Home: doc('', function(){ a.firstImage() }),
- End: doc('', function(){ a.lastImage() }),
- Left: doc('', function(){ a.prevImage() }),
- Right: doc('', function(){ a.nextImage() }),
+ Home: function(){ a.firstImage() },
+ End: function(){ a.lastImage() },
+ Left: {
+ default: function(){ a.prevImage() },
+ alt: function(){ a.shiftImageLeft() },
+ },
+ Right: {
+ default: function(){ a.nextImage() },
+ alt: function(){ a.shiftImageRight() },
+ },
Up: {
- default: doc('', function(){ a.prevRibbon() }),
- shift: doc('', function(){ a.shiftImageUp() }),
- 'ctrl+shift': doc('', function(){ a.shiftImageUpNewRibbon() }),
+ default: function(){ a.prevRibbon() },
+ shift: function(){ a.shiftImageUp() },
+ 'ctrl+shift': function(){ a.shiftImageUpNewRibbon() },
},
Down: {
- default: doc('', function(){ a.nextRibbon() }),
- shift: doc('', function(){ a.shiftImageDown() }),
- 'ctrl+shift': doc('', function(){ a.shiftImageDownNewRibbon() }),
- }
+ default: function(){ a.nextRibbon() },
+ shift: function(){ a.shiftImageDown() },
+ 'ctrl+shift': function(){ a.shiftImageDownNewRibbon() },
+ },
+ '#0': function(){ a.fitImage(20) },
+ '#1': function(){ a.fitOrig() },
+ '#2': function(){ a.fitTwo() },
+ '#3': function(){ a.fitThree() },
+ '#4': function(){ a.fitFour() },
+ '#5': function(){ a.fitFive() },
+
},
}
diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js
index 5f20e78e..65cbdfc4 100755
--- a/ui (gen4)/viewer.js
+++ b/ui (gen4)/viewer.js
@@ -132,9 +132,21 @@ actions.Actions({
function(target){
var data = this.data
var r = data.getRibbon(target)
- var t = data.getImage('current', r)
- // XXX is there a 'last' special case???
- t = t == null ? data.getImage('first', r) : t
+ if(r == null){
+ return
+ }
+ var c = data.getRibbonOrder()
+ var i = data.getRibbonOrder(r)
+
+ // NOTE: we are not changing the direction here based on
+ // this.direction as swap will confuse the user...
+ var direction = c < i ? 'before' : 'after'
+
+ var t = data.getImage(r, direction)
+
+ // if there are no images in the requied direction, try the
+ // other way...
+ t = t == null ? data.getImage(r, direction == 'before' ? 'after' : 'before') : t
this.focusImage(t, r)
}],
@@ -183,6 +195,9 @@ actions.Actions({
+'will shift to the next or previous image in the current '
+'ribbon depending on current direction.',
function(target){
+ // stop transitions...
+ this.ribbons.preventTransitions()
+
// by default we need to update the current position...
if(target == null){
var direction = this.direction == 'right' ? 'next' : 'prev'
@@ -200,12 +215,20 @@ actions.Actions({
} else {
this.data.shiftImageUp(target)
}
+
+ // restore transitions...
+ return function(){
+ this.ribbons.restoreTransitions()
+ }
}],
shiftImageDown: ['Shift image down',
'If implicitly shifting current image (i.e. no arguments), focus '
+'will shift to the next or previous image in the current '
+'ribbon depending on current direction.',
function(target){
+ // stop transitions...
+ this.ribbons.preventTransitions()
+
// by default we need to update the current position...
if(target == null){
var direction = this.direction == 'right' ? 'next' : 'prev'
@@ -223,6 +246,11 @@ actions.Actions({
} else {
this.data.shiftImageDown(target)
}
+
+ // restore transitions...
+ return function(){
+ this.ribbons.restoreTransitions()
+ }
}],
shiftImageUpNewRibbon: ['Shift image up to a new empty ribbon',
function(target){
@@ -269,9 +297,8 @@ actions.Actions({
// XXX
sortImages: [
function(){ }],
- // XXX
reverseImages: [
- function(){ }],
+ function(){ this.data.reverseImages() }],
// basic image editing...
@@ -288,6 +315,9 @@ actions.Actions({
// crop...
+ //
+ // XXX
+
})
@@ -400,6 +430,51 @@ actions.Actions(Client, {
// XXX
}],
+ // zooming...
+ // XXX
+ zoomIn: ['Zoom in',
+ function(){ }],
+ zoomOut: ['Zoom out',
+ function(){ }],
+
+ fitOrig: ['Fit to original scale',
+ function(){ this.ribbons.setScale(1) }],
+
+ // NOTE: if this gets a count argument it will fit count images,
+ // default is one.
+ // XXX animation broken for this...
+ fitImage: ['Fit image',
+ function(count){
+ this.ribbons.fitImage(count)
+ this.ribbons.updateImage('*')
+ //this.focusImage()
+ }],
+
+ // XXX should these be relative to screen rather than actual image counts?
+ fitTwo: ['Fit two images', function(){ this.fitImage(2) }],
+ fitThree: ['Fit three images', function(){ this.fitImage(3) }],
+ fitFour: ['Fit four images', function(){ this.fitImage(4) }],
+ fitFive: ['Fit five images', function(){ this.fitImage(5) }],
+ fitSix: ['Fit six images', function(){ this.fitImage(6) }],
+ fitSeven: ['Fit seven images', function(){ this.fitImage(7) }],
+ fitEight: ['Fit eight images', function(){ this.fitImage(8) }],
+ fitNine: ['Fit nine images', function(){ this.fitImage(9) }],
+
+ // XXX
+ fitMax: ['Fit the maximum number of images',
+ function(){ }],
+
+ // XXX
+ fitSmall: ['Show small image',
+ function(){ }],
+ // XXX
+ fitNormal: ['Show normal image',
+ function(){ }],
+ // XXX
+ fitScreen: ['Fit image to screen',
+ function(){ }],
+
+
// XXX
shiftImageUp: [
function(target){
@@ -415,16 +490,11 @@ actions.Actions(Client, {
this.reload()
}
}],
- /* XXX these are not needed when reloading in .shiftImageUp(..) / .shiftImageDown(..)...
- shiftImageUpNewRibbon: [
- function(target){
- // XXX only create a new ribbon...
- }],
- shiftImageDownNewRibbon: [
- function(target){
- // XXX only create a new ribbon...
- }],
- */
+
+ // NOTE: .shiftImageDownNewRibbon(..) and .shiftImageUpNewRibbon(..)
+ // are not needed here when doing a reload on vertical
+ // shifting...
+
shiftImageLeft: [
function(target){
this.ribbons.placeImage(target, -1)
@@ -442,6 +512,17 @@ actions.Actions(Client, {
function(target){
// XXX
}],
+
+ reverseImages: [
+ function(){
+ this.ribbons.preventTransitions()
+ return function(){
+ this.reload()
+ this.ribbons.restoreTransitions()
+ }
+ }],
+
+
})