Skip to content

Instantly share code, notes, and snippets.

@fordhamedu
Created January 21, 2018 07:26
Show Gist options
  • Save fordhamedu/8db28c2185e1dd9bf3948a2c70771ba0 to your computer and use it in GitHub Desktop.
Save fordhamedu/8db28c2185e1dd9bf3948a2c70771ba0 to your computer and use it in GitHub Desktop.
Tableau JS API getData() Demo
<div class="page-header">
<p>This demo gets the underlying data from a viz to create a collapsible menu. <br>
Click the menu to set parameters that change the view.</p>
</div>
<div id="menuNav">
<ul><li>Show Top Level</li></ul>
<div id="menuTree"></div>
</div>
<div id="vizContainer"></div>
<div id="dataSummary"></div>
/*
Code by Robert Rouse, InterWorks, Inc.
Required libraries: JQuery, D3, Tableau JS API 2.1.0 or later
*/
//first, create the viz
$(document).ready(function initViz() {
var containerDiv = document.getElementById("vizContainer"),
url = "https://public.tableau.com/views/hierarchy_demo/demo",
//this url shows how it works with a dashboard. Comment the above and uncomment below to switch.
//url = "https://public.tableau.com/views/hierarchy_demo/hierarchy_demo",
options = {
hideTabs: true,
hideToolbar: true,
onFirstInteractive: function () {
workbook = viz.getWorkbook();
getVizData();
}
};
viz = new tableau.Viz(containerDiv, url, options);
});
//when viz is loaded (onFirstInteractive), request data
function getVizData() {
options = {
maxRows: 0, // Max rows to return. Use 0 to return all rows
ignoreAliases: false,
ignoreSelection: true,
includeAllColumns: false
};
sheet = viz.getWorkbook().getActiveSheet();
//if active tab is a worksheet, get data from that sheet
if (sheet.getSheetType() === 'worksheet') {
sheet.getUnderlyingDataAsync(options).then(function (t) {
buildMenu(t);
});
//if active sheet is a dashboard get data from a specified sheet
} else {
worksheetArray = viz.getWorkbook().getActiveSheet().getWorksheets();
for (var i = 0; i < worksheetArray.length; i++) {
worksheet = worksheetArray[i];
sheetName = worksheet.getName();
if (sheetName == 'levels') {
worksheetArray[i].getSummaryDataAsync(options).then(function (t) {
buildMenu(t);
});
}
}
}
}
//restructure the data and build something with it
function buildMenu(table) {
//the data returned from the tableau API
var columns = table.getColumns();
var data = table.getData();
//convert to field:values convention
function reduceToObjects(cols,data) {
var fieldNameMap = $.map(cols, function(col) { return col.getFieldName(); });
var dataToReturn = $.map(data, function(d) {
return d.reduce(function(memo, value, idx) {
memo[fieldNameMap[idx]] = value.value; return memo;
}, {});
});
return dataToReturn;
}
var niceData = reduceToObjects(columns, data);
//create nested tree structure
var menuTree = d3.nest()
.key(function (d) {return d.Level1;}).sortKeys(d3.ascending)
.key(function (d) {return d.Level2;}).sortKeys(d3.ascending)
.key(function (d) {return d.Level3;}).sortKeys(d3.ascending)
.rollup(function (leaves) {return leaves.length;})
.entries(niceData);
//D3 layout menu list
var menu = d3.select('#menuTree').selectAll('ul')
.data(menuTree)
.enter()
.append('ul')
//append list items
function writeMenu(parentList) {
var item = parentList
.filter(function(d) { return d.key != "%null%";})
.append('li')
.text(function (d) {return d.key;})
.classed("collapsed", true);
var children = parentList.selectAll('ul')
.data(function (d) {return d.values})
.enter().append('ul');
if (!children.empty()) {
writeMenu(children);
}
}
writeMenu(menu);
//init collapible functions
$('ul>li').siblings("ul").toggle();
$('ul').not(':has(li)').remove(); //removes empty children with Null values. not a perfect approach, but easier for this demo
$('ul>li').click(function () {
//expand if it has children
if ($(this).siblings('ul').length) {
$(this).toggleClass("collapsed");
$(this).siblings("ul").slideToggle(300);
}
//apply parameter to change the viz
var depth = $(this).parents("ul").length;
if ($(this).text()=="Show Top Level") {
workbook.changeParameterValueAsync("nameInput","");
workbook.changeParameterValueAsync("levelInput",0);
} else {
workbook.changeParameterValueAsync("nameInput",$(this).text());
workbook.changeParameterValueAsync("levelInput",depth);
}
});
}
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script src="https://public.tableau.com/javascripts/api/tableau-2.js"></script>
.page-header{
font-family:Arial;
padding-left:25px;
}
#menuNav {
float:left;
width: 200px;
height: 500px;
overflow-y:auto;
font-family:Arial;
}
#vizContainer {
float:left;
width: 490px;
height: 500px;
}
/*********************** Tree list styling *******************/
ul {
list-style-position: inside;
padding-left: 15px;
color:#4e79a7;
font-size:11pt;
}
.collapsed {
color: #4e79a7;
}
li {
cursor: pointer;
list-style-type: none;
}
li.collapsed::before {
content: "+ ";
display: inline-block;
width: 14px;
}
li::before {
content: "- ";
display: inline-block;
width: 14px;
}
li:last-child {
color:#4e79a7;
}
li:last-child::before {
content: "";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment