dasmoth / dalliance

Interactive web-based genome browser.
http://www.biodalliance.org/
BSD 2-Clause "Simplified" License
226 stars 68 forks source link

Embed BioDalliance using react hooks #250

Closed bilalebi closed 2 years ago

bilalebi commented 3 years ago

I'm trying to embed BioDalliance using react hooks but no matter what I did I keep getting undefined Browser or syntax errors

As far as I understood, the embedded script has three parts:

// Part 1
<script language="javascript" src="//www.biodalliance.org/release-0.13/dalliance-compiled.js"></script>

// Part 2
<script language="javascript">
  new Browser({
    chr:          '22',
    viewStart:    30700000,
    viewEnd:      30900000,

    coordSystem: {
      speciesName: 'Human',
      taxon: 9606,
      auth: 'GRCh',
      version: '37',
      ucscName: 'hg19'
    },

    sources:     [{name:                 'Genome',
                   twoBitURI:            '//www.biodalliance.org/datasets/hg19.2bit',
                   tier_type:            'sequence'},
                  {name:                 'Genes',
                   desc:                 'Gene structures from GENCODE 19',
                   bwgURI:               '//www.biodalliance.org/datasets/gencode.bb',
                   stylesheet_uri:       '//www.biodalliance.org/stylesheets/gencode.xml',
                   collapseSuperGroups:  true,
                   trixURI:              '//www.biodalliance.org/datasets/geneIndex.ix'},
                  {name:                 'Repeats',
                   desc:                 'Repeat annotation from Ensembl',
                   bwgURI:               '//www.biodalliance.org/datasets/repeats.bb',
                   stylesheet_uri:       '//www.biodalliance.org/stylesheets/bb-repeats.xml'},
                  {name:                 'Conservation',
                   desc:                 'Conservation', 
                   bwgURI:               '//www.biodalliance.org/datasets/phastCons46way.bw',
                   noDownsample:         true}],

  });
</script>

// Part 3
<div id="svgHolder"></div>

The first one is simple I can use useEffect to import it like so:

useEffect(() => {
        const dallianceCompiledScriptTag = document.createElement('script');
        dallianceCompiledScriptTag.src = "http://www.biodalliance.org/release-0.13/dalliance-compiled.js";
        dallianceCompiledScriptTag.async = true;
        document.body.appendChild(dallianceCompiledScriptTag);

        return () => {
            document.body.removeChild(dallianceCompiledScriptTag);
        }
    }, []);

But I couldn't find a proper way to insert the 2nd part as I keep getting 'Browser' is not defined no-undef error

I also tried using react-script-tag without success

I've read the discussion on #242 but couldn't find a way to implement @dasmoth code snippet, as Browser was not recognized

Any help would be much appreciated

andreasprlic commented 3 years ago

You could try initiating the Browser() object in componentDidMount()

bilalebi commented 3 years ago

Thank you for your prompt reply, maybe I'm missing something but in order to initiate the Browser() object it needs to be imported from somewhere. I assumed it can be imported from www.biodalliance.org/release-0.13/dalliance-compiled.js but couldn't find it there.. it's defined here in the source code.

This is the error I get when I initialize the Browser() object in useEffect() (equivalent to componentDidMount())

Failed to compile
src/components/trackhub_view/BiodallianceView.js
  Line 39:17:  'Browser' is not defined  no-undef

Search for the keywords to learn more about each error.
dasmoth commented 3 years ago

Hi, and sorry to hear you're having trouble.

What you're trying looks reasonable to me. What does occur to me is that the script tag you're injecting is "async", so it won't take effect instantly. Trying to construct the Browser immediately after injecting the script tag is likely to fail. Were I debugging this myself, I'll try just your useEffect hook, and make sure that -- after it's run -- you can see the Browser class from the developer tools console. If that works, then it might just be a question of adding a delay (or polling) before you try to construct your Browser.

Hope this is some help,

dasmoth commented 3 years ago

One other thing I'll mention is that it's possible to use Git-latest Biodalliance as a CommonJS module, e.g.:

    const` biodalliance = require('dalliance');
    new biodalliance.Browser({
               /* Config here... */
    });

There's one example of this at https://github.com/dasmoth/headless-biodalliance . Putting together a React-based example is somewhere on my TODO list... If you're building your project with webpack or similar (and if you're using React, I'm guessing this may well be the case), that could end up being a neater solution. Of course, direct import to the global namespace via a script tag really ought to work, too.

If you try this route, you can make a new package from a Git checkout with npm compile && npm pack and then point to that in your project's package.json.

bilalebi commented 2 years ago

@dasmoth thank you for your suggestions they were very helpful, I managed to solve the problem 🎉

Here is what I've done:

I created a React-based example of Biodalliance embedded view if anyone is interested in trying it out.