Introduction
OTT Plugins are implemented with JavaScript and CSS. Anytime you are using code you want to consider code organization. In the Learning Guide: OTT Plugins document, you learned plugins are implemented by loading one JavaScript file into your Beacon Classic web app. That single file, named index.js, could hold all your OTT plugin JavaScript code, but this would lead to poor coding practices. Also, there are a myriad of other JavaScript frameworks from which you could choose. For a balance between poor practices and complexity, the documents around OTT Plugins use JavaScript modules for code organization.
Basically, the index.js acts as a "controller" and the actual implementation details for each plugin element are in a JavaScript module file. Like a "traffic police officer" directs where cars should go, the controller directs program execution. In the case of JavaScript modules, the "traffic cop" is basically importing modules and directing which modules should be called when and what data should be passed to the modules. The idea of a controller very common in programming practice and, of course, you may choose your favorite JavaScript framework.
Example code samples can be download from the ott-plugins-example-code GitHub repo.
The modules
It is consider good coding practices to:
- Not duplicate code
- Make your code as reusable as possible
Using modules help accomplish both of these tasks. First, let's take a look at the basic syntax of how modules are structured in the examples shown in these docs:
const function1 = () => {
code;
code;
code;
code;
};
const function2 = () => {
code;
code;
code;
code;
};
const function3 = () => {
code;
code;
code;
code;
};
export { function1, function2, functions3 };
You see three functions defined as constants using arrow notation. These functions performs tasks like:
- Add a button
- Open the side panel
- Place content in a custom div
- Contain the code for a button click handler
The functions are imported into the controller, which is the file index.js for OTT Plugins , then used as necessary.
Here is a simple module that contains a function that creates a button.
const addCustomButtonDetails = () => {
window.postMessage({
event: 'detailsPageAddCustomButton',
data: {
title: 'Test Button',
font_awesome_icon: 'fa fa-info-circle',
element_id: 'TEST_BTN_ID'
}
}, window.location.origin);
};
export { addCustomButtonDetails };
This functions properly, but is not reusable. You need a different function for every button you wish to create. To make the function reusable parameters are used:
const addCustomButtonDetails = (pTitle, pIcon, pID) => {
window.postMessage({
event: 'detailsPageAddCustomButton',
data: {
title: pTitle,
font_awesome_icon: pIcon,
element_id: pID
}
}, window.location.origin);
};
export { addCustomButtonDetails };
If there are buttons, there should be click handlers. A function is added to the module that is called on a button click, and simply pops up an alert with the name of the button in it. Actually handling the event is left to the controller
const addCustomButtonDetails = (pTitle, pIcon, pID) => {
window.postMessage({
event: 'detailsPageAddCustomButton',
data: {
title: pTitle,
font_awesome_icon: pIcon,
element_id: pID
}
}, window.location.origin);
};
const handleButtonClick = (buttonString) => {
alert('Button clicked: ' + buttonString);
};
export { addCustomButtonDetails, handleButtonClick };
Now it is time to move on to see how the functions can be used.
The index.js controller
The index.js file is setup to be the centralized event handler and "direct traffic" from there. In this example the following happens:
- Line 1: The functions from the module are imported
- Lines 3-8: Standard OTT plugin event handler syntax
- Line 9: A
switch-case
statement directs execution to the correct code - Lines 10-13: Adds two buttons to the web app when the
onBeaconPageLoad
event is handled - Lines 15-22: On the
detailsPageExternalButtonWasClicked
event, thehandleButtonClick()
function is called; theif
statements are used to pass the correct parameter value to the function
import { addCustomButtonDetails, handleButtonClick } from './button-demo-module.js';
window.addEventListener("message", (event) => {
const originsAllowed = [
'https://yourapplocation.com',
'https://yourapplocation.com'
];
if (originsAllowed.includes(event.origin)) {
switch (event.data.event) {
case 'onBeaconPageLoad':
addCustomButtonDetails('Download', 'fa fa-info-circle', 'download-button');
addCustomButtonDetails('Location', 'fa fa-info-circle', 'location-button');
break;
case 'detailsPageExternalButtonWasClicked':
if (event.data.data.element_id == 'download-button') {
handleButtonClick('Download');
};
if (event.data.data.element_id == 'location-button') {
handleButtonClick('Location');
};
break;
}
}
},
false
);
Here is the plugin in action:
Summary
You have seen one simple example of a module used to implement a feature of OTT Plugins, buttons. Please consider the following when you implement OTT Plugins:
- Using modules is one way to implement plugin code, but it is not the only way. Although Brightcove does not recommend this approach, you may find that it works for your use cases.
- There are degrees of code reuse and levels of abstraction. You may wish to use more or less than what you find in the Brightcove plugin examples.
- The example modules do NOT cover every possible need for every plugin implementor. The examples provide a basis on which you can develop code for your use cases.