Skip to content

Button Plugins

Allows you to add buttons in two different locations:

  • The playback bar, located at the bottom of the Paella Player container. In this case, the buttons are added below the time bar.
  • A button group menu.

The buttons can be aligned to the right or left of the playback bar. By default, this setting is specified in the configuration.

import {
ButtonPlugin,
PaellaCorePlugins
} from '@asicupv/paella-core';
export default class MyButtonPlugin extends ButtonPlugin {
getPluginModuleInstance() {
return PaellaCorePlugins.Get();
}
get name() {
return "es.upv.paella.myButtonPlugin";
}
get side() {
return "left"; // or right
}
get parentContainer() {
return "playbackBar"; // or any button group container identifier
}
async mouseOver(target) {
}
async mouseOut(target) {
}
async action() {
}
}

NOTE: consider to implement your own PluginModule to group your plugins.

Apart from the Plugin methods, ButtonPlugin provides other methods and properties that can be overridden:

  • get side(): returns the end where we want to place the button. The default implementation gets this value from the configuration. This method should be overridden only in case we want the button to be always displayed in the same place, regardless of the configuration.
  • get parentContainer(): returns the container where we want to add the button, which can be either playbackBar or videoContainer. If this function is not overridden, the value is obtained from the plugin configuration, and if it is not specified in the configuration either, it defaults to playbackBar.
  • get titleSize(): is used to set the font size of the button title. It can return small, medium or large.
  • async action(): called when the user clicks the button.
  • getDescription(): is used to return the text of the HTML attribute title.
  • getMinContainerSize(): is used to return the minimum container width required to show the plugin in the playback bar. This value is is overridden by the minContainerSize attribute of the plugin configuration.
  • getId(): Allows to set the id attribute of the <button> element, in case the id property is not defined in the plugin configuration. By default returns null.
  • getButtonName(): Allows to set the name attribute of the <button> element, in case the name property is not defined in the plugin configuration. By default, returns null.
  • getClosePopUps(): Indicates whether or not to close pop ups when the button is clicked. By default this option is true, but in the case of the button group this value is false by default.

Internally, the button is composed of four DOM elements:

  • container: is the container that encompasses the other three parts.
  • button: it is the clickable area of the button

These elements are created before the plugin is loaded, so we can access them from the same load:

async load() {
const anotherElement = document.createElement("div");
... // set the element properties
this.container.appendChild(anotherElement);
}

get iconElement(): Returns the icon DOM element, that is a child of the button element.

get titleContainer(): Returns the DOM container of the button title.

get id() (paella-core>=1.16): get the id attribute to be set in the <button> element. This property returns the value of the id property of the plugin configuration, and if it is not defined, it returns the value returned by the getId() function. If neither of these cases returns a value, then the id attribute will not be added to the <button> element.

get buttonName() (paella-core>=1.16): get the name attribute to be set in the <button> element. Not to be confused with the name attribute of the Plugin class. This property returns the value of the name property of the plugin configuration, and if it’s not defined, it returns the value returned by the getButtonName() function. If neither of these cases returns a value, it will return the value of the name property, that is: the plugin identifier. get closePopUps() (paella-core>=1.22): returns the value of the closePopUp property of the plugin configuration, and if not set, then returns the value of the getClosePopUps() function. This is used internally by paella-core to determine if we want to close pop ups that are open when this button is pressed.

hide(): hide the button.

show(): shows the button.

The hide/show APIs are used internally for some player actions, for example, to hide buttons when there is not enough space in the playbar. If you want to hide a button permanently, you have to use the enable/disable APIs.

disable(): disables and hides the button. When the disabled state is set, the show() function will have no effect when the button is disabled.

enable(): enables the button and displays it.

To specify the icon it is necessary to use icons in vector SVG format. This is a prerequisite, since CSS styles are used to specify the color of the icons. You must load the SVG icon in text fromat, for example using a JavaScript file:

myIcon.js

export default `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
...
</svg>`;

The button can be set at any time, using the set icon() property. For example, we can use the async load() method, but we can also change it at another time:

...
import myPluginIcon1 from 'icons/myIcon.js';
import myPluginIcon2 from 'icons/mySecondIcon.js';
export default class MyButtonPlugin extends ButtonPlugin {
...
async load() {
this.icon = myPluginIcon1;
}
async action() {
if (this.icon === myPluginIcon1) {
this.icon = myPluginIcon2;
}
else {
this.icon = myPluginIcon1;
}
}
}

To load the SVG icons, it is possible to use a Paella Player utility that loads the icon and makes it ready to be added as a DOM element:

import { utils } from '@asicupv/paella-core';
...
const icon = await utils.loadSvgIcon(iconPath);

NOTE: The SVG icon must meet some requirements to be displayed correctly, and to be able to change its colors according to the CSS styles. You can find more information about this in the CSS styling documentation.

To specify the button text, we use the set title() accessor. It is possible to change the button text at any time.

...
export default class MyButtonPlugin extends ButtonPlugin {
...
get titleSize() { return "small"; }
async load() {
this.title = "Hello";
}
async action() {
this.title = "World";
}
}

The parentContainer property, in its default implementation, gets its value from the plugin configuration, inside the config.json file. This property can take several values, two of which are predefined, while the rest are arbitrary:

  • playbackBar: The button will be placed on the playback bar. This is the default value, if any other is specified.
  • Any other value: The button will be placed inside a container that match that name. These containers can be created using plugins of type button group.

As with parentContainer, the side property also takes its value from the plugin configuration. This property affects the side on the horizontal axis that the button is placed, and only affects in case parentContainer is the playbar or the video container. In this case, this property has only two possible values:

  • left: The button will be placed on the left side of the playback bar or the video container.
  • right: The button will be placed on the right side of the playback bar or the video container.

The minContainerSize attribute is used to set a minimum required size of the playback bar to show the button plugin. By default, this value is zero.

The tabIndex is deprecated in paella-core v2 and should not be used.

The ariaLabel attribute defines the text used in the aria-label attribute of the button.

It is possible to add non-interactive buttons. Although strictly speaking a non-interactive button is not a button, this allows you to create plugins that are active but not usable. For example, if we want to emphasise that the player supports subtitles, but the current video does not include them, we can add a non-interactive button.

Non-interactive buttons have mouse events, keyboard events and tab stop disabled, and include the non-interactive class, as explained below in the section on modifying styles.

To disable the button interaction, you must to return false in the property interactive. This property is only read at plugin load time, after calling its isEnabled function, and before calling its load function. Therefore, a button cannot change from interactive to non-interactive during the player’s lifecycle:

export default class MyButtonPlugin extends ButtonPlugin {
...
get interactive() {
return false;
}
}

By default, buttons have a fixed size that can be configured by CSS, as shown below. But sometimes you may want to add buttons with a variable width, for example, if you want to display text.

If you specify text and an icon, variable-width buttons place the button to the left of the text rather than over the icon.

To specify that you want variable width, you must return the dynamicWidth property. As with the interactive property, this is read before the plugin is loaded and after the isEnabled function is called, so this property remains the same throughout its life cycle.

export default class MyButtonPlugin extends ButtonPlugin {
...
async load() {
this.icon = testIcon;
this.title = "Dynamic width button";
}
get dynamicWidth() {
return true;
}
}

To set up the aria-label attribute, you can use the ariaLlabel property in the button plugin configuration. In addition, the description property in the plugin configuration, will be used as title attribute in the button.

{
"plugins": {
...
"es.upv.paella.myButtonPlugin": {
"enabled": true,
"description": "My button description",
"ariaLabel": "My button accesibility string"
}
}
}

The texts of both attributes are translated using the paella player dictionary system.

In addition to using the configuration file, it is possible to define the aria-label text by implementing the getAriaLabel() function, which must return a text string. Note that the text you define in the configuration takes precedence over the text returned by getAriaLabel(). This function can be used to return a predefined text, which can be optionally customized by configuring the plugin.

export default class MyButtonPlugin extends ButtonPlugin {
...
getAriaLabel() {
return "My button predefined accesibility string";
}
...
}

There are a few things to keep in mind regarding location:

  • The ariaLabel and description attributes are translated automatically. Note that these texts are first obtained from the ariaLabel and description attributes of the plugin configuration, and if this text is not defined in the translation, they will be obtained from the getAriaLabel() and getDescription() functions. If this texts are defined for these attributes in the configuration, it must be taken into account that the player we implement must also provide translation for these texts so that they can be modified once the player is compiled.
  • If we want to parameterize the translations, then we will have to do the translation manually:
getAriaLabel() {
return this.player.translate("Forward $1 seconds", [30]);
}
  • The async load() function is called after getAriaLabel() and getDescription(). If we need to initialize something we use in these functions, we will have to do it in the async isEnabled() function.
async isEnabled() {
const enabled = await super.isEnabled();
this.time = this.config.time;
return enabled;
}
getAriaLabel() {
return this.player.translate("Forward $1 seconds", this.time);
}

If the async getAnchorUrl() function returns a value other than null, then the button will become a link and be treated as such, although visually it will share the same visual styles as buttons. When a button is implemented as a link, the async action() function will still be executed to provide flexibility in implementation, but keep in mind that if the link is set to open in the same tab, the button action will not be executed, as the browser will redirect to the link URL. If you want the action to be executed, you need to specify a different target.

The link API functions for button-type plugins that we can override to determine the behavior of the plugin are as follows:

  • getAnchorUrl(): Promise<string | null>: Returns the link URL or null if it is not a link.
  • get anchorTarget(): string | null: Returns the target attribute of the link or null if we do not want to add that attribute. Its default value is _self.
  • get anchorDownloadFilename(): string | null: Tells the browser if we want the link to be treated as a file download. If null is returned, then the link will be treated as a normal link. If a file name is returned, the browser will download the resource instead of opening it, and the file name will be the one returned in this function. If an empty string is returned, then the download name will be determined by the browser implementation.
  • get anchorReferrerPolicy(): string | null: Returns the referrer policy of the link or null if you do not want to use this attribute. The default value is no-referrer.

The following function is used to determine if the button is a link. It should not be overwritten, as its behavior is determined by the return value of the getAnchorUrl() function:

  • get isAnchor(): boolean: Returns true if the button is a link.