I was following the tutorial on how to customize the viewer with a publicly shared file described here I would like to add a button to my viewer however I keep getting the error Uncaught (in promise) Extension not found: HandleSelectionExtension. Has it been registered(1)?
. Here is the code for my js functions which I included withing my html page:
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) => {
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<dbIds.length; i++){
var namepart = it.getNodeName(dbIds[i]);
if (namepart !== undefined){
console.log(dbIds);
console.log(namepart);}}
/* for (i = 121; i<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<dbIds.length; i++){
var namepart = it.getNodeName(dbIds[i]);
if (namepart !== undefined){
console.log(dbIds);
console.log(namepart);}}
/* for (i = 121; i<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) => {
const selection = this.viewer.getSelection();
this.viewer.clearSelection();
// Anything selected?
if (selection.length > 0) {
let isolated = [];
// Iterate through the list of selected dbIds
selection.forEach((dbId) => {
// Get properties of each dbId
this.viewer.getProperties(dbId, (props) => {
// 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:[email protected]?subject=subject&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) => {
// Execute an action here
// Get current selection
const selection = this.viewer.getSelection();
this.viewer.clearSelection();
// Anything selected?
if (selection.length > 0) {
let isolated = [];
// Iterate through the list of selected dbIds
selection.forEach((dbId) => {
// Get properties of each dbId
this.viewer.getProperties(dbId, (props) => {
// 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:[email protected]?subject=subject&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);
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!
UPDATE: I have troubleshooted the program by displaying console.log( Autodesk.Viewing.theExtensionManager.registerExtension('HandleSelectionExtension', HandleSelectionExtension);
And I get the following message: "Uncaught ReferenceError: Cannot access 'HandleSelectionExtension' before initialization". Do i need to add a Autodesk.Viewing.Initializer(options, function() {
. 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!
EDIT SIMPLE QUESTION: How can I add a viewer button extension to this tutorial.
In your extensions you rely on a v7 specific functionality, the Extension.prototype.onToolbarCreated(toolbar) - see https://forge.autodesk.com/en/docs/viewer/v7/change_history/changelog_v7/migration_guide_v6_to_v7/
In order to migrate the above code to v7 all I have to change is the implementation of onDocumentLoadSuccess(). Here is the updated version
function onDocumentLoadSuccess(doc) {
// A document contains references to 3D and 2D viewables.
var viewables = doc.getRoot().search({
'type': 'geometry'
});
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()
};
viewer = new Autodesk.Viewing.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);
}
And also make sure you are referencing the v7 resources from your html page:
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css">
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.js"></script>