123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /**
- * angular-strap
- * @version v2.3.9 - 2016-06-10
- * @link http://mgcrea.github.io/angular-strap
- * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
- * @license MIT License, http://www.opensource.org/licenses/MIT
- */
- 'use strict';
- angular.module('mgcrea.ngStrap.affix', [ 'mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce' ]).provider('$affix', function() {
- var defaults = this.defaults = {
- offsetTop: 'auto',
- inlineStyles: true
- };
- this.$get = [ '$window', 'debounce', 'dimensions', function($window, debounce, dimensions) {
- var bodyEl = angular.element($window.document.body);
- var windowEl = angular.element($window);
- function AffixFactory(element, config) {
- var $affix = {};
- var options = angular.extend({}, defaults, config);
- var targetEl = options.target;
- var reset = 'affix affix-top affix-bottom';
- var setWidth = false;
- var initialAffixTop = 0;
- var initialOffsetTop = 0;
- var offsetTop = 0;
- var offsetBottom = 0;
- var affixed = null;
- var unpin = null;
- var parent = element.parent();
- if (options.offsetParent) {
- if (options.offsetParent.match(/^\d+$/)) {
- for (var i = 0; i < options.offsetParent * 1 - 1; i++) {
- parent = parent.parent();
- }
- } else {
- parent = angular.element(options.offsetParent);
- }
- }
- $affix.init = function() {
- this.$parseOffsets();
- initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;
- setWidth = !element[0].style.width;
- targetEl.on('scroll', this.checkPosition);
- targetEl.on('click', this.checkPositionWithEventLoop);
- windowEl.on('resize', this.$debouncedOnResize);
- this.checkPosition();
- this.checkPositionWithEventLoop();
- };
- $affix.destroy = function() {
- targetEl.off('scroll', this.checkPosition);
- targetEl.off('click', this.checkPositionWithEventLoop);
- windowEl.off('resize', this.$debouncedOnResize);
- };
- $affix.checkPositionWithEventLoop = function() {
- setTimeout($affix.checkPosition, 1);
- };
- $affix.checkPosition = function() {
- var scrollTop = getScrollTop();
- var position = dimensions.offset(element[0]);
- var elementHeight = dimensions.height(element[0]);
- var affix = getRequiredAffixClass(unpin, position, elementHeight);
- if (affixed === affix) return;
- affixed = affix;
- if (affix === 'top') {
- unpin = null;
- if (setWidth) {
- element.css('width', '');
- }
- if (options.inlineStyles) {
- element.css('position', options.offsetParent ? '' : 'relative');
- element.css('top', '');
- }
- } else if (affix === 'bottom') {
- if (options.offsetUnpin) {
- unpin = -(options.offsetUnpin * 1);
- } else {
- unpin = position.top - scrollTop;
- }
- if (setWidth) {
- element.css('width', '');
- }
- if (options.inlineStyles) {
- element.css('position', options.offsetParent ? '' : 'relative');
- element.css('top', options.offsetParent ? '' : bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop + 'px');
- }
- } else {
- unpin = null;
- if (setWidth) {
- element.css('width', element[0].offsetWidth + 'px');
- }
- if (options.inlineStyles) {
- element.css('position', 'fixed');
- element.css('top', initialAffixTop + 'px');
- }
- }
- element.removeClass(reset).addClass('affix' + (affix !== 'middle' ? '-' + affix : ''));
- };
- $affix.$onResize = function() {
- $affix.$parseOffsets();
- $affix.checkPosition();
- };
- $affix.$debouncedOnResize = debounce($affix.$onResize, 50);
- $affix.$parseOffsets = function() {
- var initialPosition = element.css('position');
- if (options.inlineStyles) {
- element.css('position', options.offsetParent ? '' : 'relative');
- }
- if (options.offsetTop) {
- if (options.offsetTop === 'auto') {
- options.offsetTop = '+0';
- }
- if (options.offsetTop.match(/^[-+]\d+$/)) {
- initialAffixTop = -options.offsetTop * 1;
- if (options.offsetParent) {
- offsetTop = dimensions.offset(parent[0]).top + options.offsetTop * 1;
- } else {
- offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + options.offsetTop * 1;
- }
- } else {
- offsetTop = options.offsetTop * 1;
- }
- }
- if (options.offsetBottom) {
- if (options.offsetParent && options.offsetBottom.match(/^[-+]\d+$/)) {
- offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + options.offsetBottom * 1 + 1;
- } else {
- offsetBottom = options.offsetBottom * 1;
- }
- }
- if (options.inlineStyles) {
- element.css('position', initialPosition);
- }
- };
- function getRequiredAffixClass(_unpin, position, elementHeight) {
- var scrollTop = getScrollTop();
- var scrollHeight = getScrollHeight();
- if (scrollTop <= offsetTop) {
- return 'top';
- } else if (_unpin !== null && scrollTop + _unpin <= position.top) {
- return 'middle';
- } else if (offsetBottom !== null && position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom) {
- return 'bottom';
- }
- return 'middle';
- }
- function getScrollTop() {
- return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;
- }
- function getScrollHeight() {
- return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;
- }
- $affix.init();
- return $affix;
- }
- return AffixFactory;
- } ];
- }).directive('bsAffix', [ '$affix', '$window', function($affix, $window) {
- return {
- restrict: 'EAC',
- require: '^?bsAffixTarget',
- link: function postLink(scope, element, attr, affixTarget) {
- var options = {
- scope: scope,
- target: affixTarget ? affixTarget.$element : angular.element($window)
- };
- angular.forEach([ 'offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles' ], function(key) {
- if (angular.isDefined(attr[key])) {
- var option = attr[key];
- if (/true/i.test(option)) option = true;
- if (/false/i.test(option)) option = false;
- options[key] = option;
- }
- });
- var affix = $affix(element, options);
- scope.$on('$destroy', function() {
- if (affix) affix.destroy();
- options = null;
- affix = null;
- });
- }
- };
- } ]).directive('bsAffixTarget', function() {
- return {
- controller: [ '$element', function($element) {
- this.$element = $element;
- } ]
- };
- });
|