I inherited a project that needs some minor analytics, more specifically, video plays analytics.
It's an Angular project that gets a html body from a SQL server.
It parses a string and injects in a page. So I can't add extra html to solve this issue, I can only add some Angular code.
Current analytics is Matomo, I'm using ngx-matomo to monitor views and visits.
AFAIK when a video is played I need to send the notification to the server, but the thing is, how do I get the event when a video is played?
My jQuery habits would say that monitoring events and waiting for a video element would suffice, but here's the gist, I can't get click events on video elements.
I wrote this small piece of code that mimics what I'm trying to do?
//our root app ponent
import {Component, NgModule, VERSION, ViewChild} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<div (click)="anyClick($event)" style="padding: 10px">
<div> not the video </div>
<video width="320" height="240" controls>
<source src=".ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
</div>
`,
})
export class App {
anyClick(event: String) {
console.log(event);
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App],
bootstrap: [ App ]
})
export class AppModule {
}
There's a plnkr here
If you click anywhere on the page, you'll get the event on the console, but the same is not true if you click the video, which is the event I need.
I can attach a listener to a play event using a tag like this
ngOnInit(){
let video = document.querySelector('video');
video.onplay = (event) => {
console.log('The Boolean paused property is now false. Either the ' +
'play() method was called or the autoplay attribute was toggled.');
};
}
If worked on Plunker, but it feels wrong...
Specifying the issue with more details:
The HTML file is actually just a
<div [innerHTML]="innerHTML"></div>
The ponent TS is
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Observable } from 'rxjs';
import { Product } from 'src/app/entities/product';
import { Version } from 'src/app/entities/version';
import { ProductService } from '../product.service';
@Component({
selector: 'app-content',
templateUrl: './contentponent.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./contentponent.scss']
})
export class ContentComponent implements OnInit {
@Input() product: Product;
@Output() load = new EventEmitter<{ title: string, href: string }>();
conteudo$: Observable<Version>;
innerHTML: SafeHtml;
constructor(
private productService: ProductService,
private sanitizer: DomSanitizer
) { }
ngOnInit() {
var pathToLoad;
this.productService.getVersion(pathToLoad).subscribe(version => {
this.innerHTML = this.sanitizer.bypassSecurityTrustHtml(version.conteudo);
const el = document.createElement('html');
el.innerHTML = version.conteudo;
const sections = el.getElementsByTagName('section');
for (let i = 0; i < sections.length; i++) {
const section = sections.item(i);
if (section.hasAttribute('id')) {
this.load.emit({
title: section.getElementsByTagName('h2').item(0).textContent,
href: section.getAttribute('id')
});
}
}
});
}
}
I inherited a project that needs some minor analytics, more specifically, video plays analytics.
It's an Angular project that gets a html body from a SQL server.
It parses a string and injects in a page. So I can't add extra html to solve this issue, I can only add some Angular code.
Current analytics is Matomo, I'm using ngx-matomo to monitor views and visits.
AFAIK when a video is played I need to send the notification to the server, but the thing is, how do I get the event when a video is played?
My jQuery habits would say that monitoring events and waiting for a video element would suffice, but here's the gist, I can't get click events on video elements.
I wrote this small piece of code that mimics what I'm trying to do?
//our root app ponent
import {Component, NgModule, VERSION, ViewChild} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<div (click)="anyClick($event)" style="padding: 10px">
<div> not the video </div>
<video width="320" height="240" controls>
<source src="http://download.blender/peach/trailer/trailer_400p.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
</div>
`,
})
export class App {
anyClick(event: String) {
console.log(event);
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App],
bootstrap: [ App ]
})
export class AppModule {
}
There's a plnkr here http://plnkr.co/edit/ALk16AiaHtgqYYrw
If you click anywhere on the page, you'll get the event on the console, but the same is not true if you click the video, which is the event I need.
I can attach a listener to a play event using a tag like this
ngOnInit(){
let video = document.querySelector('video');
video.onplay = (event) => {
console.log('The Boolean paused property is now false. Either the ' +
'play() method was called or the autoplay attribute was toggled.');
};
}
If worked on Plunker, but it feels wrong...
Specifying the issue with more details:
The HTML file is actually just a
<div [innerHTML]="innerHTML"></div>
The ponent TS is
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Observable } from 'rxjs';
import { Product } from 'src/app/entities/product';
import { Version } from 'src/app/entities/version';
import { ProductService } from '../product.service';
@Component({
selector: 'app-content',
templateUrl: './content.ponent.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./content.ponent.scss']
})
export class ContentComponent implements OnInit {
@Input() product: Product;
@Output() load = new EventEmitter<{ title: string, href: string }>();
conteudo$: Observable<Version>;
innerHTML: SafeHtml;
constructor(
private productService: ProductService,
private sanitizer: DomSanitizer
) { }
ngOnInit() {
var pathToLoad;
this.productService.getVersion(pathToLoad).subscribe(version => {
this.innerHTML = this.sanitizer.bypassSecurityTrustHtml(version.conteudo);
const el = document.createElement('html');
el.innerHTML = version.conteudo;
const sections = el.getElementsByTagName('section');
for (let i = 0; i < sections.length; i++) {
const section = sections.item(i);
if (section.hasAttribute('id')) {
this.load.emit({
title: section.getElementsByTagName('h2').item(0).textContent,
href: section.getAttribute('id')
});
}
}
});
}
}
Share
Improve this question
edited Mar 20, 2020 at 17:11
Johnny Bigoode
asked Mar 19, 2020 at 17:21
Johnny BigoodeJohnny Bigoode
5912 gold badges12 silver badges31 bronze badges
4
- 1 If you get a reference to the video element, you should theoretically be able to listen to the "onplay" and "onpause" events emitted from the video element. I'll try to provide some code examples soon. :) – saglamcem Commented Mar 19, 2020 at 17:50
- 2 w3/2010/05/video/mediaevents.html – M A Salman Commented Mar 19, 2020 at 18:04
- 1 html.spec.whatwg/multipage/media.html#mediaevents – M A Salman Commented Mar 19, 2020 at 18:06
- 1 You posted the javascript solution. If you want to try to find an angular solution, then post the HTML that the server sends to the app. – rickz Commented Mar 20, 2020 at 14:40
2 Answers
Reset to default 7See https://developer.mozilla/en-US/docs/Web/API/HTMLMediaElement/play_event
the play event doesn't bubble. In your plunker, add event binding to your video tag
<video (play)="anyClick($event)"
You can use onplay="script or function call"
<video width="320" onplay="console.log('hello im playing')" height="240" controls>
<source src="http://download.blender/peach/trailer/trailer_400p.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
If you are receiving html from the server and it is stored in a string variable like
let htmlString=`<video width="320" height="240" controls>
<source src="http://download.blender/peach/trailer/trailer_400p.ogg"
type="video/ogg">
Your browser does not support the video tag.
</video>`;
You can do add the onplay inside the string like this
htmlString.replace(/(video)/,"$1 onplay='onPlay($event)'");
HTML:
<div [innerHTML]="htmlString"></div>
and then
onPlay($event:any){
console.log($event.target.id);
console.log($event.target.width);
}
Run this code below in js
let htmlString=`<video width="320" id="vid20" height="240" controls>
<source src="http://download.blender/peach/trailer/trailer_400p.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>`;
document.querySelector("#main").innerHTML=htmlString.replace(/(video)/,"$1 onplay='onPlay(event)'");;
function onPlay(event){
console.clear();
console.log(event.target.id);
}
<div id="main"></div>