@niur/ng-gpt
Version:
A Angular implementation of the google GPT API.
519 lines (506 loc) • 20.3 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, InjectionToken, PLATFORM_ID, Inject, EventEmitter, Directive, Optional, Input, Output, NgModule } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { buffer, switchMap, takeUntil, filter } from 'rxjs/operators';
import { Subject, timer } from 'rxjs';
import * as i1 from '@angular/router';
import { NavigationEnd } from '@angular/router';
class SlotRequest {
constructor(slot) {
this.slot = slot;
}
}
class DisplaySlot extends SlotRequest {
}
class RefreshSlot extends SlotRequest {
}
const GPT_URL = '//securepubads.g.doubleclick.net/tag/js/gpt.js';
const DELAY_TIME = 50;
const DEFAULT_TAG_NAME = 'gpt-ad';
class NgGptEvent {
constructor(event) {
Object.assign(this, event);
}
}
class ImpressionViewableEvent extends NgGptEvent {
}
class RewardedSlotClosedEvent extends NgGptEvent {
}
class RewardedSlotGrantedEvent extends NgGptEvent {
}
class SlotOnloadEvent extends NgGptEvent {
}
class SlotRenderEndedEvent extends NgGptEvent {
}
class SlotRequestedEvent extends NgGptEvent {
}
class SlotResponseReceived extends NgGptEvent {
}
class SlotVisibilityChangedEvent extends NgGptEvent {
}
class NgGptServiceOptions {
}
NgGptServiceOptions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptServiceOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
NgGptServiceOptions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptServiceOptions, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptServiceOptions, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}] });
const GPT_OPTIONS = new InjectionToken('NgGptServiceOptions');
class ScriptInjectorUtil {
injectScript(url) {
const script = this.createScript(url);
const head = document.head || document.querySelector('head');
head.appendChild(script);
return this.promiseScript(script, url);
}
createScript(url) {
const script = document.createElement('script');
script.async = true;
script.type = 'text/javascript';
script.src = this.completeURL(url);
return script;
}
completeURL(url) {
const ssl = document.location.protocol === 'https:';
return (ssl ? 'https:' : 'http:') + url;
}
promiseScript(script, url) {
const promise = new Promise((resolve, reject) => {
script.onload = () => {
resolve(script);
};
script.onerror = () => {
reject({
path: url,
loaded: false,
});
};
});
promise.catch(() => {
console.error(`Error: loading script "${url}"`);
});
return promise;
}
}
ScriptInjectorUtil.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: ScriptInjectorUtil, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
ScriptInjectorUtil.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: ScriptInjectorUtil });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: ScriptInjectorUtil, decorators: [{
type: Injectable
}] });
class IdGeneratorUtil {
constructor() {
this.ids = {};
}
generate(element) {
if (element && element.id && !(element.id in this.ids))
return element.id;
const tagName = element.tagName || DEFAULT_TAG_NAME;
let id = '';
do {
const number = Math.random().toString().slice(2);
id = tagName + '-' + number;
} while (id in this.ids);
this.ids[id] = true;
element.id = id;
return id;
}
isTaken(id) {
return id in this.ids;
}
isUnique(id) {
return !this.isTaken(id);
}
}
IdGeneratorUtil.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: IdGeneratorUtil, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
IdGeneratorUtil.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: IdGeneratorUtil });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: IdGeneratorUtil, decorators: [{
type: Injectable
}] });
class NgGptService {
constructor(options, platformId, scriptInjector) {
this.options = options;
this.platformId = platformId;
this.scriptInjector = scriptInjector;
this.$singleRequest = new Subject();
if (isPlatformBrowser(this.platformId)) {
this.init();
}
}
init() {
if (!window.googletag) {
const loadScript = () => {
this.scriptInjector.injectScript(GPT_URL);
};
loadScript();
window.googletag = window.googletag || { cmd: [] };
}
this.$singleRequest
.pipe(buffer(this.$singleRequest.pipe(switchMap(() => timer(DELAY_TIME * 2)))))
.subscribe((acts) => {
const refreshSlots = [];
acts.forEach((act) => {
if (act instanceof DisplaySlot) {
googletag.display(act.slot);
}
else {
refreshSlots.push(act.slot);
}
});
if (refreshSlots.length > 0) {
googletag.pubads().refresh(refreshSlots);
}
});
googletag.cmd.push(() => {
const pubads = googletag.pubads();
const { address, centering, collapseEmptyDivs, enableLazyLoad, enableSingleRequest, ppid, targeting, forceSafeFrame, safeFrameConfig, privacySettingsConfig, disableInitialLoad, } = this.options;
if (disableInitialLoad)
pubads.disableInitialLoad();
// Collapse Empty Divs
if (collapseEmptyDivs)
pubads.collapseEmptyDivs();
// Centering
if (centering)
pubads.setCentering(centering);
// Location
if (address)
pubads.setLocation(address);
// Publisher Provided Id
if (ppid)
pubads.setPublisherProvidedId(ppid);
// Force Safe Frame
if (forceSafeFrame)
pubads.setForceSafeFrame(forceSafeFrame);
// Targeting
if (targeting && Object.keys(targeting).length) {
for (const key in targeting) {
if (targeting.hasOwnProperty(key)) {
pubads.setTargeting(key, targeting[key]);
}
}
}
// Safe Frame Config
if (safeFrameConfig && Object.keys(safeFrameConfig).length) {
pubads.setSafeFrameConfig(safeFrameConfig);
}
// Privacy Settings Config
if (privacySettingsConfig && Object.keys(privacySettingsConfig).length) {
googletag.pubads().setPrivacySettings(privacySettingsConfig);
}
// Enable Lazy Load
if (enableLazyLoad && Object.keys(enableLazyLoad).length) {
pubads.enableLazyLoad(enableLazyLoad);
}
if (enableSingleRequest) {
pubads.enableSingleRequest();
}
});
}
define(ad, slot) {
const id = ad.id || '';
const pubads = googletag.pubads();
if (!slot) {
const exists = this.getSlot(id);
if (exists) {
this.destroy(exists);
}
if (ad.size) {
slot = googletag.defineSlot(ad.adUnitPath, ad.size, id);
}
else {
slot = googletag.defineOutOfPageSlot(ad.adUnitPath, id);
}
}
if (ad.sizeMapping) {
slot.defineSizeMapping(ad.sizeMapping);
}
slot.clearCategoryExclusions();
if (ad.categoryExclusion) {
if (ad.categoryExclusion instanceof Array) {
const s = slot;
ad.categoryExclusion.forEach((cat) => s.setCategoryExclusion(cat));
}
else {
slot.setCategoryExclusion(ad.categoryExclusion);
}
}
slot.set('adsense_background_color', '#000000');
if (typeof ad.forceSafeFrame === 'boolean') {
slot.setForceSafeFrame(ad.forceSafeFrame);
}
if (ad.safeFrameConfig) {
slot.setSafeFrameConfig(ad.safeFrameConfig);
}
slot.clearTargeting();
if (ad.targeting) {
slot.updateTargetingFromMap(ad.targeting);
}
if (ad.collapseEmptyDiv instanceof Array) {
slot.setCollapseEmptyDiv(ad.collapseEmptyDiv[0], ad.collapseEmptyDiv[1]);
}
else if (typeof ad.collapseEmptyDiv === 'boolean') {
slot.setCollapseEmptyDiv(ad.collapseEmptyDiv);
}
if (ad.clickUrl) {
slot.setClickUrl(ad.clickUrl);
}
// Events
googletag.cmd.push(() => {
pubads.addEventListener('impressionViewable', (event) => {
ad.impressionViewable.emit(new ImpressionViewableEvent(event));
});
pubads.addEventListener('rewardedSlotClosed', (event) => {
ad.rewardedSlotClosed.emit(new RewardedSlotClosedEvent(event));
});
pubads.addEventListener('rewardedSlotGranted', (event) => {
ad.rewardedSlotGranted.emit(new RewardedSlotGrantedEvent(event));
});
pubads.addEventListener('rewardedSlotReady', (event) => {
ad.rewardedSlotReady.emit(new RewardedSlotGrantedEvent(event));
});
pubads.addEventListener('slotOnload', (event) => {
ad.slotOnload.emit(new SlotOnloadEvent(event));
});
pubads.addEventListener('slotRenderEnded', (event) => {
ad.slotRenderEnded.emit(new SlotRenderEndedEvent(event));
});
pubads.addEventListener('slotRequested', (event) => {
ad.slotRequested.emit(new SlotRequestedEvent(event));
});
pubads.addEventListener('slotResponseReceived', (event) => {
ad.slotResponseReceived.emit(new SlotResponseReceived(event));
});
pubads.addEventListener('slotVisibilityChanged', (event) => {
ad.slotVisibilityChanged.emit(new SlotVisibilityChangedEvent(event));
});
});
slot.addService(googletag.pubads());
googletag.enableServices();
return slot;
}
display(slot) {
this.$singleRequest.next(new DisplaySlot(slot));
}
refresh(slot) {
this.$singleRequest.next(new RefreshSlot(slot));
}
destroy(slot) {
googletag.destroySlots([slot]);
}
getSlot(id) {
return this.getSlots().find((slot) => slot.getSlotElementId() === id);
}
getSlots(ids) {
const slots = googletag.pubads().getSlots();
return slots.filter((slot) => !ids || ids.includes(slot.getSlotElementId()));
}
defineTask(task) {
if (isPlatformBrowser(this.platformId)) {
googletag.cmd.push(task);
return true;
}
return false;
}
}
NgGptService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptService, deps: [{ token: GPT_OPTIONS }, { token: PLATFORM_ID }, { token: ScriptInjectorUtil }], target: i0.ɵɵFactoryTarget.Injectable });
NgGptService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: function () { return [{ type: NgGptServiceOptions, decorators: [{
type: Inject,
args: [GPT_OPTIONS]
}] }, { type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: ScriptInjectorUtil }]; } });
class NgGptDirective {
constructor(router, platformId, elementRef, gptService, idGenerator) {
this.router = router;
this.platformId = platformId;
this.elementRef = elementRef;
this.gptService = gptService;
this.idGenerator = idGenerator;
this.$update = new Subject();
this.$destroy = new Subject();
this.adUnitPath = '';
this.id = '';
// Events
this.impressionViewable = new EventEmitter();
this.rewardedSlotClosed = new EventEmitter();
this.rewardedSlotGranted = new EventEmitter();
this.rewardedSlotReady = new EventEmitter();
this.slotOnload = new EventEmitter();
this.slotRenderEnded = new EventEmitter();
this.slotRequested = new EventEmitter();
this.slotResponseReceived = new EventEmitter();
this.slotVisibilityChanged = new EventEmitter();
if (isPlatformBrowser(platformId)) {
this.init();
}
}
ngAfterViewInit() {
if (this.elementRef.nativeElement && this.elementRef.nativeElement.id) {
this.destroy();
this.create();
}
}
ngOnInit() {
if (isPlatformBrowser(this.platformId) && !this.id) {
this.idGenerator.generate(this.elementRef.nativeElement);
}
}
ngDoCheck() {
if (this.elementRef.nativeElement &&
this.elementRef.nativeElement.id &&
this.id !== this.elementRef.nativeElement.id) {
this.id = this.elementRef.nativeElement.id;
this.destroy();
this.create();
}
}
ngOnDestroy() {
if (this.slot) {
googletag.destroySlots([this.slot]);
}
if (this.onSameNavigation) {
this.onSameNavigation.unsubscribe();
}
}
display() {
if (this.slot) {
this.gptService.define(this, this.slot);
this.gptService.refresh(this.slot);
}
else {
this.destroy();
this.slot = this.gptService.define(Object.assign({}, this, {
id: this.id || this.elementRef.nativeElement?.id,
}));
this.gptService.display(this.slot);
}
}
checkRequiredFields(input, name) {
if (!input) {
throw new Error(`Attribute ${name} is required`);
}
}
destroy() {
if (this.slot) {
this.gptService.destroy(this.slot);
this.slot = undefined;
}
}
init() {
this.$update
.pipe(switchMap(() => timer(DELAY_TIME)), takeUntil(this.$destroy))
.subscribe(() => {
this.checkRequiredFields(this.adUnitPath, 'adUnitPath');
this.gptService.defineTask(() => this.display());
});
if (this.router) {
this.onSameNavigation = this.router.events
.pipe(filter((event) => event instanceof NavigationEnd), takeUntil(this.$destroy))
.subscribe(() => {
this.$update.next();
});
}
}
create() {
if (this.adUnitPath) {
this.$update.next();
}
else {
this.destroy();
}
}
}
NgGptDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptDirective, deps: [{ token: i1.Router, optional: true }, { token: PLATFORM_ID }, { token: i0.ElementRef }, { token: NgGptService }, { token: IdGeneratorUtil }], target: i0.ɵɵFactoryTarget.Directive });
NgGptDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0", type: NgGptDirective, selector: "gpt-ad", inputs: { adUnitPath: "adUnitPath", id: "id", size: "size", sizeMapping: "sizeMapping", categoryExclusion: "categoryExclusion", collapseEmptyDiv: "collapseEmptyDiv", forceSafeFrame: "forceSafeFrame", safeFrameConfig: "safeFrameConfig", targeting: "targeting", clickUrl: "clickUrl", refresh: "refresh" }, outputs: { impressionViewable: "impressionViewable", rewardedSlotClosed: "rewardedSlotClosed", rewardedSlotGranted: "rewardedSlotGranted", rewardedSlotReady: "rewardedSlotReady", slotOnload: "slotOnload", slotRenderEnded: "slotRenderEnded", slotRequested: "slotRequested", slotResponseReceived: "slotResponseReceived", slotVisibilityChanged: "slotVisibilityChanged" }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptDirective, decorators: [{
type: Directive,
args: [{
selector: 'gpt-ad',
}]
}], ctorParameters: function () { return [{ type: i1.Router, decorators: [{
type: Optional
}] }, { type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i0.ElementRef }, { type: NgGptService }, { type: IdGeneratorUtil }]; }, propDecorators: { adUnitPath: [{
type: Input
}], id: [{
type: Input
}], size: [{
type: Input
}], sizeMapping: [{
type: Input
}], categoryExclusion: [{
type: Input
}], collapseEmptyDiv: [{
type: Input
}], forceSafeFrame: [{
type: Input
}], safeFrameConfig: [{
type: Input
}], targeting: [{
type: Input
}], clickUrl: [{
type: Input
}], refresh: [{
type: Input
}], impressionViewable: [{
type: Output
}], rewardedSlotClosed: [{
type: Output
}], rewardedSlotGranted: [{
type: Output
}], rewardedSlotReady: [{
type: Output
}], slotOnload: [{
type: Output
}], slotRenderEnded: [{
type: Output
}], slotRequested: [{
type: Output
}], slotResponseReceived: [{
type: Output
}], slotVisibilityChanged: [{
type: Output
}] } });
class NgGptModule {
static forRoot(options) {
return {
ngModule: NgGptModule,
providers: [
{
provide: GPT_OPTIONS,
useValue: options || {},
},
],
};
}
}
NgGptModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NgGptModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.0", ngImport: i0, type: NgGptModule, declarations: [NgGptDirective], exports: [NgGptDirective] });
NgGptModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptModule, providers: [ScriptInjectorUtil, IdGeneratorUtil] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: NgGptModule, decorators: [{
type: NgModule,
args: [{
declarations: [NgGptDirective],
providers: [ScriptInjectorUtil, IdGeneratorUtil],
exports: [NgGptDirective],
}]
}] });
/*
* Public API Surface of ng-gpt
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgGptDirective, NgGptModule, NgGptService };
//# sourceMappingURL=niur-ng-gpt.mjs.map