Jump to content

Accessing document property through JS / Automating customizable calculated columns


Recommended Posts

Hi,

I'm working with Spotfire 11.4.6

I'm trying to automate a score computation based on 40 variables with each variable having a specific weight: weight_1 x variable_1 + ..... weight_40 x variable_40

I'm trying to allow my end users to change the weight values in a text area so as to allow users to explore weight values. 

The "gold standard" seems to be: 

- create a document property for each weight (in IronPython that's doable)

- create a property control manually (I haven't found a weight to automate that in either IronPython or JS) with a slider

As the variables used for the score calculation might change from time to time, I'm really trying to avoid having to manually create the property controls manually - is there any way to circumvent that?

I'm unable to find a way to access the document properties within the JS script, nor how to trigger a column calculation based a JS script

Thanks in advance for your help,

 

Link to comment
Share on other sites

Hello Vincent. Can you provide a sample data set or even better, a sample dxp? I wonder about the data structure (e.g you have a variable per column or one per row) and if the variables are dynamic or fixed names. If they are fixed, then you can create the doc property and controls once and you are done. Creating the doc properties programmatically it's easy with Iron Python as you said and creating the property controls can be done by copying and pasting the controls and then point them to the corresponding document property. A lot of clicking, but it can be done fast.

Here is a POC

slider.thumb.gif.01e7152d489b48aff41f479192f1f23f.gif

Assuming your data set looks like this:

Variable Weight Value Calculated_Score
var_1     0.2 10 = 0.2 * 10
var_2   0.1 15 = 0.1 + 15
... ... ... ...
var_40 0.5 30 = 0.5 * 30


Then you can create a weight calculated value as:

case Right(Trim([Variable]),1)
	when "1" then ${w1}
	when "2" then ${w2}
	when "3" then ${w3}
	when "4" then ${w4}
	when "5" then ${w5}
	when "6" then ${w6}
end

This custom expression can also be created dynamically with Iron Python

For the range sliders, I tweak the script from the original article. That now looks looks like this:

html

<pre id='slider'>
   W1 <SpotfireControl id="79afbc3d87f34d14a178e8215a406a26" />  
   W2 <SpotfireControl id="05020bdb90934c979dcededb3745d2ed" />   
   W3 <SpotfireControl id="214401ec16524d9ba82a4c5d9e83e1fb" />    
   W4 <SpotfireControl id="875587aac7d742988af35b2b14877ab2" />
   W5 <SpotfireControl id="fca9c8b66ab04de99d4d4fff917ceb87" /> 
   W6 <SpotfireControl id="0a91ff3ef5e043e588198601e9becb4d" />
</pre>

JS

(()=>{
  // Select all the input elements within the #slider div
  const sliders = document.querySelectorAll('#slider input');

  sliders.forEach((slider) => {
    // Create a span element to display the slider value
    const sliderValue = document.createElement('span');
    
    // Insert the span element after the slider in the DOM
    slider.parentNode.insertBefore(sliderValue, slider.nextSibling);

    // Convert the input to a range slider (change the values as needed)
    slider.type = "range";
    slider.min = 10;
    slider.max = 50;
    slider.step = 0.5;

    // Initialize the label with the default value
    sliderValue.textContent = slider.value;

    //instead of using oninput, you can use "onmouseup" if you dont want realtime computations or a combination of both
    slider.oninput = () => {
        // Update the label with the current slider value
        sliderValue.textContent = slider.value;

        // Optional: Add a tooltip that follows the slider thumb 
        slider.title = slider.value;

        // Forcing update as per the original code (best if you move this to an onmouseup event)
        slider.blur();
        slider.focus();
    };
  });
})();

There might be another way to automate everything by creating just an array of html5 range sliders and using only one Property Control by passing an array of values and have an Iron Python script parse the values to the corresponding Document Properties

Edited by Jose Leviaguirre
Link to comment
Share on other sites

  • 2 weeks later...

Hi Jose, 

I apologize for the  late answer, I had not checked my TIBCO page.

Please find enclosed the dummy dashboard that represents my use case (in the Page tab, there's the Button that executes the dashboard preparation script that creates the document properties and computes the different scores). The element missing from the code that I added manually are 2 sliders that I added manually (which I was not able to add programmatically) - I've added 2 but I'd want to add one per document property so that my end user could customize the score computation (to explore different weighting options)

I'm not sure I see how to transfer my use case to the one you shared.

I'm trying to avoid adding manually the slider, as the number of sliders could be big (minimum 40, could reach 100) 

I'm trying to compute multiples scores with calculated columns (easily done programmatically) - it's a calculation based on row values

The score is based on weights that are independent from the rows (there is one weight per column - the global dimension weight and then weights per bin within the dimensions, with the bins defined by boundaries - so as create a step score function for each dimension)

Is there a way to add JS code to add the slider? I've succeeded in creating JS sliders but can't seem to find how to connect JS sliders to Document Properties. 

Thanks for trying to help out! I've extensively search the TIBCO documentation, community, colleagues, the internet, but have not found anything! 

staDynBenignLab.dxp

Link to comment
Share on other sites

  • 2 weeks later...

Hello @Vincent Grollemund, I understand the use case. The goal is to dynamically generate sliders in Spotfire based on a list of document property names. These sliders will control the values of corresponding document properties. The approach is to generate the range sliders in html and pass the values to a single Spotfire Input control that will further parse these values into the corresponding document properties. 

So imagine that you have an array of html5 sliders that updates a single Spotfire input field property control (that can be hidden) The values of this input field is a CSV set of values that can later be parsed to the rest of the document properties. You will need to:

  1.  Create an array of sliders based on a list of csv value pair set of document property names: dp1:1, dp2:3, dp4:2000, etc.
  2. When any of the html5 range sliders change, they update this single Spotfire Input field Property Control with a CSV set of values. e.g. dp1:44, dp2:22, dp3:12.2 etc.
  3. When this single Property Control changes, it runs an Iron Python script that parses the values to each document property

Here is a POC. Since I don't know how to create Property Controls  in text areas, I created a hidden template page containing a text area that holds the sliders.js and the required input field. This text area is added to the Foreword page generated by the script.

The template contains the JavaScript that parses the JSON into range sliders and the range sliders updates a dpValues doc prop that holds the modified JSON string that is later parsed as document properties when its value changes. The template requires the sliders.js and the multiple line Input field. The label and other elements are optional. The JavaScript takes a second to run. The template is copied to 

rangesliders.thumb.gif.46867405c6c7ea6f7ed6a6abf7755787.gif

staDynBenignLab-Jose.dxp

Edited by Jose Leviaguirre
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...