started the refactoring of image.js -- mostly merging with ribbons.js (not done yet)...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2014-07-28 06:36:02 +04:00
parent f627a2fe1b
commit 3ca05d008f
3 changed files with 345 additions and 83 deletions

View File

@ -171,6 +171,8 @@ function _loadImagePreviewURL(image, url){
// NOTE: care must be taken to reset ALL attributes an image can have,
// a common bug if this is not done correctly, is that some settings
// may leak to newly loaded images...
//
// XXX this calls .correctImageProportionsForRotation(..)
var updateImage =
module.updateImage =
function updateImage(image, gid, size, sync){
@ -317,67 +319,12 @@ function updateImages(list, size, cmp){
}
// 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.
var correctImageProportionsForRotation =
module.correctImageProportionsForRotation =
function correctImageProportionsForRotation(images, container){
container = container == null ? $('.viewer') : container
var W = container.innerWidth()
var H = container.innerHeight()
var viewer_p = W > H ? 'landscape' : 'portrait'
return $(images).each(function(i, e){
var image = $(this)
// orientation...
var o = image.attr('orientation')
o = o == null ? 0 : o
var w = image.outerWidth()
var h = image.outerHeight()
// non-square image...
if(w != h){
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){
image.css({
width: h,
height: w,
})
image.css({
'margin-top': -((w - h)/2),
'margin-bottom': -((w - h)/2),
'margin-left': (w - h)/2,
'margin-right': (w - h)/2,
})
} else if((o == 0 || o == 180) && image_p != viewer_p){
image.css({
width: h,
height: w,
})
image.css({
'margin': '',
})
}
// square image...
} else {
image.css({
'margin': '',
})
}
})
// XXX
}

View File

@ -13,6 +13,49 @@ console.log('>>> images')
/*********************************************************************/
// Calculate relative rotation angle...
//
// Calculate rotation angle relative to from:
// calcRelativeRotation(from, 'cw')
// calcRelativeRotation(from, 'ccw')
// -> 0 | 90 | 180 | 270
//
// Validate an angle:
// calcRelativeRotation(angle)
// calcRelativeRotation(from, angle)
// -> 0 | 90 | 180 | 270
// -> null
//
//
module.calcRelativeRotation = function(from, to){
if(to == null){
to = from
from = 0
}
to = to == 'cw' ? 1
: to == 'ccw' ? -1
: [0, 90, 180, 270].indexOf(to*1) >= 0 ? to*1
: [-90, -180, -270].indexOf(to*1) >= 0 ? 360+(to*1)
: null
// relative rotation...
if(to == 1 || to == -1){
var res = from
res = res == null ? 0 : res*1
res += 90*to
res = res < 0 ? 270
: res > 270 ? 0
: res
// explicit direction...
} else {
var res = to
}
return res
}
// cmp functions...
// XXX is this the right way to seporate these???
@ -174,6 +217,11 @@ module.ImagesPrototype = {
// Image data helpers...
// XXX see: ribbons.js for details...
getBestPreview: function(){
// XXX
},
// Get image filename...
getImageFileName: function(gid, do_unescape){
do_unescape = do_unescape == null ? true : do_unescape
@ -234,6 +282,80 @@ module.ImagesPrototype = {
// XXX see ../ui/sort.js
},
// Actions...
// Rotate image...
//
// Rotate image clockwise:
// .rotateImage(target, 'cw')
// -> images
//
// Rotate image counterclockwise:
// .rotateImage(target, 'ccw')
// -> images
//
// Set explicit image rotation angle:
// .rotateImage(target, 0|90|180|270)
// .rotateImage(target, -90|-180|-270)
// -> images
//
// NOTE: target can be a gid or a list of gids...
rotateImage: function(gids, direction){
gids = gids.constructor.name != 'Array' ? [gids] : gids
// validate direction...
if(module.calcRelativeRotation(direction) == null){
return this
}
var that = this
gids.forEach(function(key){
var img = that[key]
var o = direction == 'cw' || direction == 'ccw'
? module.calcRelativeRotation(img.orientation, direction)
: direction*1
if(o == 0){
delete img.orientation
} else {
img.orientation = o
}
// account for proportions...
//that.correctImageProportionsForRotation(img)
// XXX this is a bit of an overkill but it will update the
// preview if needed...
//that.updateImage(img)
})
return this
},
// Flip image...
//
// .flipImage(target, 'horizontal')
// .flipImage(target, 'vertical')
// -> images
//
flipImage: function(gids, direction){
gids = gids.constructor.name != 'Array' ? [gids] : gids
var that = this
gids.forEach(function(key){
var img = that[key]
var state = img.flipped
state = state == null ? [] : state
// toggle the specific state...
var i = state.indexOf(direction)
if(i >= 0){
state.splice(i, 1)
} else {
state.push(direction)
}
if(state.length == 0){
delete img.flipped
} else {
img.flipped = state
}
})
return this
},
// serialization...
loadJSON: function(data){

View File

@ -18,6 +18,7 @@ require('ext-lib/jquery')
var data = require('data')
var image = require('image')
var images = require('images')
@ -83,6 +84,7 @@ module.RibbonsClassPrototype = {
.replace(/^"(.*)"$/g, '$1'))
},
// XXX NOTE: quots removal might render this incompatible with older data formats...
// XXX should this do .updateImage(..) ???
createImage: function(gid){
gid = gid != null ? gid+'' : gid
return $('<div>')
@ -100,6 +102,8 @@ module.RibbonsPrototype = {
//
// .viewer (jQuery object)
//
// .images (Images object)
//
// XXX to update images we need to know about images...
// Constructors...
@ -333,6 +337,7 @@ module.RibbonsPrototype = {
//
// XXX interaction animation...
// XXX mode is ugly...
// XXX should this be strongly or weakly coupled to images.updateImage(..)???
placeImage: function(target, to, mode){
mode = mode == null ? 'before' : mode
var img = this.getImage(target)
@ -384,6 +389,8 @@ module.RibbonsPrototype = {
//
// NOTE: gids and ribbon must be .getImage(..) and .getRibbon(..)
// compatible...
//
// XXX should this be strongly or weakly coupled to images.updateImage(..)???
updateRibbon: function(gids, ribbon){
// get/create the ribbon...
var r = this.getRibbon(ribbon)
@ -621,6 +628,196 @@ module.RibbonsPrototype = {
},
getImageMarks: function(){
// XXX
},
// XXX this needs:
// IMAGE_UPDATERS -- make it a callback/event (node/jquery)...
updateImageIndicators: function(gid, image){
gid = gid == null ? this.getElemGID() : gid
image = image == null ? this.getImage() : $(image)
IMAGE_UPDATERS.forEach(function(update){
update(gid, image)
})
return image
},
_loadImagePreviewURL: function(image, url){
// pre-cache and load image...
// NOTE: this will make images load without a blackout...
var img = new Image()
img.onload = function(){
image.css({
'background-image': 'url("'+ url +'")',
})
}
img.src = url
return img
},
// Update image{s}...
//
load_img_sync: false,
//
// XXX this needs:
// STUB_IMAGE_DATA
// this.images
// XXX
updateImage: function(image, gid, size, sync){
image = image == null ? this.getImage() : $(image)
sync = sync == null ? this.load_img_sync : sync
var that = this
return image.each(function(){
var image = $(this)
var old_gid = that.getElemGID(image)
// same image -- update...
if(old_gid == gid || gid == null){
gid = old_gid
// reuse for different image -- reconstruct...
} else {
// remove old marks...
if(typeof(old_gid) == typeof('str')){
that.getImageMarks(old_gid).remove()
}
// reset gid...
image
.attr('gid', JSON.stringify(gid)
// this removes the extra quots...
.replace(/^"(.*)"$/g, '$1'))
.css({
// clear the old preview...
'background-image': '',
})
}
size = size == null ? that.getVisibleImageSize('max') : size
// get the image data...
var img_data = that.images[gid]
if(img_data == null){
img_data = STUB_IMAGE_DATA
}
/* XXX does not seem to be needing this...
// set the current class...
if(gid == DATA.current){
image.addClass('current')
} else {
image.removeClass('current')
}
*/
// preview...
var p_url = that.images.getBestPreview(gid, size).url
// update the preview if it's a new image or...
if(old_gid != gid
// the new preview (purl) is different to current...
|| image.css('background-image').indexOf(encodeURI(p_url)) < 0){
// sync load...
if(sync){
that._loadImagePreviewURL(image, p_url)
// async load...
} else {
// NOTE: storing the url in .data() makes the image load the
// last requested preview and in a case when we manage to
// call updateImage(...) on the same element multiple times
// before the previews get loaded...
// ...setting the data().loading is sync while loading an
// image is not, and if several loads are done in sequence
// there is no guarantee that they will happen in the same
// order as requested...
image.data().loading = p_url
setTimeout(function(){
that._loadImagePreviewURL(image, image.data().loading)
}, 0)
}
}
// main attrs...
image
.attr({
//order: DATA.order.indexOf(gid),
orientation: img_data.orientation == null ? 0 : img_data.orientation,
})
// flip...
setImageFlipState(image, img_data.flipped == null ? [] : img_data.flipped)
// NOTE: this only has effect on non-square image blocks...
that.correctImageProportionsForRotation(image)
// marks and other indicators...
that.updateImageIndicators(gid, image)
})
},
// XXX reread...
// 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.
correctImageProportionsForRotation: function(images){
// XXX
var W = this.viewer.innerWidth()
var H = this.viewer.innerHeight()
var viewer_p = W > H ? 'landscape' : 'portrait'
return $(images).each(function(i, e){
var image = $(this)
// orientation...
var o = image.attr('orientation')
o = o == null ? 0 : o
var w = image.outerWidth()
var h = image.outerHeight()
// non-square image...
if(w != h){
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){
image.css({
width: h,
height: w,
})
image.css({
'margin-top': -((w - h)/2),
'margin-bottom': -((w - h)/2),
'margin-left': (w - h)/2,
'margin-right': (w - h)/2,
})
} else if((o == 0 || o == 180) && image_p != viewer_p){
image.css({
width: h,
height: w,
})
image.css({
'margin': '',
})
}
// square image...
} else {
image.css({
'margin': '',
})
}
})
},
// Image manipulation...
// Rotate an image...
@ -633,45 +830,40 @@ module.RibbonsPrototype = {
// .rotateImage(target, 'ccw')
// -> image
//
// Set explicit image rotation angle:
// .rotateImage(target, 0|90|180|270)
// .rotateImage(target, -90|-180|-270)
// -> image
//
// NOTE: target must be .getImage(..) compatible.
// NOTE: this can be applied in bulk, e.g.
// this.rotateImage($('.image'), 'cw') will rotate all the
// loaded images clockwise.
//
// Rotation tables...
_cw: {
null: 90,
0: 90,
90: 180,
180: 270,
//270: 0,
270: null,
},
_ccw: {
null: 270,
0: 270,
//90: 0,
90: null,
180: 90,
270: 180,
},
// NOTE: setting a value to null will remove the attribute, 0 will
// set 0 explicitly...
// XXX should this be strongly or weakly coupled to images.updateImage(..)
// or images.correctImageProportionsForRotation(..)???
// XXX should .correctImageProportionsForRotation(..) be in images???
rotateImage: function(target, direction){
var r_table = direction == 'cw' ? this._cw : this._ccw
target = this.getImage(target)
// validate direction...
if(images.calcRelativeRotation(direction) == null){
return target
}
var that = this
target.each(function(i, e){
var img = $(this)
var o = img.attr('orientation')
o = r_table[ o == null ? null : o ]
if(o == null){
var o = direction == 'cw' || direction == 'ccw'
? images.calcRelativeRotation(img.attr('orientation'), direction)
: direction*1
if(o == 0){
img.removeAttr('orientation')
} else {
img.attr('orientation', o)
}
// account for proportions...
image.correctImageProportionsForRotation(img)
that.correctImageProportionsForRotation(img)
// XXX this is a bit of an overkill but it will update the
// preview if needed...
//image.updateImage(img)
@ -758,8 +950,9 @@ module.RibbonsPrototype = {
},
_setup: function(viewer){
_setup: function(viewer, images){
this.viewer = $(viewer)
this.images = images
},
}
@ -768,13 +961,13 @@ module.RibbonsPrototype = {
//
var Ribbons =
module.Ribbons =
function Ribbons(viewer){
function Ribbons(viewer, images){
// in case this is called as a function (without new)...
if(this.constructor.name != 'Ribbons'){
return new Ribbons(viewer)
}
this._setup(viewer)
this._setup(viewer, images)
return this
}