The Custom KPI Visualization Mod
This Custom KPI Visualization Mod can be used as is without any coding required. There are many examples to choose from from the examples menu for each category, but to make the most of it and customize it to the fullest, It requires basic knowledge of JavaScript, HTML or CSS to be able to change the look and feel. With JavaScript you can manipulate the data and behavior before and after rendering the visualization.
Default view
Before we continue with the details on how to customize it, let's first understand how it works with the default values
Here is a screenshot of the default Custom KPI Visualization view at glance.
The Custom KPI Mod consist of cards, values (KPIs) and optional hierarchies. The hierarchies will help organize the categories in big cards containing the small white cards.
The Default view is also mobile friendly so it will adjust the layout, font and text for small displays
Data Structure
The data can be of any type. Not all selectors are required to use the Custom KPI rendering capabilities, but It is useful to well organized hierarchies in it's data and the different KPI values defined
Sample Dataset
For example, consider the following dataset
Hospital ID|Hospital Name|Location|Department|Subcategory|Area|New Patients|Completed Appointments|Median Appointment Rate (days)|Fill Rate (%) 101|City Hospital|New York, NY|Cardiology|Heart Attack|East Wing|150|145|2|96 101|City Hospital|New York, NY|Neurology|Stroke|West Wing|120|115|3|95 101|City Hospital|New York, NY|Orthopedics|Fracture|North Wing|100|98|5|98 102|Green Valley Hospital|Los Angeles, CA|Maternity|Normal Delivery|South Wing|200|198|1|99 102|Green Valley Hospital|Los Angeles, CA|Oncology|Lung Cancer|East Wing|180|170|7|94 102|Green Valley Hospital|Los Angeles, CA|Gastroenterology|Ulcer|West Wing|130|125|4|96 103|Mountain Health|Denver, CO|Neurology|Parkinson's Disease|East Wing|110|105|5|95 103|Mountain Health|Denver, CO|Endocrinology|Diabetes|South Wing|160|158|2|99 104|Lakeside Medical|Dallas, TX|Neurology|Stroke|West Wing|125|120|4|96 104|Lakeside Medical|Dallas, TX|Orthopedics|Fracture|North Wing|105|103|6|98 105|Seaside Health|Miami, FL|Maternity|Normal Delivery|South Wing|210|205|1|98 105|Seaside Health|Miami, FL|Oncology|Lung Cancer|East Wing|185|180|8|95 105|Seaside Health|Miami, FL|Gastroenterology|Ulcer|West Wing|135|130|3|97 101|City Hospital|Boston, MA|Cardiology|Arrhythmia|North Wing|145|140|3|96 101|City Hospital|Boston, MA|Neurology|Parkinson's Disease|East Wing|115|110|5|94 101|City Hospital|Boston, MA|Endocrinology|Diabetes|South Wing|165|160|2|99 101|City Hospital|Boston, MA|Dermatology|Psoriasis|West Wing|95|90|7|97 102|Green Valley Hospital|San Francisco, CA|Neurology|Stroke|West Wing|130|125|4|95 102|Green Valley Hospital|San Francisco, CA|Orthopedics|Fracture|North Wing|110|108|5|98 103|Mountain Health|Seattle, WA|Maternity|Normal Delivery|South Wing|205|200|1|99 103|Mountain Health|Seattle, WA|Oncology|Lung Cancer|East Wing|190|185|6|94 103|Mountain Health|Seattle, WA|Gastroenterology|Ulcer|West Wing|140|135|3|96 104|Lakeside Medical|Chicago, IL|Cardiology|Arrhythmia|North Wing|150|145|2|97 104|Lakeside Medical|Chicago, IL|Neurology|Parkinson's Disease|East Wing|120|115|4|96 104|Lakeside Medical|Chicago, IL|Endocrinology|Diabetes|South Wing|170|165|3|99 105|Seaside Health|Houston, TX|Neurology|Stroke|West Wing|135|130|4|95 105|Seaside Health|Houston, TX|Orthopedics|Fracture|North Wing|115|110|5|98 101|City Hospital|Atlanta, GA|Maternity|Normal Delivery|South Wing|215|210|1|98 101|City Hospital|Atlanta, GA|Oncology|Lung Cancer|East Wing|195|190|7|95 101|City Hospital|Atlanta, GA|Gastroenterology|Ulcer|West Wing|145|140|3|97 102|Green Valley Hospital|Las Vegas, NV|Cardiology|Arrhythmia|North Wing|155|150|3|96 102|Green Valley Hospital|Las Vegas, NV|Neurology|Parkinson's Disease|East Wing|125|120|5|94 102|Green Valley Hospital|Las Vegas, NV|Endocrinology|Diabetes|South Wing|175|170|2|99 102|Green Valley Hospital|Las Vegas, NV|Dermatology|Psoriasis|West Wing|105|100|6|97 103|Mountain Health|Phoenix, AZ|Neurology|Stroke|West Wing|140|135|3|95 103|Mountain Health|Phoenix, AZ|Orthopedics|Fracture|North Wing|120|115|4|98 104|Lakeside Medical|Philadelphia, PA|Maternity|Normal Delivery|South Wing|220|215|1|99 104|Lakeside Medical|Philadelphia, PA|Oncology|Lung Cancer|East Wing|200|195|6|94 104|Lakeside Medical|Philadelphia, PA|Gastroenterology|Ulcer|West Wing|150|145|4|96 105|Seaside Health|San Diego, CA|Neurology|Parkinson's Disease|East Wing|130|125|5|96 105|Seaside Health|San Diego, CA|Endocrinology|Diabetes|South Wing|180|175|2|99 101|City Hospital|San Jose, CA|Dermatology|Psoriasis|West Wing|110|105|7|98 101|City Hospital|San Jose, CA|Cardiology|Heart Attack|East Wing|175|170|3|96 101|City Hospital|San Jose, CA|Neurology|Stroke|West Wing|145|140|4|95 101|City Hospital|San Jose, CA|Orthopedics|Fracture|North Wing|125|120|5|98 102|Green Valley Hospital|Austin, TX|Maternity|Normal Delivery|South Wing|225|220|1|98 102|Green Valley Hospital|Austin, TX|Oncology|Lung Cancer|East Wing|205|200|7|95 102|Green Valley Hospital|Austin, TX|Gastroenterology|Ulcer|West Wing|155|150|3|97 103|Mountain Health|San Antonio, TX|Neurology|Parkinson's Disease|East Wing|135|130|5|94 103|Mountain Health|San Antonio, TX|Endocrinology|Diabetes|South Wing|185|180|2|99 104|Lakeside Medical|Dallas, TX|Neurology|Stroke|West Wing|150|145|3|95 104|Lakeside Medical|Dallas, TX|Orthopedics|Fracture|North Wing|130|125|4|98 105|Seaside Health|Orlando, FL|Maternity|Normal Delivery|South Wing|230|225|1|99 105|Seaside Health|Orlando, FL|Oncology|Lung Cancer|East Wing|210|205|6|94 105|Seaside Health|Orlando, FL|Gastroenterology|Ulcer|West Wing|160|155|4|96
The dataset contains detailed information about hospital performance across various departments and subcategories. The data is structured with the following columns:
- Hospital ID: Unique identifier for each hospital.
- Hospital Name: Name of the hospital.
- Location: City and state where the hospital is located.
- Department: Medical department within the hospital.
- Subcategory: Specific medical condition or treatment within the department.
- Area: Section or wing of the hospital where the department is located.
- New Patients: Number of new patients admitted to the department.
- Completed Appointments: Number of appointments completed in the department.
- Median Appointment Rate (days): Median number of days for an appointment to be scheduled and completed.
- Fill Rate (%): Percentage of available appointment slots that were filled.
Example Records:
-
City Hospital in New York, NY:
- Cardiology department handling heart attacks with 150 new patients and a 96% fill rate.
- Neurology department dealing with strokes with 120 new patients and a 95% fill rate.
-
Green Valley Hospital in Los Angeles, CA:
- Maternity department handling normal deliveries with 200 new patients and a 99% fill rate.
- Oncology department dealing with lung cancer with 180 new patients and a 94% fill rate.
We can organize the same information with the Custom KPI Mod:
We can use the selectors to define what values to display on these cards. We have up to 6 available selectors, the color by and the hierarchy.
Spotfire Selectors
- Hierarchy: Allows to break down the cards in different categories
- Value 1: The value at the center of the card
- Value 2: The value at the center of the card, under Value 1
- Value 3: The value at the top left corner of the card
- Value 4: The tooltip value of the top right corner of the card
- Value 5: The value at the bottom left of the card
- Value 6: The value at the bottom right of the card
Configuration
There are different ways to modify the Custom KPI
- HTML - Modifies the html portion of the KPI's
- CSS - Changes the look and feel of the KPI's
- JavaScript - Performs data before and after rendering the KPI's
Code Editor Window
These modification can be performed by clicking the configuration icon located on the top right of the Mod while the Spotfire analysis is in edit mode. The configuration icon brings up a built in code editor window. There last 3 icons from the Code Editor hides, maximizes or restores the editor from the screen.
Please note that this editor is not draggable and can be only be maximized or show in the center of the Visualization Mod window. The best way to take advantage of it is by maximizing the Mod itself
Editor Menu
The editor menu has options to save, reset a mode or all modes, and to load a mode example. The default view of the editor is the CSS (override) mode. Depending on the selected mode, the reset menu can reset changes for that particular mode or all changes from all selected modes. This is also true for the last menu item in which each mode has code snippet examples.
Editor Modes Menu
There are 3 mode categories: HTML, CSS and JavaScript. Each mode has different samples from the Editor Menu. The editor modes menu can be found at the center of the editor.
To understand these modes, we need to first understand the KPI HTML Structure
KPI Rendering Structure
There are 4 html elements that forms the structure of the Custom KPI. These elements are nested to each other in the following order
- Root Hierarchy
- Nested Hierarchy
- Last Hierarchy
- KPI
HTML Structure
The full html with two root categories, looks like this:
<div id="mod-container"> <div> <div class="root category"><span class="title" id="root_2058">root hierarchy</span> <div> <div class="nested category"><span class="title" id="nested_2059">nested hierarchy</span> <div> <div class="last category"><span class="title" id="last_2060">last hierarchy</span> <div class="kpis">KPI's<div class="kpi" id="kpi_2061"> <div class="kpi-val1">kpi 1</div> <div class="kpi-val2">kpi 2</div> <div class="kpi-val3">kpi 3</div> <div class="kpi-val4" title="xxxxx" style="color:#FA7864">kpi 4</div> <div class="kpi-val5">kpi 5</div> <div class="kpi-val6">kpi 6</div> </div> </div> </div> </div> </div> </div> </div> </div> </div>
Editor Modes
HTML Modes
Root hierarchy
The root hierarchy in the HTML editor mode renders the piece of html portion that corresponds to the title of each hierarchy. It has a placeholder to render the category from the Hierarchy selector. You can also put the ${level} which is the level of the hierarchy. For example, if you have 4 nested hierarchies, the level will always render 1 because it's the root hierarchy.
<span class="title">${category}</span>
Use the examples from the editor menu to see different ways in which you can change the html for this specific element. Just be mindful that if you add markup styles it will generate a lot of overhead depending on how much data you have. In that case, it is better to edit or change the CSS and if you need to perform some logic, then you will need to edit the JavaScript section for it.
Nested Hierarchy
Similar to the root hierarchy, this affects the portion that creates the nested hierarchies for each root category. Keep in mind that if you add a style tag like in the example, it can lead to a lot of overhead so it is better to make these type of modifications in the CSS section. You can even add script tag and perform some logic and even passing the ${category} or the ${level} variables, but again, it is better to do this on the JavaScript section that handles this part. The HTML modes are meant for small modifications or slight changes in the html structure for further processing, if required with CSS or JavaScript.
Last hierarchy
The example on this last hierarchy mode includes an onclick event that illustrates how a JavaScript call can be made when clicking on the last hierarchy. As mentioned with the nested hierarchy, it is better to just call a JavaScript function vs rendering the same code for all elements of this kind to reduce unnecessary code.
KPI
This is the container that holds each KPI. In this mode, we have more variables (${val1},${val1},..,${val6}) to replace the value from each selector in addition to the ${category} and ${level} variables available on each hierarchy.
There are many examples to illustrate how to modify the KPI's for maximum flexibility for your specific needs
CSS Modes
The two CSS Modes allows to alter the stylesheet associated with the Custom KPI Mod. The "CSS" mode is the master stylesheet and the "CSS (Override)" mode is to override some rules for easy changes. Consider the HTML Structure above to notice the different CSS classes
- mod-container - applies to the outermost element that holds the rest of the html that conforms the kip's
- root - for the root hierarchy
- category - for the root, nested and last hierarchies
- nested - for the nested hierarchy
- last - for the last hierarchy that holds the kip's element
- kpis - the element that contains the kip's
- kpi-val1 to kpi-val6 - for the individual KPIs
CSS
There is so much you can do just by changing the CSS alone. This mode applies the CSS at the beginning of the document and contains the master stylesheet rules for the Custom KPI Mod instance. This means that any change you make it will only affect this particular visualization and not other instances. This is true for all modes.
CSS (override)
It is designed to override the master CSS. This mode applies the CSS rules at the end of the document so it will override or merge any existing rules applied on the CSS mode. This mode requires to explicit save changes every time you change the code from the examples. Some examples work best with one or no hierarchies
JavaScript Modes
These modes are the internal JavaScript functions that allows you to make modification in the logic and how the data is processed and displayed. Good programming and understanding of how this works can help you
- Before Render - This function is executed before rendering
- Root Hierarchy - This function is executed every time a root element is created. Returns the root Element
- Nested Hierarchy - Returns the html portion for each nested category
- Last Hierarchy - Executed every time a last hierarchy is found for each root or nested hierarchy and returns the html portion of it
- KPI - Returns the html portion of the KPI element
- After Render - Placeholder for a function to execute after the code is rendered
Before Render
Before the Custom KPI is rendered, this function passes important argument to the CustomKPI.init internal function that renders the final visualization after clearing the container. You can use this function to create any other visualization completely different than the Custom KPI output by exploring the examples
Definition
function beforeRender(json, hierarchy, data, mod, allRows, valueAxes, windowSize, dataView) {
document.getElementById("mod-container").innerHTML = ""; //clears the container
CustomKPI.init(hierarchy, data, mod, dataView); //renders the visual
}
Parameters
json
JSON array containing only text values of the data from the axes. For example
[ { "val1": "City Hospital", "val2": "San Jose, CA", "val3": "Cardiology", "val4": "132", "val5": "175", "val6": "96%", "color": "#6489FA", "cat1": "Cardiology", "cat2": "101" }, : { "val1": "City Hospital", "val2": "San Jose, CA", "val3": "Orthopedics", "val4": "456", "val5": "125", "val6": "98%", "color": "#FA7864", "cat1": "Orthopedics", "cat2": "101" } ]
hierarchy
This is the DataViewHierarchy object defined by the Spotfire Visualization Mods interface. For example, you could execute its methods or display the properties from it:
function beforeRender (json,hierarchy) { //this function renders the visual. you can comment it out if you want and code your own parser. document.getElementById("mod-container").innerHTML = ""; //CustomKPI.init(hierarchy, data, mod); result = "Hierarchy name:"+hierarchy.name+"\n"+ "Number of levels:"+hierarchy.leafCount+"\n"+ "is empty?:"+hierarchy.isEmpty const modContainer = document.getElementById("mod-container") modContainer.innerHTML = "<pre>"+result+"</pre>" }
data
The json object array containing values and Visualization Mod objects for each record
[
{
"allRows": "<DataViewRow[]>"
"axis": "<DataViewCategoricalAxis>"
"cat1": "Orthopedics",
"cat2": "101"
:
"catN": "<the last nested category>"
"color": "#FA7864",
"hierarchy": "<DataViewHierarchy>"
"row": "<DataViewRow>"
"val1": "City Hospital",
"val2": "San Jose, CA",
"val3": "Orthopedics",
"val4": "123",
"val5": "125",
"val6": "98%",
"valueAxes": <DataViewAxis>
}
]
mod
Represents the entire Mod API and exposes methods for interacting with and reading data from the Mod Visualization and the Spotfire document. Here is a simple example on how to show one of many mod properties directly that shows and hide the progress indicator after 5 seconds
function beforeRender (json,hierarchy, data, mod, allRows, valueAxes, windowSize, dataView) { mod.controls.progress.show() setTimeout(mod.controls.progress.hide,5000) }
Here is another example that illustrates the mod.controls.tooltip for each json element array
function beforeRender (json,hierarchy, data, mod, allRows, valueAxes, windowSize, dataView) { const modContainer = document.getElementById("mod-container") modContainer.innerHTML = "" modContainer.style.display="block" json.forEach(e =>{ div = document.createElement("span") div.style.padding="10px"; div.style.background=e.color; div.style.border="1px solid black"; div.onmouseenter = x=>{mod.controls.tooltip.show(e.val3)} div.onmouseleave = mod.controls.tooltip.hide modContainer.appendChild(div); div.innerHTML=e.val2 }) }
allRows
This is a DataViewRow array. Here is an example usage that loops through all rows and performs some operation, like marking.
function beforeRender(json, hierarchy, data, mod, allRows, valueAxes, windowSize, dataView) { const modContainer = document.getElementById("mod-container") modContainer.innerHTML = "" modContainer.style.display = "block" allRows.forEach((row, i) => { div = document.createElement("span") div.innerHTML = row.categorical("Value 2").formattedValue() div.style.background = json[i].color; div.style.padding = "10px"; if (row.isMarked()) { div.style.border = "2px solid black"; } div.onclick = event => { if (event.ctrlKey) { row.mark("Add") } else { row.mark() } } modContainer.appendChild(div); }) }
valueAxes
DataViewAxis array. This array only includes the kpi values and it is defined as:
const valueAxes = (await dataView.axes()).filter(axis => axis.name.startsWith("Value"));
windowSize
Provides read-only access to the current Size of the browser window in which the Mod is rendered. That is, the size of the iframe created for the Mod in the Spotfire UI. The beforeRender function executes every time the window size changes. This is equivalent to the Mod.WindowSize() method
Here is a simple example to show the window size
function beforeRender (json,hierarchy, data, mod, allRows, valueAxes, windowSize, dataView) { const modContainer = document.getElementById("mod-container") modContainer.innerHTML = "Mod visualization size is: "+ windowSize.width + " X " + windowSize.height }
dataView
The DataView Represents a view of the data from which the visualization can be rendered.
This object contains the result of the query made by Spotfire against the DataTable currently used by the Mod Visualization, using the Filtering, Marking, expressions on the Axes and other relevant settings.
Root Hierarchy
The function that is executed every time a root hierarchy node is rendered. This value must be returned if the beforeRender function calls the CustomKPI.init method. It is intended to expose the DOM element and being able to manipulate it.
Definition
function generateFirstCategoryElement(rootElement, category, level, items) { return rootElement; }
Parameters
rootElement
DOM element containing the entire html of the root element and its children. Here is an example html structure output
<div class="root category"><span class="title" id="root_91">Cardiology</span> <div> <div class="last category"><span class="title" id="last_92">101</span> <div class="kpis"> <div class="kpi" id="kpi_93"> <div class="kpi-val1">City Hospital</div> <div class="kpi-val2">Boston, MA</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="123" style="color:#FEE4E0">⬤</div> <div class="kpi-val5">145</div> <div class="kpi-val6">96%</div> </div> <div class="kpi" id="kpi_94"> <div class="kpi-val1">City Hospital</div> <div class="kpi-val2">New York, NY</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="465" style="color:#E0E7FE">⬤</div> <div class="kpi-val5">150</div> <div class="kpi-val6">96%</div> </div> <div class="kpi" id="kpi_95"> <div class="kpi-val1">City Hospital</div> <div class="kpi-val2">San Jose, CA</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="789" style="color:#E0E7FE">⬤</div> <div class="kpi-val5">175</div> <div class="kpi-val6">96%</div> </div> </div> </div> </div> </div>
You can manipulate this as any other DOM Object. Here is an example that makes the first child of the rootElement (the span) clickable so it uses the Mods API to navigate to the first page
function generateFirstCategoryElement(rootElement, category, level = 0, items) { //goes to the first page when clicking the root category title rootElement.firstChild.addEventListener('click', event => { CustomKPI.mod.document.pages().then(pages => pages[0].setAsActive()); }); return rootElement; }
category
String representing the category for the rendered root hierarchy
level
The level of the root category. In this case is always 1 if the root category exists
items
The logical JavaScript object of the hierarchy and items. For example the object is dynamically created depending on the hierarchy and values. The items property for each hierarchical leaf corresponds to the Mod API as defined as the beforeRender "data" parameter.
The logical JavaScript Object conforming the hierarchy and all it's items
This parameter is designed to attach it to a DOM element or node as a handy way for further process in some cases
{ "Arrhythmia": { "North Wing": { "items": [ { "val1": "City Hospital", "val2": "Boston, MA", "val3": "Cardiology", "val4": "123", "val5": "145", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item DataViewHierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing" : "catN": "the last hierarchical item value" },..., { "val1": "Green Valley Hospital", "val2": "Las Vegas, NV", "val3": "Cardiology", "val4": "456", "val5": "155", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item hierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing", : "catN": "the last hierarchical item value" } ] } }, "Heart Attack": { "East Wing": { "items": [..."<same as above>"] } } }
Nested Hierarchy
Function responsible for the rendering of any category or categories between the first and last hierarchy. The function provides some arguments that can allow enhace or modify the returned DOM element that represents the HTML structure of the nested categories and its children.
Definition
function generateNestedCategoryElement(nestedCategoryElement, category, level, items) { return nestedCategoryElement; }
Parameters
nestedCategoryElement
DOM element containing the HTML structure for nested category. Here is an example html structure output
<div class="nested category"><span class="title" id="nested_2507">North Wing</span> <div> <div class="last category"><span class="title" id="last_2508">101</span> <div class="kpis"> <div class="kpi" id="kpi_2509"> <div class="kpi-val1">City Hospital</div> <div class="kpi-val2">Boston, MA</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="xxxxx" style="color:#FA7864">⬤</div> <div class="kpi-val5">145</div> <div class="kpi-val6">96%</div> </div> </div> </div> : <div class="last category"><span class="title" id="last_2510">102</span> <div class="kpis"> <div class="kpi" id="kpi_2511"> <div class="kpi-val1">Green Valley Hospital</div> <div class="kpi-val2">Las Vegas, NV</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="xxxxx" style="color:#FA7864">⬤</div> <div class="kpi-val5">155</div> <div class="kpi-val6">96%</div> </div> </div> </div> </div> </div>
category
String representing the category for the rendered nested category hierarchy between the root or the last category node
level
The level of the nested category. it can be any number between 2 and the number of nested categories before the last hierarchy level
items
The logical JavaScript object of the hierarchy and items. For example the object is dynamically created depending on the hierarchy and values. The items property for each hierarchical leaf corresponds to the Mod API as defined as the beforeRender "data" parameter.
This parameter is designed to attach it to a DOM element or node as a handy way for further process in some cases
{ "Arrhythmia": { "North Wing": { "items": [ { "val1": "City Hospital", "val2": "Boston, MA", "val3": "Cardiology", "val4": "123", "val5": "145", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item DataViewHierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing" : "catN": "the last hierarchical item value" },..., { "val1": "Green Valley Hospital", "val2": "Las Vegas, NV", "val3": "Cardiology", "val4": "456", "val5": "155", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item hierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing", : "catN": "the last hierarchical item value" } ] } }, "Heart Attack": { "East Wing": { "items": [..."<same as above>"] } } }
Last Hierarchy
Similar to the first and nested hierarchies, the last hierarchy is the function that is executed every time a last hierarchy is found. If the hierarchy has only two levels, then there are no nested hierarchies, but just the root category and the last category hierarchy. This function can be useful to generate other types of outputs since the items for that last hierarchy are available through its parameters. For example, you can create a function that summarizes or aggregates the KPI's that corresponds to that branch. Check the examples to see some use cases.
Definition
function generateLastCategoryElement(lastCategoryElement, category, level, items) { return lastCategoryElement; }
parameter
lastCategoryElement
DOM element containing the HTML structure for nested category. Here is an example html structure output
<div class="nested category"><span class="title" id="nested_2507">North Wing</span> <div> <div class="last category"><span class="title" id="last_2508">101</span> <div class="kpis"> <div class="kpi" id="kpi_2509"> <div class="kpi-val1">City Hospital</div> <div class="kpi-val2">Boston, MA</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="xxxxx" style="color:#FA7864">⬤</div> <div class="kpi-val5">145</div> <div class="kpi-val6">96%</div> </div> </div> </div> : <div class="last category"><span class="title" id="last_2510">102</span> <div class="kpis"> <div class="kpi" id="kpi_2511"> <div class="kpi-val1">Green Valley Hospital</div> <div class="kpi-val2">Las Vegas, NV</div> <div class="kpi-val3">Cardiology</div> <div class="kpi-val4" title="xxxxx" style="color:#FA7864">⬤</div> <div class="kpi-val5">155</div> <div class="kpi-val6">96%</div> </div> </div> </div> </div> </div>
category
String representing the category for the rendered last category hierarchy
level
The level of the nested category. it can be any number between 2 and the number of nested categories before the last hierarchy level
items
The logical JavaScript object of the hierarchy and items. For example the object is dynamically created depending on the hierarchy and values. The items property for each hierarchical leaf corresponds to the Mod API as defined as the beforeRender "data" parameter.
This parameter is designed to attach it to a DOM element or node as a handy way for further process in some cases
{ "Arrhythmia": { "North Wing": { "items": [ { "val1": "City Hospital", "val2": "Boston, MA", "val3": "Cardiology", "val4": "123", "val5": "145", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item DataViewHierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing" : "catN": "the last hierarchical item value" },..., { "val1": "Green Valley Hospital", "val2": "Las Vegas, NV", "val3": "Cardiology", "val4": "456", "val5": "155", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item hierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing", : "catN": "the last hierarchical item value" } ] } }, "Heart Attack": { "East Wing": { "items": [..."<same as above>"] } } }
KPI
This function is executed for each KPI or group of KPI that is rendered. This function must return a DOM object representing the kPI Element structure
Definition
function generateKpiElement(kpiElement, item, category, level) { return kpiElement; }
Parameters
kpiElement
The DOM object representing the KPI's HTML structure. For example:
<div class="kpi" id="kpi_3732"> <div class="kpi-val1">Lakeside Medical</div> <div class="kpi-val2">Dallas, TX</div> <div class="kpi-val3">Orthopedics</div> <div class="kpi-val4" title="xxxxx" style="color:#FA7864">⬤</div> <div class="kpi-val5">235</div> <div class="kpi-val6">98%</div> </div>
item
The JavaScript Object containing the KPI information, for example:
{ "val1": "City Hospital", "val2": "Boston, MA", "val3": "Cardiology", "val4": "123", "val5": "145", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item DataViewHierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing": "catN": "the last hierarchical item value" }
category
The last category hierarchy that corresponds to this KPI
level
The total number of hierarchy levels as long as there are at least one column selected in the Hierarchy selector
After Render
This function runs after the Custom KPI function finishes rendering. It exposes elements that can be useful when post-processing is required. This function is executed only once
Definition
function afterRender(data, hierarchyNames, nestedObject, hierarchy) { //your code here }
Parameters
data
Array of objects with the following structure
{ "val1": "City Hospital", "val2": "Boston, MA", "val3": "Cardiology", "val4": "123", "val5": "145", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item DataViewHierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing" : "catN": "the last hierarchical item value" }
hierarchyNames
The name of the nested column (not the values) for the Hierarchy object. If no hierarchy values are selected, returns an empty array. For example:
[
"Department",
"Subcategory",
"Area"
]
nestedObject
The logical JavaScript object of the hierarchy and items. For example the object is dynamically created depending on the hierarchy and values. The items property for each hierarchical leaf corresponds to the Mod API as defined as the beforeRender "data" parameter. For example:
{ "Arrhythmia": { "North Wing": { "items": [ { "val1": "City Hospital", "val2": "Boston, MA", "val3": "Cardiology", "val4": "123", "val5": "145", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item DataViewHierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing" : "catN": "the last hierarchical item value" },..., { "val1": "Green Valley Hospital", "val2": "Las Vegas, NV", "val3": "Cardiology", "val4": "456", "val5": "155", "val6": "96%", "axis": { "name": "Value 6", "isCategorical": true, "hierarchy": "<the item hierarchy for this item>" }, "color": "#FA7864", "row": "<the corresponding DataViewRow>", "hierarchy": "<the item hierarchy for this item>", "allRows": "<all the DataViewRows for this item>", "valueAxes": "<the DataViewAxis for this item>", "cat1": "Cardiology", "cat2": "Arrhythmia", "cat3": "North Wing", : "catN": "the last hierarchical item value" } ] } }, "Heart Attack": { "East Wing": { "items": [..."<same as above>"] } } }
hierarchy
the DataViewHierarchy Mod Visualization API for that particular hierarchy
CustomKPI Object
This is the main object that contains all the methods described before and more. This Object has a global scope, which means you can access it from the developer tools inspector. Feel free to type CustomKPI on the Console to explore further.
One of the handy feature is that you can get the Spotfire Mod Row object associated with the KPI by calling the CustomKPI.map method. It holds values for each generated KPI id. Each individual KPI card has a unique ID. For example, if you need to programmatically mark a row, you could:
CustomKPI.map.get("kpi_1")[0].row.mark()
Here is the entire CustomKPI Object definition
{ "map": <Map Object that holds the kpi data and Mod objects like axes, rows, hierarchies and values>, "mod": <Spotfire Mod object>, "dataView": <Spotfire Mod DataView object>, "custom": { "rootNodeTemplate": <customized html template string for the root hierarchy>, "nestedNodeTemplate": <customized html template string for the nested hierarchy>, "lastNodeTemplate": <customized html template string for the last hierarchy>, "kpiTemplate": <customized html template string for the kpi>, "overrideCSS": <customized css string to override the main css>, "mainCSS": <customized main css string> }, "default": { "rootNodeTemplate": "<span class=\"title\">${category}</span>", "nestedNodeTemplate": "<span class=\"title\">${category}</span>", "lastNodeTemplate": "<span class=\"title\">${category}</span>", "kpiTemplate": "<div class=\"kpi\">\n ...", "overrideCSS": ".kpi-val1 {\n font-family: 'Roboto Regular';...", "mainCSS": "#mod-container {\n display: flex;\n flex-direction..." } "init": <the function used to initialize the mod>, "render":<function that renders the data and hierarchies>, "kpisDiv": <for internal use only> }
- 3
Recommended Comments
There are no comments to display.