Tableau Extensions Addons Introduction: Synchronized Scrollbars

Basic Concepts

Adding our own event listener to the Viz frame

This is how the “patched”, addons ready vqlweb.js looks like
Don’t forget to repack or rename the .br and .gz files (compressed version of this javascript)
{
const EXTENSION_ADDON_URL_PREFIX = 'https://your-addons-server/extension-lib';
const LOAD_MODULE_REQUEST_MESSAGE = 'LoadModule-Request';
const LOAD_MODULE_RESPONSE_MESSAGE = 'LoadModule-Response';

window.addEventListener('message', function (event) {
if (event.data && event.data.event_id === LOAD_MODULE_REQUEST_MESSAGE) {
// load our addons external js file
var addon = event.data.data.replace(/[^a-z0-9\-]/gi, '_').toLowerCase();
var script = document.createElement('script');
script.src = EXTENSION_ADDON_URL_PREFIX + "/tableau-extensions-" + addon + "-server.js";
script.onload = function () {
event.source.postMessage({ event_id: LOAD_MODULE_RESPONSE_MESSAGE, data: event.data.data }, "*");
}
document.head.appendChild(script);
}
});
}

Is this secure?

Synchronized Scrolling

Synchronized Scrolling on Superstore, based on Klaus Schulte blog post

Implementation

<!DOCTYPE html>
<html lang="en">

<head>
<script text="text/javascript"
src="https://cdn.jsdelivr.net/gh/tableau/extensions-api/lib/tableau.extensions.1.latest.js"></script>
<script text="text/javascript" src="../extension-lib/tableau-extensions-addons.js"></script>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function (event) {

tableau.extensions.initializeAsync().then(function () {

tableau.extensions.initalizeAddonsAsync("sync-scrollbar").then(function () {

tableau.extensions.dashboardContent.dashboard.syncScrollbars(0, 1);
});

});
});
</script>
</head>

<body></body>

</html>
Chain of events, we load the extensions API, then the extension adds API, that loads our client addon files in the current frame and the server addon in the Viz frame
{
const SCROLLBAR_SYNC_REQUEST_MESSAGE = "ScrollbarSync-Request";

tableau.extensions.dashboardContent.dashboard.__proto__.syncScrollbars = function (idx0, idx1) {
console.log("Sync request from client");

window.parent.postMessage(
{
event_id: SCROLLBAR_SYNC_REQUEST_MESSAGE,
data: [idx0, idx1]
},
"*");
}
}
{
const SCROLLBAR_SYNC_REQUEST_MESSAGE = "ScrollbarSync-Request";
window.addEventListener('message', function (event) {
if (event.data && event.data.event_id === SCROLLBAR_SYNC_REQUEST_MESSAGE) {
const left = event.data.data[0];
const right = event.data.data[1];
// ... actual sync scroll implementation
// https://github.com/tfoldi/tc19/blob/master/extension-lib/tableau-extensions-sync-scrollbar-server.js

Deployment

Questions? Feedback?

Tamas is co-founder and CTO of data services firm Starschema where he leads the Starschema technical team to deliver results for the most innovative enterprises

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store