document.body.onload issue when working with multiple javascript scripts in r2d3 (RMarkdown)

  Kiến thức lập trình

I have a two separate r2d3 chunks in an RMarkdown document, which I’m rendering to HTML.

Given the way r2d3 works, you can only have 1 script and 1 datasource that goes with each r2d3 call.

This chunk produces a map, with a dropdown menu:

```{r out.width='100%', fig.height=6, echo=FALSE, message=FALSE, warning=FALSE}


library(r2d3)
   
   r2d3(data = dataset_1,
     # this is the script for the first map.
     script = "X:/dataset_1_script.js",
     d3_version = "4",
     options(r2d3.shadow = FALSE),
     container="div",
     elementId = "map_1")

```

This chunk produces another map with a dropdown menu (note the script and datasource is different):

```{r out.width='100%', fig.height=6, echo=FALSE, message=FALSE, warning=FALSE}


library(r2d3)
     
   r2d3(data = dataset_2,
     # this is the script for the second map.
     script = "X:/dataset_2_script.js",
     d3_version = "4",
     options(r2d3.shadow = FALSE),
     container="div",
     elementId = "map_2")


```

Here is some of the basic content in dataset_1_script.js. The script dynamically creates a dropdown element in the DOM. While this works in dataset_1_script.js, it does NOT work in the second chunk with dataset_2_script.js. In dataset_2_script.js the dropdown doesn’t render in the DOM. The issue is due to the fact that both scripts call the addElement function on document.body.onload. And, given that document.body.onload can only be called once, it makes sense that the dropdown element is successfully created in the first chunk (first script), but not in the second chunk (second script).

So my question is: is there a way to solve this issue in r2d3? I do think I need body.onload to render the dropdown to the DOM.

document.body.onload = addElement_Tract;

function insertAfter_Tract(newNode, existingNode) {
    existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}

 function addElement_Tract() {
    
    
    // create a sidebar_tract to hold legend and dropdown
    const sidebar_tract = document.createElement("div");
    sidebar_tract.className = "sidebar_tract";
    sidebar_tract.id = "sidebar_tract";
    
    //Create array of options to be added
    var display_array_tract = ["2023", "2022","2021","2020","2019", "2018"];
    var val_array_tract = [2023, 2022, 2021, 2020, 2019, 2018];
  
    //Create and append select list
    var selectList_tract = document.createElement("select");
    selectList_tract.id = "mySelect_tract";
    selectList_tract.className = "mySelect_tract";
  
  
    //Create and append the options
    for (var i = 0; i < display_array_tract.length; i++) {
        var option_tract = document.createElement("option");
        option_tract.value = Number(val_array_tract[i]);
        console.log(option_tract.value);
        option_tract.text = display_array_tract[i];
        selectList_tract.appendChild(option_tract);
    }
  
   
    // add the newly created element and its content into the DOM
    // Get a reference to the parent node
    const parentDiv_tract = document.getElementById("map_choropleth_state_tract").parentNode;

    const mapDiv_tract = document.getElementById("map_choropleth_state_tract");


    insertAfter_Tract(sidebar_tract, mapDiv_tract)

    sidebar_tract.appendChild(selectList_tract);
    
  }

Thanks in advance!

LEAVE A COMMENT