diff --git a/ui/data.js b/ui/data.js
index d187f62b..fb06f9a8 100755
--- a/ui/data.js
+++ b/ui/data.js
@@ -20,6 +20,7 @@
// For more info see:
// DATA - main data
// IMAGES - image data
+// STUB_IMAGE_DATA - single image data stub
// MARKED - marks data
// BOOKMARKS - bookmarks data
// BOOKMARKS_DATA - bookmarks metadata
@@ -232,88 +233,6 @@ var DATA = {
image_file: null
}
-// A stub image, also here for documentation...
-var STUB_IMAGE_DATA = {
- // Entity GID...
- id: 'STUB-GID',
-
- // Entity type
- //
- // can be:
- // - 'image'
- // - 'group'
- type: 'image',
-
- // Entity state
- //
- // can be:
- // - 'single'
- // - 'grouped'
- // - 'hidden'
- // - ...
- state: 'single',
-
- // Creation time...
- ctime: 0,
-
- // Original path...
- path: './images/sizes/900px/SIZE.jpg',
-
- // Previews...
- // NOTE: the actual values depend on specific image and can be
- // any size...
- preview: {
- '150px': './images/sizes/150px/SIZE.jpg',
- '350px': './images/sizes/350px/SIZE.jpg',
- '900px': './images/sizes/900px/SIZE.jpg',
- },
-
- // Classes
- // XXX currently unused...
- classes: '',
-
- // Image orientation (optional)
- //
- // can be:
- // - null/undefined - same as 0
- // - 0 (default) - load as-is
- // - 90 - rotate 90deg CW
- // - 180 - rotate 180deg CW
- // - 270 - rotate 270deg CW (90deg CCW)
- //
- // NOTE: use orientationExif2ImageGrid(..) to convert from EXIF
- // orientation format to ImageGrid format...
- orientation: 0,
-
- // Image flip state (optional)
- //
- // can be:
- // - null/undefined
- // - array
- //
- // can contain:
- // - 'vertical'
- // - 'horizontal'
- //
- // NOTE: use orientationExif2ImageGrid(..) to convert from EXIF
- // orientation format to ImageGrid format...
- flipped: null,
-
- // Image comment (optional)
- //
- // can be:
- // - null/undefined
- // - string
- comment: null,
-
- // List of image tags (optional)
- //
- // can be:
- // - null/undefined
- // - array
- tags: null,
-}
-
// The images object, this is indexed by image GID and contains all
// the needed data...
//
@@ -330,15 +249,6 @@ var IMAGES_UPDATED = []
var BASE_URL = '.'
-// List of function that update image state...
-//
-// these are called by updateImage(..) after the image is created.
-//
-// each function must be of the form:
-// updateImage(gid, image) -> image
-//
-var IMAGE_UPDATERS = []
-
/**********************************************************************
@@ -2000,183 +1910,6 @@ function shiftRibbonsBy(n, gid, data){
* Loaders
*/
-// Run all the image update functions registered in IMAGE_UPDATERS, on
-// an image...
-//
-function updateImageIndicators(gid, image){
- gid = gid == null ? getImageGID() : gid
- image = image == null ? getImage() : $(image)
-
- IMAGE_UPDATERS.forEach(function(update){
- update(gid, image)
- })
-
- return image
-}
-
-
-// helper...
-function _loadImagePreviewURL(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 an image element
-//
-// 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...
-function updateImage(image, gid, size, sync){
- image = image == null ? getImage() : $(image)
- sync = sync == null ? CONFIG.load_img_sync : sync
- var old_gid = getImageGID(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')){
- getImageMarks(old_gid).remove()
- }
- // reset gid...
- image
- .attr('gid', JSON.stringify(gid))
- .css({
- // clear the old preview...
- 'background-image': '',
- })
- }
- size = size == null ? getVisibleImageSize('max') : size
-
- // get the image data...
- var img_data = 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 = 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){
- _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(){
- _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...
- correctImageProportionsForRotation(image)
-
- // marks and other indicators...
- updateImageIndicators(gid, image)
-
- return image
-}
-
-
-// Same as updateImage(...) but will update all loaded images.
-//
-// If list is passed this will update only the images in the list. The
-// list can contain either gids or image elements.
-//
-// If CONFIG.update_sort_enabled is set, this will prioritize images by
-// distance from current image, loading the closest images first...
-//
-// If CONFIG.update_sync is set, this will run asynchronously.
-function updateImages(list, size, cmp){
- var deferred = $.Deferred()
-
- function _worker(){
- list = list == null ? $('.image') : $(list)
- size = size == null ? getVisibleImageSize('max') : size
-
- function _update(_, e){
- var img = typeof(e) == typeof('str') ? getImage(e) : $(e)
- if(img.length > 0){
- updateImage(img, null, size)
- }
- }
-
- // sorted run...
- if(CONFIG.update_sort_enabled && cmp != false){
- cmp = cmp == null ?
- makeGIDDistanceCmp(getImageGID(), function(e){
- return typeof(e) == typeof('str') ? e : getImageGID(e)
- })
- // XXX this is more correct but is slow...
- //makeGIDRibbonDistanceCmp(getImageGID(), getImageGID)
- : cmp
- deferred.resolve(list
- // sort images by distance from current, so as to update what
- // the user is looking at first...
- .sort(cmp)
- .map(_update))
-
- // do a fast run w.o. sorting images...
- } else {
- deferred.resolve(list.map(_update))
- }
- }
-
- if(CONFIG.update_sync){
- _worker()
- } else {
- setTimeout(_worker, 0)
- }
-
- return deferred
-}
-
-
// Load count images around a given image/gid into the given ribbon.
//
// This is similar to getGIDsAround(..) but will load images into the
diff --git a/ui/image.js b/ui/image.js
new file mode 100755
index 00000000..98efed7f
--- /dev/null
+++ b/ui/image.js
@@ -0,0 +1,284 @@
+/**********************************************************************
+*
+*
+*
+**********************************************************************/
+
+// A stub image, also here for documentation...
+var STUB_IMAGE_DATA = {
+ // Entity GID...
+ id: 'STUB-GID',
+
+ // Entity type
+ //
+ // can be:
+ // - 'image'
+ // - 'group'
+ type: 'image',
+
+ // Entity state
+ //
+ // can be:
+ // - 'single'
+ // - 'grouped'
+ // - 'hidden'
+ // - ...
+ state: 'single',
+
+ // Creation time...
+ ctime: 0,
+
+ // Original path...
+ path: './images/sizes/900px/SIZE.jpg',
+
+ // Previews...
+ // NOTE: the actual values depend on specific image and can be
+ // any size...
+ preview: {
+ '150px': './images/sizes/150px/SIZE.jpg',
+ '350px': './images/sizes/350px/SIZE.jpg',
+ '900px': './images/sizes/900px/SIZE.jpg',
+ },
+
+ // Classes
+ // XXX currently unused...
+ classes: '',
+
+ // Image orientation (optional)
+ //
+ // can be:
+ // - null/undefined - same as 0
+ // - 0 (default) - load as-is
+ // - 90 - rotate 90deg CW
+ // - 180 - rotate 180deg CW
+ // - 270 - rotate 270deg CW (90deg CCW)
+ //
+ // NOTE: use orientationExif2ImageGrid(..) to convert from EXIF
+ // orientation format to ImageGrid format...
+ orientation: 0,
+
+ // Image flip state (optional)
+ //
+ // can be:
+ // - null/undefined
+ // - array
+ //
+ // can contain:
+ // - 'vertical'
+ // - 'horizontal'
+ //
+ // NOTE: use orientationExif2ImageGrid(..) to convert from EXIF
+ // orientation format to ImageGrid format...
+ flipped: null,
+
+ // Image comment (optional)
+ //
+ // can be:
+ // - null/undefined
+ // - string
+ comment: null,
+
+ // List of image tags (optional)
+ //
+ // can be:
+ // - null/undefined
+ // - array
+ tags: null,
+}
+
+
+// List of function that update image state...
+//
+// these are called by updateImage(..) after the image is created.
+//
+// each function must be of the form:
+// updateImage(gid, image) -> image
+//
+var IMAGE_UPDATERS = []
+
+
+
+/*********************************************************************/
+
+// Run all the image update functions registered in IMAGE_UPDATERS, on
+// an image...
+//
+function updateImageIndicators(gid, image){
+ gid = gid == null ? getImageGID() : gid
+ image = image == null ? getImage() : $(image)
+
+ IMAGE_UPDATERS.forEach(function(update){
+ update(gid, image)
+ })
+
+ return image
+}
+
+
+// helper...
+function _loadImagePreviewURL(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 an image element
+//
+// 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...
+function updateImage(image, gid, size, sync){
+ image = image == null ? getImage() : $(image)
+ sync = sync == null ? CONFIG.load_img_sync : sync
+ var old_gid = getImageGID(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')){
+ getImageMarks(old_gid).remove()
+ }
+ // reset gid...
+ image
+ .attr('gid', JSON.stringify(gid))
+ .css({
+ // clear the old preview...
+ 'background-image': '',
+ })
+ }
+ size = size == null ? getVisibleImageSize('max') : size
+
+ // get the image data...
+ var img_data = 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 = 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){
+ _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(){
+ _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...
+ correctImageProportionsForRotation(image)
+
+ // marks and other indicators...
+ updateImageIndicators(gid, image)
+
+ return image
+}
+
+
+// Same as updateImage(...) but will update all loaded images.
+//
+// If list is passed this will update only the images in the list. The
+// list can contain either gids or image elements.
+//
+// If CONFIG.update_sort_enabled is set, this will prioritize images by
+// distance from current image, loading the closest images first...
+//
+// If CONFIG.update_sync is set, this will run asynchronously.
+function updateImages(list, size, cmp){
+ var deferred = $.Deferred()
+
+ function _worker(){
+ list = list == null ? $('.image') : $(list)
+ size = size == null ? getVisibleImageSize('max') : size
+
+ function _update(_, e){
+ var img = typeof(e) == typeof('str') ? getImage(e) : $(e)
+ if(img.length > 0){
+ updateImage(img, null, size)
+ }
+ }
+
+ // sorted run...
+ if(CONFIG.update_sort_enabled && cmp != false){
+ cmp = cmp == null ?
+ makeGIDDistanceCmp(getImageGID(), function(e){
+ return typeof(e) == typeof('str') ? e : getImageGID(e)
+ })
+ // XXX this is more correct but is slow...
+ //makeGIDRibbonDistanceCmp(getImageGID(), getImageGID)
+ : cmp
+ deferred.resolve(list
+ // sort images by distance from current, so as to update what
+ // the user is looking at first...
+ .sort(cmp)
+ .map(_update))
+
+ // do a fast run w.o. sorting images...
+ } else {
+ deferred.resolve(list.map(_update))
+ }
+ }
+
+ if(CONFIG.update_sync){
+ _worker()
+ } else {
+ setTimeout(_worker, 0)
+ }
+
+ return deferred
+}
+
+
+
+
+
+/**********************************************************************
+* vim:set ts=4 sw=4 : */
diff --git a/ui/index.html b/ui/index.html
index 424c859f..be5b3dff 100755
--- a/ui/index.html
+++ b/ui/index.html
@@ -30,6 +30,7 @@
+