Preloading Dashboards with the Tableau JavaScript API

Data

Preloading Dashboards with the Tableau JavaScript API

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;
}

More About the Author

Derrick Austin

Curator Platform Lead
Five Years of Custom Embedded Analytics with Curator Thinking back, 2013 was an interesting year for many reasons. During the “International Year of Quinoa”, the world welcomed Prince ...
Curator by InterWorks Officially Turns 4 Curator is turning four years old! It’s awesome to be celebrating this milestone, but some of you may have just met Curator for the ...

See more from this author →

InterWorks uses cookies to allow us to better understand how the site is used. By continuing to use this site, you consent to this policy. Review Policy OK

×

Interworks GmbH
Ratinger Straße 9
40213 Düsseldorf
Germany
Geschäftsführer: Mel Stephenson

Kontaktaufnahme: markus@interworks.eu
Telefon: +49 (0)211 5408 5301

Amtsgericht Düsseldorf HRB 79752
UstldNr: DE 313 353 072

×

Love our blog? You should see our emails. Sign up for our newsletter!