Jump to content
  • How to run a JavaScript when a document property changes


    The code enables JavaScript triggers upon document property changes by observing a hidden text area's value. It toggles Boolean document properties to control visualization highlighting based on titles, facilitating dynamic interaction with visuals.

    We can use trigger a JavaScript when a document property changes by observing a value on a text area. For example, suppose you have a script or data function that performs certain calculations and the data function outputs the title of a visualization to highlight. 

    highlightVisual.thumb.gif.d103a8ee3744fd5d58a13b4e29342458.gif

    In this case and to make things simpler, I create a couple of calculated values on a text area that toggles a Boolean document property value. The document, or document properties can be hidden from the user. 

     

    More script like this one here

    html

    <pre id=docPropValues xhidden>
    { 
     "Indexed price charter":"<SpotfireControl id="calculated value here" />", 
     "Top holders by percent held":"<SpotfireControl id="calculated value here" />",
     "Historical data":"<SpotfireControl id="calculated value here" />",
     "Calendar quarter estimates":"<SpotfireControl id="calculated value here" />"
    }
    </pre>

    JavaScript

    //finds visuals in which title contains visualTitle (use *= for contains, ^= starts with, $= ends with or = exact match)
    	elements = Array.from(document.querySelectorAll(".sf-element.sf-element-visual"));
    function highlighVisual(visualTitle){
    
    	//set background for those visuals found
    	elementWithChild = elements.filter(element => element.querySelector(
           [title*='"+visualTitle+"']") !== null); //<-- change here for search operator
    	   elementWithChild.forEach(x=>x.style.background="red")
    }
    
    
    element = document.querySelector('#docPropValues'); 
    
    observer = new MutationObserver(_ => {
    	json = JSON.parse(element.innerText);
    
    	//reset visual backgrounds
    	elements.forEach(x=>{x.style.background=""})
    	Object.entries(json)
    		.filter(([key, value]) => value === "True")
    		.map(([key, value]) => key)
    		.forEach(visualTitle => {highlighVisual(visualTitle)});
    });
    
    observer.observe(element, {
        childList: true,
        characterData: true,
        subtree: true
    });

    How it works

    The calculated value expression is simply the value of a Boolean document property that triggers an Iron Python script when clicked, but in practice, the script can be much more complex that this. The idea is to trigger a JavaScript when anything inside the docPropValues change

    Notice how the value inside the docPropValues has a JSON structure that represent the title of each visual and it's state of true or false. Depending on the value of each document property, it should look like this to determine which visual based on it's title needs to be highlighted

    { 
     "Indexed price charter":"FALSE", 
     "Top holders by percent held":"TRUE",
     "Historical data":"TRUE",
     "Calendar quarter estimates":"FALSE"
    }

    Now we need some code to monitor when the value inside the element changes. For that we use the MutationObserver object that parses the JSON string inside the docPropValues and passes the visualTitle to a function that highlights the given visual

    observer = new MutationObserver(_ => {
    	json = JSON.parse(element.innerText);
    
    	//reset visual backgrounds
    	elements.forEach(x=>{x.style.background=""})
    	Object.entries(json)
    		.filter(([key, value]) => value === "True")
    		.map(([key, value]) => key)
    		.forEach(visualTitle => {highlighVisual(visualTitle)});
    });
    
    element = document.querySelector('#docPropValues'); 
    
    observer.observe(element, {
        childList: true,
        characterData: true,
        subtree: true
    });

     

    And the function that highlights the visual given it's title is:
     

    //finds visuals in which title contains visualTitle (use *= for contains, ^= starts with, $= ends with or = exact match)
    	elements = Array.from(document.querySelectorAll(".sf-element.sf-element-visual"));
    function highlighVisual(visualTitle){
    
    	//set background for those visuals found
    	elementWithChild = elements.filter(element => element.querySelector(
    [title*='"+visualTitle+"']") !== null); //<-- change here for search operator
    	elementWithChild.forEach(x=>x.style.background="red")
    }


    More JavaScript tips and tricks here


    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...