Skip to content
This repository was archived by the owner on Oct 20, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- 'stable'
- '7'
before_install: npm install -g npm@'>=2.13.5'
deploy:
provider: npm
Expand Down
11,343 changes: 5,994 additions & 5,349 deletions dist/mi-angular-bitdash-player.js

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions dist/mi-angular-bitdash-player.min.js

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions lib/uimanager/arrayutils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export namespace ArrayUtils {
/**
* Removes an item from an array.
* @param array the array that may contain the item to remove
* @param item the item to remove from the array
* @returns {any} the removed item or null if it wasn't part of the array
*/
export function remove<T>(array: T[], item: T): T | null {
let index = array.indexOf(item);

if (index > -1) {
return array.splice(index, 1)[0];
} else {
return null;
}
}
}
12 changes: 12 additions & 0 deletions lib/uimanager/browserutils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export namespace BrowserUtils {

// isMobile only needs to be evaluated once (it cannot change during a browser session)
// Mobile detection according to Mozilla recommendation: "In summary, we recommend looking for the string “Mobi”
// anywhere in the User Agent to detect a mobile device."
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
export const isMobile = navigator && navigator.userAgent && /Mobi/.test(navigator.userAgent);

export const isChrome = navigator && navigator.userAgent && /Chrome/.test(navigator.userAgent);

export const isAndroid = navigator && navigator.userAgent && /Android/.test(navigator.userAgent);
}
12 changes: 6 additions & 6 deletions lib/uimanager/components/audioonlyoverlay.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ContainerConfig, Container} from './container';
import {UIInstanceManager} from '../uimanager';
import {Component, ComponentConfig} from './component';
import PlayerEvent = bitmovin.PlayerAPI.PlayerEvent;
// import PlayerEvent = bitmovin.PlayerAPI.PlayerEvent;

/**
* Overlays the player and displays an audio-only indicator.
Expand All @@ -14,13 +14,13 @@ export class AudioOnlyOverlay extends Container<ContainerConfig> {
super(config);

this.audioonly = [
new Component<ComponentConfig>({ tag: 'div', cssClass: 'ui-audioonly-overlay-indicator' })
new Component<ComponentConfig>({ tag: 'div', cssClass: 'ui-audioonly-overlay-indicator' }),
];

this.config = this.mergeConfig(config, <ComponentConfig>{
cssClass: 'ui-audioonly-overlay',
components: this.audioonly,
hidden: false
hidden: false,
}, this.config);
}

Expand All @@ -35,12 +35,12 @@ export class AudioOnlyOverlay extends Container<ContainerConfig> {
// player.addEventHandler(player.EVENT.ON_PAUSED, (event) => {
// self.getDomElement().css('background-image', 'none');
// });

//
// player.addEventHandler(player.EVENT.ON_PLAY, (event) => {
// self.getDomElement().css('background-image', image);
// });

// Hide overlay if player is paused at init (e.g. on mobile devices)
//
// // Hide overlay if player is paused at init (e.g. on mobile devices)
// if (!player.isPlaying()) {
// self.getDomElement().css('background-image', 'none');
// }
Expand Down
8 changes: 4 additions & 4 deletions lib/uimanager/components/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ export interface ButtonConfig extends ComponentConfig {
export class Button<Config extends ButtonConfig> extends Component<ButtonConfig> {

private buttonEvents = {
onClick: new EventDispatcher<Button<Config>, NoArgs>()
onClick: new EventDispatcher<Button<Config>, NoArgs>(),
};

constructor(config: ButtonConfig) {
super(config);

this.config = this.mergeConfig(config, {
cssClass: 'ui-button'
cssClass: 'ui-button',
}, this.config);
}

Expand All @@ -34,9 +34,9 @@ export class Button<Config extends ButtonConfig> extends Component<ButtonConfig>
let buttonElement = new DOM('button', {
'type': 'button',
'id': this.config.id,
'class': this.getCssClasses()
'class': this.getCssClasses(),
}).append(new DOM('span', {
'class': this.prefixCss('label')
'class': this.prefixCss('label'),
}).html(this.config.text));

// Listen for the click event on the button element and trigger the corresponding event on the button component
Expand Down
2 changes: 1 addition & 1 deletion lib/uimanager/components/clickoverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class ClickOverlay extends Button<ClickOverlayConfig> {
super(config);

this.config = this.mergeConfig(config, {
cssClass: 'ui-clickoverlay'
cssClass: 'ui-clickoverlay',
}, <ClickOverlayConfig>this.config);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/uimanager/components/closebutton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class CloseButton extends Button<CloseButtonConfig> {

this.config = this.mergeConfig(config, {
cssClass: 'ui-closebutton',
text: 'Close'
text: 'Close',
}, this.config);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/uimanager/components/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class Component<Config extends ComponentConfig> {
cssPrefix: 'mi-wbc',
cssClass: 'ui-component',
cssClasses: [],
hidden: false
hidden: false,
}, {});
}

Expand Down Expand Up @@ -226,7 +226,7 @@ export class Component<Config extends ComponentConfig> {
protected toDomElement(): DOM {
let element = new DOM(this.config.tag, {
'id': this.config.id,
'class': this.getCssClasses()
'class': this.getCssClasses(),
});

return element;
Expand Down
42 changes: 33 additions & 9 deletions lib/uimanager/components/container.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentConfig, Component} from './component';
import {DOM} from '../dom';
import {ArrayUtils} from '../utils';
import {ArrayUtils} from '../arrayutils';

/**
* Configuration interface for a {@link Container}.
Expand Down Expand Up @@ -37,14 +37,19 @@ export class Container<Config extends ContainerConfig> extends Component<Contain
* A reference to the inner element that contains the components of the container.
*/
private innerContainerElement: DOM;
private componentsToAdd: Component<ComponentConfig>[];
private componentsToRemove: Component<ComponentConfig>[];

constructor(config: ContainerConfig) {
constructor(config: Config) {
super(config);

this.config = this.mergeConfig(config, {
cssClass: 'ui-container',
components: []
components: [],
}, this.config);

this.componentsToAdd = [];
this.componentsToRemove = [];
}

/**
Expand All @@ -53,6 +58,7 @@ export class Container<Config extends ContainerConfig> extends Component<Contain
*/
addComponent(component: Component<ComponentConfig>) {
this.config.components.push(component);
this.componentsToAdd.push(component);
}

/**
Expand All @@ -61,7 +67,12 @@ export class Container<Config extends ContainerConfig> extends Component<Contain
* @returns {boolean} true if the component has been removed, false if it is not contained in this container
*/
removeComponent(component: Component<ComponentConfig>): boolean {
return ArrayUtils.remove(this.config.components, component) != null;
if (ArrayUtils.remove(this.config.components, component) != null) {
this.componentsToRemove.push(component);
return true;
} else {
return false;
}
}

/**
Expand All @@ -76,7 +87,7 @@ export class Container<Config extends ContainerConfig> extends Component<Contain
* Removes all child components from the container.
*/
removeComponents(): void {
for (let component of this.getComponents()) {
for (let component of this.getComponents().slice()) {
this.removeComponent(component);
}
}
Expand All @@ -85,9 +96,19 @@ export class Container<Config extends ContainerConfig> extends Component<Contain
* Updates the DOM of the container with the current components.
*/
protected updateComponents(): void {
this.innerContainerElement.empty();
/* We cannot just clear the container to remove all elements and then re-add those that should stay, because
* IE looses the innerHTML of unattached elements, leading to empty elements within the container (e.g. missing
* subtitle text in SubtitleLabel).
* Instead, we keep a list of elements to add and remove, leaving remaining elements alone. By keeping them in
* the DOM, their content gets preserved in all browsers.
*/
let component;

while (component = this.componentsToRemove.shift()) {
component.getDomElement().remove();
}

for (let component of this.config.components) {
while (component = this.componentsToAdd.shift()) {
this.innerContainerElement.append(component.getDomElement());
}
}
Expand All @@ -96,15 +117,18 @@ export class Container<Config extends ContainerConfig> extends Component<Contain
// Create the container element (the outer <div>)
let containerElement = new DOM(this.config.tag, {
'id': this.config.id,
'class': this.getCssClasses()
'class': this.getCssClasses(),
});

// Create the inner container element (the inner <div>) that will contain the components
let innerContainer = new DOM(this.config.tag, {
'class': this.prefixCss('container-wrapper')
'class': this.prefixCss('container-wrapper'),
});
this.innerContainerElement = innerContainer;

for (let initialComponent of this.config.components) {
this.componentsToAdd.push(initialComponent);
}
this.updateComponents();

containerElement.append(innerContainer);
Expand Down
4 changes: 2 additions & 2 deletions lib/uimanager/components/controlbar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ContainerConfig, Container} from './container';
import {UIInstanceManager} from '../uimanager';
import {UIUtils} from '../utils';
import {UIUtils} from '../uiutils';
import {Spacer} from './spacer';

/**
Expand All @@ -21,7 +21,7 @@ export class ControlBar extends Container<ControlBarConfig> {

this.config = this.mergeConfig(config, {
cssClass: 'ui-controlbar',
hidden: autoHide
hidden: autoHide,
}, <ControlBarConfig>this.config);
}

Expand Down
9 changes: 8 additions & 1 deletion lib/uimanager/components/errormessageoverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class ErrorMessageOverlay extends Container<ErrorMessageOverlayConfig> {
this.config = this.mergeConfig(config, {
cssClass: 'ui-errormessage-overlay',
components: [this.tvNoiseBackground, this.errorLabel],
hidden: true
hidden: true,
}, this.config);
}

Expand Down Expand Up @@ -131,4 +131,11 @@ export class ErrorMessageOverlay extends Container<ErrorMessageOverlayConfig> {
}
});
}

release(): void {
super.release();

// Canvas rendering must be explicitly stopped, else it just continues forever and hogs resources
this.tvNoiseBackground.stop();
}
}
2 changes: 1 addition & 1 deletion lib/uimanager/components/fullscreentogglebutton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class FullscreenToggleButton extends ToggleButton<ToggleButtonConfig> {

this.config = this.mergeConfig(config, {
cssClass: 'ui-fullscreentogglebutton',
text: 'Fullscreen'
text: 'Fullscreen',
}, this.config);
}

Expand Down
10 changes: 5 additions & 5 deletions lib/uimanager/components/hugeplaybacktogglebutton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class HugePlaybackToggleButton extends PlaybackToggleButton {

this.config = this.mergeConfig(config, {
cssClass: 'ui-hugeplaybacktogglebutton',
text: 'Play/Pause'
text: 'Play/Pause',
}, this.config);
}

Expand All @@ -24,17 +24,17 @@ export class HugePlaybackToggleButton extends PlaybackToggleButton {

let togglePlayback = () => {
if (player.isPlaying()) {
player.pause('ui-overlay');
player.pause('ui');
} else {
player.play('ui-overlay');
player.play('ui');
}
};

let toggleFullscreen = () => {
if (player.isFullscreen()) {
player.exitFullscreen();
} else {
// player.enterFullscreen();
player.enterFullscreen();
}
};

Expand Down Expand Up @@ -125,7 +125,7 @@ export class HugePlaybackToggleButton extends PlaybackToggleButton {
// can cover the whole video player are and scaling would extend it beyond. By adding an inner element, confined
// to the size if the image, it can scale inside the player without overshooting.
buttonElement.append(new DOM('div', {
'class': this.prefixCss('image')
'class': this.prefixCss('image'),
}));

return buttonElement;
Expand Down
7 changes: 3 additions & 4 deletions lib/uimanager/components/hugereplaybutton.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {ButtonConfig, Button} from './button';
import {DOM} from '../dom';
import {UIInstanceManager} from '../uimanager';
import PlayerEvent = bitmovin.PlayerAPI.PlayerEvent;

/**
* A button to play/replay a video.
Expand All @@ -13,15 +12,15 @@ export class HugeReplayButton extends Button<ButtonConfig> {

this.config = this.mergeConfig(config, {
cssClass: 'ui-hugereplaybutton',
text: 'Replay'
text: 'Replay',
}, this.config);
}

configure(player: bitmovin.PlayerAPI, uimanager: UIInstanceManager): void {
super.configure(player, uimanager);

this.onClick.subscribe(() => {
player.play('ui-overlay');
player.play('ui');
});
}

Expand All @@ -33,7 +32,7 @@ export class HugeReplayButton extends Button<ButtonConfig> {
// can cover the whole video player are and scaling would extend it beyond. By adding an inner element, confined
// to the size if the image, it can scale inside the player without overshooting.
buttonElement.append(new DOM('div', {
'class': this.prefixCss('image')
'class': this.prefixCss('image'),
}));

return buttonElement;
Expand Down
Loading