简体   繁体   中英

javascript not working on ajax loaded content; not using jquery

I'm using ajax to load all the content from 'mysite/math/' into math.php. Inside math.php I want to render the loaded math content using katex.

https://github.com/Khan/KaTeX

Inside math.php I load the library katex from the cdn which can be found in the link above.

math.php's html:

<body>
  <div id='main'>
</body>

Inside math.php's script tags, i have some php to get a list of urls from 'mysite/math/'

echo "var x = [];";
$dir = "./math/";
$a = scandir($dir);
foreach ($a as $x) {
if ($x === '.' or $x === '..') continue;
  echo "x.push('mysite/math/" . $x . "');";
}

So this gives me an array, x, which contains the location of each file whose content I want to load into my webpage.

Now, in javascript, I make multiple AJAX calls to the urls in the array x:

// defining the ajaxing function
function myfunction(url, someFunction) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (this.readyState === 4 && this.status === 200) {
      someFunction(this, url);
    }
  };
  xhr.open('GET', url, true);
  xhr.send(null);
}

// defining the callback function
function callbackfunction(xhr, url) {
  var name = url;
  var div = document.createElement('div');
  div.innerHTML = xhr.responseText;
  div.className += name;
  document.getElementById('main').appendChild(div);
}

// here, I'm actually executing the ajax calls
for (var i = 0; i < x.length; i++) {
  myfunction(x[i] + '?w=' + Math.random(), callbackfunction);
}

All of this works fine so far.

The problem:

Inside each of the html files living inside 'mysite/math/' there are span tags with the class='math' that contain the math content I want to render. So inside math.php, I see all my content, and I see my span tags with class='math'; they're all there.

Inside math.php there is also the following javascript which uses the katex function katex.render()

var math = document.getElementsByClassName('math');
for (var i = 0; i < math.length; i++) {
  katex.render(math[i].innerHTML, math[i]);
}

The way I've used katex works fine if the content is not loaded using ajax.

Note: I've seen this question asked several times but the answers are always using jquery. I would like a solution in javascript.

The problem is very likely that your AJAX-supplied content is not yet on the page when the browser invokes katex.render .

Since you're making multiple calls to load your content, you need to wait until all of the calls have returned to invoke katex.render . There are a couple of ways I can think of to do this using vanilla JavaScript:

  1. Create an event handler that listens for each of the calls to finish. When they're all done (maybe keep track of the number of calls completed in a variable,) invoke katex.render .
  2. Wrap each of your AJAX calls in a promise, push them all into an array, and invoke Promise.all on the array. In Promise.all().then() , invoke katex.render .

This solution is not so sophisticated but I think it does the job.

I changed my callback function by including a line applyKatex(div)

// defining the callback function
function callbackfunction(xhr, url) {
  var name = url;
  var div = document.createElement('div');
  div.innerHTML = xhr.responseText;
  div.className += name;
  document.getElementById('main').appendChild(div);
  applyKatex(div); //  <---this is what i added
}

I made a function, applyKatex() which accepts an html element and applies the function katex.render() to each child-element with the class name 'math'

As each new div is added to the page, katex.render() will be applied to it

function applyKatex(element) {
  var math = element.getElementsByClassName('math');
  for (var i = 0; i < math.length; i++) {
    katex.render(math[i].innerHTML, math[i]);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM