@bigfishtv/cockpit
Version:
189 lines (142 loc) • 5.15 kB
JavaScript
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* BreadcrumbHandler
* @module Components/BreadCrumbHandler
*/
import $ from 'jquery';
import throttle from 'lodash/throttle';
var headerBuffer = -5; // px, appromixate size before title is shown
var scrollThrottle = 150;
var $window = $(window);
function animateScroll(position) {
var time = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
var ease = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'linear';
var callback = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {};
$('html, body').animate({ scrollTop: position }, time, ease, callback);
}
/**
* Breadcrumb handler class, uses jquery to look at nested breadcrumb data tags and dispatches updates all subscribed callbacks.
* Typically, one instance of this class is created in the global scope so it can be referenced easily
*/
var BreadcrumbHandler = function () {
function BreadcrumbHandler() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, BreadcrumbHandler);
window.breadcrumbs = {
addCallback: this.addCallback.bind(this),
removeCallback: this.removeCallback.bind(this),
scrollTo: this.scrollTo.bind(this),
update: this.update.bind(this)
};
this.breadcrumbs = [];
this.callbacks = [];
this.currentElement = null;
this.headerHeight = config.headerHeight || 90;
$window.scroll(throttle(this.handleScroll.bind(this), scrollThrottle));
}
/**
* Called by something that wants to subscribe to updates
* @param {Function} callback
*/
BreadcrumbHandler.prototype.addCallback = function addCallback(callback) {
this.callbacks.push(callback);
};
/**
* Called by something that wants to unsubscribe from updates
* @param {Function} callback
*/
BreadcrumbHandler.prototype.removeCallback = function removeCallback(callback) {
this.callbacks = this.callbacks.filter(function (cb) {
return cb !== callback;
});
};
/**
* Called when a new breadcrumb wrapper comes into view, dispatches updates to all subscribed callbacks
* @param {jQueryDOM} elem The element currently in view
*/
BreadcrumbHandler.prototype.newFocus = function newFocus(elem) {
if (elem == this.currentElement) return;else this.currentElement = elem;
var trail = this.getCurrentTrail(elem);
for (var _iterator = this.callbacks, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var callback = _ref;
callback(trail);
}
};
/**
* Gets
* @param {jQueryDOM} elem The element to get the breadcrumb trail from
* @return {Object[]} Returns a trail as an array of objects containg title url and elem
*/
BreadcrumbHandler.prototype.getCurrentTrail = function getCurrentTrail(elem) {
if (!elem) {
return [];
}
var $elem = $(elem);
var trail = [{
title: $elem.attr('data-breadcrumb') || 'Untitled',
url: $elem.attr('data-breadcrumb-url'),
elem: elem
}];
$elem.parents('[data-breadcrumb]').each(function (i, crumb) {
var $crumb = $(crumb);
trail.push({
title: $crumb.attr('data-breadcrumb') || 'Untitled',
url: $crumb.attr('data-breadcrumb-url'),
elem: crumb
});
});
trail.reverse();
return trail;
};
/**
* Called on breadcrumb trail segment click, smooth scrolls to relevant section
* @param {jQueryDOM} breadcrumb element to scroll to
*/
BreadcrumbHandler.prototype.scrollTo = function scrollTo(breadcrumb) {
var scrollTop = $window.scrollTop();
var offsetY = $(breadcrumb).offset().top - this.headerHeight - headerBuffer - 1;
if (scrollTop == offsetY) return;
$('[data-breadcrumb-focus]').removeAttr('data-breadcrumb-focus');
animateScroll(offsetY, 500, 'swing', function () {
if (!breadcrumb.active) $(breadcrumb).attr('data-breadcrumb-focus', '');
});
};
BreadcrumbHandler.prototype.update = function update() {
this.currentElement = null;
this.handleScroll();
};
/**
* Called on (throttled) scroll change, gets most visible breadcrumb
*/
BreadcrumbHandler.prototype.handleScroll = function handleScroll() {
var currentElement = null;
var threshold = $window.scrollTop() + this.headerHeight - headerBuffer;
$($('[data-breadcrumb]').get().reverse()).each(function (i, crumb) {
var $crumb = $(crumb);
var top = $crumb.offset().top;
var bottom = top + $crumb.height();
if (threshold >= top && threshold < bottom) {
currentElement = crumb;
return false;
}
});
this.newFocus(currentElement);
};
/**
* Inits breadcrumb handler by calling handleScroll
*/
BreadcrumbHandler.prototype.init = function init() {
this.handleScroll();
};
return BreadcrumbHandler;
}();
export { BreadcrumbHandler as default };