From e2931cf62ae445c804ea20e05caa00f23b4ec44f Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 29 Oct 2014 23:38:27 +0300 Subject: [PATCH] added partial ribbon loading feature (needs revision) + several tweaks and fixes... Signed-off-by: Alex A. Naanou --- ui (gen4)/data.js | 2 - ui (gen4)/index.html | 4 +- ui (gen4)/ribbons.js | 108 ++++++++++++++++++++++++++++++------------- ui (gen4)/ui.js | 1 + ui (gen4)/viewer.js | 97 ++++++++++++++++++++++++++++++++++---- 5 files changed, 166 insertions(+), 46 deletions(-) diff --git a/ui (gen4)/data.js b/ui (gen4)/data.js index bf393956..acd9998c 100755 --- a/ui (gen4)/data.js +++ b/ui (gen4)/data.js @@ -1452,8 +1452,6 @@ module.DataPrototype = { // NOTE: this will not affect the original data object... // NOTE: this may result in empty ribbons... // NOTE: this will not crop the .order... - // - // XXX should this link to .root and .parent data??? crop: function(list, flatten){ var crop = this.clone() list = crop.makeSparseImages(list) diff --git a/ui (gen4)/index.html b/ui (gen4)/index.html index 55691a10..e9f7d5fe 100755 --- a/ui (gen4)/index.html +++ b/ui (gen4)/index.html @@ -60,7 +60,7 @@ } /* basic animation... */ -.viewer:not(.no-transitions) .ribbon-set { +.viewer:not(.no-transitions) .ribbon-set:not(.no-transitions) { -webkit-transition: all 0.2s linear, transform 0.2s linear; -moz-transition: all 0.2s linear, transform 0.2s linear; -ms-transition: all 0.2s linear, transform 0.2s linear; @@ -68,7 +68,7 @@ transition: all 0.2s linear, transform 0.2s linear; } -.viewer:not(.no-transitions) .ribbon { +.viewer:not(.no-transitions) .ribbon:not(.no-transitions) { -webkit-transition: all 0.2s ease-out; -moz-transition: all 0.2s ease-out; -ms-transition: all 0.2s ease-out; diff --git a/ui (gen4)/ribbons.js b/ui (gen4)/ribbons.js index c8bafd51..0ad8cfee 100755 --- a/ui (gen4)/ribbons.js +++ b/ui (gen4)/ribbons.js @@ -127,43 +127,55 @@ module.RibbonsPrototype = { // Helpers... // XXX need a better way of doing this... - preventTransitions: function(){ - this.viewer.addClass('no-transitions') - var v = this.viewer[0] - getComputedStyle(v).webkitTransition - getComputedStyle(v).mozTransition - getComputedStyle(v).msTransition - getComputedStyle(v).oTransition - getComputedStyle(v).transition + preventTransitions: function(target){ + target = target || this.viewer + target.addClass('no-transitions') + var t = target[0] + getComputedStyle(t).webkitTransition + getComputedStyle(t).mozTransition + getComputedStyle(t).msTransition + getComputedStyle(t).oTransition + getComputedStyle(t).transition + + return this }, - restoreTransitions: function(now){ + restoreTransitions: function(target, now){ + if(target === true || target === false){ + now = target + target = this.viewer + } else { + target = target || this.viewer + } // sync... if(now){ - this.viewer.removeClass('no-transitions') - var v = this.viewer[0] - getComputedStyle(v).webkitTransition - getComputedStyle(v).mozTransition - getComputedStyle(v).msTransition - getComputedStyle(v).oTransition - getComputedStyle(v).transition + target.removeClass('no-transitions') + var t = target[0] + getComputedStyle(t).webkitTransition + getComputedStyle(t).mozTransition + getComputedStyle(t).msTransition + getComputedStyle(t).oTransition + getComputedStyle(t).transition // on next exec frame... } else { var that = this setTimeout(function(){ - that.viewer.removeClass('no-transitions')}, 0) - var v = that.viewer[0] - getComputedStyle(v).webkitTransition - getComputedStyle(v).mozTransition - getComputedStyle(v).msTransition - getComputedStyle(v).oTransition - getComputedStyle(v).transition + target.removeClass('no-transitions')}, 0) + var t = target[0] + getComputedStyle(t).webkitTransition + getComputedStyle(t).mozTransition + getComputedStyle(t).msTransition + getComputedStyle(t).oTransition + getComputedStyle(t).transition } + + return this }, noTransitions: function(func){ this.preventTransitions() func.apply(this, args2array(arguments).slice(1)) this.restoreTransitions(true) + return this }, @@ -927,12 +939,18 @@ module.RibbonsPrototype = { // This will reuse the images that already exist, thus if updating or // adding images to an already loaded set this should be very fast. // - // NOTE: gids and ribbon must be .getImage(..) and .getRibbon(..) - // compatible... + // If reference is given then this will compensate ribbon offset to + // keep the reference image in the same position (XXX ???) // - // XXX at this point this expects gids to be a list of gids, need - // to make this compatible with jQuery collections... - updateRibbon: function(gids, ribbon){ + // gids must be a list of gids. + // + // ribbons must be .getRibbon(..) compatible. + // + // reference must be .getImage(..) compatible. + // + // XXX should this compensate for load offset??? + // XXX need to make this animation-neutral... + updateRibbon: function(gids, ribbon, reference){ var that = this // get/create the ribbon... var r = this.getRibbon(ribbon) @@ -942,17 +960,40 @@ module.RibbonsPrototype = { } var loaded = r.find('.image') + var unload = $() + + // compensate for new/removed images... + // XXX need to make this animation-neutral... + if(reference != null){ + var ref = this.getImage(reference) + + // align only if ref is loaded... + // XXX + if(ref.length > 0){ + var gid = this.getElemGID(ref) + var w = ref.outerWidth() + + // calculate offset... + // NOTE: this will not work for non-square images... + var dl = loaded.index(ref) - gids.indexOf(gid) + + if(dl != 0){ + r.css({left: parseFloat(r.css('left')) + dl * w}) + } + } + } // remove all images that we do not need... loaded = loaded .filter(function(i, img){ - // XXX .indexOf(..) will not work for a jQuery collection... if(gids.indexOf(that.getElemGID($(img))) >= 0){ return true } - $(img).remove() + unload.push(img) return false }) + // remove everything in one go... + unload.remove() $(gids).each(function(i, gid){ // support for sparse ribbons... @@ -990,12 +1031,13 @@ module.RibbonsPrototype = { that.updateImage(img) }) + /* // remove the rest of the stuff in ribbon... if(loaded.length > gids.length){ - loaded.eq(gids.length).nextAll().remove() - loaded.eq(gids.length).remove() + loaded.eq(gids.length-1).nextAll().remove() } - + */ + return this }, diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js index b6c29179..6d2158c1 100755 --- a/ui (gen4)/ui.js +++ b/ui (gen4)/ui.js @@ -172,6 +172,7 @@ $(function(){ //viewer.RibbonAlignToFirst.setup(a) viewer.ShiftAnimation.setup(a) viewer.BoundsIndicators.setup(a) + viewer.PartialRibbons.setup(a) // this publishes all the actions... //module.GLOBAL_KEYBOARD.__proto__ = a diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js index ee3c9bdd..ff8e734f 100755 --- a/ui (gen4)/viewer.js +++ b/ui (gen4)/viewer.js @@ -540,7 +540,7 @@ actions.Actions(Client, { : data.getImage(target) // align current ribbon... - ribbons + this .centerRibbon(gid) .centerImage(gid) @@ -565,9 +565,9 @@ actions.Actions(Client, { if(f == null){ continue } - ribbons.centerImage(f, 'before') + this.centerImage(f, 'before') } else { - ribbons.centerImage(t, 'after') + this.centerImage(t, 'after') } } }], @@ -585,7 +585,7 @@ actions.Actions(Client, { : data.getImage(target) // align current ribbon... - ribbons + this .centerRibbon(gid) .centerImage(gid) @@ -607,20 +607,28 @@ actions.Actions(Client, { if(f == null){ continue } - ribbons.centerImage(f, 'before') + this.centerImage(f, 'before') } }], // NOTE: this will align only a single image... - centerImage: ['Center image', + // XXX do we need these low level primitives here??? + centerImage: ['Center an image in ribbon horizontally', + function(target, align){ + target = target instanceof jQuery + ? this.ribbons.getElemGID(target) + : target + + // align current ribbon... + this.ribbons.centerImage(target, align) + }], + centerRibbon: ['Center a ribbon vertically', function(target){ target = target instanceof jQuery ? this.ribbons.getElemGID(target) : target // align current ribbon... - this.ribbons - .centerRibbon(target) - .centerImage(target) + this.ribbons.centerRibbon(target) }], // XXX skip invisible ribbons (???) @@ -897,6 +905,73 @@ function Feature(obj){ +// XXX revise... +var PartialRibbons = +module.PartialRibbons = Feature({ + tag: 'ui-partial-ribbons', + + // number of screen widths to load... + size: 5, + + // number of screen widths to edge to trigger reload... + threshold: 1, + + setup: function(actions){ + var feature = this + + var updateRibbon = function(target, w){ + target = target instanceof jQuery + ? this.ribbons.getElemGID(target) + : this.data.getImage(target) + + w = w || this.screenwidth + + var s = feature.size * w + var t = feature.threshold * w + + // next/prev loaded... + var nl = this.ribbons.getImage(target).nextAll('.image').length + var pl = this.ribbons.getImage(target).prevAll('.image').length + + // next/prev available... + var na = this.data.getImages(target, s/2, 'after').length - 1 + var pa = this.data.getImages(target, s/2, 'before').length - 1 + + // the target is not loaded... + if(this.ribbons.getImage(target).length == 0 + // passed threshold on the right... + || (nl < t && na > nl) + // passed threshold on the left... + || (pl < t && pa > pl) + // loaded more than we need by threshold... + || nl + pl + 1 > s + t){ + + // localize transition prevention... + // NOTE: we can't get ribbon via target directly here as + // the target might not be loaded... + var r = this.ribbons.getRibbon(this.data.getRibbon(target)) + + this.ribbons + .preventTransitions(r) + .updateRibbon( + this.data.getImages(target, s), + this.data.getRibbon(target), + target) + .restoreTransitions(r, true) + } + } + + return actions + .on('focusImage.pre centerImage.pre', this.tag, function(target){ + return updateRibbon.call(this, target) + }) + .on('fitImage.pre', this.tag, function(n){ + return updateRibbon.call(this, 'current', n || 1) + }) + }, +}) + + // XXX need a better name... // XXX this should also define up/down navigation behavior... var RibbonAlignToOrder = @@ -905,6 +980,7 @@ module.RibbonAlignToOrder = Feature({ setup: function(actions){ return actions + // XXX this can be either pre or post... .on('focusImage.post', this.tag, function(target){ this.alignByOrder(target) }) @@ -921,6 +997,7 @@ module.RibbonAlignToFirst = Feature({ setup: function(actions){ return actions + // XXX this can be either pre or post... .on('focusImage.post', this.tag, function(target){ this.alignByFirst(target) }) @@ -969,6 +1046,8 @@ module.CurrentIndicator = Feature({ }) +// XXX should we keep actions in a closure (like it is done here) or get +// them live as in PartialRibbons??? var BoundsIndicators = module.BoundsIndicators = Feature({ tag: 'ui-bounds-indicators',