title: Add toolbar buttons to embedded viewer
body: <p>I was following the tutorial on how to customize the viewer with a publicly shared file described <a href="https://forge.autodesk.com/blog/publicly-share-models-customized-viewer" rel="nofollow noreferrer">here</a> I would like to add a button to my viewer however I keep getting the error <code>Uncaught (in promise) Extension not found: HandleSelectionExtension. Has it been registered(1)?</code>. Here is the code for my js functions which I included withing my html page: </p>
  
  <pre><code>var viewer;
  displayViewer();
  //CODE FOR CUSTOMER VIEWER
  function displayViewer(){
    //  assemblyname = '';
  var embedURLfromA360 = "https://afasystemsinc2.autodesk360.com/shares/public/SH56a43QTfd62c1cd96838ebd0c0ce1c251d?mode=embed";
  
  
  function getURN(onURNCallback) {
      $.get({
          url: embedURLfromA360.replace('public', 'metadata').replace('mode=embed', ''),
          dataType: 'json',
          success: function (metadata) {
              if (onURNCallback) {
                  onURNCallback(metadata.success.body.viewing.views.viewableUrn);
              }
          }
      })
  }
  
  function getForgeToken(onTokenCallback) {
      $.post({
          url: embedURLfromA360.replace('public', 'sign').replace('mode=embed', 'oauth2=true'),
          data: '{}',
          success: function (oauth) {
              if (onTokenCallback)
                  onTokenCallback(oauth.accessToken, oauth.validitySeconds);
          }
      });
  }
  
  getURN(function (urn) {
      var options = {
          env: 'AutodeskProduction',
          getAccessToken: getForgeToken
      };
      var documentId = 'urn:' + urn;
      Autodesk.Viewing.Initializer(options, function onInitialized() {
          Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
      });
  });
  
  // used by viewer.addEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, onToolbarCreated)
  
  const onToolbarCreated = (e) =&gt; {
      const settingsTools = viewer.toolbar.getControl('settingsTools')
      /*
      settingsTools.removeControl('toolbar-modelStructureTool') 
      settingsTools.removeControl('toolbar-propertiesTool')            
      settingsTools.removeControl('toolbar-settingsTool')          
      settingsTools.removeControl('toolbar-fullscreenTool')           
  */
      viewer.removeEventListener(
          Autodesk.Viewing.TOOLBAR_CREATED_EVENT,
          onToolbarCreated)  
  } 
  
  /**
   * Autodesk.Viewing.Document.load() success callback.
   * Proceeds with model initialization.
   */
  function onDocumentLoadSuccess(doc) {
  
      // A document contains references to 3D and 2D viewables.
      var viewables = Autodesk.Viewing.Document.getSubItemsWithProperties(doc.getRootItem(), {
          'type': 'geometry'
      }, true);
      if (viewables.length === 0) {
          console.error('Document contains no viewables.');
          return;
      }
  
      // Choose any of the avialble viewables
      var initialViewable = viewables[0];
      var svfUrl = doc.getViewablePath(initialViewable);
      var modelOptions = {
          sharedPropertyDbPath: doc.getPropertyDbPath()
      };
  
     // var viewerDiv = document.getElementById('MyViewerDiv');
   //viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
  
   viewer = new Autodesk.Viewing.Private.GuiViewer3D(document.getElementById('MyViewerDiv'),{extensions:['HandleSelectionExtension', 'ModelSummaryExtension']});
  
      // Our customization of the Viewer: we are removing some of the toolbar buttons
      viewer.addEventListener(Autodesk.Viewing.TOOLBAR_CREATED_EVENT, onToolbarCreated)
      viewer.start(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
  }
  
  /**
   * Autodesk.Viewing.Document.load() failuire callback.
   */
  function onDocumentLoadFailure(viewerErrorCode) {}
  
  /**
   * viewer.loadModel() success callback.
   * Invoked after the model's SVF has been initially loaded.
   * It may trigger before any geometry has been downloaded and displayed on-screen.
   */
  function onLoadModelSuccess(model) {}
  
  /**
   * viewer.loadModel() failure callback.
   * Invoked when there's an error fetching the SVF file.
   */
  function onLoadModelError(viewerErrorCode) {}
  }
  function view(){
      console.log(viewer);
  }
  
  function destroyViewer(){
      console.log(viewer);
      console.log(viewer.contextMenu);
      viewer.finish();
  viewer = null;
  Autodesk.Viewing.shutdown();
  console.log(viewer);
  }
  
  var ext = '';
  var dim = '';
  var assemblyname = '';
  
  function getAssemblyName(){
  assemblyname = sessionStorage.getItem("assemblyName");
  //var ext = partname.substr(partname.lastIndexOf('.'));
  ext = assemblyname.split('.');
  dim = ext[0] + ':1';
  //dim = ext[0];
  console.log(assemblyname);
  console.log(dim);
  if (dim !== ''){
      isolateSelected();
  }
  }
  
  
  //function to get part name from __MachineParts.php
  var partname = '';
  var extension = '';
  var namewithoutextension = '';
  function getPartName(){
  partname = sessionStorage.getItem("partName");
  //var ext = partname.substr(partname.lastIndexOf('.'));
  extension = partname.split('.');
  namewithoutextension = extension[0] + ':1'
  console.log(partname);
  console.log(namewithoutextension);
  if (namewithoutextension !== ''){
      isolateSelectedPart();
  }
  }
  
  function isolateSelected(){
      console.log(dim);
      console.log(viewer);
     /* if (viewer == null){
          getItem();
      }*/
      viewer.search(dim, function(dbIds) {
     // viewer.search('"' + 'M-109408 FOLDING PLOUGH:2' + '"', function(dbIds) {
          console.log(dbIds.length);
         if (dbIds.length == 0){
          dim = ext[0] + ':2';
         // isolateSelected();
       }
          getSubset(dbIds, 'label', dim, function(dbIds) {
         // getSubset(dbIds, 'label', 'M-109408 FOLDING PLOUGH:2', function(dbIds) {
         // getSubset(dbIds, property.name, 'M-54439 POST TUBING:1', function(dbIds) {
              //getSubset(dbIds, property.name, property.value, function(dbIds){
              var it = viewer.model.getData().instanceTree;
              //console.log(it);
             for (i = 0; i&lt;dbIds.length; i++){
                 var namepart = it.getNodeName(dbIds[i]);
                 if (namepart !== undefined){
              console.log(dbIds);
              console.log(namepart);}}
            /*  for (i = 121; i&lt;381;i++){
                  var dbId = i;
              var it = NOP_VIEWER.model.getData().instanceTree;
              var name = it.getNodeName(dbId);
              console.log(name);}*/
             // viewer.setBackgroundColor(255,0,0,255,0,0);
           //  viewer.setSelectionColor(new THREE.Color(1,1,1));
          // viewer.setSelectionColor(new THREE.Color(0xFFAB33));
          viewer.setSelectionColor(new THREE.Color(0xFFC000));
            //  viewer.setBackgroundOpacity(1.0);
              viewer.isolate(dbIds)
             viewer.select(dbIds);
              viewer.utilities.fitToView();
              $(window).scrollTop(300);
          })
      }, function(error) {})
  }
  
  function isolateSelectedPart(){
      console.log(namewithoutextension);
      if (viewer == null){
          getItem();
      }
      viewer.search(namewithoutextension, function(dbIds) {
     // viewer.search('"' + 'M-109408 FOLDING PLOUGH:2' + '"', function(dbIds) {
          console.log(dbIds.length);
          if (dbIds.length == 0){
              getItem();
          }
          getSubset(dbIds, 'label', namewithoutextension, function(dbIds) {
         // getSubset(dbIds, 'label', 'M-109408 FOLDING PLOUGH:2', function(dbIds) {
         // getSubset(dbIds, property.name, 'M-54439 POST TUBING:1', function(dbIds) {
              //getSubset(dbIds, property.name, property.value, function(dbIds){
              var it = viewer.model.getData().instanceTree;
              //console.log(it);
             for (i = 0; i&lt;dbIds.length; i++){
                 var namepart = it.getNodeName(dbIds[i]);
                 if (namepart !== undefined){
              console.log(dbIds);
              console.log(namepart);}}
            /*  for (i = 121; i&lt;381;i++){
                  var dbId = i;
              var it = NOP_VIEWER.model.getData().instanceTree;
              var name = it.getNodeName(dbId);
              console.log(name);}*/
              viewer.setSelectionColor(new THREE.Color(0xFFC000));
             // viewer.setBackgroundOpacity(1.0);
              viewer.isolate(dbIds)
             viewer.select(dbIds);
              viewer.utilities.fitToView();
              $(window).scrollTop(300);
          })
      }, function(error) {})
  }
  
  //function to find the dbid of the part/assembly
  function getSubset(dbIds, name, value, callback) {
      console.log("getSubset, dbIds.length before = " + dbIds.length)
      viewer.model.getBulkProperties(dbIds, {
          propFilter: [name],
          ignoreHidden: true
      }, function(data) {
          var newDbIds = []
          for (var key in data) {
              var item = data[key]
             // console.log(item.properties);
              if (item.properties[0].displayValue === value) {
                  newDbIds.push(item.dbId)
              }
          }
  
          console.log("getSubset, dbIds.length after = " + newDbIds.length)
  
          callback(newDbIds)
  
      }, function(error) {})
  }
  
  class HandleSelectionExtension extends Autodesk.Viewing.Extension {
      constructor(viewer, options) {
          super(viewer, options);
          this._group = null;
          this._button = null;
      }
  
      load() {
          console.log('HandleSelectionExtension has been loaded');
          return true;
      }
  
      unload() {
          // Clean our UI elements if we added any
          if (this._group) {
              this._group.removeControl(this._button);
              if (this._group.getNumberOfControls() === 0) {
                  this.viewer.toolbar.removeControl(this._group);
              }
          }
          console.log('HandleSelectionExtension has been unloaded');
          return true;
      }
  
      onToolbarCreated() {
          // Create a new toolbar group if it doesn't exist
          this._group = this.viewer.toolbar.getControl('allMyAwesomeExtensionsToolbar');
          if (!this._group) {
              this._group = new Autodesk.Viewing.UI.ControlGroup('allMyAwesomeExtensionsToolbar');
              this.viewer.toolbar.addControl(this._group);
          }
  
          // Add a new button to the toolbar group
          this._button = new Autodesk.Viewing.UI.Button('handleSelectionExtensionButton');
          this._button.onClick = (ev) =&gt; {
              const selection = this.viewer.getSelection();
  this.viewer.clearSelection();
  // Anything selected?
  if (selection.length &gt; 0) {
      let isolated = [];
      // Iterate through the list of selected dbIds
      selection.forEach((dbId) =&gt; {
          // Get properties of each dbId
          this.viewer.getProperties(dbId, (props) =&gt; {
              // Output properties to console
              console.log(props);
              console.log(props.name);
              // Ask if want to isolate
            //  if (confirm(`Isolate ${props.name} (${props.externalId})?`)) {
                  isolated.push(dbId);
                  this.viewer.isolate(isolated);
                  //window.open('mailto:test@example.com?subject=subject&amp;body='+props.name);
              //}
          });
      });
  } else {
      // If nothing selected, restore
      this.viewer.isolate(0);
  }
          };
          this._button.setToolTip('Isolate Part');
          this._button.addClass('handleSelectionExtensionIcon');
          this._group.addControl(this._button);
      }
  }
  
  Autodesk.Viewing.theExtensionManager.registerExtension('HandleSelectionExtension', HandleSelectionExtension);
  
  //CODE FOR BUTTON TO ORDER A SPARE PART
  
  class ModelSummaryExtension extends Autodesk.Viewing.Extension {
      constructor(viewer, options) {
          super(viewer, options);
          this._group = null;
          this._button = null;
      }
  
      load() {
          console.log('ModelSummaryExtension has been loaded');
          return true;
      }
  
      unload() {
          // Clean our UI elements if we added any
          if (this._group) {
              this._group.removeControl(this._button);
              if (this._group.getNumberOfControls() === 0) {
                  this.viewer.toolbar.removeControl(this._group);
              }
          }
          console.log('ModelSummaryExtension has been unloaded');
          return true;
      }
  
      onToolbarCreated() {
          // Create a new toolbar group if it doesn't exist
          this._group = this.viewer.toolbar.getControl('allMyAwesomeExtensionsToolbar');
          if (!this._group) {
              this._group = new Autodesk.Viewing.UI.ControlGroup('allMyAwesomeExtensionsToolbar');
              this.viewer.toolbar.addControl(this._group);
          }
  
          // Add a new button to the toolbar group
          this._button = new Autodesk.Viewing.UI.Button('ModelSummaryExtensionButton');
          this._button.onClick = (ev) =&gt; {
              // Execute an action here
              // Get current selection
  const selection = this.viewer.getSelection();
  this.viewer.clearSelection();
  // Anything selected?
  if (selection.length &gt; 0) {
      let isolated = [];
      // Iterate through the list of selected dbIds
      selection.forEach((dbId) =&gt; {
          // Get properties of each dbId
          this.viewer.getProperties(dbId, (props) =&gt; {
              // Output properties to console
              console.log(props);
              // Ask if want to isolate
              if (confirm(`Would you like to order a spare of ${props.name} ?`)) {
                  isolated.push(dbId);
                  this.viewer.isolate(isolated);
                  window.open('mailto:test@example.com?subject=subject&amp;body='+props.name);
              }
          });
      });
  } else {
      // If nothing selected, restore
      this.viewer.isolate(0);
  }
          };
          this._button.setToolTip('Order this Part');
          this._button.addClass('modelSummaryExtensionIcon');
          this._group.addControl(this._button);
      }
  }
  
  Autodesk.Viewing.theExtensionManager.registerExtension('ModelSummaryExtension', ModelSummaryExtension);
  </code></pre>
  
  <p>I have set up additional buttons before without any problems, does this have anything to do with the fact that I'm using a publicly shared model. Both buttons have that error. Any guidance or reason as to why this is happening would be greatly appreciated. Cheers!</p>
  
  <p>UPDATE: I have troubleshooted the program by displaying <code>console.log( Autodesk.Viewing.theExtensionManager.registerExtension('HandleSelectionExtension', HandleSelectionExtension);</code> And I get the following message: "Uncaught ReferenceError: Cannot access 'HandleSelectionExtension' before initialization". Do i need to add a <code>Autodesk.Viewing.Initializer(options, function() {</code>. The tutorial did not include this. If i do need to include it, how would I implement it for the extension to successfully load. Thanks!</p>
  
  <p>EDIT SIMPLE QUESTION: How can I add a viewer button extension to  <a href="https://forge.autodesk.com/blog/publicly-share-models-customized-viewer" rel="nofollow noreferrer">this</a> tutorial.</p>