Sketcher: Listening to User Changes

The sketcher in the ChemDoodle Web Components allows your users to describe and submit chemical information to your systems. But there may be times where you need to provide your users with immediate feedback as they are drawing their figures. This tutorial describes how to achieve this functionality.

Demonstration

The following sketcher will tell you how many atoms and bonds are present in your structure after each edit.




Programmatically Listening to Actions

All of the edits a user performs in the sketcher are logged in the HistoryManager (mySketcher.historyManager) for that sketcher. These could be adding bonds, changing atom labels, moving structures, etc. This facilitates the undo and redo functionality associated with these types of content editors. In the ChemDoodle Web Components, the Action class will notify the associated sketcher of it forward or reverse execution. We can listen to these notifications by overriding the SketcherCanvas.checksOnAction() function.

The SketcherCanvas.checksOnAction() is already used by the core SketcherCanvas class to react to changes, such as updating numbers on atom mappings or correctly orienting dynamic brackets. So it is essential that we still call the parent function even if we are overriding it to add our own listener. This can be done in the following manner:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var sketcher = new ChemDoodle.SketcherCanvas('sketcher', 500, 300, {});
// ... set up your sketcher
// now we override the checksOnAction function, making sure to save the old one and also call it
sketcher.oldFunc = sketcher.checksOnAction;
// using force improves efficiency, so changes will not be checked until a render occurs
// you can force a check by sending true to this function after calling check with a false
sketcher.checksOnAction = function(force){
  // call the old checksOnAction function
  this.oldFunc(force);
  // add in your functionality
  for(var i = 0, ii = this.molecules.length; i<ii; i++){
     // do calculations on each molecule
  }
};

Full Example

First we create the HTML element within the DOM that we will update with our information, using feedback as its id:

1
<span id="feedback" style="font-size:24px;"></span>

Now we create the sketcher and override the checksOnAction function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
  ChemDoodle.ELEMENT['H'].jmolColor = 'black';
  ChemDoodle.ELEMENT['S'].jmolColor = '#B9A130';
  var sketcher = new ChemDoodle.SketcherCanvas('sketcher', 550, 300, {useServices:true, oneMolecule:true});
  sketcher.specs.atoms_useJMOLColors = true;
  sketcher.specs.bonds_clearOverlaps_2D = true;
  sketcher.oldFunc = sketcher.checksOnAction;
  // using force improves efficiency, so changes will not be checked until a render occurs
  // you can force a check by sending true to this function after calling check with a false
  sketcher.checksOnAction = function(force){
    // call the old checksOnAction function
    this.oldFunc(force);
    // there will only be one molecule because this is a single molecule sketcher
    var m = this.getMolecule();
    // update the DOM element with the information using jQuery
    ChemDoodle.lib.jQuery('#feedback').html('<strong>Atoms</strong>: '+m.atoms.length+', <strong>Bonds</strong>: '+m.bonds.length);
  };
  sketcher.repaint();
</script>

There you have it, simple as that!