Skip to content

Commit

Permalink
feat(ad-block): introduce structural directives (#223)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickmichalina authored Aug 27, 2019
1 parent daa8d8a commit 455e91f
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 1 deletion.
28 changes: 28 additions & 0 deletions projects/flosportsinc/ng-ad-block/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,32 @@ import { FloAdBlockServerModule } from '@flosportsinc/ng-universal-services/ad-b
]
})
export class AppServerModule { }
```

## Usage

### Programmatic
```js
import { NgComponent } from '@angular/core'
import { AdBlockService } from '@flosportsinc/ng-ad-block'

@NgModule()
export class SomeComponent {
constructor(ads: AdBlockService) {
ads.isAnAdBlockerActive.subscribe(isBlocked => {
// access the boolean here
})
}
}
```

### Stuctural HTML
To hide or show content depending on ad-blocker detection status simply decorate your html like so:

```html
<!-- Show content if an ad blocker is NOT detected -->
<div *floIfNotAdBlocked>I am an ad that can likely be shown to the user</div>

<!-- Show content if an ad blocker is detected -->
<div *floIfAdBlocked>Hey, turn off your ad-blocker</div>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Component, NgModule } from '@angular/core'
import { TestBed } from '@angular/core/testing'
import { By } from '@angular/platform-browser'
import { of } from 'rxjs'
import { FloAdBlockModule } from './ad-block.module'
import { FloIfAdBlockedDirective } from './ad-block.directive'
import { AD_BLOCK_LOADER } from './ad-block.tokens'
import { AdBlockService } from './ad-block.service'

@Component({
selector: 'flo-test-component',
template: `
<div id="floIfAdBlocked" *floIfAdBlocked>floIfAdBlocked</div>
<div id="floIfNotAdBlocked" *floIfNotAdBlocked>floIfNotAdBlocked</div>
`})
export class FloTestComponent { }

export const trueLoader = () => of(true)
export const falseLoader = () => of(false)

@NgModule({
declarations: [FloTestComponent],
imports: [FloAdBlockModule],
exports: [FloAdBlockModule, FloTestComponent],
providers: [
AdBlockService,
{ provide: AD_BLOCK_LOADER, useFactory: falseLoader }
]
})
export class FloFullscreenTestModule { }

const createSut = () => {
const sut = TestBed.createComponent(FloTestComponent)
sut.detectChanges()
return sut
}

describe(FloIfAdBlockedDirective.name, () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FloFullscreenTestModule]
}).compileComponents()
})

it('should compile', () => {
expect(createSut()).toBeTruthy()
})

it('should show floIfAdBlocked element', () => {
TestBed.resetTestingModule()
TestBed.configureTestingModule({
imports: [FloFullscreenTestModule],
providers: [
{ provide: AD_BLOCK_LOADER, useFactory: trueLoader }
]
})
const sut = createSut()
const element1 = sut.debugElement.query(By.css('#floIfAdBlocked'))
const element2 = sut.debugElement.query(By.css('#floIfNotAdBlocked'))
sut.detectChanges()
expect(element1.nativeElement.innerText).toEqual('floIfAdBlocked')
expect(element2).toBeNull()
})

it('should show floIfNotAdBlocked element', () => {
const sut = createSut()
const element1 = sut.debugElement.query(By.css('#floIfAdBlocked'))
const element2 = sut.debugElement.query(By.css('#floIfNotAdBlocked'))
sut.detectChanges()
expect(element1).toBeNull()
expect(element2.nativeElement.innerText).toEqual('floIfNotAdBlocked')
})
})
70 changes: 70 additions & 0 deletions projects/flosportsinc/ng-ad-block/common/ad-block.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Directive, TemplateRef, ViewContainerRef, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'
import { AdBlockService } from './ad-block.service'
import { Subject } from 'rxjs'
import { takeUntil } from 'rxjs/operators'

export abstract class FloAdBlockDirective implements OnInit, OnDestroy {
constructor(protected tr: TemplateRef<any>, protected vc: ViewContainerRef,
protected ads: AdBlockService, protected cd: ChangeDetectorRef) { }

protected readonly ngOnDestroy$ = new Subject()
// tslint:disable-next-line: readonly-keyword
protected showWhenAdBlocked: boolean

ngOnInit() {
this.ads.isAnAdBlockerActive()
.pipe(takeUntil(this.ngOnDestroy$))
.subscribe(isActive => {
if (isActive) {
if (this.showWhenAdBlocked) {
this.vc.createEmbeddedView(this.tr)
} else {
this.vc.clear()
}
} else {
if (this.showWhenAdBlocked) {
this.vc.clear()
} else {
this.vc.createEmbeddedView(this.tr)
}
}
this.cd.detectChanges()
})
}

ngOnDestroy() {
this.ngOnDestroy$.next()
this.ngOnDestroy$.complete()
}
}

const IF_BLOCKED_SELECTOR = 'floIfAdBlocked'
const IF_NOT_BLOCKED_SELECTOR = 'floIfNotAdBlocked'

@Directive({
selector: `[${IF_BLOCKED_SELECTOR}]`,
inputs: [IF_BLOCKED_SELECTOR]
})
export class FloIfAdBlockedDirective extends FloAdBlockDirective {
constructor(protected tr: TemplateRef<any>, protected vc: ViewContainerRef, protected ads: AdBlockService,
protected cd: ChangeDetectorRef) {
super(tr, vc, ads, cd)
this.showWhenAdBlocked = true
}

readonly elmInputKey = IF_BLOCKED_SELECTOR
}

@Directive({
selector: `[${IF_NOT_BLOCKED_SELECTOR}]`,
inputs: [IF_NOT_BLOCKED_SELECTOR]
})
export class FloIfNotAdBlockedDirective extends FloAdBlockDirective {
constructor(protected tr: TemplateRef<any>, protected vc: ViewContainerRef, protected ads: AdBlockService,
protected cd: ChangeDetectorRef) {
super(tr, vc, ads, cd)
this.showWhenAdBlocked = false
}

readonly elmInputKey = IF_NOT_BLOCKED_SELECTOR
}
5 changes: 4 additions & 1 deletion projects/flosportsinc/ng-ad-block/common/ad-block.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { NgModule } from '@angular/core'
import { AdBlockService } from './ad-block.service'
import { FloIfAdBlockedDirective, FloIfNotAdBlockedDirective } from './ad-block.directive'

@NgModule({
providers: [AdBlockService]
providers: [AdBlockService],
declarations: [FloIfAdBlockedDirective, FloIfNotAdBlockedDirective],
exports: [FloIfAdBlockedDirective, FloIfNotAdBlockedDirective]
})
export class FloAdBlockModule { }
1 change: 1 addition & 0 deletions projects/flosportsinc/ng-ad-block/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './common/ad-block.interface'
export * from './common/ad-block.module'
export * from './common/ad-block.service'
export * from './common/ad-block.tokens'
export * from './common/ad-block.directive'
3 changes: 3 additions & 0 deletions src/app/flo.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { FloNodeEnvTransferModule } from '@flosportsinc/ng-env-transfer-state'
import { FloFullscreenModule } from '@flosportsinc/ng-fullscreen'
import { FloFetchFillModule } from '@flosportsinc/ng-fetch-fill'
import { SvgTransferStateModule } from '@flosportsinc/ng-svg-transfer-state'
import { FloAdBlockModule } from '@flosportsinc/ng-ad-block'

@NgModule({
imports: [
FloAdBlockModule,
FloVideoEventsModule,
FloVideoAutoplayModule,
FloFullscreenModule,
Expand All @@ -30,6 +32,7 @@ import { SvgTransferStateModule } from '@flosportsinc/ng-svg-transfer-state'
})
],
exports: [
FloAdBlockModule,
FloVideoEventsModule,
FloVideoAutoplayModule,
FloFullscreenModule,
Expand Down

0 comments on commit 455e91f

Please sign in to comment.