hvianna/audioMotion-analyzer

Behaviour when container element is not found

Staijn1 opened this issue · 3 comments

Hi,

I was running into an issue today where the element I wanted the visualizer in was not loaded yet.
I did not receive an error, it just didn't work.

So I went into the sourcecode and saw in the constructor:

this._container = container || document.body;

I am wondering if this is the best way to handle this, because in my environment (angular) it didn't put the visualizer in the body, but also didn't throw an error.

It may be easier to just throw an error because if, for some reason, you want the visualizer in the body element you can always get the element yourself.

I can create a pull request for it, because it ain't hard to implement, but I wanted to discuss it first if this is desired.

Greetings,
Staijn

Hi!

The body will only be used if the container is null or undefined, which doesn't seem to be the case. Can you try adding a console.log( container ) to that point in the constructor to see what it outputs?

If the element exists but just isn't ready, maybe we could use an event listener to delay appending the analyzer to it.

I added the console.log to print _container after the line in my first message.
It prints the element it is supposed to be in, so I figured maybe it was some angular shenanigans going on with loading the component etc.

When I wrote my initial post I used the OnInit lifecycle, which is one of the first to be fired after the constructor.
I changed this to some others, eventually to AfterContentInit, which is (I think) the last one to be called.
In this cycle I called the constructor for Audiomotion analyzer.

Still the same result, container prints out nicely, but element does not get shown in the element, or appended to the body.

I am kinda suprised container is still defined, I expected it to be undefined. Seems like something else is going on..

I got around it yesterday, by delaying the call to the constructor with 25 ms, using setTimeout. It then shows the visualizer properly in the element I want it to.

ngAfterContentInit(): void {
    this.init();
  }
ngAfterContentInit(): void {
   setTimeout(() => this.init(), 25)
  }

private init(): void {
    const elem = document.getElementById('visualizer');
    this.audioMotion = new AudioMotionAnalyzer(elem, this.options);
    this.setSource();
    this.updateOptions()
  }

Thanks for the update!

I have no experience with angular, but my guess is it's resetting the element's innerHTML content during the initialization cycle.

After my previous post I realized the idea of using an onload event listener wouldn't work on <div> elements, so I don't think we can solve/improve this on the module side. But for now, your solution should be helpful for anyone that may run into this issue.

Cheers!