Skip to content

Instantly share code, notes, and snippets.

@MeoMix
Created February 1, 2016 23:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MeoMix/d716a4adcc4bc6f4bdf6 to your computer and use it in GitHub Desktop.
Save MeoMix/d716a4adcc4bc6f4bdf6 to your computer and use it in GitHub Desktop.
import { LayoutView } from 'marionette';
import styles from './application.css!';
import template from './application.hbs!';
import _ from 'lodash';
export default LayoutView.extend({
el: 'main',
template,
templateHelpers: {
styles: styles
},
initialize() {
// Provide a throttled version of _onWindowScroll because event can fire at a high rate.
// https://developer.mozilla.org/en-US/docs/Web/Events/scroll
this._onWindowScroll = _.throttleFramerate(this._onWindowScroll.bind(this));
this._onWindowResize = _.throttleFramerate(this._onWindowResize.bind(this));
window.addEventListener('scroll', this._onWindowScroll);
window.addEventListener('resize', this._onWindowResize);
},
onBeforeDestroy() {
window.removeEventListener('scroll', this._onWindowScroll);
window.removeEventListener('resize', this._onWindowResize);
},
_onWindowScroll() {
App.channels.window.vent.trigger('scroll', {
scrollY: window.scrollY
});
},
_onWindowResize() {
App.channels.window.vent.trigger('resize', {
height: window.innerHeight,
width: window.innerWidth
});
}
});
import { Behavior } from 'marionette';
import _ from 'lodash';
// Lazy load images which are not currently in the viewport to save on bandwidth.
export default Behavior.extend({
defaults: {
// An amount (in px) to trigger showing an image before it is in the viewport.
threshold: 200
},
ui: {
lazyImage: 'lazyImage'
},
_unloadedImages: null,
_windowHeight: 0,
_windowEvents: {
'scroll': '_onWindowScroll',
'resize': '_onWindowResize'
}
initialize() {
this._windowHeight = window.innerHeight;
this.bindEntityEvents(App.channels.window.vent, this._windowEvents);
},
onRender() {
// Cache a copy of the images to load so processing a subset is simple.
this._unloadedImages = Array.from(this.ui.lazyImage);
},
_onWindowScroll() {
this._loadImages();
},
_onWindowResize(event) {
this._windowHeight = event.height;
this._loadImages();
},
_loadImages() {
// Determine which images (if any) need to be loaded.
const threshold = _.result(this, 'defaults').threshold;
const imagesInThreshold = _.filter(this._unloadedImages, (image) => {
return image.getBoundingClientRect().bottom <= this._windowHeight + threshold;
}, this);
// Load images which are within the allowed threshold.
_.each(imagesInThreshold, (image) => {
image.setAttribute('src', image.getAttribute('data-src'));
});
// Stop considering images which have been loaded.
_.remove(this._unloadedImages, (imageElement) => {
return _.contains(imagesInThreshold, imageElement);
});
}
});
import _ from 'lodash';
_.mixin({
// Inspired by: https://gist.github.com/danro/7846358
// Leverage requestAnimationFrame for throttling function calls instead of setTimeout for better perf.
throttleFramerate: function(callback) {
var wait = false;
var args = null;
var context = null;
return function() {
if (!wait) {
wait = true;
args = arguments;
context = this;
window.requestAnimationFrame(function() {
wait = false;
callback.apply(context, args);
});
}
};
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment