Beeminder Forum

updating source of the `object` tag

#1

I posed two related questions on SO tonight, in case any javascript aficionados here have any help to offer, I’m mentioning it here.

This is related to reloading new svg sources when the graph is updated, and some stuff with the graphs sometimes going missing (until you reload the page) after you’ve made an update.


2 Likes

#2

Re the first one: someone replied and pointed me toward Node.replaceChild, which was helpful. I wound up not using the suggestion about setting and then un-setting the parent node’s width & height because if there’s an error reloading the new data source (which happens not infrequently), the onload won’t fire, and then you kind of mess up the css. Also the answer that I marked as correct has you creating a new element in the DOM each time you update, but you can actually call replaceChild with the original node, and so this is what I came up with ultimately:

  function updateSVG_js(obj, url) {
    if (svgLoaded_js(obj)) {
      obj.setAttribute("data", url)
      obj.onload = function() {}
      obj.parentNode.replaceChild(obj,obj)
    } else {
    // if the svg has already failed to load, Chrome won't correctly reload
    // the object from source. which means we have to create a new element and
    // add it to the DOM. If this turns out to cause noticable memory problems
    // or whatever, because who knows what's going on with garbage collection,
    // then we can add in a check of window.navigator.userAgent and look to see
    // if this is a Chrome browser, and only do this in that case?
      var reSVG = document.createElement("object");
      reSVG.setAttribute("type", "image/svg+xml");
      reSVG.setAttribute("data", url);
      reSVG.id = "graph-svg";
      reSVG.innerHTML = '<div class="fallback"><p>Whoops, something went wrong loading your graph!</p><p>Give us a second to try\'n fix that, or <a href="#" id="svg-reload" class="">Reload</a></p></div>'
      obj.parentNode.replaceChild(reSVG,obj)
    }
    clearTimeout(checkGraphTimeout);
    checkGraphTimeout = setTimeout(function() {
      checkGraph($("#graph-svg"))
    }, 3000);
  }

The second question I answered for myself. It looks like it amounts to maybe-a-bug in how some browsers are handling the case of getting of 403 when they load the svg data url. From reading the HTML spec, it sounds to me like the browser is expected to fire an error event, but Firefox is the only browser that does that (having tested in Chrome, Safari, and Firefox), so I worked around it. Chrome also has this annoying thing where once it shows the fallback, it’s impossible to update that node again. Both Safari and Chrome are fine with updating the data attribute and re-loading it into the dom, but Chrome won’t do shit with that node anymore after the fallback has been shown.

So the workaround for that inconsistent behavior around firing the error event – we look for the fallback HTML on the page and test its boundingClientRect’s dimensions to test if it is currently visible on the page or not. If the fallback is visible, then an error occurred and we need to reload the graph.

3 Likes

#3

I have nothing contribute here except to say I’m sorry your life choices have led you to this lonely hell and we’re all here for you spiritually.

4 Likes

#4

The galactic community is waiting to usher us in as soon as we get this figured out on our own.

Thanks Bee!

2 Likes