test

Warning when upgrading to Spotfire 10

TIBCO has deprecated the JQueryUI Javascript library in the latest Spotfire 10.0 release

TIBCO Community pages show us how to use JQuery properly

Hide crosstable header columns or rowheaders

from Spotfire.Dxp.Application.Visuals import *
from Spotfire.Dxp.Application.Visuals.Miniatures import *

#gt = VisualTypeIdentifiers.GraphicalTable
ct = VisualTypeIdentifiers.CrossTable


def hideColums(x,n,w):
   for vis in Document.ActivePageReference.Visuals:
     if vis.TypeId==x:
         vis = vis.As[Visualization]()
                          for i in range(0,n): 
                              vis.RowHeaderWidths[i] = w


hideColums(ct, 2, 0) #vis type, n=number of headers, width 




Thanks Jolene Robertson!

Comments in custom expressions

To add a comment to a custom expression, just wrap it with an if or case statement:


Original expression

 First(If(UniqueCount([ProjectName])=1,[ProjectName],Concatenate(UniqueCount([ProjectName])," projects selected")))


Expression with comment

case "comment"<>"this expression shows the full name when only one item is marked. Else it shows the item count"
when true then 
  First(If(UniqueCount([ProjectName])=1,[ProjectName],Concatenate(UniqueCount([ProjectName])," projects selected")))
end


Show / Hide Details on Demand Panel

script

from Spotfire.Dxp.Application import PanelTypeIdentifiers

activePage = Document.ActivePageReference
filter = activePage.FilterPanel.Visible

#ignore these tabs
xTabs = ['HOME','css']

for p in Document.Pages:
if p.Title <> activePage.Title and p.Title not in xTabs:
print p.Title
p.FilterPanel.Visible = filter

# change the PanelTyupeIdentifier. For example .FilterPanel
for p in Document.Pages:
print p.Title
for f in p.Panels:
#print f.GetType()
if f.TypeId == PanelTypeIdentifiers.DetailsOnDemandPanel and p.Title not in xTabs:
f.Visible = not f.Visible

css tabs

No jquery, no js. Just edit html on text area and paste the code below. It can handle spotfire conttrols too



html
<div class="tab_container"> <input id="tab1" type="radio" name="tabs" checked> <label for="tab1"><i class="far fa-arrow-alt-circle-right"></i> <span>Highlights & Forward Look</span></label> <input id="tab2" type="radio" name="tabs"> <label for="tab2"><i class="fas fa-bullseye"></i><span> Scope</span></label> <input id="tab3" type="radio" name="tabs"> <label for="tab3"><i class="fas fa-user-tie"></i><span> Ejecutive Summary</span></label> <section id="content1" class="tab-content"> <h3>Highlights</h3> <p> <ul> <li>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </li> <li>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, </li> <li> sunt in culpa qui officia deserunt mollit anim id est laborum. </li> </ul> </p> <h3>Forward Look</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p> </section> <section id="content2" class="tab-content"> <h3>Scope</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. </p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> </section> <section id="content3" class="tab-content"> <h3>Ejecutive Summary</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> </section> <section id="content4" class="tab-content"> <h3>Headline 4</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </p> </section> <section id="content5" class="tab-content"> <h3>Headline 5</h3> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo. </p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> </section> </div> <p class="no_wrap"> something static here </p> <style> @import url('https://use.fontawesome.com/releases/v5.7.0/css/all.css'); .clearfix:before, .clearfix:after { content: " "; display: table; } .clearfix:after {clear: both;} .tab_container { width: 90%; margin: 0 auto; padding-top: 10px; position: relative; } .tab_container input, .tab_container section { clear: both; padding-top: 10px; display: none; } .tab_container label { font-size: 12px; display: block; float: left; xwidth: 100%; padding: 1.0em; color: #757575; cursor: pointer; text-decoration: none; text-align: center; background: #f0f0f0; } #tab1:checked ~ #content1, #tab2:checked ~ #content2, #tab3:checked ~ #content3, #tab4:checked ~ #content4, #tab5:checked ~ #content5 { display: block; padding: 20px; background: #fff; color: #999; border-bottom: 2px solid #f0f0f0; } .tab_container .tab-content p, .tab_container .tab-content h3 { -webkit-animation: fadeInScale 0.7s ease-in-out; -moz-animation: fadeInScale 0.7s ease-in-out; animation: fadeInScale 0.7s ease-in-out; } .tab_container .tab-content h3 { text-align: center; } .tab_container [id^="tab"]:checked + label { background: #fff; box-shadow: inset 0 3px #0CE; } .tab_container [id^="tab"]:checked + label .fa { color: #0CE; } .tab_container label .fa { font-size: 1.3em; margin: 0 0.4em 0 0; } /*Media query*/ @media only screen and (max-width: 900px) { .tab_container label span { display: none; } .tab_container { width: 98%; } } /*Content Animation*/ @keyframes fadeInScale { 0% { transform: scale(0.9); opacity: 0; } 100% { transform: scale(1); opacity: 1; } } .no_wrap { text-align:center; color: gray; } .link { text-align:center; } </style>

Create a document property

from Spotfire.Dxp.Data import DataProperty
from Spotfire.Dxp.Data import DataType
from Spotfire.Dxp.Data import DataPropertyClass

propName = "docProp"
attr = DataProperty.DefaultAttributes

prop = DataProperty.CreateCustomPrototype(propName, DataType.String, attr)

Document.Data.Properties.AddProperty(DataPropertyClass.Document, prop)
prop.Value = "test"

Editing text area in text mode removes CSS

When editing text area in html mode sometimes you can no longer edit in regular text mode. Spotfire "cleans" the code by removing the css style and other tags. That is inconvenient for end users who wants to change typos or text in Spotfire text area in text mode. 

BUT If you put the <style>or <link> tags at the end of your html code, Spotfire does not removes the tags!

Happy styling



html

<textarea rows=3 style='width:333px'id=hidden>&lt;style&gt; and &lt;link&gt; tags should be at the end of the html code </textarea>

<H3>Try again to edit in text mode. <BR><BR> </H3>

<H2><I class=material-icons style="FONT-SIZE: 36px; COLOR: #e65400">mail_outline</I> contact us </H2>


<LINK href="https://fonts.googleapis.com/icon?family=Material+Icons" rel=stylesheet>

<STYLE>
#hidden{display:none}
h2{font-style:arial;font-weight:bold;font-size:30px;}
</STYLE>

Table column selector tool

This template contains a tool for users to be able to select columns from a table. It is a mix of iron python, action controls, java script and css that works on both webplayer. It is very useful for end users to be able to select the columns they want to see. It has 3 presets for each individual user, and a default preset. Users can save 3 different column selection sets. Tested on 7.11. Easy to tweak for additional presets.


pill buttons

Change look and feel standard buttons




html
<Pre style="margin-left:500px">
Button     <span class='pill button'> <SpotfireControl id="baef049d975f4210af51b20c9a1c60b7" /> </span><br/>
Switch      off <span class='pill switch'>  <SpotfireControl id="0351da843e684914ab3978b18b0bade6" />  </span> on<br/>
Dropdown    <span class='pill dropdown'> <SpotfireControl id="afdad0889d0b4f00b3e72cbc7827a88c" /></span>
</Pre>


<style>
.pill{
 white-space:pre;
 cursor: pointer;
 background: #efefef;  
 border-radius: 100px;
}

.pill:hover {
 background: #fff;  
}

.switch{ border:1px inset #dfdfdf;}
.button, .dropdown{ border:1px outset #dfdfdf;}
.button:active, .dropdown:active{ border:1px inset #dfdfdf;}

.pill.dropdown .sf-element-dropdown,
.pill.dropdown .sf-element-dropdown:hover
{
border:none;
background-image:none;
}

.sf-element.sf-element-control.sfc-action.sfc-action-button
{
border:none;
background-image:none;
}

.sf-element.sf-element-control.sfc-action.sfc-action-button.sfpc-active
{
border:none;
background-image:none;
}
</style>


pill switch

Here is a simple way to create a pill switch without javascript. All you need is a calculated value that changes a boolean document property and some css to change the look and feel of it. The boolean doc property can then trigger another script when this property changes.

calculated value custom expression:
If(${myDocProp},"      ⚫","⚫      ") as [click to toggle]

The colors can be changed with the calculated values rules

html
<span class='pill'> calculated value goes here </span>

<style>
.pill {
 white-space:pre;
 border:1px solid #dfdfdf;
 cursor: pointer;
 background: #efefef;  
 border-radius: 100px;
}
</style>




Overlay spotfire controls values over visualizations






html

<div class='drag' id='hint1'>drag me</div>
<div class='drag' id='hint2'>take me</div>
<div class='drag' id='hint3'>move me</div>


<!--DRAG TOOL STARTS HERE-->
<div class='drag' style="display:none" id="dragTool">
<div id='title'>Drag Tool</div>
<textarea id='style' >

1. Edit text area in html

2. Drag spotfire controls wrapped in class='drag' html tag
   E.g.: <font size=3 class='drag'><spotifrecontrol></font>

3. After dragging all the elements, copy the generated 
   output inside the <style> tag

4. Optionally remove javascript script (don't delete) 
   when done and save text area.

</textarea>
</div>


<style>
/*Draggable tool*/
#dragTool {top:36.21345%; left:5.46445%;}


.drag{
 position:fixed;
 z-index:10;
}

#dragTool{
 position:fixed;
 height:220px; 
 z-index:10;

}
#dragTool textarea{
 height:200px;
 width:400px;
 background:#fff;
 color: rgb(135,0,135);
 font-family:courier;
 padding:10px;
 opacity: 1;
}

#dragTool #title{
 background:rgb(75,75,75);
 color:#fff;
 border:1px solid rgb(64,64,64);;
 padding:5px;
 font-size:13px;
 opacity: 1;
 padding:10px;
}

.container {position:relative;width: 100%;line-height: 0;}
.container img{max-width: 100%;}

</STYLE>



js 

highlightOn = true

//show window
$("#dragTool").show();


//make spotfire controls draggable by adding drag class
//<div class='drag'>test</div>
$(".drag").draggable({

cursor: "move",
drag: function (e) {

id = $(this).attr('id')

//calculate magic % numbers
let left = (parseFloat($(this).position().left)) + "px" // / parseFloat($(window).width())) ).toFixed(5) + "%" ;
let top = (parseFloat($(this).position().top)) + "px" // / parseFloat($(window).height())) ).toFixed(5) + "%" ;

//store magic numbers
mn = `#${id}\t\t{top:${top}; left:${left};}`
$(this).attr("magicNumbers", mn)
},
refreshPositions: true,
stop: getPositions
}).css({
//border:"1px dashed blue",
//"padding-bottom":"2%",
//background:'yellow',
cursor: "move",
'backgroundColor': (highlightOn) ? "rgba(255, 55, 00,.09)" : ""
})

function getPositions() {
positions = "";
$(".drag").each(function (i, e) {
//newMN = $(this).attr('magicNumbers')
el = $(this)
aPos = $(this).attr('magicNumbers')
positions += aPos ? aPos + "\n" : "";
})
$('#style').val(positions)
}



Dendogram












data
L0 L1 L2 L3 L4
x a a1
x a a2 a2a
x a a3
x b b1 b1a b1a1
x c c1
x c c2 c2a
x c c3

x d


script
#dataTable and ta (text area) are script parameters

#settings
delim = ","
cr = "\n"

#get list of filtered rows
rows = Document.ActiveFilteringSelectionReference.GetSelection(dataTable).AsIndexSet()

#generate tree
html = "<div class='tree'>"+cr # rendering text
r=0 # row #
l=0 # level
ll=0 # previous level
D=-1 # delta level change 
cc=[""]*(dataTable.Columns.Count+1) # previous level value


for row in rows:
c=0
for column in dataTable.Columns:
#get a cell value
v =  column.RowValues.GetFormattedValue(row) 
v = v if v!="(Empty)"  else ""

#is a node
isNode=v<>""

# record previous level and previous level value
if(isNode):
l=c+1

#calculate delta between levels
isBranch =v<>cc[l]
D=l-ll

if isBranch:

#construct text
if D>0 : html +=  "<ul>" * D + "<li><a>"+v+"</a>"+cr
if D<0 : html += "</ul>" * abs(D) + "<li><a>"+v+"</a>"+cr
if D==0 : html += "       <li><a>"+v+"</a></li</ul>"+cr


#record previous level and previous column value
ll=l
cc[l]=v

#increment col index
c+=1

#new row
#increment row index
r=0
#print cr + html + "</ul></div>"


#render results to a target textArea
from Spotfire.Dxp.Application.Visuals import HtmlTextArea
vis = ta.As[HtmlTextArea]()
vis.HtmlContent = html 

javascript (optional to make nodes collapsible)
//place this in the target textarea

$(function () {
    $('.tree li').hide();
    $('.tree li:first').show();
    $('.tree li').on('click', function (e) {
        var children = $(this).find('> ul > li');
        if (children.is(":visible")) children.hide('fast');
        else children.show('fast');
        e.stopPropagation();
    });

});


css (horizontal) 
/*Place this style in a different text area other than the target text area*/

<style>
* {margin: 0; padding: 0;}

.tree ul {
padding-top: 20px; position: relative;

transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}

.tree li {
float: left; text-align: center;
list-style-type: none;
position: relative;
padding: 20px 5px 0 5px;

transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}

.tree li::before, .tree li::after{
content: '';
position: absolute; top: 0; right: 50%;
border-top: 1px solid #ccc;
width: 50%; height: 20px;
}
.tree li::after{
right: auto; left: 50%;
border-left: 1px solid #ccc;
}

.tree li:only-child::after, .tree li:only-child::before {
display: none;
}

.tree li:only-child{ padding-top: 0;}

right connector from last child*/
.tree li:first-child::before, .tree li:last-child::after{
border: 0 none;
}

.tree li:last-child::before{ border-right: 1px solid #ccc;
border-radius: 0 5px 0 0;
-webkit-border-radius: 0 5px 0 0;
-moz-border-radius: 0 5px 0 0;
}
.tree li:first-child::after{
border-radius: 5px 0 0 0;
-webkit-border-radius: 5px 0 0 0;
-moz-border-radius: 5px 0 0 0;
}


.down-connector {
  position: absolute; top: -100; left: 50%;
border-left: 1px solid #ccc;
width: 0; 
  height: 20px;
}

.connector{
  position: absolute; 
  left: 50%;
border-left: 1px solid #ccc;
width: 0; 
  height: 20px;
}

.tree li a{
border: 1px solid #ccc;
padding: 5px 10px;
text-decoration: none;
color: #666;
font-family: arial, verdana, tahoma;
font-size: 11px;
display: inline-block;

border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;

transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}

.tree li a:hover, .tree li a:hover + ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}

.tree li a:hover+ul li::after, 
.tree li a:hover+ul li::before, 
.tree li a:hover+ul::before, 
.tree li a:hover+ul ul::before{
border-color:  #94a0b4;
}

/*Time for some hover effects*/
/*We will apply the hover the the lineage of the element also*/
.tree li a:hover, .tree li a:hover + ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}

.tree li a:hover, .tree li a:hover + ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}

.tree li a:hover+div+ul li::after, 
.tree li a:hover+div+ul li::before, 
.tree li a:hover+div+ul::before, 
.tree li a:hover+div+ul ul::before{
border-color:  #94a0b4;
}


.tree li a:hover, .tree li a:hover + div+ ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}
</style>


css vertical (one or the other)
<style>
.tree li {
    margin: 0px 0;
    list-style-type: none;
    position: relative;
    padding: 20px 5px 0px 5px;
}
.tree li::before {
    content:'';
    position: absolute;
    top: 0;
    width: 1px;
    height: 100%;
    right: auto;
    left: -20px;
    border-left: 1px solid #ccc;
    bottom: 50px;
}
.tree li::after {
    content:'';
    position: absolute;
    top: 30px;
    width: 25px;
    height: 20px;
    right: auto;
    left: -20px;
    border-top: 1px solid #ccc;
}
.tree li a {
    display: inline-block;
    border: 1px solid #ccc;
    padding: 5px 10px;
    text-decoration: none;
    color: #666;
    font-family: arial, verdana, tahoma;
    font-size: 11px;
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
}
 .tree > ul > li::before, .tree > ul > li::after {
    border: 0;
}
 .tree li:last-child::before {
    height: 30px;
}

 .tree li a:hover, .tree li a:hover+ul li a {
    background: #c8e4f8;
    color: #000;
    border: 1px solid #94a0b4;
}
 .tree li a:hover+ul li::after, .tree li a:hover+ul li::before, .tree li a:hover+ul::before, .tree li a:hover+ul ul::before {
    border-color: #94a0b4;
}

</style>