diff --git a/README.md b/README.md
index 136460d..49b491f 100644
--- a/README.md
+++ b/README.md
@@ -42,20 +42,26 @@ npm install sticky-sidebar
Your website's html structure has to be similar to this in order to work:
````html
-
-
-
-
-
+
````
Note that inner sidebar wrapper ``.sidebar__innner`` is optional but highly recommended, if you don't write it yourself, the script will create one for you under class name ``inner-wrapper-sticky``. but this may cause many problems.
+If your content is inside a container with scroll, this must be specified with the ``scrollContainerSelector`` option.
+
+If you need native CSS sticky, use the ``nativeSticky`` option.
+
For the above example, you can use the following JavaScript:
````html
@@ -65,8 +71,10 @@ For the above example, you can use the following JavaScript:
var sidebar = new StickySidebar('.sidebar', {
topSpacing: 20,
bottomSpacing: 20,
+ scrollContainerSelector: '.scroll-container',
containerSelector: '.main-content',
- innerWrapperSelector: '.sidebar__inner'
+ innerWrapperSelector: '.sidebar__inner',
+ nativeSticky: true
});
````
diff --git a/bower.json b/bower.json
index dc3a48a..6c551ce 100644
--- a/bower.json
+++ b/bower.json
@@ -1,7 +1,7 @@
{
"name": "sticky-sidebar",
"description": "A JavaScript plugin for making smart and high performance.",
- "version": "3.3.1",
+ "version": "3.3.5",
"authors": [
"Ahmed Bouhuolia
"
],
diff --git a/dist/jquery.sticky-sidebar.js b/dist/jquery.sticky-sidebar.js
index f60442b..2582582 100644
--- a/dist/jquery.sticky-sidebar.js
+++ b/dist/jquery.sticky-sidebar.js
@@ -1,750 +1,810 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
- (global.StickySidebar = factory());
-}(this, (function () { 'use strict';
-
-var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
-
-
-
-function unwrapExports (x) {
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
-}
-
-function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
-}
-
-var stickySidebar = createCommonjsModule(function (module, exports) {
-(function (global, factory) {
- if (typeof undefined === "function" && undefined.amd) {
- undefined(['exports'], factory);
- } else {
- factory(exports);
- }
-})(commonjsGlobal, function (exports) {
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
-
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
-
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
-
- /**
- * Sticky Sidebar JavaScript Plugin.
- * @version 3.3.4
- * @author Ahmed Bouhuolia
- * @license The MIT License (MIT)
- */
- var StickySidebar = function () {
-
- // ---------------------------------
- // # Define Constants
- // ---------------------------------
- //
- var EVENT_KEY = '.stickySidebar';
- var DEFAULTS = {
- /**
- * Additional top spacing of the element when it becomes sticky.
- * @type {Numeric|Function}
- */
- topSpacing: 0,
-
- /**
- * Additional bottom spacing of the element when it becomes sticky.
- * @type {Numeric|Function}
- */
- bottomSpacing: 0,
-
- /**
- * Container sidebar selector to know what the beginning and end of sticky element.
- * @type {String|False}
- */
- containerSelector: false,
-
- /**
- * Inner wrapper selector.
- * @type {String}
- */
- innerWrapperSelector: '.inner-wrapper-sticky',
-
- /**
- * The name of CSS class to apply to elements when they have become stuck.
- * @type {String|False}
- */
- stickyClass: 'is-affixed',
-
- /**
- * Detect when sidebar and its container change height so re-calculate their dimensions.
- * @type {Boolean}
- */
- resizeSensor: true,
-
- /**
- * The sidebar returns to its normal position if its width below this value.
- * @type {Numeric}
- */
- minWidth: false
- };
-
- // ---------------------------------
- // # Class Definition
- // ---------------------------------
- //
- /**
- * Sticky Sidebar Class.
- * @public
- */
-
- var StickySidebar = function () {
-
- /**
- * Sticky Sidebar Constructor.
- * @constructor
- * @param {HTMLElement|String} sidebar - The sidebar element or sidebar selector.
- * @param {Object} options - The options of sticky sidebar.
- */
- function StickySidebar(sidebar) {
- var _this = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- _classCallCheck(this, StickySidebar);
-
- this.options = StickySidebar.extend(DEFAULTS, options);
-
- // Sidebar element query if there's no one, throw error.
- this.sidebar = 'string' === typeof sidebar ? document.querySelector(sidebar) : sidebar;
- if ('undefined' === typeof this.sidebar) throw new Error("There is no specific sidebar element.");
-
- this.sidebarInner = false;
- this.container = this.sidebar.parentElement;
-
- // Current Affix Type of sidebar element.
- this.affixedType = 'STATIC';
- this.direction = 'down';
- this.support = {
- transform: false,
- transform3d: false
- };
-
- this._initialized = false;
- this._reStyle = false;
- this._breakpoint = false;
-
- // Dimensions of sidebar, container and screen viewport.
- this.dimensions = {
- translateY: 0,
- maxTranslateY: 0,
- topSpacing: 0,
- lastTopSpacing: 0,
- bottomSpacing: 0,
- lastBottomSpacing: 0,
- sidebarHeight: 0,
- sidebarWidth: 0,
- containerTop: 0,
- containerHeight: 0,
- viewportHeight: 0,
- viewportTop: 0,
- lastViewportTop: 0
- };
-
- // Bind event handlers for referencability.
- ['handleEvent'].forEach(function (method) {
- _this[method] = _this[method].bind(_this);
- });
-
- // Initialize sticky sidebar for first time.
- this.initialize();
- }
-
- /**
- * Initializes the sticky sidebar by adding inner wrapper, define its container,
- * min-width breakpoint, calculating dimensions, adding helper classes and inline style.
- * @private
- */
-
-
- _createClass(StickySidebar, [{
- key: 'initialize',
- value: function initialize() {
- var _this2 = this;
-
- this._setSupportFeatures();
-
- // Get sticky sidebar inner wrapper, if not found, will create one.
- if (this.options.innerWrapperSelector) {
- this.sidebarInner = this.sidebar.querySelector(this.options.innerWrapperSelector);
-
- if (null === this.sidebarInner) this.sidebarInner = false;
- }
-
- if (!this.sidebarInner) {
- var wrapper = document.createElement('div');
- wrapper.setAttribute('class', 'inner-wrapper-sticky');
- this.sidebar.appendChild(wrapper);
-
- while (this.sidebar.firstChild != wrapper) {
- wrapper.appendChild(this.sidebar.firstChild);
- }this.sidebarInner = this.sidebar.querySelector('.inner-wrapper-sticky');
- }
-
- // Container wrapper of the sidebar.
- if (this.options.containerSelector) {
- var containers = document.querySelectorAll(this.options.containerSelector);
- containers = Array.prototype.slice.call(containers);
-
- containers.forEach(function (container, item) {
- if (!container.contains(_this2.sidebar)) return;
- _this2.container = container;
- });
-
- if (!containers.length) throw new Error("The container does not contains on the sidebar.");
- }
-
- // If top/bottom spacing is not function parse value to integer.
- if ('function' !== typeof this.options.topSpacing) this.options.topSpacing = parseInt(this.options.topSpacing) || 0;
-
- if ('function' !== typeof this.options.bottomSpacing) this.options.bottomSpacing = parseInt(this.options.bottomSpacing) || 0;
-
- // Breakdown sticky sidebar if screen width below `options.minWidth`.
- this._widthBreakpoint();
-
- // Calculate dimensions of sidebar, container and viewport.
- this.calcDimensions();
-
- // Affix sidebar in proper position.
- this.stickyPosition();
-
- // Bind all events.
- this.bindEvents();
-
- // Inform other properties the sticky sidebar is initialized.
- this._initialized = true;
- }
- }, {
- key: 'bindEvents',
- value: function bindEvents() {
- window.addEventListener('resize', this, { passive: true, capture: false });
- window.addEventListener('scroll', this, { passive: true, capture: false });
-
- this.sidebar.addEventListener('update' + EVENT_KEY, this);
-
- if (this.options.resizeSensor && 'undefined' !== typeof ResizeSensor) {
- new ResizeSensor(this.sidebarInner, this.handleEvent);
- new ResizeSensor(this.container, this.handleEvent);
- }
- }
- }, {
- key: 'handleEvent',
- value: function handleEvent(event) {
- this.updateSticky(event);
- }
- }, {
- key: 'calcDimensions',
- value: function calcDimensions() {
- if (this._breakpoint) return;
- var dims = this.dimensions;
-
- // Container of sticky sidebar dimensions.
- dims.containerTop = StickySidebar.offsetRelative(this.container).top;
- dims.containerHeight = this.container.clientHeight;
- dims.containerBottom = dims.containerTop + dims.containerHeight;
-
- // Sidebar dimensions.
- dims.sidebarHeight = this.sidebarInner.offsetHeight;
- dims.sidebarWidth = this.sidebarInner.offsetWidth;
-
- // Screen viewport dimensions.
- dims.viewportHeight = window.innerHeight;
-
- // Maximum sidebar translate Y.
- dims.maxTranslateY = dims.containerHeight - dims.sidebarHeight;
-
- this._calcDimensionsWithScroll();
- }
- }, {
- key: '_calcDimensionsWithScroll',
- value: function _calcDimensionsWithScroll() {
- var dims = this.dimensions;
-
- dims.sidebarLeft = StickySidebar.offsetRelative(this.sidebar).left;
-
- dims.viewportTop = document.documentElement.scrollTop || document.body.scrollTop;
- dims.viewportBottom = dims.viewportTop + dims.viewportHeight;
- dims.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
-
- dims.topSpacing = this.options.topSpacing;
- dims.bottomSpacing = this.options.bottomSpacing;
-
- if ('function' === typeof dims.topSpacing) dims.topSpacing = parseInt(dims.topSpacing(this.sidebar)) || 0;
-
- if ('function' === typeof dims.bottomSpacing) dims.bottomSpacing = parseInt(dims.bottomSpacing(this.sidebar)) || 0;
-
- if ('VIEWPORT-TOP' === this.affixedType) {
- // Adjust translate Y in the case decrease top spacing value.
- if (dims.topSpacing < dims.lastTopSpacing) {
- dims.translateY += dims.lastTopSpacing - dims.topSpacing;
- this._reStyle = true;
- }
- } else if ('VIEWPORT-BOTTOM' === this.affixedType) {
- // Adjust translate Y in the case decrease bottom spacing value.
- if (dims.bottomSpacing < dims.lastBottomSpacing) {
- dims.translateY += dims.lastBottomSpacing - dims.bottomSpacing;
- this._reStyle = true;
- }
- }
-
- dims.lastTopSpacing = dims.topSpacing;
- dims.lastBottomSpacing = dims.bottomSpacing;
- }
- }, {
- key: 'isSidebarFitsViewport',
- value: function isSidebarFitsViewport() {
- var dims = this.dimensions;
- var offset = this.scrollDirection === 'down' ? dims.lastBottomSpacing : dims.lastTopSpacing;
- return this.dimensions.sidebarHeight + offset < this.dimensions.viewportHeight;
- }
- }, {
- key: 'observeScrollDir',
- value: function observeScrollDir() {
- var dims = this.dimensions;
- if (dims.lastViewportTop === dims.viewportTop) return;
-
- var furthest = 'down' === this.direction ? Math.min : Math.max;
-
- // If the browser is scrolling not in the same direction.
- if (dims.viewportTop === furthest(dims.viewportTop, dims.lastViewportTop)) this.direction = 'down' === this.direction ? 'up' : 'down';
- }
- }, {
- key: 'getAffixType',
- value: function getAffixType() {
- this._calcDimensionsWithScroll();
- var dims = this.dimensions;
- var colliderTop = dims.viewportTop + dims.topSpacing;
- var affixType = this.affixedType;
-
- if (colliderTop <= dims.containerTop || dims.containerHeight <= dims.sidebarHeight) {
- dims.translateY = 0;
- affixType = 'STATIC';
- } else {
- affixType = 'up' === this.direction ? this._getAffixTypeScrollingUp() : this._getAffixTypeScrollingDown();
- }
-
- // Make sure the translate Y is not bigger than container height.
- dims.translateY = Math.max(0, dims.translateY);
- dims.translateY = Math.min(dims.containerHeight, dims.translateY);
- dims.translateY = Math.round(dims.translateY);
-
- dims.lastViewportTop = dims.viewportTop;
- return affixType;
- }
- }, {
- key: '_getAffixTypeScrollingDown',
- value: function _getAffixTypeScrollingDown() {
- var dims = this.dimensions;
- var sidebarBottom = dims.sidebarHeight + dims.containerTop;
- var colliderTop = dims.viewportTop + dims.topSpacing;
- var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
- var affixType = this.affixedType;
-
- if (this.isSidebarFitsViewport()) {
- if (dims.sidebarHeight + colliderTop >= dims.containerBottom) {
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
- } else if (colliderTop >= dims.containerTop) {
- dims.translateY = colliderTop - dims.containerTop;
- affixType = 'VIEWPORT-TOP';
- }
- } else {
- if (dims.containerBottom <= colliderBottom) {
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
- } else if (sidebarBottom + dims.translateY <= colliderBottom) {
- dims.translateY = colliderBottom - sidebarBottom;
- affixType = 'VIEWPORT-BOTTOM';
- } else if (dims.containerTop + dims.translateY <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
- affixType = 'VIEWPORT-UNBOTTOM';
- }
- }
-
- return affixType;
- }
- }, {
- key: '_getAffixTypeScrollingUp',
- value: function _getAffixTypeScrollingUp() {
- var dims = this.dimensions;
- var sidebarBottom = dims.sidebarHeight + dims.containerTop;
- var colliderTop = dims.viewportTop + dims.topSpacing;
- var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
- var affixType = this.affixedType;
-
- if (colliderTop <= dims.translateY + dims.containerTop) {
- dims.translateY = colliderTop - dims.containerTop;
- affixType = 'VIEWPORT-TOP';
- } else if (dims.containerBottom <= colliderBottom) {
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
- } else if (!this.isSidebarFitsViewport()) {
-
- if (dims.containerTop <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
- affixType = 'VIEWPORT-UNBOTTOM';
- }
- }
-
- return affixType;
- }
- }, {
- key: '_getStyle',
- value: function _getStyle(affixType) {
- if ('undefined' === typeof affixType) return;
-
- var style = { inner: {}, outer: {} };
- var dims = this.dimensions;
-
- switch (affixType) {
- case 'VIEWPORT-TOP':
- style.inner = { position: 'fixed', top: dims.topSpacing,
- left: dims.sidebarLeft - dims.viewportLeft, width: dims.sidebarWidth };
- break;
- case 'VIEWPORT-BOTTOM':
- style.inner = { position: 'fixed', top: 'auto', left: dims.sidebarLeft,
- bottom: dims.bottomSpacing, width: dims.sidebarWidth };
- break;
- case 'CONTAINER-BOTTOM':
- case 'VIEWPORT-UNBOTTOM':
- var translate = this._getTranslate(0, dims.translateY + 'px');
-
- if (translate) style.inner = { transform: translate };else style.inner = { position: 'absolute', top: dims.translateY, width: dims.sidebarWidth };
- break;
- }
-
- switch (affixType) {
- case 'VIEWPORT-TOP':
- case 'VIEWPORT-BOTTOM':
- case 'VIEWPORT-UNBOTTOM':
- case 'CONTAINER-BOTTOM':
- style.outer = { height: dims.sidebarHeight, position: 'relative' };
- break;
- }
-
- style.outer = StickySidebar.extend({ height: '', position: '' }, style.outer);
- style.inner = StickySidebar.extend({ position: 'relative', top: '', left: '',
- bottom: '', width: '', transform: '' }, style.inner);
-
- return style;
- }
- }, {
- key: 'stickyPosition',
- value: function stickyPosition(force) {
- if (this._breakpoint) return;
-
- force = this._reStyle || force || false;
-
- var offsetTop = this.options.topSpacing;
- var offsetBottom = this.options.bottomSpacing;
-
- var affixType = this.getAffixType();
- var style = this._getStyle(affixType);
-
- if ((this.affixedType != affixType || force) && affixType) {
- var affixEvent = 'affix.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
- StickySidebar.eventTrigger(this.sidebar, affixEvent);
-
- if ('STATIC' === affixType) StickySidebar.removeClass(this.sidebar, this.options.stickyClass);else StickySidebar.addClass(this.sidebar, this.options.stickyClass);
-
- for (var key in style.outer) {
- var unit = 'number' === typeof style.outer[key] ? 'px' : '';
- this.sidebar.style[key] = style.outer[key] + unit;
- }
-
- for (var _key in style.inner) {
- var _unit = 'number' === typeof style.inner[_key] ? 'px' : '';
- this.sidebarInner.style[_key] = style.inner[_key] + _unit;
- }
-
- var affixedEvent = 'affixed.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
- StickySidebar.eventTrigger(this.sidebar, affixedEvent);
- } else {
- if (this._initialized) this.sidebarInner.style.left = style.inner.left;
- }
-
- this.affixedType = affixType;
- }
- }, {
- key: '_widthBreakpoint',
- value: function _widthBreakpoint() {
-
- if (window.innerWidth <= this.options.minWidth) {
- this._breakpoint = true;
- this.affixedType = 'STATIC';
-
- this.sidebar.removeAttribute('style');
- StickySidebar.removeClass(this.sidebar, this.options.stickyClass);
- this.sidebarInner.removeAttribute('style');
- } else {
- this._breakpoint = false;
- }
- }
- }, {
- key: 'updateSticky',
- value: function updateSticky() {
- var _this3 = this;
-
- var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- if (this._running) return;
- this._running = true;
-
- (function (eventType) {
- requestAnimationFrame(function () {
- switch (eventType) {
- // When browser is scrolling and re-calculate just dimensions
- // within scroll.
- case 'scroll':
- _this3._calcDimensionsWithScroll();
- _this3.observeScrollDir();
- _this3.stickyPosition();
- break;
-
- // When browser is resizing or there's no event, observe width
- // breakpoint and re-calculate dimensions.
- case 'resize':
- default:
- _this3._widthBreakpoint();
- _this3.calcDimensions();
- _this3.stickyPosition(true);
- break;
- }
- _this3._running = false;
- });
- })(event.type);
- }
- }, {
- key: '_setSupportFeatures',
- value: function _setSupportFeatures() {
- var support = this.support;
-
- support.transform = StickySidebar.supportTransform();
- support.transform3d = StickySidebar.supportTransform(true);
- }
- }, {
- key: '_getTranslate',
- value: function _getTranslate() {
- var y = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
- var x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
-
- if (this.support.transform3d) return 'translate3d(' + y + ', ' + x + ', ' + z + ')';else if (this.support.translate) return 'translate(' + y + ', ' + x + ')';else return false;
- }
- }, {
- key: 'destroy',
- value: function destroy() {
- window.removeEventListener('resize', this, { capture: false });
- window.removeEventListener('scroll', this, { capture: false });
-
- this.sidebar.classList.remove(this.options.stickyClass);
- this.sidebar.style.minHeight = '';
-
- this.sidebar.removeEventListener('update' + EVENT_KEY, this);
-
- var styleReset = { inner: {}, outer: {} };
-
- styleReset.inner = { position: '', top: '', left: '', bottom: '', width: '', transform: '' };
- styleReset.outer = { height: '', position: '' };
-
- for (var key in styleReset.outer) {
- this.sidebar.style[key] = styleReset.outer[key];
- }for (var _key2 in styleReset.inner) {
- this.sidebarInner.style[_key2] = styleReset.inner[_key2];
- }if (this.options.resizeSensor && 'undefined' !== typeof ResizeSensor) {
- ResizeSensor.detach(this.sidebarInner, this.handleEvent);
- ResizeSensor.detach(this.container, this.handleEvent);
- }
- }
- }], [{
- key: 'supportTransform',
- value: function supportTransform(transform3d) {
- var result = false,
- property = transform3d ? 'perspective' : 'transform',
- upper = property.charAt(0).toUpperCase() + property.slice(1),
- prefixes = ['Webkit', 'Moz', 'O', 'ms'],
- support = document.createElement('support'),
- style = support.style;
-
- (property + ' ' + prefixes.join(upper + ' ') + upper).split(' ').forEach(function (property, i) {
- if (style[property] !== undefined) {
- result = property;
- return false;
- }
- });
- return result;
- }
- }, {
- key: 'eventTrigger',
- value: function eventTrigger(element, eventName, data) {
- try {
- var event = new CustomEvent(eventName, { detail: data });
- } catch (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent(eventName, true, true, data);
- }
- element.dispatchEvent(event);
- }
- }, {
- key: 'extend',
- value: function extend(defaults, options) {
- var results = {};
- for (var key in defaults) {
- if ('undefined' !== typeof options[key]) results[key] = options[key];else results[key] = defaults[key];
- }
- return results;
- }
- }, {
- key: 'offsetRelative',
- value: function offsetRelative(element) {
- var result = { left: 0, top: 0 };
-
- do {
- var offsetTop = element.offsetTop;
- var offsetLeft = element.offsetLeft;
-
- if (!isNaN(offsetTop)) result.top += offsetTop;
-
- if (!isNaN(offsetLeft)) result.left += offsetLeft;
-
- element = 'BODY' === element.tagName ? element.parentElement : element.offsetParent;
- } while (element);
- return result;
- }
- }, {
- key: 'addClass',
- value: function addClass(element, className) {
- if (!StickySidebar.hasClass(element, className)) {
- if (element.classList) element.classList.add(className);else element.className += ' ' + className;
- }
- }
- }, {
- key: 'removeClass',
- value: function removeClass(element, className) {
- if (StickySidebar.hasClass(element, className)) {
- if (element.classList) element.classList.remove(className);else element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
- }
- }
- }, {
- key: 'hasClass',
- value: function hasClass(element, className) {
- if (element.classList) return element.classList.contains(className);else return new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className);
- }
- }, {
- key: 'defaults',
- get: function () {
- return DEFAULTS;
- }
- }]);
-
- return StickySidebar;
- }();
-
- return StickySidebar;
- }();
-
- exports.default = StickySidebar;
-
-
- // Global
- // -------------------------
- window.StickySidebar = StickySidebar;
-});
-});
-
-unwrapExports(stickySidebar);
-
-var jquery_stickySidebar = createCommonjsModule(function (module, exports) {
-(function (global, factory) {
- if (typeof undefined === "function" && undefined.amd) {
- undefined(['./sticky-sidebar'], factory);
- } else {
- factory(stickySidebar);
- }
-})(commonjsGlobal, function (_stickySidebar) {
- var _stickySidebar2 = _interopRequireDefault(_stickySidebar);
-
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
-
- (function () {
- if ('undefined' === typeof window) return;
-
- var plugin = window.$ || window.jQuery || window.Zepto;
- var DATA_NAMESPACE = 'stickySidebar';
-
- // Make sure the site has jquery or zepto plugin.
- if (plugin) {
- var _jQueryPlugin = function (config) {
- return this.each(function () {
- var $this = plugin(this),
- data = plugin(this).data(DATA_NAMESPACE);
-
- if (!data) {
- data = new _stickySidebar2.default(this, typeof config == 'object' && config);
- $this.data(DATA_NAMESPACE, data);
- }
-
- if ('string' === typeof config) {
- if (data[config] === undefined && ['destroy', 'updateSticky'].indexOf(config) === -1) throw new Error('No method named "' + config + '"');
-
- data[config]();
- }
- });
- };
-
- plugin.fn.stickySidebar = _jQueryPlugin;
- plugin.fn.stickySidebar.Constructor = _stickySidebar2.default;
-
- var old = plugin.fn.stickySidebar;
-
- /**
- * Sticky Sidebar No Conflict.
- */
- plugin.fn.stickySidebar.noConflict = function () {
- plugin.fn.stickySidebar = old;
- return this;
- };
- }
- })();
-});
-});
-
-var jquery_stickySidebar$1 = unwrapExports(jquery_stickySidebar);
-
-return jquery_stickySidebar$1;
-
-})));
+ (global = global || self, global.StickySidebar = factory());
+}(this, function () { 'use strict';
+
+ var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
+
+ function unwrapExports (x) {
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
+ }
+
+ function createCommonjsModule(fn, module) {
+ return module = { exports: {} }, fn(module, module.exports), module.exports;
+ }
+
+ var stickySidebar = createCommonjsModule(function (module, exports) {
+ (function (global, factory) {
+ {
+ factory(exports);
+ }
+ })(commonjsGlobal, function (exports) {
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ }
+
+ var _createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+ }();
+
+ /**
+ * Sticky Sidebar JavaScript Plugin.
+ * @version 3.3.5
+ * @author Ahmed Bouhuolia
+ * @license The MIT License (MIT)
+ */
+ var StickySidebar = function () {
+
+ // ---------------------------------
+ // # Define Constants
+ // ---------------------------------
+ //
+ var EVENT_KEY = '.stickySidebar';
+
+ var DEFAULTS = {
+ /**
+ * Additional top spacing of the element when it becomes sticky.
+ * @type {Numeric|Function}
+ */
+ topSpacing: 0,
+
+ /**
+ * Additional bottom spacing of the element when it becomes sticky.
+ * @type {Numeric|Function}
+ */
+ bottomSpacing: 0,
+
+ /**
+ * Scroll container selector.
+ * @type {String|False}
+ */
+ scrollContainerSelector: false,
+
+ /**
+ * Container sidebar selector to know what the beginning and end of sticky element.
+ * @type {String|False}
+ */
+ containerSelector: false,
+
+ /**
+ * Inner wrapper selector.
+ * @type {String}
+ */
+ innerWrapperSelector: '.inner-wrapper-sticky',
+
+ /**
+ * The name of CSS class to apply to elements when they have become stuck.
+ * @type {String|False}
+ */
+ stickyClass: 'is-affixed',
+
+ /**
+ * Detect when sidebar and its container change height so re-calculate their dimensions.
+ * @type {Boolean}
+ */
+ resizeSensor: true,
+
+ /**
+ * The sidebar returns to its normal position if its width below this value.
+ * @type {Numeric}
+ */
+ minWidth: false,
+
+ /**
+ * Use native CSS position sticky.
+ * @type {Boolean}
+ */
+ nativeSticky: false
+ };
+
+ // ---------------------------------
+ // # Class Definition
+ // ---------------------------------
+ //
+ /**
+ * Sticky Sidebar Class.
+ * @public
+ */
+
+ var StickySidebar = function () {
+
+ /**
+ * Sticky Sidebar Constructor.
+ * @constructor
+ * @param {HTMLElement|String} sidebar - The sidebar element or sidebar selector.
+ * @param {Object} options - The options of sticky sidebar.
+ */
+ function StickySidebar(sidebar) {
+ var _this = this;
+
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ _classCallCheck(this, StickySidebar);
+
+ this.options = StickySidebar.extend(DEFAULTS, options);
+
+ // Sidebar element query if there's no one, throw error.
+ this.sidebar = 'string' === typeof sidebar ? document.querySelector(sidebar) : sidebar;
+ if ('undefined' === typeof this.sidebar) throw new Error("There is no specific sidebar element.");
+
+ this.sidebarInner = false;
+ this.container = this.sidebar.parentElement;
+
+ // Get scroll container, if provided
+ this.scrollContainer = this.options.scrollContainerSelector ? 'string' === typeof this.options.scrollContainerSelector ? document.querySelector(this.options.scrollContainerSelector) : this.options.scrollContainerSelector : undefined;
+
+ // Current Affix Type of sidebar element.
+ this.affixedType = 'STATIC';
+ this.direction = 'down';
+ this.support = {
+ transform: false,
+ transform3d: false
+ };
+
+ this._initialized = false;
+ this._reStyle = false;
+ this._breakpoint = false;
+
+ // Dimensions of sidebar, container and screen viewport.
+ this.dimensions = {
+ translateY: 0,
+ maxTranslateY: 0,
+ topSpacing: 0,
+ lastTopSpacing: 0,
+ bottomSpacing: 0,
+ lastBottomSpacing: 0,
+ sidebarHeight: 0,
+ sidebarWidth: 0,
+ containerTop: 0,
+ containerHeight: 0,
+ viewportHeight: 0,
+ viewportTop: 0,
+ lastViewportTop: 0
+ };
+
+ // Bind event handlers for referencability.
+ ['handleEvent'].forEach(function (method) {
+ _this[method] = _this[method].bind(_this);
+ });
+
+ // Initialize sticky sidebar for first time.
+ this.initialize();
+ }
+
+ /**
+ * Initializes the sticky sidebar by adding inner wrapper, define its container,
+ * min-width breakpoint, calculating dimensions, adding helper classes and inline style.
+ * @private
+ */
+
+
+ _createClass(StickySidebar, [{
+ key: 'initialize',
+ value: function initialize() {
+ var _this2 = this;
+
+ this._setSupportFeatures();
+
+ // Get sticky sidebar inner wrapper, if not found, will create one.
+ if (this.options.innerWrapperSelector) {
+ this.sidebarInner = this.sidebar.querySelector(this.options.innerWrapperSelector);
+
+ if (null === this.sidebarInner) this.sidebarInner = false;
+ }
+
+ if (!this.sidebarInner) {
+ var wrapper = document.createElement('div');
+ wrapper.setAttribute('class', 'inner-wrapper-sticky');
+ this.sidebar.appendChild(wrapper);
+
+ while (this.sidebar.firstChild != wrapper) {
+ wrapper.appendChild(this.sidebar.firstChild);
+ }this.sidebarInner = this.sidebar.querySelector('.inner-wrapper-sticky');
+ }
+
+ // Container wrapper of the sidebar.
+ if (this.options.containerSelector) {
+ var containers = document.querySelectorAll(this.options.containerSelector);
+ containers = Array.prototype.slice.call(containers);
+
+ containers.forEach(function (container, item) {
+ if (!container.contains(_this2.sidebar)) return;
+ _this2.container = container;
+ });
+
+ if (!containers.length) throw new Error("The container does not contains on the sidebar.");
+ }
+
+ // If top/bottom spacing is not function parse value to integer.
+ if ('function' !== typeof this.options.topSpacing) this.options.topSpacing = parseInt(this.options.topSpacing) || 0;
+
+ if ('function' !== typeof this.options.bottomSpacing) this.options.bottomSpacing = parseInt(this.options.bottomSpacing) || 0;
+
+ // Breakdown sticky sidebar if screen width below `options.minWidth`.
+ this._widthBreakpoint();
+
+ // Calculate dimensions of sidebar, container and viewport.
+ this.calcDimensions();
+
+ // Affix sidebar in proper position.
+ this.stickyPosition();
+
+ // Bind all events.
+ this.bindEvents();
+
+ // Inform other properties the sticky sidebar is initialized.
+ this._initialized = true;
+ }
+ }, {
+ key: 'bindEvents',
+ value: function bindEvents() {
+ var _this3 = this;
+
+ window.addEventListener('resize', this, { passive: true, capture: false });
+ (this.scrollContainer || window).addEventListener('scroll', this, { passive: true, capture: false });
+
+ this.sidebar.addEventListener('update' + EVENT_KEY, this);
+
+ if (this.options.resizeSensor && 'undefined' !== typeof ResizeObserver) {
+ this.resizeObserver = new ResizeObserver(function () {
+ return _this3.handleEvent({ type: 'resize' });
+ });
+ this.resizeObserver.observe(this.sidebarInner);
+ this.resizeObserver.observe(this.container);
+ if (this.scrollContainer) this.resizeObserver.observe(this.scrollContainer);
+ }
+ }
+ }, {
+ key: 'handleEvent',
+ value: function handleEvent(event) {
+ this.updateSticky(event);
+ }
+ }, {
+ key: 'calcDimensions',
+ value: function calcDimensions() {
+ if (this._breakpoint) return;
+ var dims = this.dimensions;
+
+ // Container of sticky sidebar dimensions.
+ dims.containerTop = StickySidebar.offsetRelative(this.container, this.scrollContainer).top;
+ dims.containerHeight = this.container.clientHeight;
+ dims.containerBottom = dims.containerTop + dims.containerHeight;
+
+ // Sidebar dimensions.
+ dims.sidebarHeight = this.sidebarInner.offsetHeight;
+ dims.sidebarWidth = this.sidebarInner.offsetWidth;
+
+ // Screen viewport dimensions.
+ if (this.scrollContainer) {
+ var scrollContainerPaddingTop = parseFloat(getComputedStyle(this.scrollContainer).paddingTop) || 0;
+ var scrollContainerPaddingBottom = parseFloat(getComputedStyle(this.scrollContainer).paddingBottom) || 0;
+
+ dims.viewportHeight = this.scrollContainer.clientHeight - scrollContainerPaddingTop - scrollContainerPaddingBottom;
+ } else {
+ dims.viewportHeight = window.innerHeight;
+ }
+
+ // Maximum sidebar translate Y.
+ dims.maxTranslateY = dims.containerHeight - dims.sidebarHeight;
+
+ this._calcDimensionsWithScroll();
+ }
+ }, {
+ key: '_calcDimensionsWithScroll',
+ value: function _calcDimensionsWithScroll() {
+ var dims = this.dimensions;
+
+ dims.sidebarLeft = StickySidebar.offsetRelative(this.sidebar, this.scrollContainer).left;
+
+ if (this.scrollContainer) {
+ var scrollContainerPaddingTop = parseFloat(getComputedStyle(this.scrollContainer).paddingTop) || 0;
+ var scrollContainerPaddingLeft = parseFloat(getComputedStyle(this.scrollContainer).paddingLeft) || 0;
+
+ dims.viewportTop = this.scrollContainer.scrollTop + scrollContainerPaddingTop;
+ dims.viewportLeft = this.scrollContainer.scrollLeft + scrollContainerPaddingLeft;
+ } else {
+ dims.viewportTop = document.documentElement.scrollTop || document.body.scrollTop;
+ dims.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
+ }
+ dims.viewportBottom = dims.viewportTop + dims.viewportHeight;
+
+ dims.topSpacing = this.options.topSpacing;
+ dims.bottomSpacing = this.options.bottomSpacing;
+
+ if ('function' === typeof dims.topSpacing) dims.topSpacing = parseInt(dims.topSpacing(this.sidebar)) || 0;
+
+ if ('function' === typeof dims.bottomSpacing) dims.bottomSpacing = parseInt(dims.bottomSpacing(this.sidebar)) || 0;
+
+ if ('VIEWPORT-TOP' === this.affixedType) {
+ // Adjust translate Y in the case decrease top spacing value.
+ if (dims.topSpacing < dims.lastTopSpacing) {
+ dims.translateY += dims.lastTopSpacing - dims.topSpacing;
+ this._reStyle = true;
+ }
+ } else if ('VIEWPORT-BOTTOM' === this.affixedType) {
+ // Adjust translate Y in the case decrease bottom spacing value.
+ if (dims.bottomSpacing < dims.lastBottomSpacing) {
+ dims.translateY += dims.lastBottomSpacing - dims.bottomSpacing;
+ this._reStyle = true;
+ }
+ }
+
+ dims.lastTopSpacing = dims.topSpacing;
+ dims.lastBottomSpacing = dims.bottomSpacing;
+ }
+ }, {
+ key: 'isSidebarFitsViewport',
+ value: function isSidebarFitsViewport() {
+ var dims = this.dimensions;
+ var offset = this.scrollDirection === 'down' ? dims.lastBottomSpacing : dims.lastTopSpacing;
+ return this.dimensions.sidebarHeight + offset < this.dimensions.viewportHeight;
+ }
+ }, {
+ key: 'observeScrollDir',
+ value: function observeScrollDir() {
+ var dims = this.dimensions;
+ if (dims.lastViewportTop === dims.viewportTop) return;
+
+ var furthest = 'down' === this.direction ? Math.min : Math.max;
+
+ // If the browser is scrolling not in the same direction.
+ if (dims.viewportTop === furthest(dims.viewportTop, dims.lastViewportTop)) this.direction = 'down' === this.direction ? 'up' : 'down';
+ }
+ }, {
+ key: 'getAffixType',
+ value: function getAffixType() {
+ this._calcDimensionsWithScroll();
+ var dims = this.dimensions;
+ var colliderTop = dims.viewportTop + dims.topSpacing;
+ var affixType = this.affixedType;
+
+ if (colliderTop <= dims.containerTop || dims.containerHeight <= dims.sidebarHeight) {
+ dims.translateY = 0;
+ affixType = 'STATIC';
+ } else {
+ affixType = 'up' === this.direction ? this._getAffixTypeScrollingUp() : this._getAffixTypeScrollingDown();
+ }
+
+ // Make sure the translate Y is not bigger than container height.
+ dims.translateY = Math.max(0, dims.translateY);
+ dims.translateY = Math.min(dims.containerHeight, dims.translateY);
+ dims.translateY = Math.round(dims.translateY);
+
+ dims.lastViewportTop = dims.viewportTop;
+ return affixType;
+ }
+ }, {
+ key: '_getAffixTypeScrollingDown',
+ value: function _getAffixTypeScrollingDown() {
+ var dims = this.dimensions;
+ var sidebarBottom = dims.sidebarHeight + dims.containerTop;
+ var colliderTop = dims.viewportTop + dims.topSpacing;
+ var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
+ var affixType = this.affixedType;
+
+ if (this.isSidebarFitsViewport()) {
+ if (dims.sidebarHeight + colliderTop >= dims.containerBottom) {
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
+ } else if (colliderTop >= dims.containerTop) {
+ dims.translateY = colliderTop - dims.containerTop;
+ affixType = 'VIEWPORT-TOP';
+ }
+ } else {
+ if (dims.containerBottom <= colliderBottom) {
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
+ } else if (sidebarBottom + dims.translateY <= colliderBottom) {
+ dims.translateY = colliderBottom - sidebarBottom;
+ affixType = 'VIEWPORT-BOTTOM';
+ } else if (dims.containerTop + dims.translateY <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
+ affixType = 'VIEWPORT-UNBOTTOM';
+ }
+ }
+
+ return affixType;
+ }
+ }, {
+ key: '_getAffixTypeScrollingUp',
+ value: function _getAffixTypeScrollingUp() {
+ var dims = this.dimensions;
+ var sidebarBottom = dims.sidebarHeight + dims.containerTop;
+ var colliderTop = dims.viewportTop + dims.topSpacing;
+ var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
+ var affixType = this.affixedType;
+
+ if (colliderTop <= dims.translateY + dims.containerTop) {
+ dims.translateY = colliderTop - dims.containerTop;
+ affixType = 'VIEWPORT-TOP';
+ } else if (dims.containerBottom <= colliderBottom) {
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
+ } else if (!this.isSidebarFitsViewport()) {
+
+ if (dims.containerTop <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
+ affixType = 'VIEWPORT-UNBOTTOM';
+ }
+ }
+
+ return affixType;
+ }
+ }, {
+ key: '_getStyle',
+ value: function _getStyle(affixType) {
+ if ('undefined' === typeof affixType) return;
+
+ var style = { inner: {}, outer: {} };
+ var dims = this.dimensions;
+
+ if (this.options.nativeSticky) {
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ style.inner = { position: 'sticky', top: dims.topSpacing };
+ break;
+ case 'VIEWPORT-BOTTOM':
+ style.inner = { position: 'sticky', top: dims.viewportHeight - dims.sidebarHeight - dims.bottomSpacing };
+ break;
+ case 'CONTAINER-BOTTOM':
+ style.inner = { position: 'sticky', top: '100%' };
+ break;
+ case 'VIEWPORT-UNBOTTOM':
+ style.inner = { position: 'relative', top: dims.translateY };
+ break;
+ }
+
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ case 'VIEWPORT-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ case 'CONTAINER-BOTTOM':
+ style.outer = { height: '100%', position: 'relative' };
+ break;
+ }
+ } else {
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ style.inner = { position: 'fixed', top: dims.topSpacing,
+ left: dims.sidebarLeft - dims.viewportLeft, width: dims.sidebarWidth };
+ break;
+ case 'VIEWPORT-BOTTOM':
+ style.inner = { position: 'fixed', top: 'auto', left: dims.sidebarLeft,
+ bottom: dims.bottomSpacing, width: dims.sidebarWidth };
+ break;
+ case 'CONTAINER-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ var translate = this._getTranslate(0, dims.translateY + 'px');
+
+ if (translate) style.inner = { transform: translate };else style.inner = { position: 'absolute', top: dims.translateY, width: dims.sidebarWidth };
+ break;
+ }
+
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ case 'VIEWPORT-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ case 'CONTAINER-BOTTOM':
+ style.outer = { height: dims.sidebarHeight, position: 'relative' };
+ break;
+ }
+ }
+
+ style.outer = StickySidebar.extend({ height: '', position: '' }, style.outer);
+ style.inner = StickySidebar.extend({ position: 'relative', top: '', left: '',
+ bottom: '', width: '', transform: '' }, style.inner);
+
+ return style;
+ }
+ }, {
+ key: 'stickyPosition',
+ value: function stickyPosition(force) {
+ if (this._breakpoint) return;
+
+ force = this._reStyle || force || false;
+
+ var offsetTop = this.options.topSpacing;
+ var offsetBottom = this.options.bottomSpacing;
+
+ var affixType = this.getAffixType();
+ var style = this._getStyle(affixType);
+
+ if ((this.affixedType != affixType || force) && affixType) {
+ var affixEvent = 'affix.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
+ StickySidebar.eventTrigger(this.sidebar, affixEvent);
+
+ if ('STATIC' === affixType) StickySidebar.removeClass(this.sidebar, this.options.stickyClass);else StickySidebar.addClass(this.sidebar, this.options.stickyClass);
+
+ for (var key in style.outer) {
+ var unit = 'number' === typeof style.outer[key] ? 'px' : '';
+ this.sidebar.style[key] = style.outer[key] + unit;
+ }
+
+ for (var _key in style.inner) {
+ var _unit = 'number' === typeof style.inner[_key] ? 'px' : '';
+ this.sidebarInner.style[_key] = style.inner[_key] + _unit;
+ }
+
+ var affixedEvent = 'affixed.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
+ StickySidebar.eventTrigger(this.sidebar, affixedEvent);
+ } else {
+ if (this._initialized) this.sidebarInner.style.left = style.inner.left;
+ }
+
+ this.affixedType = affixType;
+ }
+ }, {
+ key: '_widthBreakpoint',
+ value: function _widthBreakpoint() {
+
+ if (window.innerWidth <= this.options.minWidth) {
+ this._breakpoint = true;
+ this.affixedType = 'STATIC';
+
+ this.sidebar.removeAttribute('style');
+ StickySidebar.removeClass(this.sidebar, this.options.stickyClass);
+ this.sidebarInner.removeAttribute('style');
+ } else {
+ this._breakpoint = false;
+ }
+ }
+ }, {
+ key: 'updateSticky',
+ value: function updateSticky() {
+ var _this4 = this;
+
+ var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ if (this._running) return;
+ this._running = true;
+
+ (function (eventType) {
+ requestAnimationFrame(function () {
+ switch (eventType) {
+ // When browser is scrolling and re-calculate just dimensions
+ // within scroll.
+ case 'scroll':
+ _this4._calcDimensionsWithScroll();
+ _this4.observeScrollDir();
+ _this4.stickyPosition();
+ break;
+
+ // When browser is resizing or there's no event, observe width
+ // breakpoint and re-calculate dimensions.
+ case 'resize':
+ default:
+ _this4._widthBreakpoint();
+ _this4.calcDimensions();
+ _this4.stickyPosition(true);
+ break;
+ }
+ _this4._running = false;
+ });
+ })(event.type);
+ }
+ }, {
+ key: '_setSupportFeatures',
+ value: function _setSupportFeatures() {
+ var support = this.support;
+
+ support.transform = StickySidebar.supportTransform();
+ support.transform3d = StickySidebar.supportTransform(true);
+ }
+ }, {
+ key: '_getTranslate',
+ value: function _getTranslate() {
+ var y = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
+
+ if (this.support.transform3d) return 'translate3d(' + y + ', ' + x + ', ' + z + ')';else if (this.support.translate) return 'translate(' + y + ', ' + x + ')';else return false;
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy() {
+ window.removeEventListener('resize', this, { capture: false });
+ window.removeEventListener('scroll', this, { capture: false });
+
+ this.sidebar.classList.remove(this.options.stickyClass);
+ this.sidebar.style.minHeight = '';
+
+ this.sidebar.removeEventListener('update' + EVENT_KEY, this);
+
+ var styleReset = { inner: {}, outer: {} };
+
+ styleReset.inner = { position: '', top: '', left: '', bottom: '', width: '', transform: '' };
+ styleReset.outer = { height: '', position: '' };
+
+ for (var key in styleReset.outer) {
+ this.sidebar.style[key] = styleReset.outer[key];
+ }for (var _key2 in styleReset.inner) {
+ this.sidebarInner.style[_key2] = styleReset.inner[_key2];
+ }if (this.options.resizeSensor && 'undefined' !== typeof ResizeObserver && this.resizeObserver) {
+ this.resizeObserver.unobserve(this.sidebarInner);
+ this.resizeObserver.unobserve(this.container);
+ if (this.scrollContainer) this.resizeObserver.unobserve(this.scrollContainer);
+ }
+ }
+ }], [{
+ key: 'supportTransform',
+ value: function supportTransform(transform3d) {
+ var result = false,
+ property = transform3d ? 'perspective' : 'transform',
+ upper = property.charAt(0).toUpperCase() + property.slice(1),
+ prefixes = ['Webkit', 'Moz', 'O', 'ms'],
+ support = document.createElement('support'),
+ style = support.style;
+
+ (property + ' ' + prefixes.join(upper + ' ') + upper).split(' ').forEach(function (property, i) {
+ if (style[property] !== undefined) {
+ result = property;
+ return false;
+ }
+ });
+ return result;
+ }
+ }, {
+ key: 'eventTrigger',
+ value: function eventTrigger(element, eventName, data) {
+ try {
+ var event = new CustomEvent(eventName, { detail: data });
+ } catch (e) {
+ var event = document.createEvent('CustomEvent');
+ event.initCustomEvent(eventName, true, true, data);
+ }
+ element.dispatchEvent(event);
+ }
+ }, {
+ key: 'extend',
+ value: function extend(defaults, options) {
+ var results = {};
+ for (var key in defaults) {
+ if ('undefined' !== typeof options[key]) results[key] = options[key];else results[key] = defaults[key];
+ }
+ return results;
+ }
+ }, {
+ key: 'offsetRelative',
+ value: function offsetRelative(element, scrollContainer) {
+ var result = { left: 0, top: 0 };
+
+ do {
+ var offsetTop = element.offsetTop;
+ var offsetLeft = element.offsetLeft;
+
+ if (!isNaN(offsetTop)) result.top += offsetTop;
+
+ if (!isNaN(offsetLeft)) result.left += offsetLeft;
+
+ element = 'BODY' === element.tagName ? element.parentElement : element.offsetParent;
+ } while (element !== scrollContainer && element);
+ return result;
+ }
+ }, {
+ key: 'addClass',
+ value: function addClass(element, className) {
+ if (!StickySidebar.hasClass(element, className)) {
+ if (element.classList) element.classList.add(className);else element.className += ' ' + className;
+ }
+ }
+ }, {
+ key: 'removeClass',
+ value: function removeClass(element, className) {
+ if (StickySidebar.hasClass(element, className)) {
+ if (element.classList) element.classList.remove(className);else element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
+ }
+ }
+ }, {
+ key: 'hasClass',
+ value: function hasClass(element, className) {
+ if (element.classList) return element.classList.contains(className);else return new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className);
+ }
+ }, {
+ key: 'defaults',
+ get: function () {
+ return DEFAULTS;
+ }
+ }]);
+
+ return StickySidebar;
+ }();
+
+ return StickySidebar;
+ }();
+
+ exports.default = StickySidebar;
+
+
+ // Global
+ // -------------------------
+ window.StickySidebar = StickySidebar;
+ });
+ });
+
+ unwrapExports(stickySidebar);
+
+ var jquery_stickySidebar = createCommonjsModule(function (module, exports) {
+ (function (global, factory) {
+ {
+ factory(stickySidebar);
+ }
+ })(commonjsGlobal, function (_stickySidebar) {
+
+ var _stickySidebar2 = _interopRequireDefault(_stickySidebar);
+
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+
+ (function () {
+ if ('undefined' === typeof window) return;
+
+ var plugin = window.$ || window.jQuery || window.Zepto;
+ var DATA_NAMESPACE = 'stickySidebar';
+
+ // Make sure the site has jquery or zepto plugin.
+ if (plugin) {
+ var _jQueryPlugin = function (config) {
+ return this.each(function () {
+ var $this = plugin(this),
+ data = plugin(this).data(DATA_NAMESPACE);
+
+ if (!data) {
+ data = new _stickySidebar2.default(this, typeof config == 'object' && config);
+ $this.data(DATA_NAMESPACE, data);
+ }
+
+ if ('string' === typeof config) {
+ if (data[config] === undefined && ['destroy', 'updateSticky'].indexOf(config) === -1) throw new Error('No method named "' + config + '"');
+
+ data[config]();
+ }
+ });
+ };
+
+ plugin.fn.stickySidebar = _jQueryPlugin;
+ plugin.fn.stickySidebar.Constructor = _stickySidebar2.default;
+
+ var old = plugin.fn.stickySidebar;
+
+ /**
+ * Sticky Sidebar No Conflict.
+ */
+ plugin.fn.stickySidebar.noConflict = function () {
+ plugin.fn.stickySidebar = old;
+ return this;
+ };
+ }
+ })();
+ });
+ });
+
+ var jquery_stickySidebar$1 = unwrapExports(jquery_stickySidebar);
+
+ return jquery_stickySidebar$1;
+
+}));
//# sourceMappingURL=jquery.sticky-sidebar.js.map
diff --git a/dist/jquery.sticky-sidebar.js.map b/dist/jquery.sticky-sidebar.js.map
index a90bb21..5c0ee2b 100644
--- a/dist/jquery.sticky-sidebar.js.map
+++ b/dist/jquery.sticky-sidebar.js.map
@@ -1 +1 @@
-{"version":3,"file":"jquery.sticky-sidebar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
\ No newline at end of file
+{"version":3,"file":"jquery.sticky-sidebar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
\ No newline at end of file
diff --git a/dist/jquery.sticky-sidebar.min.js b/dist/jquery.sticky-sidebar.min.js
index a83e472..2c52cd7 100644
--- a/dist/jquery.sticky-sidebar.min.js
+++ b/dist/jquery.sticky-sidebar.min.js
@@ -1,8 +1,8 @@
/**
* sticky-sidebar - A JavaScript plugin for making smart and high performance.
- * @version v3.3.1
+ * @version v3.3.5
* @link https://github.com/abouolia/sticky-sidebar
* @author Ahmed Bouhuolia
* @license The MIT License (MIT)
**/
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.StickySidebar=e()}(this,function(){"use strict";"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function t(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function e(t,e){return t(e={exports:{}},e.exports),e.exports}var i=e(function(t,e){(function(t){Object.defineProperty(t,"__esModule",{value:!0});var l,n,e=function(){function n(t,e){for(var i=0;i=t.containerBottom?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):i>=t.containerTop&&(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):e+t.translateY<=n?(t.translateY=n-e,o="VIEWPORT-BOTTOM"):t.containerTop+t.translateY<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getAffixTypeScrollingUp",value:function(){var t=this.dimensions,e=t.sidebarHeight+t.containerTop,i=t.viewportTop+t.topSpacing,n=t.viewportBottom-t.bottomSpacing,o=this.affixedType;return i<=t.translateY+t.containerTop?(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):this.isSidebarFitsViewport()||t.containerTop<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getStyle",value:function(t){if(void 0!==t){var e={inner:{},outer:{}},i=this.dimensions;switch(t){case"VIEWPORT-TOP":e.inner={position:"fixed",top:i.topSpacing,left:i.sidebarLeft-i.viewportLeft,width:i.sidebarWidth};break;case"VIEWPORT-BOTTOM":e.inner={position:"fixed",top:"auto",left:i.sidebarLeft,bottom:i.bottomSpacing,width:i.sidebarWidth};break;case"CONTAINER-BOTTOM":case"VIEWPORT-UNBOTTOM":var n=this._getTranslate(0,i.translateY+"px");e.inner=n?{transform:n}:{position:"absolute",top:i.translateY,width:i.sidebarWidth}}switch(t){case"VIEWPORT-TOP":case"VIEWPORT-BOTTOM":case"VIEWPORT-UNBOTTOM":case"CONTAINER-BOTTOM":e.outer={height:i.sidebarHeight,position:"relative"}}return e.outer=c.extend({height:"",position:""},e.outer),e.inner=c.extend({position:"relative",top:"",left:"",bottom:"",width:"",transform:""},e.inner),e}}},{key:"stickyPosition",value:function(t){if(!this._breakpoint){t=this._reStyle||t||!1,this.options.topSpacing,this.options.bottomSpacing;var e=this.getAffixType(),i=this._getStyle(e);if((this.affixedType!=e||t)&&e){var n="affix."+e.toLowerCase().replace("viewport-","")+l;for(var o in c.eventTrigger(this.sidebar,n),"STATIC"===e?c.removeClass(this.sidebar,this.options.stickyClass):c.addClass(this.sidebar,this.options.stickyClass),i.outer){var s="number"==typeof i.outer[o]?"px":"";this.sidebar.style[o]=i.outer[o]+s}for(var r in i.inner){var a="number"==typeof i.inner[r]?"px":"";this.sidebarInner.style[r]=i.inner[r]+a}var p="affixed."+e.toLowerCase().replace("viewport-","")+l;c.eventTrigger(this.sidebar,p)}else this._initialized&&(this.sidebarInner.style.left=i.inner.left);this.affixedType=e}}},{key:"_widthBreakpoint",value:function(){window.innerWidth<=this.options.minWidth?(this._breakpoint=!0,this.affixedType="STATIC",this.sidebar.removeAttribute("style"),c.removeClass(this.sidebar,this.options.stickyClass),this.sidebarInner.removeAttribute("style")):this._breakpoint=!1}},{key:"updateSticky",value:function(){var t,e=this,i=0=t.containerBottom?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):i>=t.containerTop&&(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):e+t.translateY<=n?(t.translateY=n-e,o="VIEWPORT-BOTTOM"):t.containerTop+t.translateY<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getAffixTypeScrollingUp",value:function(){var t=this.dimensions,e=t.sidebarHeight+t.containerTop,i=t.viewportTop+t.topSpacing,n=t.viewportBottom-t.bottomSpacing,o=this.affixedType;return i<=t.translateY+t.containerTop?(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):this.isSidebarFitsViewport()||t.containerTop<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getStyle",value:function(t){if(void 0!==t){var e={inner:{},outer:{}},i=this.dimensions;if(this.options.nativeSticky){switch(t){case"VIEWPORT-TOP":e.inner={position:"sticky",top:i.topSpacing};break;case"VIEWPORT-BOTTOM":e.inner={position:"sticky",top:i.viewportHeight-i.sidebarHeight-i.bottomSpacing};break;case"CONTAINER-BOTTOM":e.inner={position:"sticky",top:"100%"};break;case"VIEWPORT-UNBOTTOM":e.inner={position:"relative",top:i.translateY}}switch(t){case"VIEWPORT-TOP":case"VIEWPORT-BOTTOM":case"VIEWPORT-UNBOTTOM":case"CONTAINER-BOTTOM":e.outer={height:"100%",position:"relative"}}}else{switch(t){case"VIEWPORT-TOP":e.inner={position:"fixed",top:i.topSpacing,left:i.sidebarLeft-i.viewportLeft,width:i.sidebarWidth};break;case"VIEWPORT-BOTTOM":e.inner={position:"fixed",top:"auto",left:i.sidebarLeft,bottom:i.bottomSpacing,width:i.sidebarWidth};break;case"CONTAINER-BOTTOM":case"VIEWPORT-UNBOTTOM":var n=this._getTranslate(0,i.translateY+"px");e.inner=n?{transform:n}:{position:"absolute",top:i.translateY,width:i.sidebarWidth}}switch(t){case"VIEWPORT-TOP":case"VIEWPORT-BOTTOM":case"VIEWPORT-UNBOTTOM":case"CONTAINER-BOTTOM":e.outer={height:i.sidebarHeight,position:"relative"}}}return e.outer=p.extend({height:"",position:""},e.outer),e.inner=p.extend({position:"relative",top:"",left:"",bottom:"",width:"",transform:""},e.inner),e}}},{key:"stickyPosition",value:function(t){if(!this._breakpoint){t=this._reStyle||t||!1;this.options.topSpacing,this.options.bottomSpacing;var e=this.getAffixType(),i=this._getStyle(e);if((this.affixedType!=e||t)&&e){var n,o,t="affix."+e.toLowerCase().replace("viewport-","")+a;for(n in p.eventTrigger(this.sidebar,t),"STATIC"===e?p.removeClass(this.sidebar,this.options.stickyClass):p.addClass(this.sidebar,this.options.stickyClass),i.outer){var s="number"==typeof i.outer[n]?"px":"";this.sidebar.style[n]=i.outer[n]+s}for(o in i.inner){var r="number"==typeof i.inner[o]?"px":"";this.sidebarInner.style[o]=i.inner[o]+r}t="affixed."+e.toLowerCase().replace("viewport-","")+a;p.eventTrigger(this.sidebar,t)}else this._initialized&&(this.sidebarInner.style.left=i.inner.left);this.affixedType=e}}},{key:"_widthBreakpoint",value:function(){window.innerWidth<=this.options.minWidth?(this._breakpoint=!0,this.affixedType="STATIC",this.sidebar.removeAttribute("style"),p.removeClass(this.sidebar,this.options.stickyClass),this.sidebarInner.removeAttribute("style")):this._breakpoint=!1}},{key:"updateSticky",value:function(){var t,e=this,i=0
- * @license The MIT License (MIT)
- */
- var StickySidebar = function () {
-
- // ---------------------------------
- // # Define Constants
- // ---------------------------------
- //
- var EVENT_KEY = '.stickySidebar';
- var DEFAULTS = {
- /**
- * Additional top spacing of the element when it becomes sticky.
- * @type {Numeric|Function}
- */
- topSpacing: 0,
-
- /**
- * Additional bottom spacing of the element when it becomes sticky.
- * @type {Numeric|Function}
- */
- bottomSpacing: 0,
-
- /**
- * Container sidebar selector to know what the beginning and end of sticky element.
- * @type {String|False}
- */
- containerSelector: false,
-
- /**
- * Inner wrapper selector.
- * @type {String}
- */
- innerWrapperSelector: '.inner-wrapper-sticky',
-
- /**
- * The name of CSS class to apply to elements when they have become stuck.
- * @type {String|False}
- */
- stickyClass: 'is-affixed',
-
- /**
- * Detect when sidebar and its container change height so re-calculate their dimensions.
- * @type {Boolean}
- */
- resizeSensor: true,
-
- /**
- * The sidebar returns to its normal position if its width below this value.
- * @type {Numeric}
- */
- minWidth: false
- };
-
- // ---------------------------------
- // # Class Definition
- // ---------------------------------
- //
- /**
- * Sticky Sidebar Class.
- * @public
- */
-
- var StickySidebar = function () {
-
- /**
- * Sticky Sidebar Constructor.
- * @constructor
- * @param {HTMLElement|String} sidebar - The sidebar element or sidebar selector.
- * @param {Object} options - The options of sticky sidebar.
- */
- function StickySidebar(sidebar) {
- var _this = this;
-
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- _classCallCheck(this, StickySidebar);
-
- this.options = StickySidebar.extend(DEFAULTS, options);
-
- // Sidebar element query if there's no one, throw error.
- this.sidebar = 'string' === typeof sidebar ? document.querySelector(sidebar) : sidebar;
- if ('undefined' === typeof this.sidebar) throw new Error("There is no specific sidebar element.");
-
- this.sidebarInner = false;
- this.container = this.sidebar.parentElement;
-
- // Current Affix Type of sidebar element.
- this.affixedType = 'STATIC';
- this.direction = 'down';
- this.support = {
- transform: false,
- transform3d: false
- };
-
- this._initialized = false;
- this._reStyle = false;
- this._breakpoint = false;
-
- // Dimensions of sidebar, container and screen viewport.
- this.dimensions = {
- translateY: 0,
- maxTranslateY: 0,
- topSpacing: 0,
- lastTopSpacing: 0,
- bottomSpacing: 0,
- lastBottomSpacing: 0,
- sidebarHeight: 0,
- sidebarWidth: 0,
- containerTop: 0,
- containerHeight: 0,
- viewportHeight: 0,
- viewportTop: 0,
- lastViewportTop: 0
- };
-
- // Bind event handlers for referencability.
- ['handleEvent'].forEach(function (method) {
- _this[method] = _this[method].bind(_this);
- });
-
- // Initialize sticky sidebar for first time.
- this.initialize();
- }
-
- /**
- * Initializes the sticky sidebar by adding inner wrapper, define its container,
- * min-width breakpoint, calculating dimensions, adding helper classes and inline style.
- * @private
- */
-
-
- _createClass(StickySidebar, [{
- key: 'initialize',
- value: function initialize() {
- var _this2 = this;
-
- this._setSupportFeatures();
-
- // Get sticky sidebar inner wrapper, if not found, will create one.
- if (this.options.innerWrapperSelector) {
- this.sidebarInner = this.sidebar.querySelector(this.options.innerWrapperSelector);
-
- if (null === this.sidebarInner) this.sidebarInner = false;
- }
-
- if (!this.sidebarInner) {
- var wrapper = document.createElement('div');
- wrapper.setAttribute('class', 'inner-wrapper-sticky');
- this.sidebar.appendChild(wrapper);
-
- while (this.sidebar.firstChild != wrapper) {
- wrapper.appendChild(this.sidebar.firstChild);
- }this.sidebarInner = this.sidebar.querySelector('.inner-wrapper-sticky');
- }
-
- // Container wrapper of the sidebar.
- if (this.options.containerSelector) {
- var containers = document.querySelectorAll(this.options.containerSelector);
- containers = Array.prototype.slice.call(containers);
-
- containers.forEach(function (container, item) {
- if (!container.contains(_this2.sidebar)) return;
- _this2.container = container;
- });
-
- if (!containers.length) throw new Error("The container does not contains on the sidebar.");
- }
-
- // If top/bottom spacing is not function parse value to integer.
- if ('function' !== typeof this.options.topSpacing) this.options.topSpacing = parseInt(this.options.topSpacing) || 0;
-
- if ('function' !== typeof this.options.bottomSpacing) this.options.bottomSpacing = parseInt(this.options.bottomSpacing) || 0;
-
- // Breakdown sticky sidebar if screen width below `options.minWidth`.
- this._widthBreakpoint();
-
- // Calculate dimensions of sidebar, container and viewport.
- this.calcDimensions();
-
- // Affix sidebar in proper position.
- this.stickyPosition();
-
- // Bind all events.
- this.bindEvents();
-
- // Inform other properties the sticky sidebar is initialized.
- this._initialized = true;
- }
- }, {
- key: 'bindEvents',
- value: function bindEvents() {
- window.addEventListener('resize', this, { passive: true, capture: false });
- window.addEventListener('scroll', this, { passive: true, capture: false });
-
- this.sidebar.addEventListener('update' + EVENT_KEY, this);
-
- if (this.options.resizeSensor && 'undefined' !== typeof ResizeSensor) {
- new ResizeSensor(this.sidebarInner, this.handleEvent);
- new ResizeSensor(this.container, this.handleEvent);
- }
- }
- }, {
- key: 'handleEvent',
- value: function handleEvent(event) {
- this.updateSticky(event);
- }
- }, {
- key: 'calcDimensions',
- value: function calcDimensions() {
- if (this._breakpoint) return;
- var dims = this.dimensions;
-
- // Container of sticky sidebar dimensions.
- dims.containerTop = StickySidebar.offsetRelative(this.container).top;
- dims.containerHeight = this.container.clientHeight;
- dims.containerBottom = dims.containerTop + dims.containerHeight;
-
- // Sidebar dimensions.
- dims.sidebarHeight = this.sidebarInner.offsetHeight;
- dims.sidebarWidth = this.sidebarInner.offsetWidth;
-
- // Screen viewport dimensions.
- dims.viewportHeight = window.innerHeight;
-
- // Maximum sidebar translate Y.
- dims.maxTranslateY = dims.containerHeight - dims.sidebarHeight;
-
- this._calcDimensionsWithScroll();
- }
- }, {
- key: '_calcDimensionsWithScroll',
- value: function _calcDimensionsWithScroll() {
- var dims = this.dimensions;
-
- dims.sidebarLeft = StickySidebar.offsetRelative(this.sidebar).left;
-
- dims.viewportTop = document.documentElement.scrollTop || document.body.scrollTop;
- dims.viewportBottom = dims.viewportTop + dims.viewportHeight;
- dims.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
-
- dims.topSpacing = this.options.topSpacing;
- dims.bottomSpacing = this.options.bottomSpacing;
-
- if ('function' === typeof dims.topSpacing) dims.topSpacing = parseInt(dims.topSpacing(this.sidebar)) || 0;
-
- if ('function' === typeof dims.bottomSpacing) dims.bottomSpacing = parseInt(dims.bottomSpacing(this.sidebar)) || 0;
-
- if ('VIEWPORT-TOP' === this.affixedType) {
- // Adjust translate Y in the case decrease top spacing value.
- if (dims.topSpacing < dims.lastTopSpacing) {
- dims.translateY += dims.lastTopSpacing - dims.topSpacing;
- this._reStyle = true;
- }
- } else if ('VIEWPORT-BOTTOM' === this.affixedType) {
- // Adjust translate Y in the case decrease bottom spacing value.
- if (dims.bottomSpacing < dims.lastBottomSpacing) {
- dims.translateY += dims.lastBottomSpacing - dims.bottomSpacing;
- this._reStyle = true;
- }
- }
-
- dims.lastTopSpacing = dims.topSpacing;
- dims.lastBottomSpacing = dims.bottomSpacing;
- }
- }, {
- key: 'isSidebarFitsViewport',
- value: function isSidebarFitsViewport() {
- var dims = this.dimensions;
- var offset = this.scrollDirection === 'down' ? dims.lastBottomSpacing : dims.lastTopSpacing;
- return this.dimensions.sidebarHeight + offset < this.dimensions.viewportHeight;
- }
- }, {
- key: 'observeScrollDir',
- value: function observeScrollDir() {
- var dims = this.dimensions;
- if (dims.lastViewportTop === dims.viewportTop) return;
-
- var furthest = 'down' === this.direction ? Math.min : Math.max;
-
- // If the browser is scrolling not in the same direction.
- if (dims.viewportTop === furthest(dims.viewportTop, dims.lastViewportTop)) this.direction = 'down' === this.direction ? 'up' : 'down';
- }
- }, {
- key: 'getAffixType',
- value: function getAffixType() {
- this._calcDimensionsWithScroll();
- var dims = this.dimensions;
- var colliderTop = dims.viewportTop + dims.topSpacing;
- var affixType = this.affixedType;
-
- if (colliderTop <= dims.containerTop || dims.containerHeight <= dims.sidebarHeight) {
- dims.translateY = 0;
- affixType = 'STATIC';
- } else {
- affixType = 'up' === this.direction ? this._getAffixTypeScrollingUp() : this._getAffixTypeScrollingDown();
- }
-
- // Make sure the translate Y is not bigger than container height.
- dims.translateY = Math.max(0, dims.translateY);
- dims.translateY = Math.min(dims.containerHeight, dims.translateY);
- dims.translateY = Math.round(dims.translateY);
-
- dims.lastViewportTop = dims.viewportTop;
- return affixType;
- }
- }, {
- key: '_getAffixTypeScrollingDown',
- value: function _getAffixTypeScrollingDown() {
- var dims = this.dimensions;
- var sidebarBottom = dims.sidebarHeight + dims.containerTop;
- var colliderTop = dims.viewportTop + dims.topSpacing;
- var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
- var affixType = this.affixedType;
-
- if (this.isSidebarFitsViewport()) {
- if (dims.sidebarHeight + colliderTop >= dims.containerBottom) {
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
- } else if (colliderTop >= dims.containerTop) {
- dims.translateY = colliderTop - dims.containerTop;
- affixType = 'VIEWPORT-TOP';
- }
- } else {
- if (dims.containerBottom <= colliderBottom) {
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
- } else if (sidebarBottom + dims.translateY <= colliderBottom) {
- dims.translateY = colliderBottom - sidebarBottom;
- affixType = 'VIEWPORT-BOTTOM';
- } else if (dims.containerTop + dims.translateY <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
- affixType = 'VIEWPORT-UNBOTTOM';
- }
- }
-
- return affixType;
- }
- }, {
- key: '_getAffixTypeScrollingUp',
- value: function _getAffixTypeScrollingUp() {
- var dims = this.dimensions;
- var sidebarBottom = dims.sidebarHeight + dims.containerTop;
- var colliderTop = dims.viewportTop + dims.topSpacing;
- var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
- var affixType = this.affixedType;
-
- if (colliderTop <= dims.translateY + dims.containerTop) {
- dims.translateY = colliderTop - dims.containerTop;
- affixType = 'VIEWPORT-TOP';
- } else if (dims.containerBottom <= colliderBottom) {
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
- } else if (!this.isSidebarFitsViewport()) {
-
- if (dims.containerTop <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
- affixType = 'VIEWPORT-UNBOTTOM';
- }
- }
-
- return affixType;
- }
- }, {
- key: '_getStyle',
- value: function _getStyle(affixType) {
- if ('undefined' === typeof affixType) return;
-
- var style = { inner: {}, outer: {} };
- var dims = this.dimensions;
-
- switch (affixType) {
- case 'VIEWPORT-TOP':
- style.inner = { position: 'fixed', top: dims.topSpacing,
- left: dims.sidebarLeft - dims.viewportLeft, width: dims.sidebarWidth };
- break;
- case 'VIEWPORT-BOTTOM':
- style.inner = { position: 'fixed', top: 'auto', left: dims.sidebarLeft,
- bottom: dims.bottomSpacing, width: dims.sidebarWidth };
- break;
- case 'CONTAINER-BOTTOM':
- case 'VIEWPORT-UNBOTTOM':
- var translate = this._getTranslate(0, dims.translateY + 'px');
-
- if (translate) style.inner = { transform: translate };else style.inner = { position: 'absolute', top: dims.translateY, width: dims.sidebarWidth };
- break;
- }
-
- switch (affixType) {
- case 'VIEWPORT-TOP':
- case 'VIEWPORT-BOTTOM':
- case 'VIEWPORT-UNBOTTOM':
- case 'CONTAINER-BOTTOM':
- style.outer = { height: dims.sidebarHeight, position: 'relative' };
- break;
- }
-
- style.outer = StickySidebar.extend({ height: '', position: '' }, style.outer);
- style.inner = StickySidebar.extend({ position: 'relative', top: '', left: '',
- bottom: '', width: '', transform: '' }, style.inner);
-
- return style;
- }
- }, {
- key: 'stickyPosition',
- value: function stickyPosition(force) {
- if (this._breakpoint) return;
-
- force = this._reStyle || force || false;
-
- var offsetTop = this.options.topSpacing;
- var offsetBottom = this.options.bottomSpacing;
-
- var affixType = this.getAffixType();
- var style = this._getStyle(affixType);
-
- if ((this.affixedType != affixType || force) && affixType) {
- var affixEvent = 'affix.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
- StickySidebar.eventTrigger(this.sidebar, affixEvent);
-
- if ('STATIC' === affixType) StickySidebar.removeClass(this.sidebar, this.options.stickyClass);else StickySidebar.addClass(this.sidebar, this.options.stickyClass);
-
- for (var key in style.outer) {
- var unit = 'number' === typeof style.outer[key] ? 'px' : '';
- this.sidebar.style[key] = style.outer[key] + unit;
- }
-
- for (var _key in style.inner) {
- var _unit = 'number' === typeof style.inner[_key] ? 'px' : '';
- this.sidebarInner.style[_key] = style.inner[_key] + _unit;
- }
-
- var affixedEvent = 'affixed.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
- StickySidebar.eventTrigger(this.sidebar, affixedEvent);
- } else {
- if (this._initialized) this.sidebarInner.style.left = style.inner.left;
- }
-
- this.affixedType = affixType;
- }
- }, {
- key: '_widthBreakpoint',
- value: function _widthBreakpoint() {
-
- if (window.innerWidth <= this.options.minWidth) {
- this._breakpoint = true;
- this.affixedType = 'STATIC';
-
- this.sidebar.removeAttribute('style');
- StickySidebar.removeClass(this.sidebar, this.options.stickyClass);
- this.sidebarInner.removeAttribute('style');
- } else {
- this._breakpoint = false;
- }
- }
- }, {
- key: 'updateSticky',
- value: function updateSticky() {
- var _this3 = this;
-
- var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- if (this._running) return;
- this._running = true;
-
- (function (eventType) {
- requestAnimationFrame(function () {
- switch (eventType) {
- // When browser is scrolling and re-calculate just dimensions
- // within scroll.
- case 'scroll':
- _this3._calcDimensionsWithScroll();
- _this3.observeScrollDir();
- _this3.stickyPosition();
- break;
-
- // When browser is resizing or there's no event, observe width
- // breakpoint and re-calculate dimensions.
- case 'resize':
- default:
- _this3._widthBreakpoint();
- _this3.calcDimensions();
- _this3.stickyPosition(true);
- break;
- }
- _this3._running = false;
- });
- })(event.type);
- }
- }, {
- key: '_setSupportFeatures',
- value: function _setSupportFeatures() {
- var support = this.support;
-
- support.transform = StickySidebar.supportTransform();
- support.transform3d = StickySidebar.supportTransform(true);
- }
- }, {
- key: '_getTranslate',
- value: function _getTranslate() {
- var y = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
- var x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
-
- if (this.support.transform3d) return 'translate3d(' + y + ', ' + x + ', ' + z + ')';else if (this.support.translate) return 'translate(' + y + ', ' + x + ')';else return false;
- }
- }, {
- key: 'destroy',
- value: function destroy() {
- window.removeEventListener('resize', this, { capture: false });
- window.removeEventListener('scroll', this, { capture: false });
-
- this.sidebar.classList.remove(this.options.stickyClass);
- this.sidebar.style.minHeight = '';
-
- this.sidebar.removeEventListener('update' + EVENT_KEY, this);
-
- var styleReset = { inner: {}, outer: {} };
-
- styleReset.inner = { position: '', top: '', left: '', bottom: '', width: '', transform: '' };
- styleReset.outer = { height: '', position: '' };
-
- for (var key in styleReset.outer) {
- this.sidebar.style[key] = styleReset.outer[key];
- }for (var _key2 in styleReset.inner) {
- this.sidebarInner.style[_key2] = styleReset.inner[_key2];
- }if (this.options.resizeSensor && 'undefined' !== typeof ResizeSensor) {
- ResizeSensor.detach(this.sidebarInner, this.handleEvent);
- ResizeSensor.detach(this.container, this.handleEvent);
- }
- }
- }], [{
- key: 'supportTransform',
- value: function supportTransform(transform3d) {
- var result = false,
- property = transform3d ? 'perspective' : 'transform',
- upper = property.charAt(0).toUpperCase() + property.slice(1),
- prefixes = ['Webkit', 'Moz', 'O', 'ms'],
- support = document.createElement('support'),
- style = support.style;
-
- (property + ' ' + prefixes.join(upper + ' ') + upper).split(' ').forEach(function (property, i) {
- if (style[property] !== undefined) {
- result = property;
- return false;
- }
- });
- return result;
- }
- }, {
- key: 'eventTrigger',
- value: function eventTrigger(element, eventName, data) {
- try {
- var event = new CustomEvent(eventName, { detail: data });
- } catch (e) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent(eventName, true, true, data);
- }
- element.dispatchEvent(event);
- }
- }, {
- key: 'extend',
- value: function extend(defaults, options) {
- var results = {};
- for (var key in defaults) {
- if ('undefined' !== typeof options[key]) results[key] = options[key];else results[key] = defaults[key];
- }
- return results;
- }
- }, {
- key: 'offsetRelative',
- value: function offsetRelative(element) {
- var result = { left: 0, top: 0 };
-
- do {
- var offsetTop = element.offsetTop;
- var offsetLeft = element.offsetLeft;
-
- if (!isNaN(offsetTop)) result.top += offsetTop;
-
- if (!isNaN(offsetLeft)) result.left += offsetLeft;
-
- element = 'BODY' === element.tagName ? element.parentElement : element.offsetParent;
- } while (element);
- return result;
- }
- }, {
- key: 'addClass',
- value: function addClass(element, className) {
- if (!StickySidebar.hasClass(element, className)) {
- if (element.classList) element.classList.add(className);else element.className += ' ' + className;
- }
- }
- }, {
- key: 'removeClass',
- value: function removeClass(element, className) {
- if (StickySidebar.hasClass(element, className)) {
- if (element.classList) element.classList.remove(className);else element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
- }
- }
- }, {
- key: 'hasClass',
- value: function hasClass(element, className) {
- if (element.classList) return element.classList.contains(className);else return new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className);
- }
- }, {
- key: 'defaults',
- get: function () {
- return DEFAULTS;
- }
- }]);
-
- return StickySidebar;
- }();
-
- return StickySidebar;
- }();
-
- exports.default = StickySidebar;
-
-
- // Global
- // -------------------------
- window.StickySidebar = StickySidebar;
-});
-});
-
-var stickySidebar$1 = unwrapExports(stickySidebar);
-
-exports['default'] = stickySidebar$1;
-exports.__moduleExports = stickySidebar;
-
-Object.defineProperty(exports, '__esModule', { value: true });
-
-})));
+ (global = global || self, factory(global.StickySidebar = {}));
+}(this, function (exports) { 'use strict';
+
+ var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
+
+ function unwrapExports (x) {
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
+ }
+
+ function createCommonjsModule(fn, module) {
+ return module = { exports: {} }, fn(module, module.exports), module.exports;
+ }
+
+ var stickySidebar = createCommonjsModule(function (module, exports) {
+ (function (global, factory) {
+ {
+ factory(exports);
+ }
+ })(commonjsGlobal, function (exports) {
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ }
+
+ var _createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+ }();
+
+ /**
+ * Sticky Sidebar JavaScript Plugin.
+ * @version 3.3.5
+ * @author Ahmed Bouhuolia
+ * @license The MIT License (MIT)
+ */
+ var StickySidebar = function () {
+
+ // ---------------------------------
+ // # Define Constants
+ // ---------------------------------
+ //
+ var EVENT_KEY = '.stickySidebar';
+
+ var DEFAULTS = {
+ /**
+ * Additional top spacing of the element when it becomes sticky.
+ * @type {Numeric|Function}
+ */
+ topSpacing: 0,
+
+ /**
+ * Additional bottom spacing of the element when it becomes sticky.
+ * @type {Numeric|Function}
+ */
+ bottomSpacing: 0,
+
+ /**
+ * Scroll container selector.
+ * @type {String|False}
+ */
+ scrollContainerSelector: false,
+
+ /**
+ * Container sidebar selector to know what the beginning and end of sticky element.
+ * @type {String|False}
+ */
+ containerSelector: false,
+
+ /**
+ * Inner wrapper selector.
+ * @type {String}
+ */
+ innerWrapperSelector: '.inner-wrapper-sticky',
+
+ /**
+ * The name of CSS class to apply to elements when they have become stuck.
+ * @type {String|False}
+ */
+ stickyClass: 'is-affixed',
+
+ /**
+ * Detect when sidebar and its container change height so re-calculate their dimensions.
+ * @type {Boolean}
+ */
+ resizeSensor: true,
+
+ /**
+ * The sidebar returns to its normal position if its width below this value.
+ * @type {Numeric}
+ */
+ minWidth: false,
+
+ /**
+ * Use native CSS position sticky.
+ * @type {Boolean}
+ */
+ nativeSticky: false
+ };
+
+ // ---------------------------------
+ // # Class Definition
+ // ---------------------------------
+ //
+ /**
+ * Sticky Sidebar Class.
+ * @public
+ */
+
+ var StickySidebar = function () {
+
+ /**
+ * Sticky Sidebar Constructor.
+ * @constructor
+ * @param {HTMLElement|String} sidebar - The sidebar element or sidebar selector.
+ * @param {Object} options - The options of sticky sidebar.
+ */
+ function StickySidebar(sidebar) {
+ var _this = this;
+
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ _classCallCheck(this, StickySidebar);
+
+ this.options = StickySidebar.extend(DEFAULTS, options);
+
+ // Sidebar element query if there's no one, throw error.
+ this.sidebar = 'string' === typeof sidebar ? document.querySelector(sidebar) : sidebar;
+ if ('undefined' === typeof this.sidebar) throw new Error("There is no specific sidebar element.");
+
+ this.sidebarInner = false;
+ this.container = this.sidebar.parentElement;
+
+ // Get scroll container, if provided
+ this.scrollContainer = this.options.scrollContainerSelector ? 'string' === typeof this.options.scrollContainerSelector ? document.querySelector(this.options.scrollContainerSelector) : this.options.scrollContainerSelector : undefined;
+
+ // Current Affix Type of sidebar element.
+ this.affixedType = 'STATIC';
+ this.direction = 'down';
+ this.support = {
+ transform: false,
+ transform3d: false
+ };
+
+ this._initialized = false;
+ this._reStyle = false;
+ this._breakpoint = false;
+
+ // Dimensions of sidebar, container and screen viewport.
+ this.dimensions = {
+ translateY: 0,
+ maxTranslateY: 0,
+ topSpacing: 0,
+ lastTopSpacing: 0,
+ bottomSpacing: 0,
+ lastBottomSpacing: 0,
+ sidebarHeight: 0,
+ sidebarWidth: 0,
+ containerTop: 0,
+ containerHeight: 0,
+ viewportHeight: 0,
+ viewportTop: 0,
+ lastViewportTop: 0
+ };
+
+ // Bind event handlers for referencability.
+ ['handleEvent'].forEach(function (method) {
+ _this[method] = _this[method].bind(_this);
+ });
+
+ // Initialize sticky sidebar for first time.
+ this.initialize();
+ }
+
+ /**
+ * Initializes the sticky sidebar by adding inner wrapper, define its container,
+ * min-width breakpoint, calculating dimensions, adding helper classes and inline style.
+ * @private
+ */
+
+
+ _createClass(StickySidebar, [{
+ key: 'initialize',
+ value: function initialize() {
+ var _this2 = this;
+
+ this._setSupportFeatures();
+
+ // Get sticky sidebar inner wrapper, if not found, will create one.
+ if (this.options.innerWrapperSelector) {
+ this.sidebarInner = this.sidebar.querySelector(this.options.innerWrapperSelector);
+
+ if (null === this.sidebarInner) this.sidebarInner = false;
+ }
+
+ if (!this.sidebarInner) {
+ var wrapper = document.createElement('div');
+ wrapper.setAttribute('class', 'inner-wrapper-sticky');
+ this.sidebar.appendChild(wrapper);
+
+ while (this.sidebar.firstChild != wrapper) {
+ wrapper.appendChild(this.sidebar.firstChild);
+ }this.sidebarInner = this.sidebar.querySelector('.inner-wrapper-sticky');
+ }
+
+ // Container wrapper of the sidebar.
+ if (this.options.containerSelector) {
+ var containers = document.querySelectorAll(this.options.containerSelector);
+ containers = Array.prototype.slice.call(containers);
+
+ containers.forEach(function (container, item) {
+ if (!container.contains(_this2.sidebar)) return;
+ _this2.container = container;
+ });
+
+ if (!containers.length) throw new Error("The container does not contains on the sidebar.");
+ }
+
+ // If top/bottom spacing is not function parse value to integer.
+ if ('function' !== typeof this.options.topSpacing) this.options.topSpacing = parseInt(this.options.topSpacing) || 0;
+
+ if ('function' !== typeof this.options.bottomSpacing) this.options.bottomSpacing = parseInt(this.options.bottomSpacing) || 0;
+
+ // Breakdown sticky sidebar if screen width below `options.minWidth`.
+ this._widthBreakpoint();
+
+ // Calculate dimensions of sidebar, container and viewport.
+ this.calcDimensions();
+
+ // Affix sidebar in proper position.
+ this.stickyPosition();
+
+ // Bind all events.
+ this.bindEvents();
+
+ // Inform other properties the sticky sidebar is initialized.
+ this._initialized = true;
+ }
+ }, {
+ key: 'bindEvents',
+ value: function bindEvents() {
+ var _this3 = this;
+
+ window.addEventListener('resize', this, { passive: true, capture: false });
+ (this.scrollContainer || window).addEventListener('scroll', this, { passive: true, capture: false });
+
+ this.sidebar.addEventListener('update' + EVENT_KEY, this);
+
+ if (this.options.resizeSensor && 'undefined' !== typeof ResizeObserver) {
+ this.resizeObserver = new ResizeObserver(function () {
+ return _this3.handleEvent({ type: 'resize' });
+ });
+ this.resizeObserver.observe(this.sidebarInner);
+ this.resizeObserver.observe(this.container);
+ if (this.scrollContainer) this.resizeObserver.observe(this.scrollContainer);
+ }
+ }
+ }, {
+ key: 'handleEvent',
+ value: function handleEvent(event) {
+ this.updateSticky(event);
+ }
+ }, {
+ key: 'calcDimensions',
+ value: function calcDimensions() {
+ if (this._breakpoint) return;
+ var dims = this.dimensions;
+
+ // Container of sticky sidebar dimensions.
+ dims.containerTop = StickySidebar.offsetRelative(this.container, this.scrollContainer).top;
+ dims.containerHeight = this.container.clientHeight;
+ dims.containerBottom = dims.containerTop + dims.containerHeight;
+
+ // Sidebar dimensions.
+ dims.sidebarHeight = this.sidebarInner.offsetHeight;
+ dims.sidebarWidth = this.sidebarInner.offsetWidth;
+
+ // Screen viewport dimensions.
+ if (this.scrollContainer) {
+ var scrollContainerPaddingTop = parseFloat(getComputedStyle(this.scrollContainer).paddingTop) || 0;
+ var scrollContainerPaddingBottom = parseFloat(getComputedStyle(this.scrollContainer).paddingBottom) || 0;
+
+ dims.viewportHeight = this.scrollContainer.clientHeight - scrollContainerPaddingTop - scrollContainerPaddingBottom;
+ } else {
+ dims.viewportHeight = window.innerHeight;
+ }
+
+ // Maximum sidebar translate Y.
+ dims.maxTranslateY = dims.containerHeight - dims.sidebarHeight;
+
+ this._calcDimensionsWithScroll();
+ }
+ }, {
+ key: '_calcDimensionsWithScroll',
+ value: function _calcDimensionsWithScroll() {
+ var dims = this.dimensions;
+
+ dims.sidebarLeft = StickySidebar.offsetRelative(this.sidebar, this.scrollContainer).left;
+
+ if (this.scrollContainer) {
+ var scrollContainerPaddingTop = parseFloat(getComputedStyle(this.scrollContainer).paddingTop) || 0;
+ var scrollContainerPaddingLeft = parseFloat(getComputedStyle(this.scrollContainer).paddingLeft) || 0;
+
+ dims.viewportTop = this.scrollContainer.scrollTop + scrollContainerPaddingTop;
+ dims.viewportLeft = this.scrollContainer.scrollLeft + scrollContainerPaddingLeft;
+ } else {
+ dims.viewportTop = document.documentElement.scrollTop || document.body.scrollTop;
+ dims.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
+ }
+ dims.viewportBottom = dims.viewportTop + dims.viewportHeight;
+
+ dims.topSpacing = this.options.topSpacing;
+ dims.bottomSpacing = this.options.bottomSpacing;
+
+ if ('function' === typeof dims.topSpacing) dims.topSpacing = parseInt(dims.topSpacing(this.sidebar)) || 0;
+
+ if ('function' === typeof dims.bottomSpacing) dims.bottomSpacing = parseInt(dims.bottomSpacing(this.sidebar)) || 0;
+
+ if ('VIEWPORT-TOP' === this.affixedType) {
+ // Adjust translate Y in the case decrease top spacing value.
+ if (dims.topSpacing < dims.lastTopSpacing) {
+ dims.translateY += dims.lastTopSpacing - dims.topSpacing;
+ this._reStyle = true;
+ }
+ } else if ('VIEWPORT-BOTTOM' === this.affixedType) {
+ // Adjust translate Y in the case decrease bottom spacing value.
+ if (dims.bottomSpacing < dims.lastBottomSpacing) {
+ dims.translateY += dims.lastBottomSpacing - dims.bottomSpacing;
+ this._reStyle = true;
+ }
+ }
+
+ dims.lastTopSpacing = dims.topSpacing;
+ dims.lastBottomSpacing = dims.bottomSpacing;
+ }
+ }, {
+ key: 'isSidebarFitsViewport',
+ value: function isSidebarFitsViewport() {
+ var dims = this.dimensions;
+ var offset = this.scrollDirection === 'down' ? dims.lastBottomSpacing : dims.lastTopSpacing;
+ return this.dimensions.sidebarHeight + offset < this.dimensions.viewportHeight;
+ }
+ }, {
+ key: 'observeScrollDir',
+ value: function observeScrollDir() {
+ var dims = this.dimensions;
+ if (dims.lastViewportTop === dims.viewportTop) return;
+
+ var furthest = 'down' === this.direction ? Math.min : Math.max;
+
+ // If the browser is scrolling not in the same direction.
+ if (dims.viewportTop === furthest(dims.viewportTop, dims.lastViewportTop)) this.direction = 'down' === this.direction ? 'up' : 'down';
+ }
+ }, {
+ key: 'getAffixType',
+ value: function getAffixType() {
+ this._calcDimensionsWithScroll();
+ var dims = this.dimensions;
+ var colliderTop = dims.viewportTop + dims.topSpacing;
+ var affixType = this.affixedType;
+
+ if (colliderTop <= dims.containerTop || dims.containerHeight <= dims.sidebarHeight) {
+ dims.translateY = 0;
+ affixType = 'STATIC';
+ } else {
+ affixType = 'up' === this.direction ? this._getAffixTypeScrollingUp() : this._getAffixTypeScrollingDown();
+ }
+
+ // Make sure the translate Y is not bigger than container height.
+ dims.translateY = Math.max(0, dims.translateY);
+ dims.translateY = Math.min(dims.containerHeight, dims.translateY);
+ dims.translateY = Math.round(dims.translateY);
+
+ dims.lastViewportTop = dims.viewportTop;
+ return affixType;
+ }
+ }, {
+ key: '_getAffixTypeScrollingDown',
+ value: function _getAffixTypeScrollingDown() {
+ var dims = this.dimensions;
+ var sidebarBottom = dims.sidebarHeight + dims.containerTop;
+ var colliderTop = dims.viewportTop + dims.topSpacing;
+ var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
+ var affixType = this.affixedType;
+
+ if (this.isSidebarFitsViewport()) {
+ if (dims.sidebarHeight + colliderTop >= dims.containerBottom) {
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
+ } else if (colliderTop >= dims.containerTop) {
+ dims.translateY = colliderTop - dims.containerTop;
+ affixType = 'VIEWPORT-TOP';
+ }
+ } else {
+ if (dims.containerBottom <= colliderBottom) {
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
+ } else if (sidebarBottom + dims.translateY <= colliderBottom) {
+ dims.translateY = colliderBottom - sidebarBottom;
+ affixType = 'VIEWPORT-BOTTOM';
+ } else if (dims.containerTop + dims.translateY <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
+ affixType = 'VIEWPORT-UNBOTTOM';
+ }
+ }
+
+ return affixType;
+ }
+ }, {
+ key: '_getAffixTypeScrollingUp',
+ value: function _getAffixTypeScrollingUp() {
+ var dims = this.dimensions;
+ var sidebarBottom = dims.sidebarHeight + dims.containerTop;
+ var colliderTop = dims.viewportTop + dims.topSpacing;
+ var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
+ var affixType = this.affixedType;
+
+ if (colliderTop <= dims.translateY + dims.containerTop) {
+ dims.translateY = colliderTop - dims.containerTop;
+ affixType = 'VIEWPORT-TOP';
+ } else if (dims.containerBottom <= colliderBottom) {
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
+ } else if (!this.isSidebarFitsViewport()) {
+
+ if (dims.containerTop <= colliderTop && 0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) {
+ affixType = 'VIEWPORT-UNBOTTOM';
+ }
+ }
+
+ return affixType;
+ }
+ }, {
+ key: '_getStyle',
+ value: function _getStyle(affixType) {
+ if ('undefined' === typeof affixType) return;
+
+ var style = { inner: {}, outer: {} };
+ var dims = this.dimensions;
+
+ if (this.options.nativeSticky) {
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ style.inner = { position: 'sticky', top: dims.topSpacing };
+ break;
+ case 'VIEWPORT-BOTTOM':
+ style.inner = { position: 'sticky', top: dims.viewportHeight - dims.sidebarHeight - dims.bottomSpacing };
+ break;
+ case 'CONTAINER-BOTTOM':
+ style.inner = { position: 'sticky', top: '100%' };
+ break;
+ case 'VIEWPORT-UNBOTTOM':
+ style.inner = { position: 'relative', top: dims.translateY };
+ break;
+ }
+
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ case 'VIEWPORT-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ case 'CONTAINER-BOTTOM':
+ style.outer = { height: '100%', position: 'relative' };
+ break;
+ }
+ } else {
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ style.inner = { position: 'fixed', top: dims.topSpacing,
+ left: dims.sidebarLeft - dims.viewportLeft, width: dims.sidebarWidth };
+ break;
+ case 'VIEWPORT-BOTTOM':
+ style.inner = { position: 'fixed', top: 'auto', left: dims.sidebarLeft,
+ bottom: dims.bottomSpacing, width: dims.sidebarWidth };
+ break;
+ case 'CONTAINER-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ var translate = this._getTranslate(0, dims.translateY + 'px');
+
+ if (translate) style.inner = { transform: translate };else style.inner = { position: 'absolute', top: dims.translateY, width: dims.sidebarWidth };
+ break;
+ }
+
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ case 'VIEWPORT-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ case 'CONTAINER-BOTTOM':
+ style.outer = { height: dims.sidebarHeight, position: 'relative' };
+ break;
+ }
+ }
+
+ style.outer = StickySidebar.extend({ height: '', position: '' }, style.outer);
+ style.inner = StickySidebar.extend({ position: 'relative', top: '', left: '',
+ bottom: '', width: '', transform: '' }, style.inner);
+
+ return style;
+ }
+ }, {
+ key: 'stickyPosition',
+ value: function stickyPosition(force) {
+ if (this._breakpoint) return;
+
+ force = this._reStyle || force || false;
+
+ var offsetTop = this.options.topSpacing;
+ var offsetBottom = this.options.bottomSpacing;
+
+ var affixType = this.getAffixType();
+ var style = this._getStyle(affixType);
+
+ if ((this.affixedType != affixType || force) && affixType) {
+ var affixEvent = 'affix.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
+ StickySidebar.eventTrigger(this.sidebar, affixEvent);
+
+ if ('STATIC' === affixType) StickySidebar.removeClass(this.sidebar, this.options.stickyClass);else StickySidebar.addClass(this.sidebar, this.options.stickyClass);
+
+ for (var key in style.outer) {
+ var unit = 'number' === typeof style.outer[key] ? 'px' : '';
+ this.sidebar.style[key] = style.outer[key] + unit;
+ }
+
+ for (var _key in style.inner) {
+ var _unit = 'number' === typeof style.inner[_key] ? 'px' : '';
+ this.sidebarInner.style[_key] = style.inner[_key] + _unit;
+ }
+
+ var affixedEvent = 'affixed.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
+ StickySidebar.eventTrigger(this.sidebar, affixedEvent);
+ } else {
+ if (this._initialized) this.sidebarInner.style.left = style.inner.left;
+ }
+
+ this.affixedType = affixType;
+ }
+ }, {
+ key: '_widthBreakpoint',
+ value: function _widthBreakpoint() {
+
+ if (window.innerWidth <= this.options.minWidth) {
+ this._breakpoint = true;
+ this.affixedType = 'STATIC';
+
+ this.sidebar.removeAttribute('style');
+ StickySidebar.removeClass(this.sidebar, this.options.stickyClass);
+ this.sidebarInner.removeAttribute('style');
+ } else {
+ this._breakpoint = false;
+ }
+ }
+ }, {
+ key: 'updateSticky',
+ value: function updateSticky() {
+ var _this4 = this;
+
+ var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ if (this._running) return;
+ this._running = true;
+
+ (function (eventType) {
+ requestAnimationFrame(function () {
+ switch (eventType) {
+ // When browser is scrolling and re-calculate just dimensions
+ // within scroll.
+ case 'scroll':
+ _this4._calcDimensionsWithScroll();
+ _this4.observeScrollDir();
+ _this4.stickyPosition();
+ break;
+
+ // When browser is resizing or there's no event, observe width
+ // breakpoint and re-calculate dimensions.
+ case 'resize':
+ default:
+ _this4._widthBreakpoint();
+ _this4.calcDimensions();
+ _this4.stickyPosition(true);
+ break;
+ }
+ _this4._running = false;
+ });
+ })(event.type);
+ }
+ }, {
+ key: '_setSupportFeatures',
+ value: function _setSupportFeatures() {
+ var support = this.support;
+
+ support.transform = StickySidebar.supportTransform();
+ support.transform3d = StickySidebar.supportTransform(true);
+ }
+ }, {
+ key: '_getTranslate',
+ value: function _getTranslate() {
+ var y = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var x = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
+
+ if (this.support.transform3d) return 'translate3d(' + y + ', ' + x + ', ' + z + ')';else if (this.support.translate) return 'translate(' + y + ', ' + x + ')';else return false;
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy() {
+ window.removeEventListener('resize', this, { capture: false });
+ window.removeEventListener('scroll', this, { capture: false });
+
+ this.sidebar.classList.remove(this.options.stickyClass);
+ this.sidebar.style.minHeight = '';
+
+ this.sidebar.removeEventListener('update' + EVENT_KEY, this);
+
+ var styleReset = { inner: {}, outer: {} };
+
+ styleReset.inner = { position: '', top: '', left: '', bottom: '', width: '', transform: '' };
+ styleReset.outer = { height: '', position: '' };
+
+ for (var key in styleReset.outer) {
+ this.sidebar.style[key] = styleReset.outer[key];
+ }for (var _key2 in styleReset.inner) {
+ this.sidebarInner.style[_key2] = styleReset.inner[_key2];
+ }if (this.options.resizeSensor && 'undefined' !== typeof ResizeObserver && this.resizeObserver) {
+ this.resizeObserver.unobserve(this.sidebarInner);
+ this.resizeObserver.unobserve(this.container);
+ if (this.scrollContainer) this.resizeObserver.unobserve(this.scrollContainer);
+ }
+ }
+ }], [{
+ key: 'supportTransform',
+ value: function supportTransform(transform3d) {
+ var result = false,
+ property = transform3d ? 'perspective' : 'transform',
+ upper = property.charAt(0).toUpperCase() + property.slice(1),
+ prefixes = ['Webkit', 'Moz', 'O', 'ms'],
+ support = document.createElement('support'),
+ style = support.style;
+
+ (property + ' ' + prefixes.join(upper + ' ') + upper).split(' ').forEach(function (property, i) {
+ if (style[property] !== undefined) {
+ result = property;
+ return false;
+ }
+ });
+ return result;
+ }
+ }, {
+ key: 'eventTrigger',
+ value: function eventTrigger(element, eventName, data) {
+ try {
+ var event = new CustomEvent(eventName, { detail: data });
+ } catch (e) {
+ var event = document.createEvent('CustomEvent');
+ event.initCustomEvent(eventName, true, true, data);
+ }
+ element.dispatchEvent(event);
+ }
+ }, {
+ key: 'extend',
+ value: function extend(defaults, options) {
+ var results = {};
+ for (var key in defaults) {
+ if ('undefined' !== typeof options[key]) results[key] = options[key];else results[key] = defaults[key];
+ }
+ return results;
+ }
+ }, {
+ key: 'offsetRelative',
+ value: function offsetRelative(element, scrollContainer) {
+ var result = { left: 0, top: 0 };
+
+ do {
+ var offsetTop = element.offsetTop;
+ var offsetLeft = element.offsetLeft;
+
+ if (!isNaN(offsetTop)) result.top += offsetTop;
+
+ if (!isNaN(offsetLeft)) result.left += offsetLeft;
+
+ element = 'BODY' === element.tagName ? element.parentElement : element.offsetParent;
+ } while (element !== scrollContainer && element);
+ return result;
+ }
+ }, {
+ key: 'addClass',
+ value: function addClass(element, className) {
+ if (!StickySidebar.hasClass(element, className)) {
+ if (element.classList) element.classList.add(className);else element.className += ' ' + className;
+ }
+ }
+ }, {
+ key: 'removeClass',
+ value: function removeClass(element, className) {
+ if (StickySidebar.hasClass(element, className)) {
+ if (element.classList) element.classList.remove(className);else element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
+ }
+ }
+ }, {
+ key: 'hasClass',
+ value: function hasClass(element, className) {
+ if (element.classList) return element.classList.contains(className);else return new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className);
+ }
+ }, {
+ key: 'defaults',
+ get: function () {
+ return DEFAULTS;
+ }
+ }]);
+
+ return StickySidebar;
+ }();
+
+ return StickySidebar;
+ }();
+
+ exports.default = StickySidebar;
+
+
+ // Global
+ // -------------------------
+ window.StickySidebar = StickySidebar;
+ });
+ });
+
+ var stickySidebar$1 = unwrapExports(stickySidebar);
+
+ exports.default = stickySidebar$1;
+ exports.__moduleExports = stickySidebar;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
//# sourceMappingURL=sticky-sidebar.js.map
diff --git a/dist/sticky-sidebar.js.map b/dist/sticky-sidebar.js.map
index a73d5cd..ba314fa 100644
--- a/dist/sticky-sidebar.js.map
+++ b/dist/sticky-sidebar.js.map
@@ -1 +1 @@
-{"version":3,"file":"sticky-sidebar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
\ No newline at end of file
+{"version":3,"file":"sticky-sidebar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
\ No newline at end of file
diff --git a/dist/sticky-sidebar.min.js b/dist/sticky-sidebar.min.js
index 1462f11..222be65 100644
--- a/dist/sticky-sidebar.min.js
+++ b/dist/sticky-sidebar.min.js
@@ -1,8 +1,8 @@
/**
* sticky-sidebar - A JavaScript plugin for making smart and high performance.
- * @version v3.3.1
+ * @version v3.3.5
* @link https://github.com/abouolia/sticky-sidebar
* @author Ahmed Bouhuolia
* @license The MIT License (MIT)
**/
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.StickySidebar={})}(this,function(t){"use strict";"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var e,i,n=(function(t,e){(function(t){Object.defineProperty(t,"__esModule",{value:!0});var l,n,e=function(){function n(t,e){for(var i=0;i=t.containerBottom?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):i>=t.containerTop&&(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):e+t.translateY<=n?(t.translateY=n-e,o="VIEWPORT-BOTTOM"):t.containerTop+t.translateY<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getAffixTypeScrollingUp",value:function(){var t=this.dimensions,e=t.sidebarHeight+t.containerTop,i=t.viewportTop+t.topSpacing,n=t.viewportBottom-t.bottomSpacing,o=this.affixedType;return i<=t.translateY+t.containerTop?(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):this.isSidebarFitsViewport()||t.containerTop<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getStyle",value:function(t){if(void 0!==t){var e={inner:{},outer:{}},i=this.dimensions;switch(t){case"VIEWPORT-TOP":e.inner={position:"fixed",top:i.topSpacing,left:i.sidebarLeft-i.viewportLeft,width:i.sidebarWidth};break;case"VIEWPORT-BOTTOM":e.inner={position:"fixed",top:"auto",left:i.sidebarLeft,bottom:i.bottomSpacing,width:i.sidebarWidth};break;case"CONTAINER-BOTTOM":case"VIEWPORT-UNBOTTOM":var n=this._getTranslate(0,i.translateY+"px");e.inner=n?{transform:n}:{position:"absolute",top:i.translateY,width:i.sidebarWidth}}switch(t){case"VIEWPORT-TOP":case"VIEWPORT-BOTTOM":case"VIEWPORT-UNBOTTOM":case"CONTAINER-BOTTOM":e.outer={height:i.sidebarHeight,position:"relative"}}return e.outer=c.extend({height:"",position:""},e.outer),e.inner=c.extend({position:"relative",top:"",left:"",bottom:"",width:"",transform:""},e.inner),e}}},{key:"stickyPosition",value:function(t){if(!this._breakpoint){t=this._reStyle||t||!1,this.options.topSpacing,this.options.bottomSpacing;var e=this.getAffixType(),i=this._getStyle(e);if((this.affixedType!=e||t)&&e){var n="affix."+e.toLowerCase().replace("viewport-","")+l;for(var o in c.eventTrigger(this.sidebar,n),"STATIC"===e?c.removeClass(this.sidebar,this.options.stickyClass):c.addClass(this.sidebar,this.options.stickyClass),i.outer){var s="number"==typeof i.outer[o]?"px":"";this.sidebar.style[o]=i.outer[o]+s}for(var r in i.inner){var a="number"==typeof i.inner[r]?"px":"";this.sidebarInner.style[r]=i.inner[r]+a}var p="affixed."+e.toLowerCase().replace("viewport-","")+l;c.eventTrigger(this.sidebar,p)}else this._initialized&&(this.sidebarInner.style.left=i.inner.left);this.affixedType=e}}},{key:"_widthBreakpoint",value:function(){window.innerWidth<=this.options.minWidth?(this._breakpoint=!0,this.affixedType="STATIC",this.sidebar.removeAttribute("style"),c.removeClass(this.sidebar,this.options.stickyClass),this.sidebarInner.removeAttribute("style")):this._breakpoint=!1}},{key:"updateSticky",value:function(){var t,e=this,i=0=t.containerBottom?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):i>=t.containerTop&&(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):e+t.translateY<=n?(t.translateY=n-e,o="VIEWPORT-BOTTOM"):t.containerTop+t.translateY<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getAffixTypeScrollingUp",value:function(){var t=this.dimensions,e=t.sidebarHeight+t.containerTop,i=t.viewportTop+t.topSpacing,n=t.viewportBottom-t.bottomSpacing,o=this.affixedType;return i<=t.translateY+t.containerTop?(t.translateY=i-t.containerTop,o="VIEWPORT-TOP"):t.containerBottom<=n?(t.translateY=t.containerBottom-e,o="CONTAINER-BOTTOM"):this.isSidebarFitsViewport()||t.containerTop<=i&&0!==t.translateY&&t.maxTranslateY!==t.translateY&&(o="VIEWPORT-UNBOTTOM"),o}},{key:"_getStyle",value:function(t){if(void 0!==t){var e={inner:{},outer:{}},i=this.dimensions;if(this.options.nativeSticky){switch(t){case"VIEWPORT-TOP":e.inner={position:"sticky",top:i.topSpacing};break;case"VIEWPORT-BOTTOM":e.inner={position:"sticky",top:i.viewportHeight-i.sidebarHeight-i.bottomSpacing};break;case"CONTAINER-BOTTOM":e.inner={position:"sticky",top:"100%"};break;case"VIEWPORT-UNBOTTOM":e.inner={position:"relative",top:i.translateY}}switch(t){case"VIEWPORT-TOP":case"VIEWPORT-BOTTOM":case"VIEWPORT-UNBOTTOM":case"CONTAINER-BOTTOM":e.outer={height:"100%",position:"relative"}}}else{switch(t){case"VIEWPORT-TOP":e.inner={position:"fixed",top:i.topSpacing,left:i.sidebarLeft-i.viewportLeft,width:i.sidebarWidth};break;case"VIEWPORT-BOTTOM":e.inner={position:"fixed",top:"auto",left:i.sidebarLeft,bottom:i.bottomSpacing,width:i.sidebarWidth};break;case"CONTAINER-BOTTOM":case"VIEWPORT-UNBOTTOM":var n=this._getTranslate(0,i.translateY+"px");e.inner=n?{transform:n}:{position:"absolute",top:i.translateY,width:i.sidebarWidth}}switch(t){case"VIEWPORT-TOP":case"VIEWPORT-BOTTOM":case"VIEWPORT-UNBOTTOM":case"CONTAINER-BOTTOM":e.outer={height:i.sidebarHeight,position:"relative"}}}return e.outer=p.extend({height:"",position:""},e.outer),e.inner=p.extend({position:"relative",top:"",left:"",bottom:"",width:"",transform:""},e.inner),e}}},{key:"stickyPosition",value:function(t){if(!this._breakpoint){t=this._reStyle||t||!1;this.options.topSpacing,this.options.bottomSpacing;var e=this.getAffixType(),i=this._getStyle(e);if((this.affixedType!=e||t)&&e){var n,o,t="affix."+e.toLowerCase().replace("viewport-","")+a;for(n in p.eventTrigger(this.sidebar,t),"STATIC"===e?p.removeClass(this.sidebar,this.options.stickyClass):p.addClass(this.sidebar,this.options.stickyClass),i.outer){var s="number"==typeof i.outer[n]?"px":"";this.sidebar.style[n]=i.outer[n]+s}for(o in i.inner){var r="number"==typeof i.inner[o]?"px":"";this.sidebarInner.style[o]=i.inner[o]+r}t="affixed."+e.toLowerCase().replace("viewport-","")+a;p.eventTrigger(this.sidebar,t)}else this._initialized&&(this.sidebarInner.style.left=i.inner.left);this.affixedType=e}}},{key:"_widthBreakpoint",value:function(){window.innerWidth<=this.options.minWidth?(this._breakpoint=!0,this.affixedType="STATIC",this.sidebar.removeAttribute("style"),p.removeClass(this.sidebar,this.options.stickyClass),this.sidebarInner.removeAttribute("style")):this._breakpoint=!1}},{key:"updateSticky",value:function(){var t,e=this,i=0
* @license The MIT License (MIT)
*/
const StickySidebar = (() => {
-
+
// ---------------------------------
// # Define Constants
// ---------------------------------
//
const EVENT_KEY = '.stickySidebar';
- const VERSION = '3.3.4';
-
+ const VERSION = '3.3.5';
+
const DEFAULTS = {
/**
* Additional top spacing of the element when it becomes sticky.
* @type {Numeric|Function}
*/
topSpacing: 0,
-
+
/**
* Additional bottom spacing of the element when it becomes sticky.
* @type {Numeric|Function}
*/
bottomSpacing: 0,
-
+
+ /**
+ * Scroll container selector.
+ * @type {String|False}
+ */
+ scrollContainerSelector: false,
+
/**
* Container sidebar selector to know what the beginning and end of sticky element.
* @type {String|False}
*/
containerSelector: false,
-
+
/**
* Inner wrapper selector.
* @type {String}
*/
innerWrapperSelector: '.inner-wrapper-sticky',
-
+
/**
* The name of CSS class to apply to elements when they have become stuck.
* @type {String|False}
*/
stickyClass: 'is-affixed',
-
+
/**
* Detect when sidebar and its container change height so re-calculate their dimensions.
* @type {Boolean}
*/
resizeSensor: true,
-
+
/**
* The sidebar returns to its normal position if its width below this value.
* @type {Numeric}
*/
- minWidth: false
+ minWidth: false,
+
+ /**
+ * Use native CSS position sticky.
+ * @type {Boolean}
+ */
+ nativeSticky: false
};
-
+
// ---------------------------------
// # Class Definition
// ---------------------------------
@@ -66,7 +78,7 @@ const StickySidebar = (() => {
* @public
*/
class StickySidebar{
-
+
/**
* Sticky Sidebar Constructor.
* @constructor
@@ -75,27 +87,34 @@ const StickySidebar = (() => {
*/
constructor(sidebar, options = {}){
this.options = StickySidebar.extend(DEFAULTS, options);
-
+
// Sidebar element query if there's no one, throw error.
this.sidebar = ('string' === typeof sidebar ) ? document.querySelector(sidebar) : sidebar;
if( 'undefined' === typeof this.sidebar )
throw new Error("There is no specific sidebar element.");
-
+
this.sidebarInner = false;
this.container = this.sidebar.parentElement;
-
+
+ // Get scroll container, if provided
+ this.scrollContainer = this.options.scrollContainerSelector
+ ? 'string' === typeof this.options.scrollContainerSelector
+ ? document.querySelector(this.options.scrollContainerSelector)
+ : this.options.scrollContainerSelector
+ : undefined;
+
// Current Affix Type of sidebar element.
this.affixedType = 'STATIC';
this.direction = 'down';
- this.support = {
+ this.support = {
transform: false,
transform3d: false
};
-
+
this._initialized = false;
this._reStyle = false;
this._breakpoint = false;
-
+
// Dimensions of sidebar, container and screen viewport.
this.dimensions = {
translateY: 0,
@@ -109,99 +128,101 @@ const StickySidebar = (() => {
containerTop: 0,
containerHeight: 0,
viewportHeight: 0,
- viewportTop: 0,
+ viewportTop: 0,
lastViewportTop: 0,
};
-
+
// Bind event handlers for referencability.
['handleEvent'].forEach( (method) => {
this[method] = this[method].bind(this);
});
-
+
// Initialize sticky sidebar for first time.
this.initialize();
}
-
+
/**
- * Initializes the sticky sidebar by adding inner wrapper, define its container,
+ * Initializes the sticky sidebar by adding inner wrapper, define its container,
* min-width breakpoint, calculating dimensions, adding helper classes and inline style.
* @private
*/
initialize(){
this._setSupportFeatures();
-
+
// Get sticky sidebar inner wrapper, if not found, will create one.
if( this.options.innerWrapperSelector ){
this.sidebarInner = this.sidebar.querySelector(this.options.innerWrapperSelector);
-
+
if( null === this.sidebarInner )
this.sidebarInner = false;
}
-
+
if( ! this.sidebarInner ){
let wrapper = document.createElement('div');
wrapper.setAttribute('class', 'inner-wrapper-sticky');
this.sidebar.appendChild(wrapper);
-
+
while( this.sidebar.firstChild != wrapper )
wrapper.appendChild(this.sidebar.firstChild);
-
+
this.sidebarInner = this.sidebar.querySelector('.inner-wrapper-sticky');
}
-
+
// Container wrapper of the sidebar.
if( this.options.containerSelector ){
let containers = document.querySelectorAll(this.options.containerSelector);
containers = Array.prototype.slice.call(containers);
-
+
containers.forEach((container, item) => {
if( ! container.contains(this.sidebar) ) return;
this.container = container;
});
-
+
if( ! containers.length )
throw new Error("The container does not contains on the sidebar.");
}
-
+
// If top/bottom spacing is not function parse value to integer.
if( 'function' !== typeof this.options.topSpacing )
this.options.topSpacing = parseInt(this.options.topSpacing) || 0;
-
+
if( 'function' !== typeof this.options.bottomSpacing )
this.options.bottomSpacing = parseInt(this.options.bottomSpacing) || 0;
-
+
// Breakdown sticky sidebar if screen width below `options.minWidth`.
this._widthBreakpoint();
-
+
// Calculate dimensions of sidebar, container and viewport.
this.calcDimensions();
-
+
// Affix sidebar in proper position.
this.stickyPosition();
-
+
// Bind all events.
this.bindEvents();
-
+
// Inform other properties the sticky sidebar is initialized.
this._initialized = true;
}
-
+
/**
* Bind all events of sticky sidebar plugin.
* @protected
*/
bindEvents(){
window.addEventListener('resize', this, {passive: true, capture: false});
- window.addEventListener('scroll', this, {passive: true, capture: false});
-
+ (this.scrollContainer || window).addEventListener('scroll', this, {passive: true, capture: false});
+
this.sidebar.addEventListener('update' + EVENT_KEY, this);
-
- if( this.options.resizeSensor && 'undefined' !== typeof ResizeSensor ){
- new ResizeSensor(this.sidebarInner, this.handleEvent);
- new ResizeSensor(this.container, this.handleEvent);
+
+ if( this.options.resizeSensor && 'undefined' !== typeof ResizeObserver ){
+ this.resizeObserver = new ResizeObserver(() => this.handleEvent({ type: 'resize' }));
+ this.resizeObserver.observe(this.sidebarInner);
+ this.resizeObserver.observe(this.container);
+ if( this.scrollContainer ) this.resizeObserver.observe(this.scrollContainer);
}
}
-
+
/**
* Handles all events of the plugin.
* @param {Object} event - Event object passed from listener.
@@ -209,7 +230,7 @@ const StickySidebar = (() => {
handleEvent(event){
this.updateSticky(event);
}
-
+
/**
* Calculates dimensions of sidebar, container and screen viewpoint
* @public
@@ -217,52 +238,67 @@ const StickySidebar = (() => {
calcDimensions(){
if( this._breakpoint ) return;
var dims = this.dimensions;
-
+
// Container of sticky sidebar dimensions.
- dims.containerTop = StickySidebar.offsetRelative(this.container).top;
+ dims.containerTop = StickySidebar.offsetRelative(this.container, this.scrollContainer).top;
dims.containerHeight = this.container.clientHeight;
dims.containerBottom = dims.containerTop + dims.containerHeight;
-
+
// Sidebar dimensions.
dims.sidebarHeight = this.sidebarInner.offsetHeight;
dims.sidebarWidth = this.sidebarInner.offsetWidth;
-
+
// Screen viewport dimensions.
- dims.viewportHeight = window.innerHeight;
+ if( this.scrollContainer ){
+ var scrollContainerPaddingTop = parseFloat(getComputedStyle(this.scrollContainer).paddingTop) || 0
+ var scrollContainerPaddingBottom = parseFloat(getComputedStyle(this.scrollContainer).paddingBottom) || 0
+
+ dims.viewportHeight = this.scrollContainer.clientHeight - scrollContainerPaddingTop - scrollContainerPaddingBottom;
+ } else {
+ dims.viewportHeight = window.innerHeight;
+ }
// Maximum sidebar translate Y.
dims.maxTranslateY = dims.containerHeight - dims.sidebarHeight;
this._calcDimensionsWithScroll();
}
-
+
/**
* Some dimensions values need to be up-to-date when scrolling the page.
* @private
*/
_calcDimensionsWithScroll(){
var dims = this.dimensions;
-
- dims.sidebarLeft = StickySidebar.offsetRelative(this.sidebar).left;
-
- dims.viewportTop = document.documentElement.scrollTop || document.body.scrollTop;
+
+ dims.sidebarLeft = StickySidebar.offsetRelative(this.sidebar, this.scrollContainer).left;
+
+ if( this.scrollContainer ){
+ var scrollContainerPaddingTop = parseFloat(getComputedStyle(this.scrollContainer).paddingTop) || 0
+ var scrollContainerPaddingLeft = parseFloat(getComputedStyle(this.scrollContainer).paddingLeft) || 0
+
+ dims.viewportTop = this.scrollContainer.scrollTop + scrollContainerPaddingTop;
+ dims.viewportLeft = this.scrollContainer.scrollLeft + scrollContainerPaddingLeft;
+ } else {
+ dims.viewportTop = document.documentElement.scrollTop || document.body.scrollTop;
+ dims.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
+ }
dims.viewportBottom = dims.viewportTop + dims.viewportHeight;
- dims.viewportLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
-
+
dims.topSpacing = this.options.topSpacing;
dims.bottomSpacing = this.options.bottomSpacing;
-
+
if( 'function' === typeof dims.topSpacing )
dims.topSpacing = parseInt(dims.topSpacing(this.sidebar)) || 0;
-
+
if( 'function' === typeof dims.bottomSpacing )
dims.bottomSpacing = parseInt(dims.bottomSpacing(this.sidebar)) || 0;
-
+
if( 'VIEWPORT-TOP' === this.affixedType ){
// Adjust translate Y in the case decrease top spacing value.
if( dims.topSpacing < dims.lastTopSpacing ){
dims.translateY += dims.lastTopSpacing - dims.topSpacing;
- this._reStyle = true;
+ this._reStyle = true;
}
} else if( 'VIEWPORT-BOTTOM' === this.affixedType ){
// Adjust translate Y in the case decrease bottom spacing value.
@@ -271,11 +307,11 @@ const StickySidebar = (() => {
this._reStyle = true;
}
}
-
+
dims.lastTopSpacing = dims.topSpacing;
dims.lastBottomSpacing = dims.bottomSpacing;
}
-
+
/**
* Determine whether the sidebar is bigger than viewport.
* @public
@@ -286,21 +322,21 @@ const StickySidebar = (() => {
let offset = this.scrollDirection === 'down' ? dims.lastBottomSpacing : dims.lastTopSpacing;
return this.dimensions.sidebarHeight + offset < this.dimensions.viewportHeight;
}
-
+
/**
* Observe browser scrolling direction top and down.
*/
observeScrollDir(){
var dims = this.dimensions;
if( dims.lastViewportTop === dims.viewportTop ) return;
-
+
var furthest = 'down' === this.direction ? Math.min : Math.max;
-
+
// If the browser is scrolling not in the same direction.
if( dims.viewportTop === furthest(dims.viewportTop, dims.lastViewportTop) )
this.direction = 'down' === this.direction ? 'up' : 'down';
}
-
+
/**
* Gets affix type of sidebar according to current scroll top and scrolling direction.
* @public
@@ -316,7 +352,7 @@ const StickySidebar = (() => {
dims.translateY = 0;
affixType = 'STATIC';
} else {
- affixType = ( 'up' === this.direction ) ?
+ affixType = ( 'up' === this.direction ) ?
this._getAffixTypeScrollingUp() : this._getAffixTypeScrollingDown();
}
@@ -324,7 +360,7 @@ const StickySidebar = (() => {
dims.translateY = Math.max(0, dims.translateY);
dims.translateY = Math.min(dims.containerHeight, dims.translateY);
dims.translateY = Math.round(dims.translateY);
-
+
dims.lastViewportTop = dims.viewportTop;
return affixType;
}
@@ -340,11 +376,11 @@ const StickySidebar = (() => {
var colliderTop = dims.viewportTop + dims.topSpacing;
var colliderBottom = dims.viewportBottom - dims.bottomSpacing;
var affixType = this.affixedType;
-
+
if( this.isSidebarFitsViewport() ){
if( dims.sidebarHeight + colliderTop >= dims.containerBottom ){
dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
+ affixType = 'CONTAINER-BOTTOM';
} else if( colliderTop >= dims.containerTop ){
dims.translateY = colliderTop - dims.containerTop;
@@ -352,13 +388,13 @@ const StickySidebar = (() => {
}
} else {
if( dims.containerBottom <= colliderBottom ){
- dims.translateY = dims.containerBottom - sidebarBottom;
- affixType = 'CONTAINER-BOTTOM';
+ dims.translateY = dims.containerBottom - sidebarBottom;
+ affixType = 'CONTAINER-BOTTOM';
} else if( sidebarBottom + dims.translateY <= colliderBottom ){
dims.translateY = colliderBottom - sidebarBottom;
affixType = 'VIEWPORT-BOTTOM';
-
+
} else if( dims.containerTop + dims.translateY <= colliderTop &&
(0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) ){
affixType = 'VIEWPORT-UNBOTTOM';
@@ -367,7 +403,7 @@ const StickySidebar = (() => {
return affixType;
}
-
+
/**
* Get affix type while scrolling up.
* @private
@@ -383,24 +419,24 @@ const StickySidebar = (() => {
if( colliderTop <= dims.translateY + dims.containerTop ){
dims.translateY = colliderTop - dims.containerTop;
affixType = 'VIEWPORT-TOP';
-
+
} else if( dims.containerBottom <= colliderBottom ){
dims.translateY = dims.containerBottom - sidebarBottom;
affixType = 'CONTAINER-BOTTOM';
} else if( ! this.isSidebarFitsViewport() ){
- if( dims.containerTop <= colliderTop &&
+ if( dims.containerTop <= colliderTop &&
(0 !== dims.translateY && dims.maxTranslateY !== dims.translateY) ){
affixType = 'VIEWPORT-UNBOTTOM';
- }
+ }
}
return affixType;
}
/**
- * Gets inline style of sticky sidebar wrapper and inner wrapper according
+ * Gets inline style of sticky sidebar wrapper and inner wrapper according
* to its affix type.
* @private
* @param {String} affixType - Affix type of sticky sidebar.
@@ -408,46 +444,72 @@ const StickySidebar = (() => {
*/
_getStyle(affixType){
if( 'undefined' === typeof affixType ) return;
-
+
var style = {inner: {}, outer: {}};
var dims = this.dimensions;
-
- switch( affixType ){
- case 'VIEWPORT-TOP':
- style.inner = {position: 'fixed', top: dims.topSpacing,
- left: dims.sidebarLeft - dims.viewportLeft, width: dims.sidebarWidth};
- break;
- case 'VIEWPORT-BOTTOM':
- style.inner = {position: 'fixed', top: 'auto', left: dims.sidebarLeft,
- bottom: dims.bottomSpacing, width: dims.sidebarWidth};
- break;
- case 'CONTAINER-BOTTOM':
- case 'VIEWPORT-UNBOTTOM':
- let translate = this._getTranslate(0, dims.translateY + 'px');
-
- if( translate )
- style.inner = {transform: translate};
- else
- style.inner = {position: 'absolute', top: dims.translateY, width: dims.sidebarWidth};
- break;
- }
-
- switch( affixType ){
- case 'VIEWPORT-TOP':
- case 'VIEWPORT-BOTTOM':
- case 'VIEWPORT-UNBOTTOM':
- case 'CONTAINER-BOTTOM':
- style.outer = {height: dims.sidebarHeight, position: 'relative'};
- break;
+
+ if( this.options.nativeSticky ){
+ switch ( affixType ) {
+ case 'VIEWPORT-TOP':
+ style.inner = {position: 'sticky', top: dims.topSpacing};
+ break;
+ case 'VIEWPORT-BOTTOM':
+ style.inner = {position: 'sticky', top: dims.viewportHeight - dims.sidebarHeight - dims.bottomSpacing};
+ break;
+ case 'CONTAINER-BOTTOM':
+ style.inner = {position: 'sticky', top: '100%'};
+ break;
+ case 'VIEWPORT-UNBOTTOM':
+ style.inner = {position: 'relative', top: dims.translateY};
+ break;
+ }
+
+ switch (affixType) {
+ case 'VIEWPORT-TOP':
+ case 'VIEWPORT-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ case 'CONTAINER-BOTTOM':
+ style.outer = {height: '100%', position: 'relative'};
+ break;
+ }
+ } else {
+ switch( affixType ){
+ case 'VIEWPORT-TOP':
+ style.inner = {position: 'fixed', top: dims.topSpacing,
+ left: dims.sidebarLeft - dims.viewportLeft, width: dims.sidebarWidth};
+ break;
+ case 'VIEWPORT-BOTTOM':
+ style.inner = {position: 'fixed', top: 'auto', left: dims.sidebarLeft,
+ bottom: dims.bottomSpacing, width: dims.sidebarWidth};
+ break;
+ case 'CONTAINER-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ let translate = this._getTranslate(0, dims.translateY + 'px');
+
+ if( translate )
+ style.inner = {transform: translate};
+ else
+ style.inner = {position: 'absolute', top: dims.translateY, width: dims.sidebarWidth};
+ break;
+ }
+
+ switch( affixType ){
+ case 'VIEWPORT-TOP':
+ case 'VIEWPORT-BOTTOM':
+ case 'VIEWPORT-UNBOTTOM':
+ case 'CONTAINER-BOTTOM':
+ style.outer = {height: dims.sidebarHeight, position: 'relative'};
+ break;
+ }
}
-
+
style.outer = StickySidebar.extend({height: '', position: ''}, style.outer);
style.inner = StickySidebar.extend({position: 'relative', top: '', left: '',
bottom: '', width: '', transform: ''}, style.inner);
-
+
return style;
}
-
+
/**
* Cause the sidebar to be sticky according to affix type by adding inline
* style, adding helper class and trigger events.
@@ -457,53 +519,53 @@ const StickySidebar = (() => {
*/
stickyPosition(force){
if( this._breakpoint ) return;
-
+
force = this._reStyle || force || false;
-
+
var offsetTop = this.options.topSpacing;
var offsetBottom = this.options.bottomSpacing;
-
+
var affixType = this.getAffixType();
var style = this._getStyle(affixType);
-
+
if( (this.affixedType != affixType || force) && affixType ){
let affixEvent = 'affix.' + affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
StickySidebar.eventTrigger(this.sidebar, affixEvent);
-
+
if( 'STATIC' === affixType )
StickySidebar.removeClass(this.sidebar, this.options.stickyClass);
else
StickySidebar.addClass(this.sidebar, this.options.stickyClass);
-
+
for( let key in style.outer ){
let unit = ('number' === typeof style.outer[key]) ? 'px' : '';
this.sidebar.style[key] = style.outer[key] + unit;
}
-
+
for( let key in style.inner ){
let unit = ('number' === typeof style.inner[key]) ? 'px' : '';
this.sidebarInner.style[key] = style.inner[key] + unit;
}
-
+
let affixedEvent = 'affixed.'+ affixType.toLowerCase().replace('viewport-', '') + EVENT_KEY;
StickySidebar.eventTrigger(this.sidebar, affixedEvent);
} else {
if( this._initialized ) this.sidebarInner.style.left = style.inner.left;
}
-
+
this.affixedType = affixType;
}
-
+
/**
* Breakdown sticky sidebar when window width is below `options.minWidth` value.
* @protected
*/
_widthBreakpoint(){
-
+
if( window.innerWidth <= this.options.minWidth ){
this._breakpoint = true;
this.affixedType = 'STATIC';
-
+
this.sidebar.removeAttribute('style');
StickySidebar.removeClass(this.sidebar, this.options.stickyClass);
this.sidebarInner.removeAttribute('style');
@@ -511,31 +573,31 @@ const StickySidebar = (() => {
this._breakpoint = false;
}
}
-
+
/**
- * Switches between functions stack for each event type, if there's no
+ * Switches between functions stack for each event type, if there's no
* event, it will re-initialize sticky sidebar.
* @public
*/
updateSticky(event = {}){
if( this._running ) return;
this._running = true;
-
+
((eventType) => {
requestAnimationFrame(() => {
switch( eventType ){
// When browser is scrolling and re-calculate just dimensions
- // within scroll.
+ // within scroll.
case 'scroll':
this._calcDimensionsWithScroll();
this.observeScrollDir();
this.stickyPosition();
break;
-
+
// When browser is resizing or there's no event, observe width
// breakpoint and re-calculate dimensions.
case 'resize':
- default:
+ default:
this._widthBreakpoint();
this.calcDimensions();
this.stickyPosition(true);
@@ -545,18 +607,18 @@ const StickySidebar = (() => {
});
})(event.type);
}
-
+
/**
* Set browser support features to the public property.
* @private
*/
_setSupportFeatures(){
var support = this.support;
-
+
support.transform = StickySidebar.supportTransform();
support.transform3d = StickySidebar.supportTransform(true);
}
-
+
/**
* Get translate value, if the browser supports transfrom3d, it will adopt it.
* and the same with translate. if browser doesn't support both return false.
@@ -570,7 +632,7 @@ const StickySidebar = (() => {
else if( this.support.translate ) return 'translate('+ y +', '+ x +')';
else return false;
}
-
+
/**
* Destroy sticky sidebar plugin.
* @public
@@ -578,29 +640,30 @@ const StickySidebar = (() => {
destroy(){
window.removeEventListener('resize', this, {capture: false});
window.removeEventListener('scroll', this, {capture: false});
-
+
this.sidebar.classList.remove(this.options.stickyClass);
this.sidebar.style.minHeight = '';
-
+
this.sidebar.removeEventListener('update' + EVENT_KEY, this);
-
+
var styleReset = {inner: {}, outer: {}};
-
+
styleReset.inner = {position: '', top: '', left: '', bottom: '', width: '', transform: ''};
styleReset.outer = {height: '', position: ''};
-
+
for( let key in styleReset.outer )
this.sidebar.style[key] = styleReset.outer[key];
-
+
for( let key in styleReset.inner )
this.sidebarInner.style[key] = styleReset.inner[key];
-
- if( this.options.resizeSensor && 'undefined' !== typeof ResizeSensor ){
- ResizeSensor.detach(this.sidebarInner, this.handleEvent);
- ResizeSensor.detach(this.container, this.handleEvent);
+
+ if( this.options.resizeSensor && 'undefined' !== typeof ResizeObserver && this.resizeObserver ){
+ this.resizeObserver.unobserve(this.sidebarInner);
+ this.resizeObserver.unobserve(this.container);
+ if( this.scrollContainer ) this.resizeObserver.unobserve(this.scrollContainer);
}
}
-
+
/**
* Determine if the browser supports CSS transform feature.
* @function
@@ -615,7 +678,7 @@ const StickySidebar = (() => {
prefixes = ['Webkit', 'Moz', 'O', 'ms'],
support = document.createElement('support'),
style = support.style;
-
+
(property + ' ' + prefixes.join(upper + ' ') + upper).split(' ').forEach(function(property, i) {
if (style[property] !== undefined) {
result = property;
@@ -624,13 +687,13 @@ const StickySidebar = (() => {
});
return result;
}
-
+
/**
* Trigger custom event.
* @static
* @param {DOMObject} element - Target element on the DOM.
* @param {String} eventName - Event name.
- * @param {Object} data -
+ * @param {Object} data -
*/
static eventTrigger(element, eventName, data){
try{
@@ -641,7 +704,7 @@ const StickySidebar = (() => {
}
element.dispatchEvent(event);
}
-
+
/**
* Extend options object with defaults.
* @function
@@ -655,35 +718,35 @@ const StickySidebar = (() => {
}
return results;
}
-
+
/**
* Get current coordinates left and top of specific element.
* @static
*/
- static offsetRelative(element){
+ static offsetRelative(element, scrollContainer){
var result = {left: 0, top: 0};
do{
let offsetTop = element.offsetTop;
let offsetLeft = element.offsetLeft;
-
+
if( ! isNaN(offsetTop) )
result.top += offsetTop;
-
+
if( ! isNaN(offsetLeft) )
result.left += offsetLeft;
element = ( 'BODY' === element.tagName ) ?
element.parentElement : element.offsetParent;
- } while(element)
+ } while (element !== scrollContainer && element);
return result;
}
-
+
/**
* Add specific class name to specific element.
- * @static
- * @param {ObjectDOM} element
- * @param {String} className
+ * @static
+ * @param {ObjectDOM} element
+ * @param {String} className
*/
static addClass(element, className){
if( ! StickySidebar.hasClass(element, className) ){
@@ -693,12 +756,12 @@ const StickySidebar = (() => {
element.className += ' ' + className;
}
}
-
+
/**
* Remove specific class name to specific element
* @static
- * @param {ObjectDOM} element
- * @param {String} className
+ * @param {ObjectDOM} element
+ * @param {String} className
*/
static removeClass(element, className){
if( StickySidebar.hasClass(element, className) ){
@@ -712,8 +775,8 @@ const StickySidebar = (() => {
/**
* Determine weather the element has specific class name.
* @static
- * @param {ObjectDOM} element
- * @param {String} className
+ * @param {ObjectDOM} element
+ * @param {String} className
*/
static hasClass(element, className){
if (element.classList)
@@ -725,18 +788,18 @@ const StickySidebar = (() => {
/**
* Gets default values of configuration options.
* @static
- * @return {Object}
+ * @return {Object}
*/
static get defaults(){
return DEFAULTS;
}
}
-
+
return StickySidebar;
})();
-
+
export default StickySidebar;
-
+
// Global
// -------------------------
- window.StickySidebar = StickySidebar;
\ No newline at end of file
+ window.StickySidebar = StickySidebar;