PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, October 15, 2022

[FIXED] Why does my callback become undefined using JavaScript

 October 15, 2022     dom, javascript     No comments   

Issue

I am working on a page that needs to insert a script into the DOM and evaluate it. This script contains a class that will instantiate some callbacks to particular elements that are also being inserted into the page.

If i do this process for one event handler, everything works as expected. However when i do this for a second event handler the first event handler stops working

function processJson(outputJson) {
  for (var i in outputJson) {
    let divIDForPlot = "plot_" + i;
    document.getElementById("parent").innerHTML += "<div id='" + divIDForPlot + "'></div>";

    let item = outputJson[i];
    let type = item["outputType"];

    if (type == "plot") {
      processPlot(divIDForPlot, item);
    } else if (type == "table") {

    }
    // break;

  }
}


function processPlot(elementId, plotData) {

  let additionalHtml = plotData["AdditionalHtml"];

  document.getElementById(elementId).innerHTML = additionalHtml;
  let script = plotData["script"];
  let outputData = " ";
  let dataString = "var data = " + JSON.stringify(outputData) + ";";
  let finalScript = dataString + "\n" + script;

  var s = document.createElement('script');
  s.type = 'text/javascript';
  try {
    s.appendChild(document.createTextNode(finalScript));
    document.getElementById(elementId).appendChild(s);
  } catch (e) {
    s.text = finalScript;
    document.getElementById(elementId).appendChild(s);
  }
}


function run() {
  processJson(dataJson["output"]);
}




let dataJson = {
  "output": [{

      "outputType": "plot",
      "AdditionalHtml": "<div id='revenue_trend'></div> <div class='control-row' >Periodicity:<select  id='revenue_trend_periodicity'></select>Measure:<select id = 'revenue_trend_measure' ></select ></div > ",
      "script": "class RevenueTrend{constructor(e){this.data=e,this.periodicitySelector=document.getElementById('revenue_trend_periodicity'),this.measureSelector=document.getElementById('revenue_trend_measure'),this.periodicitySelector.addEventListener('change',()=>{console.log('periodicitySelector changed')},!1),this.measureSelector.addEventListener('change',()=>{console.log('measureSelector changed')},!1),this.#b(['monthly','weekly'],this.periodicitySelector),this.#b(['revenue','profit','margin'],this.measureSelector)}updateBySelector=()=>{this.#a(this.periodicitySelector.value,this.measureSelector.value)};#a=(e,t)=>{var r=this.data.data[t][e];let i=this.data.layout[t]};#b=(e,t)=>{for(var r=0;r<e.length;r++){var i=document.createElement('option');i.text=e[r],t.appendChild(i)}}}let revenue_trend = new RevenueTrend(data);"
    },
    {

      "outputType": "plot",
      "AdditionalHtml": "<div id='revenue_trend2'></div> <div class='control-row' >Periodicity:<select  id='revenue_trend_periodicity2'></select>Measure:<select id = 'revenue_trend_measure2' ></select ></div > ",
      "script": "class RevenueTrend2{constructor(e){this.data=e,this.periodicitySelector=document.getElementById('revenue_trend_periodicity2'),this.measureSelector=document.getElementById('revenue_trend_measure2'),this.periodicitySelector.addEventListener('change',()=>{console.log('periodicitySelector2 changed')},!1),this.measureSelector.addEventListener('change',()=>{console.log('measureSelector2 changed')},!1),this.#b(['monthly','weekly'],this.periodicitySelector),this.#b(['revenue','profit','margin'],this.measureSelector)}updateBySelector=()=>{this.#a(this.periodicitySelector.value,this.measureSelector.value)};#a=(e,t)=>{};#b=(e,t)=>{for(var r=0;r<e.length;r++){var i=document.createElement('option');i.text=e[r],t.appendChild(i)}}}let revenue_trend2 = new RevenueTrend2(data);"
    }
  ]
};

run()
<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <div id="parent"></div>
</body>

</html>


Solution

The problem here is with this line

document.getElementById("parent").innerHTML += "<div id='" + divIDForPlot + "'></div>";

You need use appendChild to maintain the previous element's event listeners.

You can learn more about innerHTML vs appendChild here

function processJson(outputJson) {
  for (var i in outputJson) {
    let divIDForPlot = "plot_" + i;
    const plotElement = document.createElement('div');
    plotElement.id = divIDForPlot;
    document.getElementById("parent").appendChild(plotElement);

    let item = outputJson[i];
    let type = item["outputType"];

    if (type == "plot") {
      processPlot(divIDForPlot, item);
    } else if (type == "table") {

    }
    // break;

  }
}


function processPlot(elementId, plotData) {

  let additionalHtml = plotData["AdditionalHtml"];

  document.getElementById(elementId).innerHTML = additionalHtml;
  let script = plotData["script"];
  let outputData = " ";
  let dataString = "var data = " + JSON.stringify(outputData) + ";";
  let finalScript = dataString + "\n" + script;

  var s = document.createElement('script');
  s.type = 'text/javascript';
  try {
    s.appendChild(document.createTextNode(finalScript));
    document.getElementById(elementId).appendChild(s);
  } catch (e) {
    s.text = finalScript;
    document.getElementById(elementId).appendChild(s);
  }
}


function run() {
  processJson(dataJson["output"]);
}




let dataJson = {
  "output": [{

      "outputType": "plot",
      "AdditionalHtml": "<div id='revenue_trend'></div> <div class='control-row' >Periodicity:<select  id='revenue_trend_periodicity'></select>Measure:<select id = 'revenue_trend_measure' ></select ></div > ",
      "script": "class RevenueTrend{constructor(e){this.data=e,this.periodicitySelector=document.getElementById('revenue_trend_periodicity'),this.measureSelector=document.getElementById('revenue_trend_measure'),this.periodicitySelector.addEventListener('change',()=>{console.log('periodicitySelector changed')},!1),this.measureSelector.addEventListener('change',()=>{console.log('measureSelector changed')},!1),this.#b(['monthly','weekly'],this.periodicitySelector),this.#b(['revenue','profit','margin'],this.measureSelector)}updateBySelector=()=>{this.#a(this.periodicitySelector.value,this.measureSelector.value)};#a=(e,t)=>{var r=this.data.data[t][e];let i=this.data.layout[t]};#b=(e,t)=>{for(var r=0;r<e.length;r++){var i=document.createElement('option');i.text=e[r],t.appendChild(i)}}}let revenue_trend = new RevenueTrend(data);"
    },
    {

      "outputType": "plot",
      "AdditionalHtml": "<div id='revenue_trend2'></div> <div class='control-row' >Periodicity:<select  id='revenue_trend_periodicity2'></select>Measure:<select id = 'revenue_trend_measure2' ></select ></div > ",
      "script": "class RevenueTrend2{constructor(e){this.data=e,this.periodicitySelector=document.getElementById('revenue_trend_periodicity2'),this.measureSelector=document.getElementById('revenue_trend_measure2'),this.periodicitySelector.addEventListener('change',()=>{console.log('periodicitySelector2 changed')},!1),this.measureSelector.addEventListener('change',()=>{console.log('measureSelector2 changed')},!1),this.#b(['monthly','weekly'],this.periodicitySelector),this.#b(['revenue','profit','margin'],this.measureSelector)}updateBySelector=()=>{this.#a(this.periodicitySelector.value,this.measureSelector.value)};#a=(e,t)=>{};#b=(e,t)=>{for(var r=0;r<e.length;r++){var i=document.createElement('option');i.text=e[r],t.appendChild(i)}}}let revenue_trend2 = new RevenueTrend2(data);"
    }
  ]
};

run()
<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <div id="parent"></div>
</body>

</html>



Answered By - Syed
Answer Checked By - David Goodson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing