@thisissoon/angular-scrollspy
Version:
A simple lightweight library for Angular which automatically updates links to indicate the currently active section in the viewport
508 lines (494 loc) • 18 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@thisissoon/angular-inviewport')) :
typeof define === 'function' && define.amd ? define('@thisissoon/angular-scrollspy', ['exports', '@angular/core', '@thisissoon/angular-inviewport'], factory) :
(factory((global.thisissoon = global.thisissoon || {}, global.thisissoon['angular-scrollspy'] = {}),global.ng.core,global.angularInviewport));
}(this, (function (exports,core,angularInviewport) { 'use strict';
/**
* @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: core.Directive, args: [{
selector: '[snScrollSpyItem]',
},] }
];
/** @nocollapse */
ScrollSpyItemDirective.ctorParameters = function () {
return [
{ type: core.ChangeDetectorRef }
];
};
ScrollSpyItemDirective.propDecorators = {
active: [{ type: core.HostBinding, args: ['class.active',] }],
for: [{ type: core.Input }],
href: [{ type: core.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: core.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: core.Directive, args: [{
selector: '[snScrollSpy]',
},] }
];
/** @nocollapse */
ScrollSpyDirective.ctorParameters = function () {
return [
{ type: ScrollSpyService }
];
};
ScrollSpyDirective.propDecorators = {
items: [{ type: core.ContentChildren, args: [ScrollSpyItemDirective,] }],
id: [{ type: core.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: core.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: core.Input }],
for: [{ type: core.Input }]
};
return ScrollSpySectionComponent;
}());
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/**
* @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: core.NgModule, args: [{
imports: [angularInviewport.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
*/
exports.ScrollSpyDirective = ScrollSpyDirective;
exports.ScrollSpyItemDirective = ScrollSpyItemDirective;
exports.ScrollSpySectionComponent = ScrollSpySectionComponent;
exports.ScrollSpyService = ScrollSpyService;
exports.ScrollSpyModule = ScrollSpyModule;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=thisissoon-angular-scrollspy.umd.js.map