BookmarkSubscribeRSS Feed

Using the Data-Driven Content Object in Visual Analytics to Display Product Photos: Debugging

Started ‎10-10-2023 by
Modified ‎11-20-2023 by
Views 1,182

This is the third part of a four-part series that discusses how to display product photos in SAS Visual Analytics.

 

Basics

Validating Data

• Debugging (this article!)

Viewing Multiple Photos

 

Scenario

 

Recall from previous posts that you would like to display an image of a selected product in a report. In this post, we will see how to add sample data to your code so the visualization can be displayed outside of SAS Visual Analytics. This is helpful for debugging the code before you use it in Visual Analytics. Note: More detail about the requirements and steps for using the data-driven content object in Visual Analytics can be found in the first post in this series. Note: The entire code is available at the end of this post.

 

Data Messages

 

Recall that data messages are sent from Visual Analytics to the data-driven content object in JSON format. We will create a sample data message (also in JSON format) so we can render the visualization outside of Visual Analytics. Note: Communication between Visual Analytics and the third-party visualization is discussed in more detail in the second post in this series.

 

To do this, we need to see the Product Line data for this example in JSON format. The SAS GitHub repository for third-party visualizations includes a visualization (jsonDataViewer.html) that can be used to display your data as a JSON object.

 

In Visual Analytics, add a data-driven content object to the canvas that references the jsonDataViewer sample from the SAS GitHub repository. This is the value I entered in the URL field on the Options pane: https://sassoftware.github.io/sas-visualanalytics-thirdpartyvisualizations/samples/jsonDataViewer.html .

 

nb_1_niball_ddc3_jsonDataViewer.png

Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.

 

Note: Details on how to reference samples can be found in the samples folder on the SAS GitHub repository for third-party visualizations.

 

Then, on the Roles pane, assign Product Line to the Variables role.

 

nb_2_niball_ddc3_jsonDataViewer_with_data.png

 

The data-driven content object displays the Product Line data in JSON format, which is how data is passed from Visual Analytics to the third-party visualization. You can filter or edit the result to return a smaller number of rows. For this example, we only want to return one row of data so we can select a Product Line value from the page prompt (Beach).

 

nb_3_niball_ddc3_jsonDataViewer_Beach.png

 

Declaring a Sample Data Message

 

We can use the data from the jsonDataViewer sample to add a sample data message to the code.

 

nb_4_niball_ddc3_sample_data_message.png

 

Recall that in the code for this visualization, if one row is passed from Visual Analytics that means a single product line is selected and an image of that product line appears. If more than one row is passed from Visual Analytics that means no product line is selected and the company logo appears. For this example, we want to test the code when one row is returned, so only one row is included in the sample data message.

Displaying Sample Data

 

Next, code needs to be added to display the sample data (rather than the data passed from Visual Analytics) when the visualization is viewed outside of Visual Analytics.

 

nb_5_niball_ddc3_displaying_sample_data.png

 

The if statement checks to see if the function returns not true (! means not). If it does, then the sample data (sampleData) is passed to the onDataReceived function. Recall that the onDataReceived function initializes data variables, validates the data, and adds an image to the web page.

 

The inIframe function checks to see if the visualization is being rendered in an iFrame.

 

nb_6_niball_ddc3_inIframe.png

 

If the visualization is used inside Visual Analytics (in a data-driven content object), it’s rendered inside an iFrame (the window of the object is not the same as the topmost window in the window hierarchy, window.self !== window.top). If this is the case, the data passed from Visual Analytics is used. If the visualization is viewed outside of Visual Analytics (to test the validity of the code), it’s not rendered inside an iFrame (the window of the object is the same as the topmost window in the hierarchy). If this is the case, the sample data is used.

 

Testing

 

When the code is complete, you can test it by viewing the HTML file in a browser (outside of Visual Analytics).

 

nb_7_niball_ddc3_sample_test_beach.png

 

Because the visualization is not viewed in an iFrame (outside of Visual Analytics), sample data is used. Recall that sample data has a rowCount of 1 and data for the Beach product line, so the Beach image is displayed. Note: For testing purposes, I used the FiveServer extension in Visual Studio Code to use my machine as a web server.

 

To test all scenarios, change the rowCount for the sample data message to 2.

 

nb_8_niball_ddc3_sample_data_message_2rows_highlight.png

 

When you view the updated HTML file in the browser, the company logo is displayed.

 

nb_9_niball_ddc3_sample_test_logo.png

 

 

Notice, for this example, you don’t have to add additional data items to the sample data message. The value of rowCount determines whether a product line image is displayed or the company logo is displayed.

 

Summary

 

You can use this code to view any third-party visualization outside of Visual Analytics for debugging purposes. Remember to use the jsonDataViewer sample from the SAS GitHub repository for third-party visualizations to create the sample data in JSON format.

 

In the next part of this series, we will discuss how to view multiple photos if more than one product line is selected in the Visual Analytics report.

 

References

 

Documentation: Working with Data-Driven Content

 

Documentation: Programming Considerations for Data-Driven Visualizations

 

Resource: SAS GitHub repository for third-party visualizations

 

Book: Interactive Reports in SAS Visual Analytics 

 

Code

 

Below is the code in its entirety.

 

!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <!-- Utilities for DDC -->
    <script type="text/javascript" src="util/messagingUtil.js"></script>
    <script type="text/javascript" src="util/contentUtil.js"></script>
</head>
<body>
    <!-- Container for Photo -->
    <div class="container" id="photo">
    </div>

    <!-- Custom JavaScript -->
    <script>

        // Listening for HTML document completely loaded and parsed, best practice
        document.addEventListener("DOMContentLoaded", function() {


            /******************************* Declare variables ***************************************/

            // Sample data message to render outside of VA for debugging
            const sampleData = {
                "version": "1",
                "resultName": "dd60",
                "rowCount": 2,
                "availableRowCount": 1,
                "data": [
                    [
                        "Beach"
                    ]
                ],
                "columns": [
                    {
                        "name": "bi69",
                        "label": "Product Line",
                        "type": "string"
                    }
               ]
            };

            // Dynamic data variables
            let vaMessage; // Data message from VA
            let vaResult; // Name of DDC object, required to send messages back to VA
            let rowCount; // Number of rows passed from VA
            let data; // Data to be parsed from VA data message

            // Selection variables
            let photoDiv;  // Div for photo
            let itemPhoto; // Element for photo

            /******************************* Setup Callback Functions ***************************************/
            // Attach event for data message from VA
            va.messagingUtil.setOnDataReceivedCallback(onDataReceived);

            // If not being rendered in iFrame (outside of VA), render with sample data
            if (!inIframe()) {
                onDataReceived(sampleData);
            }

            // Take action on received data
            function onDataReceived(messageFromVA) {

                // Initialize data variables
                vaMessage = messageFromVA;
                vaResult = messageFromVA.resultName;
                rowCount = messageFromVA.rowCount;

                // Validate data roles
                if (
                    !va.contentUtil.validateRoles(
                        messageFromVA, 
                        ["string"],     // data from DDC object
                        ["number"]      // additional field for brush column (not needed in this example)
                    )
                ) {
                    // If roles are invalid or no data is being passed, display a message in VA about required roles (requires https)
                    va.messagingUtil.postInstructionalMessage(
                    vaResult,
                    "Display Photo expects columns to be assigned in this order:\n" +
                    " 1. Item (string)" 
                );
                } 

                // Add photo to DOM
                const photoDiv = document.getElementById("photo");
                photoDiv.innerText = "";

                // Display photo for selected item
                if (
                    rowCount == 1 
                ) {
                    itemPhoto = document.createElement("img");
                    itemPhoto.src="images/"+vaMessage.data[0][0].toLowerCase()+".jpg";
                    itemPhoto.alt = vaMessage.data[0][0];
                    itemPhoto.classList.add("img-fluid");

                    photoDiv.appendChild(itemPhoto);
                } else {
                    itemPhoto = document.createElement("img");
                    itemPhoto.src="images/insight_toys_logo.png";
                    itemPhoto.alt = "Insight Toys Logo";
                    itemPhoto.classList.add("img-fluid");

                    photoDiv.appendChild(itemPhoto);
                };

            };

            /******************************** Helper functions *****************************************/
            function inIframe() {
                try {
                    return window.self !== window.top;
                } catch (e) {
                    return true;
                }
            };

        });
    </script>
</body>
</html>

 

 

Comments

Thanks for the information!

@melissa69 sure!

Thanks

@Cayden my pleasure!

Version history
Last update:
‎11-20-2023 10:35 AM
Updated by:
Contributors

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags