Browse Source

Simplify visibility/sticky to use .load instead of worrying about each image loading

pull/2034/head
jlukic 10 years ago
parent
commit
360f9ddbd7
3 changed files with 91 additions and 39 deletions
  1. 2
      RELEASE-NOTES.md
  2. 89
      src/definitions/behaviors/visibility.js
  3. 39
      src/definitions/modules/sticky.js

2
RELEASE-NOTES.md

@ -4,6 +4,8 @@
**Enhancements**
- **Grid** - `equal height` and `equal width` now work without `row` wrappers
- **Visibility/Sticky** - Visibility now uses pub/sub pattern to greatly improve scroll performance when attaching multiple events
- **Visibility/Sticky** - Visibility and sticky now refresh automatically after page content loading to deal with changes in position from images loading
**Bugs**
- **All Modules** - Performance logging now delays 500ms instead of 100ms for console logging to ensure all logs are captured in one group

89
src/definitions/behaviors/visibility.js

@ -44,7 +44,6 @@ $.fn.visibility = function(parameters) {
$window = $(window),
$module = $(this),
$context = $(settings.context),
$images = $module.find('img'),
selector = $module.selector || '',
instance = $module.data(moduleNamespace),
@ -100,8 +99,8 @@ $.fn.visibility = function(parameters) {
.off(eventNamespace)
.removeData(moduleNamespace)
;
$window.off('resize' + eventNamespace, module.event.refresh);
$context.off('scroll' + eventNamespace, module.event.scroll);
$window.off(eventNamespace);
$context.off('scrollchange');
},
observeChanges: function() {
@ -125,17 +124,19 @@ $.fn.visibility = function(parameters) {
events: function() {
module.verbose('Binding visibility events to scroll and resize');
$window
.on('load' + eventNamespace, module.event.refresh)
.on('resize' + eventNamespace, module.event.refresh)
;
// pub/sub pattern
$context
.off('scroll' + eventNamespace)
.on('scroll' + eventNamespace, module.event.scroll)
.on('scrollchange' + eventNamespace, module.event.scrollchange)
;
if($images.length > 0) {
module.bind.imageLoad();
}
},
imageLoad: function() {
var
$images = $module.find('img'),
imageCount = $images.length,
index = imageCount,
loadedCount = 0,
@ -150,17 +151,19 @@ $.fn.visibility = function(parameters) {
}
}
;
$images
.each(function() {
images.push( $(this).attr('src') );
})
;
while(index--) {
cacheImage = document.createElement('img');
cacheImage.onload = handleLoad;
cacheImage.onerror = handleLoad;
cacheImage.src = images[index];
cache.push(cacheImage);
if(imageCount > 0) {
$images
.each(function() {
images.push( $(this).attr('src') );
})
;
while(index--) {
cacheImage = document.createElement('img');
cacheImage.onload = handleLoad;
cacheImage.onerror = handleLoad;
cacheImage.src = images[index];
cache.push(cacheImage);
}
}
}
},
@ -169,19 +172,50 @@ $.fn.visibility = function(parameters) {
refresh: function() {
requestAnimationFrame(module.refresh);
},
// published event
scroll: function() {
module.verbose('Scroll position changed');
if(settings.throttle) {
clearTimeout(module.timer);
module.timer = setTimeout(function() {
module.checkVisibility();
$context.trigger('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
}, settings.throttle);
}
else {
requestAnimationFrame(function() {
module.checkVisibility();
$context.trigger('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
});
}
},
// subscribed event
scrollchange: function(event, scrollPosition) {
module.checkVisibility(scrollPosition);
},
},
precache: function(images, callback) {
if (!(images instanceof Array)) {
images = [images];
}
var
imagesLength = images.length,
loadedCounter = 0,
cache = [],
cacheImage = document.createElement('img'),
handleLoad = function() {
loadedCounter++;
if (loadedCounter >= images.length) {
if ($.isFunction(callback)) {
callback();
}
}
}
;
while (imagesLength--) {
cacheImage = document.createElement('img');
cacheImage.onload = handleLoad;
cacheImage.onerror = handleLoad;
cacheImage.src = images[imagesLength];
cache.push(cacheImage);
}
},
@ -291,6 +325,7 @@ $.fn.visibility = function(parameters) {
module.reset();
module.save.position();
module.checkVisibility();
settings.onRefresh.call(element);
},
@ -302,11 +337,14 @@ $.fn.visibility = function(parameters) {
}
},
checkVisibility: function() {
checkVisibility: function(scrollPosition) {
module.verbose('Checking visibility of element', module.cache.element);
if( module.is.visible() ) {
// save scroll position
module.save.scroll(scrollPosition);
// update calculations derived from scroll
module.save.calculations();
@ -616,7 +654,6 @@ $.fn.visibility = function(parameters) {
save: {
calculations: function() {
module.verbose('Saving all calculations necessary to determine positioning');
module.save.scroll();
module.save.direction();
module.save.screenCalculations();
module.save.elementCalculations();
@ -629,8 +666,9 @@ $.fn.visibility = function(parameters) {
}
}
},
scroll: function() {
module.cache.scroll = $context.scrollTop() + settings.offset;
scroll: function(scrollPosition) {
scrollPosition = scrollPosition || $context.scrollTop();
module.cache.scroll = scrollPosition;
},
direction: function() {
var
@ -975,6 +1013,9 @@ $.fn.visibility.settings = {
// whether to use mutation observers to follow changes
observeChanges : true,
// whether to refresh calculations after all page images load
refreshOnLoad : true,
// callback should only occur one time
once : true,

39
src/definitions/modules/sticky.js

@ -92,8 +92,8 @@ $.fn.sticky = function(parameters) {
if(observer) {
observer.disconnect();
}
$window.off('resize' + eventNamespace, module.event.resize);
$scroll.off('scroll' + eventNamespace, module.event.scroll);
$window.off('resize' + eventNamespace);
$scroll.off('scrollchange' + eventNamespace);
$module.removeData(moduleNamespace);
},
@ -147,23 +147,31 @@ $.fn.sticky = function(parameters) {
bind: {
events: function() {
$window.on('resize' + eventNamespace, module.event.resize);
$scroll.on('scroll' + eventNamespace, module.event.scroll);
$window
.on('load' + eventNamespace, module.event.refresh)
.on('resize' + eventNamespace, module.event.refresh)
;
// pub/sub pattern
$scroll
.off('scroll' + eventNamespace)
.on('scroll' + eventNamespace, module.event.scroll)
.on('scrollchange' + eventNamespace, module.event.scrollchange)
;
}
},
event: {
resize: function() {
requestAnimationFrame(function() {
module.refresh();
module.stick();
});
refresh: function() {
requestAnimationFrame(module.refresh);
},
scroll: function() {
requestAnimationFrame(function() {
module.stick();
settings.onScroll.call(element);
$scroll.trigger('scrollchange' + eventNamespace, $scroll.scrollTop() );
});
},
scrollchange: function(event, scrollPosition) {
module.stick(scrollPosition);
settings.onScroll.call(element);
}
},
@ -268,6 +276,7 @@ $.fn.sticky = function(parameters) {
: Math.abs(parseInt($module.css('bottom'), 10)) || 0
;
},
elementScroll: function(scroll) {
scroll = scroll || $scroll.scrollTop();
var
@ -369,8 +378,9 @@ $.fn.sticky = function(parameters) {
}
},
stick: function() {
stick: function(scroll) {
var
cachedPosition = scroll || $scroll.scrollTop(),
cache = module.cache,
fits = cache.fits,
element = cache.element,
@ -380,8 +390,8 @@ $.fn.sticky = function(parameters) {
? settings.bottomOffset
: settings.offset,
scroll = {
top : $scroll.scrollTop() + offset,
bottom : $scroll.scrollTop() + offset + window.height
top : cachedPosition + offset,
bottom : cachedPosition + offset + window.height
},
direction = module.get.direction(scroll.top),
elementScroll = module.get.elementScroll(scroll.top),
@ -398,7 +408,6 @@ $.fn.sticky = function(parameters) {
if( module.is.initialPosition() ) {
if(scroll.top >= context.bottom) {
console.log(scroll.top, context.bottom);
module.debug('Element bottom of container');
module.bindBottom();
}

Loading…
Cancel
Save