Giter Site home page Giter Site logo

jonnybgod / ngx-scrollspy Goto Github PK

View Code? Open in Web Editor NEW
94.0 7.0 21.0 282 KB

Angular ScrollSpy Service

License: MIT License

JavaScript 15.17% TypeScript 84.83%
ng2-scrollspy angular2-service angular angular2 aot scrollspy parallax parallax-scrolling sticky infinite-scroll

ngx-scrollspy's Introduction

npm version Build Status Codacy Badge Coverage Status devDependency Status

NPM downloads

You can use this angular2 service to spy scroll events from window or any other scrollable element.

This library implements an service to collect observables from scroll spy directives. It can be used to create you own components or if you prefer use on of the following components that leverage this library functionality to accomplish different behaviors:

  • index: create and display and index from content inside and element.
  • affix: make element follow scroll inside its parent.
  • parallax: create very simple parallax effects based on scroll.
  • infinite: infinite scroll

Repository change

Please not that the repository and npm package changed from ng2-scrollspy to ngx-scrollspy

Installation

First you need to install the npm module:

npm install ngx-scrollspy --save

If you use SystemJS to load your files, you might have to update your config with this if you don't use defaultJSExtensions: true:

System.config({
	packages: {
		"ngx-scrollspy": {"defaultExtension": "js"}
	}
});

Finally, you can use ngx-scrollspy in your Angular 2 project. It is recommended to instantiate ScrollSpyService in the bootstrap of your application and to never add it to the "providers" property of your components, this way you will keep it as a singleton. If you add it to the "providers" property of a component it will instantiate a new instance of the service that won't be initialized.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { ScrollSpyModule } from 'ngx-scrollspy';

@NgModule({
  imports: [
  	BrowserModule,
  	ScrollSpyModule.forRoot()
  ],
  declarations: [ AppComponent ], 
  bootstrap: [ AppComponent ]
})

Using

Spy window scroll

Use ScrollSpyDirective to spy on window.

import { NgModule, Component, Injectable, AfterViewInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { ScrollSpyModule, ScrollSpyService } from 'ngx-scrollspy';

@Injectable()
@Component({
	selector: 'app',
	template: `<div scrollSpy></div>`
})
export class AppComponent implements AfterViewInit {
	constructor(private scrollSpyService: ScrollSpyService) {}

	ngAfterViewInit() {
		this.scrollSpyService.getObservable('window').subscribe((e: any) => {
			console.log('ScrollSpy::window: ', e);
		});
	}
}

@NgModule({
  imports: [
  	BrowserModule,
  	ScrollSpyModule.forRoot()
  ],
  declarations: [
  	AppComponent
  ], 
  bootstrap: [ AppComponent ]
})

Spy any element scroll

Use ScrollSpyElementDirective to spy on any element. You must give an unique id to each instance.

import { NgModule, Component, Injectable, AfterViewInit } from '@angular/core';
import { ScrollSpyModule, ScrollSpyService } from 'ngx-scrollspy';

@Injectable()
@Component({
	selector: 'yourComponent',
	template: `
	<div scrollSpyElement="test" style="max-height: 100px; overflow: auto;">
		<div style="height: 500px;"></div>
	</div>`
})
export class YourComponent implements AfterViewInit {

	constructor(private scrollSpyService: ScrollSpyService) {}

	ngAfterViewInit() {
		this.scrollSpyService.getObservable('test').subscribe((e: any) => {
			console.log('ScrollSpy::test: ', e);
		});
	}
}

@NgModule({
  imports: [
		ScrollSpyModule
  ],
  declarations: [
  	AppComponent
  ], 
  providers: [ ] 
})
export class YourModule { }

Because ScrollSpyService is a singleton, you can get any ScrollSpy observable from anywhere withing your application.

TODO:

  • Documentation/examples webpage
  • Finish unit tests

License

MIT

ngx-scrollspy's People

Contributors

carathorys avatar fume avatar greenkeeperio-bot avatar jonnybgod avatar maxisam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngx-scrollspy's Issues

Using scrollSpyAffix directive

Hello,

I'm trying to make an affix in my app but can't figure out how to do this.

Have you got some example of scrollSpyAffix working fine?

I've tried the following but nothing appens

<div scrollSpy>
    <div class="white-strip"></div>
    <header>
        <div class="title" scrollSpyAffix >
            <h1>Hello world</h1>
        </div>
    </header>
<div>

Thanks !

ng2-scrollspy/src/core/service 404 (Not Found)

Hi,

I'm building an Angular 2 Typescript project using angular-cli (https://github.com/angular/angular-cli). They use SystemJS as loader.

After adding ng2-scrollspy to main.ts (bootstrap) and configuring the package in SystemJS I get the following errors:

zone.js:101 GET http://localhost:4200/vendor/ng2-scrollspy/src/core/service 404 (Not Found)
zone.js:101 GET http://localhost:4200/vendor/ng2-scrollspy/src/core/window.directive 404 (Not Found)
zone.js:101 GET http://localhost:4200/vendor/ng2-scrollspy/src/core/element.directive 404 (Not Found)

I have checked /vendor/ng2-scrollspy. All scripts are there (I have used ng2-scrollspy/**/*.js during copy)
It seems that the file extension is not appended, although I explicitly use defaultExtension: 'js'.

This is my system-config.ts:

/** Map relative paths to URLs. */
const map: any = {
  'ng2-scrollspy': 'vendor/ng2-scrollspy/src/index.js'
};
/** User packages configuration. */
const packages: any = {
  'ng2-scrollspy': {
    format: 'cjs',
    defaultExtension: 'js'
  }
};

What could be wrong?

Thanks!

capture

How to use this plugin with scrollspy bootstrap 4.0 list.

I need add active class when user scroll on the page depdending to the item id https://getbootstrap.com/docs/4.0/components/scrollspy I don't have idea how to do it

<div id="list-example" class="list-group">
  <a class="list-group-item list-group-item-action" href="#list-item-1">Item 1</a>
  <a class="list-group-item list-group-item-action" href="#list-item-2">Item2</a>
  <a class="list-group-item list-group-item-action" href="#list-item-3">Item 3</a>
  <a class="list-group-item list-group-item-action" href="#list-item-4">Item 4</a>
</div>
<div data-spy="scroll" data-target="#list-example" data-offset="0" class="scrollspy-example">
  <h4 id="list-item-1">Item 1</h4>
  <p>...</p>
  <h4 id="list-item-2">Item 2</h4>
  <p>...</p>
  <h4 id="list-item-3">Item 3</h4>
  <p>...</p>
  <h4 id="list-item-4">Item 4</h4>
  <p>...</p>
</div>

Any Help? Thanks.

Spying on an element doesn't resolve.

Hi. I need some help. I am trying to spy on an element but the observable never resolves. This is my code:

import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { ScrollSpyModule, ScrollSpyService, ScrollSpyDirective } from 'ngx-scrollspy';

@Component({
	selector: 'app-root',
	template: `
		<div style="background-color: red;height: 1400px; width: 500px;"></div>
		<div  style="max-height: 1000px; overflow: scroll; background-color: blue;">
			<div scrollSpyElement="test" style="height: 500px;"></div>
		</div>
	`
})
export class AppComponent implements AfterViewInit{
	@ViewChild('secondarySidebar') sidebar: ElementRef;

	constructor(private scrollSpyService: ScrollSpyService) {}

	ngAfterViewInit() {
		console.log(this.scrollSpyService.getObservable('test'), 'hoho**********');
		this.scrollSpyService.getObservable('test').subscribe((e: any) => {
			console.log('ScrollSpy::window: ', e, 'Window');
		});
	}
}

Any ideas?

scrollSpyService.getObservable('window') returns Undefined

When I call the getObservable('window') in the ScrollSpyService, the service is returning 'undefined'. Can you please point out what the issue mightbe? Here's my setup:

Module:

import { ScrollSpyModule } from 'ng2-scrollspy';
...
@NgModule({
    imports: [
        ScrollSpyModule.forRoot(),

Component:

import { ScrollSpyService } from 'ng2-scrollspy';
...
constructor(private scrollSpyService: ScrollSpyService) {
    }
...
ngAfterViewInit() {
    console.log(this.scrollSpyService.getObservable('window'));
}

Better looking scrollSpy-index-render

Is there a way to make scrollSpy-index-render use a different class so it can look like a list-group?

Code generated by the scrollSpy-index-render:

<ul class="nav flex-column menu">
    <li class="active ng-star-inserted">
        <a ng-reflect-fragment="SQLServer" href="/chat#SQLServer"> SQLServer </a>
        <ul class="nav menu ng-star-inserted">
            <li class="ng-star-inserted">
                <a ng-reflect-fragment="a" href="/chat#a"> A</a>
            </li>
            <li class="ng-star-inserted">
                <a ng-reflect-fragment="b" href="/chat#b"> B</a>
            </li>
            <li class="ng-star-inserted">
                <a ng-reflect-fragment="API" href="/chat#API"> API </a>
            </li>
            <li class="ng-star-inserted">
                <a ng-reflect-fragment="PlugIn" href="/chat#PlugIn"> PlugIn </a>
            </li>
        </ul>
    </li>
</ul>

Bootstrap Code:

<ul class="list-group">
    <li class="list-group-item">Cras justo odio</li>
    <li class="list-group-item">Dapibus ac facilisis in</li>
    <li class="list-group-item">Morbi leo risus</li>
    <li class="list-group-item">Porta ac consectetur ac</li>
    <li class="list-group-item">Vestibulum at eros</li>
</ul>

Parallax does not work

I've imported everything into the app module as directed, but when I roll scrool, the console is notified and nothing happens!

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { AppComponent } from './app.component';
import { PageIndexComponent } from './page-index/page-index.component';
import { ScrollSpyModule,  ScrollSpyParallaxModule } from 'ngx-scrollspy';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    ScrollSpyModule.forRoot(),
    ScrollSpyParallaxModule 
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

page-index.component.html

 <div [scrollSpyParallax] = "{
    property: 'backgroundPositionX',
    ratio: -.2
  }"   class="divimage dzsparallaxer--target w-100 g-bg-pos-bottom-center" style="height: 120%; background-image: url(assets/img-temp/1920x1080/img25.jpg);"></div>

firefox parallax not working

Hi, Thanks for the great directive, It seems that the parallax effect is not working on firefox, but it works on other browsers, any ideas?

Next release for Angular 5

Hello,

Do you have a deadline to publish a new version with the bug fix for Angular 5 (OpaqueToken) ? Angular 5 is in RC9 so it will be available soon.
I tried to use the master branch directly but I couldn't build the library.

Thanks a lot
Denis

scrollspy-style plugin for animations

I like to submit scrollspy-style plugin that adds a css class if the element is in viewport.
It can be used for adding scroll animations to elements or hide/show navbar.

import {
  Directive, EventEmitter, Output, OnDestroy, ElementRef, Input, AfterViewInit, Inject,
  Renderer, OnInit
} from '@angular/core';

import {Subscription} from 'rxjs/Subscription';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/debounceTime';
import {ScrollSpyService} from 'ng2-scrollspy';
import {WindowService} from '../../../core/services/window.service';
import {DOCUMENT} from '@angular/platform-browser';

declare var $: any;


export interface ScrollSpyStyleOptions {
  className?: string;
  debounce?: number;
  cushion?: number;
  fullyInView?: boolean;
}
@Directive({
  selector: '[scrollSpyStyle]',
})
export class ScrollSpyStyleDirective implements OnInit, OnDestroy, AfterViewInit {

  private sub: Subscription;
  private element: HTMLElement;

  @Input('scrollSpyStyle') public options: ScrollSpyStyleOptions;
  @Output() onVisibilityChange: EventEmitter<boolean> = new EventEmitter();

  private defaultOptions: ScrollSpyStyleOptions = {
    className: 'appeared',
    debounce: 0,
    cushion: 0,
    fullyInView: false
  };

  constructor(private scrollSpyService: ScrollSpyService, elementRef: ElementRef,
              @Inject(DOCUMENT) private _document: Document, private renderer: Renderer,
              @Inject(WindowService) private _window: Window) {
    this.element = elementRef.nativeElement;
  }

  ngOnInit() {
    if (!this.options) {
      this.options = this.defaultOptions;
    } else {
      this.options = Object.assign(this.defaultOptions, this.options);
    }
  }

  ngAfterViewInit() {
    this.sub = this.scrollSpyService.getObservable('window')
      // .debounce(this.options.debounce)
      .map(() => this.isElementInViewport())
      .distinctUntilChanged()
      .subscribe((inView: boolean) => {
        console.log('inView', inView);
        this.onVisibilityChange.emit(inView);
        this.renderer.setElementClass(this.element, this.options.className, inView);
      });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

  private isElementInViewport() {
    let rect = this.element.getBoundingClientRect();
    const html = this._document.documentElement;

    if (this.options.cushion !== 0) {
      rect = this.addCushion(rect, this.options.cushion);
    }
    if (this.options.fullyInView === true) {
      return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (this._window.innerHeight || html.clientHeight) &&
        rect.right <= (this._window.innerWidth || html.clientWidth)
      );
    } else {
      return (
        rect.bottom >= 0 &&
        rect.right >= 0 &&
        rect.top <= (this._window.innerHeight || html.clientHeight) &&
        rect.left <= (this._window.innerWidth || html.clientWidth)
      );
    }
  }

  /**
   *  If a cushion is specified, the properties are adjusted according to the cushion amount.
   *  If the cushion is positive the rectangle will represent an area that is larger that the actual element.
   *  If the cushion is negative then the rectangle will represent an area that is smaller that the actual element.
   */
  private addCushion(rect: ClientRect, cushion: number) {
    return {
      right: rect.right + cushion,
      left: rect.left - cushion,
      top: rect.top - cushion,
      bottom: rect.bottom + cushion,
      get width() {return this.right - this.left; },
      get height() {return this.bottom - this.top; },
    };
  }
}

ScrollSpyService should accept Observable<any> as well

I propose we should have setObservable like
public setObservable(key: string, observable: ReplaySubject<any> | Observable<any>)

So in some cases, that we can't put a spy directive to the dom element we want, we still can use the service.

Does not work with angular universal

Works fine running client side but not with Universal.

/node_modules/ngx-scrollspy/dist/index.js:1 (function (exports, require, module, __filename, __dirname) { import { NgModule, Inject, Optional, OpaqueToken, SkipSelf } from '@angular/core'; ^^^^^^ SyntaxError: Unexpected token import at Object.exports.runInThisContext (vm.js:76:16) at Module._compile (module.js:542:28) at Object.Module._extensions..js (module.js:579:10) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.require (module.js:497:17) at require (internal/module.js:20:19) at Object.<anonymous> (/Users/aharris/Projects/PNC/portal/src/app/app.module.ts:15:1) at Module._compile (module.js:570:32)

Any help with this much appreciated.

How to use scrollspy?

Can you provide demo of scrollspy? I don't know which directive should I use for scrollspy?

Property 'scrollSpyService' does not exist on type 'AppComponent'

I am getting this error at this.scrollSpyService = scrollSpyService; and this.scrollSpyService.getObservable('window').subscribe((e: any) => {

in following code


constructor(scrollSpyService: ScrollSpyService) {
        this.scrollSpyService = scrollSpyService;
    }


  ngAfterViewInit() {
    this.scrollSpyService.getObservable('window').subscribe((e: any) => {
        console.log('ScrollSpy::window: ', e);
    });

Angular -rc version.

is importing View necessary?

because @view decorator was dropped in beta. but still i tried and it gave error

Module '"try2/node_modules/@angular/core/index"' has no export
ed member 'View'.

ScrollSpyElementDirective import causing error in browser.

The error says:
Uncaught Error: Type ScrollSpyElementDirective is part of the declarations of 2 modules: ScrollSpyModule and AppModule! Please consider moving ScrollSpyElementDirective to a higher module that imports ScrollSpyModule and AppModule.

I am getting this error in browser, the ScrollSpyElementDirective is imported only one time and added in @NgModule imports metadata.

I am importing these:
import { ScrollSpyModule, ScrollSpyService, ScrollSpyElementDirective } from 'ngx-scrollspy';
Is it OK if I don't import ScrollSpyElementDirective, whether ScrollSpyElementDirective is included in ScrollSpyModule which I've also imported.
Please help. Thanks

Unable to get ScrollSpyInfiniteDirective to work

I cant seem to get ScrollSpyInfiniteDirective to work. I have added ScrollSpyInfiniteDirective to declarations in my module and ScrollSpyModule.forRoot() to my module imports. I added scrollSpy to my top level div and in my component i have imported ScrollSpyInfiniteDirective and set up my template as follows:

<div class="app-body" scrollSpyInfinite (scrollSpyInfiniteEvent)="scrollDown()">

But i do not see scrollDown() being called on scrolling all the way to the bottom. Is it possible to get some documentation on how to use it?

Thanks

Cannot find name 'ScrollSpyModule'.

i did as per the readme text .

when i try to start using npm,i get the below error

app/app.module.ts(19,5): error TS2304: Cannot find name 'ScrollSpyModule'.

Not working: Cannot read property 'subscribe' of undefined

Hi, I tried to add ng2-scrollspy to angular2 webpack starter project. I'm getting this error ORIGINAL EXCEPTION: TypeError: Cannot read property 'subscribe' of undefined

import {ScrollSpyDirective, ScrollSpyService} from 'ng2-scrollspy';

@Component({
  selector: 'single',
  template: require('./single.html'),
  directives: [ScrollSpyDirective]
})
export class Single{
  constructor(public scrollSpyService: ScrollSpyService){
  }
  ngAfterViewInit(){
    this.scrollSpyService.getObservable('test').subscribe((e: any) => {
      console.log('ScrollSpy::test: ', e);
    });
  }
}

template

<div class="post-card">
  <div scrollSpyElement="test" class="post-header fillheight">
    <div class="post-image" *ngIf="post.featuredMedia()"
        [ngStyle]="getFeaturedImage()">
    </div>
...

How to make a Scrollbox with Scrollspy

I added this scrollbox to the scollspy example but i don't get it work.

29814541-04733b9c-8cae-11e7-8ef8-2ddce94b3db3

Can you help me making scrollspy on a scrollable box?

import { Component } from '@angular/core';

@Component({
  selector: 'app-scrollbox',
  styleUrls: [ '../page.component.scss' ],
  template: `
    <div class="container">
      <div class="row">
        <div class="col-md-9 myScrollArea" role="main" scrollSpy scrollSpyElement="myScrollArea">
          <div class="main" [scrollSpyIndex]="{id: 'home', selector: 'anchor'}">
            <div>
              <h2 id="home" class="anchor">Home</h2>
              <p>Lorem ipsum...</p>
              <h3 id="services" class="anchor">Services</h3>
              <p>Lorem ipsum...</p>
              <h3 id="clients" class="anchor">Clients</h3>
              <p>Lorem ipsum...</p>
              <h2 id="about" class="anchor">About Us</h2>
              <p>Lorem ipsum...</p>
              <h3 id="contact" class="anchor">Contact</h3>
              <p>Lorem ipsum...</p>
            </div>
          </div>
        </div>

        <div class="col-md-3" role="complementary">
          <scrollSpy-index-render
            [scrollSpyIndexRenderOptions]="{id: 'home', spyId: 'myScrollArea', topMargin: 90}"
            [scrollSpyAffix]="{topMargin: 70, bottomMargin: 70}"
            class="hidden-print hidden-xs hidden-sm">
          </scrollSpy-index-render>
        </div>
      </div>
    </div>

  `,
})
export class ScrollboxComponent {

}
.myScrollArea {
    max-height:500px;
    overflow-y:auto;
    overflow-x:hidden;
    background:lightcyan;
  }

You can use this demo https://github.com/JavanXD/ngx-scrollspy-angular-cli-demo/tree/scrollbox

ngx-scrollspy destroys previous url query parameters after anchor tag is clicked

The plugin destroys and does not maintain current query parameters upon anchor link clicking. This is an issue if one is attempting to use queries for any of the data on the page, and observing that data as well in the URL. One cannot refresh the page, bookmark, nor go back to a working position due to the plugin stripping away any url query parameters that were being used. The example is shown below of what happens.

DEFAULT URL LINK:
http://www.somedomain.com/users?id=5q23jn34&filter=true

ISSUE LINK AFTER ANCHOR TAG IS CLICKED
(so when anchor tag is clicked the url parameters are stripped and replaced):
http://www.somedomain.com/users#home


The Ideal Result After Clicking an Anchor Tag:
http://www.somedomain.com/users?id=5q23jn34&filter=true#home

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.