@flosportsinc/ng-video-autoplay
Version:
Simple way to ensure videos autoplay even if they need to be muted first.
293 lines (289 loc) • 9.79 kB
JavaScript
import { Directive, ElementRef, Renderer2, Input, ContentChildren, NgModule } from '@angular/core';
import { takeUntil, share, map, tap, take, filter, flatMap } from 'rxjs/operators';
import { fromEvent, Subject } from 'rxjs';
import { either, maybe } from 'typescript-monads';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// tslint:disable:no-object-mutation
/** @type {?} */
var filterHalted = (/**
* @param {?} source
* @return {?}
*/
function (source) {
return source.pipe(filter((/**
* @param {?} res
* @return {?}
*/
function (res) { return res.halted === true; })));
});
/** @type {?} */
var tryPlayVideoAsIs = (/**
* @param {?} source
* @return {?}
*/
function (source) {
return source.pipe(flatMap((/**
* @param {?} videoElement
* @return {?}
*/
function (videoElement) { return videoElement.play()
.then((/**
* @return {?}
*/
function () { return ({ videoElement: videoElement, halted: false }); }))
.catch((/**
* @return {?}
*/
function () { return ({ videoElement: videoElement, halted: true }); })); })), filterHalted);
});
/** @type {?} */
var tryPlayVideoMuted = (/**
* @param {?} source
* @return {?}
*/
function (source) {
return source.pipe(map((/**
* @param {?} res
* @return {?}
*/
function (res) {
res.videoElement.muted = true;
res.videoElement.volume = 0;
return res.videoElement;
})), tryPlayVideoAsIs);
})
// 1) attempt to play as-is (including autoplay + unmuted)
// 2) attempt to play muted, showing unmite button
// 3) show click to play
;
// 1) attempt to play as-is (including autoplay + unmuted)
// 2) attempt to play muted, showing unmite button
// 3) show click to play
var FloVideoAutoplayDirective = /** @class */ (function () {
function FloVideoAutoplayDirective(elmRef, rd) {
var _this = this;
this.elmRef = elmRef;
this.rd = rd;
this.floVideoAutoplay = true;
this.floVideoAutoplayIndex = 0;
this.onDestroySource = new Subject();
this.onDestroy = this.onDestroySource.pipe(share());
this.canExecute = (/**
* @return {?}
*/
function () { return _this.floVideoAutoplay === true || _this.floVideoAutoplay === ''; });
this.maybeVideoElement = (/**
* @return {?}
*/
function () { return maybe(_this.elmRef.nativeElement).filter((/**
* @param {?} e
* @return {?}
*/
function (e) { return e.nodeName === 'VIDEO'; })); });
this.maybeUnmuteActionRef = (/**
* @return {?}
*/
function () { return maybe(_this.floVideoAutoplayClickUnmuteRef).filter((/**
* @param {?} a
* @return {?}
*/
function (a) { return (/** @type {?} */ (a)) !== ''; })); });
this.maybePlayActionRef = (/**
* @return {?}
*/
function () { return maybe(_this.floVideoAutoplayClickPlayRef).filter((/**
* @param {?} a
* @return {?}
*/
function (a) { return (/** @type {?} */ (a)) !== ''; })); });
this.hideRef = (/**
* @param {?} ref
* @return {?}
*/
function (ref) { return _this.rd.setStyle(ref, 'display', 'none'); });
this.showRef = (/**
* @param {?} ref
* @return {?}
*/
function (ref) { return _this.rd.setStyle(ref, 'display', 'block'); });
this.volumeChange = (/**
* @param {?} videoElement
* @return {?}
*/
function (videoElement) {
return fromEvent(videoElement, 'volumechange', { passive: true }).pipe(map((/**
* @param {?} evt
* @return {?}
*/
function (evt) { return (/** @type {?} */ (evt.target)); })), share(), takeUntil(_this.onDestroy));
});
this.initOnVideo = (/**
* @param {?} videoElement
* @return {?}
*/
function (videoElement) {
return fromEvent(videoElement, 'loadstart').pipe(tap((/**
* @return {?}
*/
function () { return videoElement.setAttribute('autoplay', 'true'); })), map((/**
* @param {?} evt
* @return {?}
*/
function (evt) { return (/** @type {?} */ (evt.target)); })), tryPlayVideoAsIs, tryPlayVideoMuted, take(1)).subscribe((/**
* @param {?} res
* @return {?}
*/
function (res) {
res.videoElement.preload = 'none';
res.videoElement.muted = false;
res.videoElement.volume = 1;
_this.maybePlayActionRef().tapSome(_this.showRef);
}));
});
this.runUnmuteSequence = (/**
* @param {?} actionRef
* @return {?}
*/
function (actionRef) { return (/**
* @param {?} runOnce
* @return {?}
*/
function (runOnce) { return (/**
* @param {?} videoElement
* @return {?}
*/
function (videoElement) {
videoElement.setAttribute('autoplay', 'true');
fromEvent(actionRef, 'click').pipe(takeUntil(_this.onDestroy)).subscribe((/**
* @return {?}
*/
function () {
videoElement.muted = false;
videoElement.volume = 1;
}));
_this.volumeChange(videoElement).pipe(filter((/**
* @param {?} v
* @return {?}
*/
function (v) { return !v.muted || v.volume > 0; })), takeUntil(_this.onDestroy))
.subscribe((/**
* @return {?}
*/
function () { return _this.hideRef(actionRef); }));
/** @type {?} */
var showRef = _this.volumeChange(videoElement).pipe(filter((/**
* @param {?} v
* @return {?}
*/
function (v) { return v.muted || v.volume <= 0; })));
(runOnce ? showRef.pipe(take(1)) : showRef).subscribe((/**
* @return {?}
*/
function () { return _this.showRef(actionRef); }));
}); }); });
}
/**
* @return {?}
*/
FloVideoAutoplayDirective.prototype.ngAfterContentInit = /**
* @return {?}
*/
function () {
var _this = this;
if (!this.canExecute()) {
return;
}
this.maybeVideoElement().tapSome(this.initOnVideo);
this.videos.map((/**
* @param {?} a
* @return {?}
*/
function (a) { return a.nativeElement; })).forEach(this.initOnVideo);
this.maybeUnmuteActionRef().tapSome((/**
* @param {?} ref
* @return {?}
*/
function (ref) {
_this.hideRef(ref);
either(_this.maybeVideoElement().valueOrUndefined(), maybe(_this.videos.toArray()[_this.floVideoAutoplayIndex]).map((/**
* @param {?} a
* @return {?}
*/
function (a) { return a.nativeElement; })).valueOrUndefined())
.tap({
left: _this.runUnmuteSequence(ref)(false),
right: _this.runUnmuteSequence(ref)(true)
});
}));
this.maybePlayActionRef().tapSome((/**
* @param {?} actionRef
* @return {?}
*/
function (actionRef) {
_this.hideRef(actionRef);
fromEvent(actionRef, 'click').pipe(takeUntil(_this.onDestroy)).subscribe((/**
* @return {?}
*/
function () {
_this.hideRef(actionRef);
_this.maybeVideoElement().tapSome((/**
* @param {?} v
* @return {?}
*/
function (v) { return v.play(); }));
}));
}));
};
/**
* @return {?}
*/
FloVideoAutoplayDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.onDestroySource.next();
this.onDestroySource.complete();
};
FloVideoAutoplayDirective.decorators = [
{ type: Directive, args: [{
selector: '[floVideoAutoplay]'
},] }
];
/** @nocollapse */
FloVideoAutoplayDirective.ctorParameters = function () { return [
{ type: ElementRef },
{ type: Renderer2 }
]; };
FloVideoAutoplayDirective.propDecorators = {
floVideoAutoplay: [{ type: Input }],
floVideoAutoplayClickUnmuteRef: [{ type: Input }],
floVideoAutoplayClickPlayRef: [{ type: Input }],
floVideoAutoplayIndex: [{ type: Input }],
videos: [{ type: ContentChildren, args: ['floVideoAutoplay', { descendants: true },] }]
};
return FloVideoAutoplayDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var FloVideoAutoplayModule = /** @class */ (function () {
function FloVideoAutoplayModule() {
}
FloVideoAutoplayModule.decorators = [
{ type: NgModule, args: [{
declarations: [
FloVideoAutoplayDirective
],
exports: [
FloVideoAutoplayDirective
]
},] }
];
return FloVideoAutoplayModule;
}());
export { FloVideoAutoplayModule, FloVideoAutoplayDirective as ɵa };
//# sourceMappingURL=flosportsinc-ng-video-autoplay.js.map