Even with the best planning, we occasionally end up with less than speedy dashboards. Tableau is great at crunching large amounts of data – but when you are looking at many different slices of millions of records, anything would be slow. There are many ways to improve the performance of your dashboard through improving the data aggregation before extracting into Tableau or in Tableau Desktop itself. Even so, your dashboards are still occasionally slow.

Luckily, using the Tableau JavaScript API, you can do some magic to help alleviate the problem! While your users are looking at other dashboards, why not simply load more behind the scenes?

Once the user is ready to view a different dashboard, it is loaded and ready to go! Switching is instantaneous! I’ve attached the code to reproduce this to the bottom of this blog. If you’d like to try out a live example, feel free to try it out here.

How It’s Done

I’ve attached an example, so feel free to dive into that now if you feel comfortable. If you’d like more information, let’s run through the pieces. First, we will create a JavaScript array to hold the visualizations to load:

/** * This is an array that holds information about our visualizations. */ myVizes = new Array( { 'name' : 'Obesity vs. Physical Activity Rates', 'url' : 'https://public.tableau.com/shared/G3X7GFKF8?:embed=y&:display_count=yes', 'hash' : 'obesity' }, { 'name' : 'Stillwater Kitchen Activity', 'url' : 'https://public.tableau.com/views/KitchenMonitor/STWOfficeTraffic?:embed=y&:display_count=yes', 'hash' : 'kitchen' }, { 'name' : 'The Pyramids of Egypt', 'url' : 'https://public.tableau.com/views/Pyramids_1/EgyptianPyramids?:embed=y&:display_count=yes&:showTabs=y', 'hash' : 'pyramids' }, { 'name' : 'Sleep Changes in Parenthood', 'url' : 'https://public.tableau.com/views/Sleepbeforeandafterbaby/Sleep?:embed=y&:display_count=yes&:showTabs=y', 'hash' : 'sleep' } );

Next, we will create a function to load any particular visualization from the array. This will pull information from the array, load it and create a navigational element so that the user can click a link to load the dashboard:

/** * Load a visualization. */ function load(i) { var url = myVizes[i].url; var vizOptions = { showTabs : true, hideToolbar : true }; var vizDiv = document.createElement('div'); vizDiv.id = myVizes[i].hash + 'Viz'; document.getElementById('vizes').appendChild(vizDiv); myVizes[i].viz = new tableauSoftware.Viz( document.getElementById(myVizes[i].hash + 'Viz'), url, vizOptions ); var el = document.createElement('li'); el.id = myVizes[i].hash + 'Nav'; document.getElementById('topNavigation').appendChild(el); $('#' + myVizes[i].hash + 'Nav').html('' + myVizes[i].name + ''); $('#' + myVizes[i].hash + 'Nav').data('id', i); $('#' + myVizes[i].hash + 'Nav').click(function () { switchDashboard($(this).data('id')); }); if ($('.nav .active').length > 0) { $('#' + myVizes[i].hash + 'Viz').hide(); } else { $('#' + myVizes[i].hash + 'Viz').addClass('active'); $('#' + myVizes[i].hash + 'Nav').addClass('active'); } // Ok, we loaded one, now wait a few seconds and load another. setTimeout(loadNext, 2000); }

Now that we have a load function, let’s create a function to determine which visualization needs loaded next and load them slowly over time. This will offset an initial spike on the system when the user hits the page. A few dashboards loaded all at once would not require this; but if you load more than a few, this will become necessary fast.

/** * Load one viz, then wait a few seconds before triggering the next load. */ function loadNext() { // If we have a hash, load it first. for (i = 0; i < myVizes.length; i++) { if (location.hash && location.hash == '#' + myVizes[i].hash) { if (!myVizes[i].hasOwnProperty('viz') || !myVizes[i].viz) { load(i); return; } } } // Otherwise, load the viz list. for (i = 0; i < myVizes.length; i++) { // Skip vizes that are already loaded. if (myVizes[i].hasOwnProperty('viz') && myVizes[i].viz) { continue; } load(i); return; } } /** * Start loading visualizations when the page is ready. */ $(loadNext);

Finally, we need to create a way to switch dashboards. Since our dashboards are already loaded, there is no reason to switch URLs like you would with a normal link. We’ll simply show the visualization we want to see instead of the one that is currently showing. We will hide the active visualization with JavaScript, then unhide the inactive one.

/** * Unhide a dashboard; hide the currently active one. */ function switchDashboard(id) { $('#vizes .active').hide().removeClass('active'); $('.navbar-nav .active').removeClass('active'); $('#' + myVizes[id].hash + 'Viz').show().addClass('active'); $('#' + myVizes[id].hash + 'Nav').addClass('active'); location.hash = myVizes[id].hash; }