@thisissoon/angular-scrollspy
Version:
A simple lightweight library for Angular which automatically updates links to indicate the currently active section in the viewport
449 lines (440 loc) • 13.6 kB
JavaScript
import { __spread } from 'tslib';
import { Directive, Input, HostBinding, ChangeDetectorRef, Injectable, ContentChildren, Component, NgModule } from '@angular/core';
import { InViewportModule } from '@thisissoon/angular-inviewport';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A directive used to add an `active` class to a nav item
* when the section is in the viewport
*
* \@example
* ```html
* <a snScrollSpyItem for="foo" href="#section1">Section 1</a>
* ```
*
*/
var ScrollSpyItemDirective = /** @class */ (function () {
/**
* Creates an instance of ScrollSpyItemDirective.
* @memberof ScrollSpyItemDirective
*/
function ScrollSpyItemDirective(cdRef) {
this.cdRef = cdRef;
/**
* True if the nav item is the active item in the `items` list
* for `ScrollSpyDirective` instance
*
* \@memberof ScrollSpyItemDirective
*/
this.active = false;
/**
* If true means the section is in the viewport
*
* \@memberof ScrollSpyItemDirective
*/
this.inViewport = false;
}
Object.defineProperty(ScrollSpyItemDirective.prototype, "section", {
/**
* Id of section that links navigates to
*
* @readonly
* @memberof ScrollSpyItemDirective
*/
get: /**
* Id of section that links navigates to
*
* \@readonly
* \@memberof ScrollSpyItemDirective
* @return {?}
*/
function () {
return this.href.replace('#', '');
},
enumerable: true,
configurable: true
});
/**
* Manually trigger change detection
*
* @memberof ScrollSpyItemDirective
*/
/**
* Manually trigger change detection
*
* \@memberof ScrollSpyItemDirective
* @return {?}
*/
ScrollSpyItemDirective.prototype.detectChanges = /**
* Manually trigger change detection
*
* \@memberof ScrollSpyItemDirective
* @return {?}
*/
function () {
this.cdRef.detectChanges();
};
ScrollSpyItemDirective.decorators = [
{ type: Directive, args: [{
selector: '[snScrollSpyItem]',
},] }
];
/** @nocollapse */
ScrollSpyItemDirective.ctorParameters = function () { return [
{ type: ChangeDetectorRef }
]; };
ScrollSpyItemDirective.propDecorators = {
active: [{ type: HostBinding, args: ['class.active',] }],
for: [{ type: Input }],
href: [{ type: Input }]
};
return ScrollSpyItemDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Service that stores a list of `Spy`'s and the state
* of their nav items `inViewport` and `active` state
*
*/
var ScrollSpyService = /** @class */ (function () {
function ScrollSpyService() {
/**
* List of `Spy`'s
*
* \@memberof ScrollSpyService
*/
this.spys = [];
/**
* Stores requests to add items to spy when spy hasn't been created
* yet. Once spy has been added then request will be made again.
*
* \@memberof ScrollSpyService
*/
this.buffer = [];
}
/**
* Add spy to list of `spys`
*
* @memberof ScrollSpyService
*/
/**
* Add spy to list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @param {?} items
* @return {?}
*/
ScrollSpyService.prototype.addSpy = /**
* Add spy to list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @param {?} items
* @return {?}
*/
function (id, items) {
var _this = this;
this.spys.push({ id: id, items: items });
/** @type {?} */
var buffer = this.buffer.filter(function (i) { return i.spyId === id; });
this.buffer = this.buffer.filter(function (i) { return i.spyId !== id; });
buffer.forEach(function (i) {
return _this.setSpySectionStatus(i.sectionId, i.spyId, i.inViewport);
});
};
/**
* Remove spy from list of `spys`
*
* @memberof ScrollSpyService
*/
/**
* Remove spy from list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @return {?}
*/
ScrollSpyService.prototype.removeSpy = /**
* Remove spy from list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @return {?}
*/
function (id) {
/** @type {?} */
var i = this.spys.findIndex(function (s) { return s.id === id; });
this.spys.splice(i, 1);
};
/**
* Set the `inViewport` status for a spy item then sets the active
* to true for the first item in the list that has `inViewport`
* set to true
*
* @memberof ScrollSpyService
*/
/**
* Set the `inViewport` status for a spy item then sets the active
* to true for the first item in the list that has `inViewport`
* set to true
*
* \@memberof ScrollSpyService
* @param {?} sectionId
* @param {?} spyId
* @param {?} inViewport
* @return {?}
*/
ScrollSpyService.prototype.setSpySectionStatus = /**
* Set the `inViewport` status for a spy item then sets the active
* to true for the first item in the list that has `inViewport`
* set to true
*
* \@memberof ScrollSpyService
* @param {?} sectionId
* @param {?} spyId
* @param {?} inViewport
* @return {?}
*/
function (sectionId, spyId, inViewport) {
/** @type {?} */
var spy = this.spys.find(function (s) { return s.id === spyId; });
if (!spy) {
this.buffer.push({ sectionId: sectionId, spyId: spyId, inViewport: inViewport });
return;
}
/** @type {?} */
var item = spy.items.find(function (i) { return i.section === sectionId; });
if (!item) {
return;
}
item.inViewport = inViewport;
/** @type {?} */
var firstInViewport = spy.items.filter(function (i) { return i.inViewport; })[0];
spy.items.forEach(function (i) { return (i.active = false); });
if (firstInViewport) {
firstInViewport.active = true;
firstInViewport.detectChanges();
}
};
ScrollSpyService.decorators = [
{ type: Injectable }
];
return ScrollSpyService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Adds `active` class to navigation links when section is in the viewport.
* Used in conjuction with `snScrollItem` directive which should be added
* to anchor links in the nav
*
* \@example
* ```
* <ul role="navigation" snScrollSpy id="foo">
* <li><a snScrollSpyItem for="foo" href="#section1">Section 1</a></li>
* <li><a snScrollSpyItem for="foo" href="#section2">Section 2</a></li>
* <li><a snScrollSpyItem for="foo" href="#section3">Section 3</a></li>
* <li><a snScrollSpyItem for="foo" href="#section4">Section 4</a></li>
* </ul>
* ```
*
*/
var ScrollSpyDirective = /** @class */ (function () {
/**
* Creates an instance of ScrollSpyDirective.
* @memberof ScrollSpyDirective
*/
function ScrollSpyDirective(scrollSpySvc) {
this.scrollSpySvc = scrollSpySvc;
}
/**
* Adds spy to list of spys in `ScrollSpyService`
*
* @memberof ScrollSpyDirective
*/
/**
* Adds spy to list of spys in `ScrollSpyService`
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
ScrollSpyDirective.prototype.ngAfterViewInit = /**
* Adds spy to list of spys in `ScrollSpyService`
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
function () {
this.scrollSpySvc.addSpy(this.id, this.items);
};
/**
* Remove spy from list of spys when directive is destroyed
*
* @memberof ScrollSpyDirective
*/
/**
* Remove spy from list of spys when directive is destroyed
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
ScrollSpyDirective.prototype.ngOnDestroy = /**
* Remove spy from list of spys when directive is destroyed
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
function () {
this.scrollSpySvc.removeSpy(this.id);
};
ScrollSpyDirective.decorators = [
{ type: Directive, args: [{
selector: '[snScrollSpy]',
},] }
];
/** @nocollapse */
ScrollSpyDirective.ctorParameters = function () { return [
{ type: ScrollSpyService }
]; };
ScrollSpyDirective.propDecorators = {
items: [{ type: ContentChildren, args: [ScrollSpyItemDirective,] }],
id: [{ type: Input }]
};
return ScrollSpyDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* A component to wrap section content within that will update the
* `ScrollSpyService` when it's in view
*
* \@example
* ```html
* <sn-scroll-spy-section id="section1" for="foo">
* ...
* </sn-scroll-spy-section>
* ```
*/
var ScrollSpySectionComponent = /** @class */ (function () {
/**
* Creates an instance of ScrollSpySectionComponent.
* @memberof ScrollSpySectionComponent
*/
function ScrollSpySectionComponent(scrollSpySvc) {
this.scrollSpySvc = scrollSpySvc;
}
/**
* Updates `ScrollSpy` section when element enters/leaves viewport
*
* @memberof ScrollSpySectionComponent
*/
/**
* Updates `ScrollSpy` section when element enters/leaves viewport
*
* \@memberof ScrollSpySectionComponent
* @param {?} inViewport
* @return {?}
*/
ScrollSpySectionComponent.prototype.onInViewportChange = /**
* Updates `ScrollSpy` section when element enters/leaves viewport
*
* \@memberof ScrollSpySectionComponent
* @param {?} inViewport
* @return {?}
*/
function (inViewport) {
this.scrollSpySvc.setSpySectionStatus(this.id, this.for, inViewport);
};
ScrollSpySectionComponent.decorators = [
{ type: Component, args: [{
selector: 'sn-scroll-spy-section',
template: "<div\n class=\"sn-hidden\"\n snInViewport\n (inViewportChange)=\"onInViewportChange($event)\">\n</div>\n<ng-content></ng-content>\n",
styles: [":host{display:block;position:relative}.sn-hidden{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0;z-index:-1}"]
}] }
];
/** @nocollapse */
ScrollSpySectionComponent.ctorParameters = function () { return [
{ type: ScrollSpyService }
]; };
ScrollSpySectionComponent.propDecorators = {
id: [{ type: Input }],
for: [{ type: Input }]
};
return ScrollSpySectionComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
var directives = [ScrollSpyDirective, ScrollSpyItemDirective];
/** @type {?} */
var components = [ScrollSpySectionComponent];
/** @type {?} */
var providers = [ScrollSpyService];
/**
* A simple lightweight library for Angular which automatically
* updates links to indicate the currently active section in the viewport
*
*/
var ScrollSpyModule = /** @class */ (function () {
function ScrollSpyModule() {
}
/**
* Specify a static method for root module to ensure providers are
* only provided once but allows the module to still be imported
* into other modules without reproviding services.
*
* @memberof ScrollSpyModule
*/
/**
* Specify a static method for root module to ensure providers are
* only provided once but allows the module to still be imported
* into other modules without reproviding services.
*
* \@memberof ScrollSpyModule
* @return {?}
*/
ScrollSpyModule.forRoot = /**
* Specify a static method for root module to ensure providers are
* only provided once but allows the module to still be imported
* into other modules without reproviding services.
*
* \@memberof ScrollSpyModule
* @return {?}
*/
function () {
return {
ngModule: ScrollSpyModule,
providers: __spread(providers),
};
};
ScrollSpyModule.decorators = [
{ type: NgModule, args: [{
imports: [InViewportModule],
declarations: __spread(directives, components),
exports: __spread(directives, components),
},] }
];
return ScrollSpyModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { ScrollSpyDirective, ScrollSpyItemDirective, ScrollSpySectionComponent, ScrollSpyService, ScrollSpyModule };
//# sourceMappingURL=thisissoon-angular-scrollspy.js.map