Extending Canvases

Sometimes, just overriding or implementing functions for the current canvases will not be enough to produce the functionality you desire. In these more advanced scenarios, you may want to develop a new canvas type from scratch. Creating new child canvases also has the added benefit of scalability; you only need to call the new constructor to initialize multiple instances, instead of having to extend each and every canvas initialized.

There are four abstract classes in the ChemDoodle Web Components library that can be extended to create new child components:

  • _Canvas
  • _AnimatorCanvas
  • _Canvas3D
  • _SpectrumCanvas

Canvas is the most basic class and provides functionality for drawing molecules and handling events. SpectrumCanvas extends and alters Canvas to provide functionality for drawing spectra. AnimatorCanvas extends Canvas to provide a framework for producing animations and is discussed on the next page. Canvas3D overrides Canvas and provides a framework for displaying molecules with WebGL.

Implementing a child of any of these canvases is standard Javascript, utilizing the prototype keyword. The procedure is to define the new name, setup the class, call the Canvas.create() function, and then bind the prototype to a new Canvas instance. As an example, we will be creating a new canvas type that initially displays a solid color, but when we move the mouse pointer over it, a molecule will appear. We will call it a HideAndSeekCanvas.

So the elements we will need are as follows. First we need to declare our new class. We will pass the constructor the standard parameters that are required by all canvases, a name, width and height. We will also pass in a string that defines the color that will be shown when a mouse is not over it.

1
2
HideAndSeekCanvas = function(id, width, height, color){
}

Next we will fill out the innards of the constructor by saving the color, setting the mouseover and mouseout event handlers, and overriding the drawChildExtras() function. At the end, we will call the Canvas.create() function that completes a canvas and puts it into the HTML page.

1
2
3
4
5
6
7
8
9
10
11
HideAndSeekCanvas = function(id, width, height, color){
  //set variables
  this.color = color;
  //set event handlers
  this.mouseover = function(){}
  this.mouseout = function(){}
  //draw additional graphics
  this.drawChildExtras = function(){};
  //setup
  this.create();
}

Lastly, we will bind our new class’s prototype to a new Canvas instance. Remember that the Canvas class is actually inside of the global ChemDoodle variable. It should also be noted that all abstract classes in the ChemDoodle Web Components library are prepended with an underscore (_). This way users don’t accidentally call these constructors.

1
HideAndSeekCanvas.prototype = new ChemDoodle._Canvas();

So let’s now complete the code and put everything together:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
  HideAndSeekCanvas = function(id, width, height, color){
    this.color = color;
    this.fillOverlay = true;
    this.mouseover = function(){
      this.fillOverlay = false;
      this.repaint();
    }
    this.mouseout = function(){
      this.fillOverlay = true;
      this.repaint();
    }
    this.drawChildExtras = function(ctx){
      if(this.fillOverlay){
        ctx.fillStyle=this.color;
        ctx.fillRect(0, 0, this.width, this.height);
      }
    }
    this.create(id, width, height);
  }
  HideAndSeekCanvas.prototype = new ChemDoodle._Canvas();
</script>

Ok, we are done! So where is the canvas? Well, we only created a new class that defines the canvas, we haven’t made any instances of it yet, so let’s do that now:

1
2
3
4
5
6
7
8
<script>
  var first = new HideAndSeekCanvas('first', 100, 100, 'blue');
  first.loadMolecule(ChemDoodle.readMOL('Molecule Name\n  CHEMDOOD08260921043D 0   0.00000     0.00000     0\n[Insert Comment Here]\n  6  6  0  0  0  0  0  0  0  0  1 V2000\n    0.0000    1.0000    0.0000 N   0  0  0  1  0  0  0  0  0  0  0  0\n   -0.8660    0.5000    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n   -0.8660   -0.5000    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.0000   -1.0000    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.8660   -0.5000    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.8660    0.5000    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n  1  2  2  0  0  0  0\n  2  3  1  0  0  0  0\n  3  4  2  0  0  0  0\n  4  5  1  0  0  0  0\n  5  6  2  0  0  0  0\n  6  1  1  0  0  0  0\nM  END'));
  var second = new HideAndSeekCanvas('second', 100, 100, 'red');
  second.loadMolecule(ChemDoodle.readMOL('Molecule Name\n  CHEMDOOD08260921053D 0   0.00000     0.00000     0\n[Insert Comment Here]\n  5  5  0  0  0  0  0  0  0  0  1 V2000\n    0.0000    0.7694    0.0000 O   0  0  0  1  0  0  0  0  0  0  0  0\n   -0.8090    0.1816    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n   -0.5000   -0.7694    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.5000   -0.7694    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.8090    0.1816    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n  1  2  1  0  0  0  0\n  2  3  2  0  0  0  0\n  3  4  1  0  0  0  0\n  4  5  2  0  0  0  0\n  5  1  1  0  0  0  0\nM  END'));
  var third = new HideAndSeekCanvas('third', 100, 100, 'green');
  third.loadMolecule(ChemDoodle.readMOL('Molecule Name\n  CHEMDOOD08260921053D 0   0.00000     0.00000     0\n[Insert Comment Here]\n  5  5  0  0  0  0  0  0  0  0  1 V2000\n    0.0000    0.7694    0.0000 S   0  0  0  1  0  0  0  0  0  0  0  0\n   -0.8090    0.1816    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n   -0.5000   -0.7694    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.5000   -0.7694    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n    0.8090    0.1816    0.0000 C   0  0  0  2  0  0  0  0  0  0  0  0\n  1  2  1  0  0  0  0\n  2  3  2  0  0  0  0\n  3  4  1  0  0  0  0\n  4  5  2  0  0  0  0\n  5  1  1  0  0  0  0\nM  END'));
</script>


And that completes this example. To summarize, we discussed how to create child classes of the abstract parent classes provided by the ChemDoodle Web Components library. This allows us to custom create components for specific tasks that can be instantiated like other canvases.

Continue to Animations →