I'm trying to change the color of elements in 3D Viewer using the Autodesk-forge platform, and for this I'm using this API https://forge.autodesk.com/cloud_and_mobile/2015/12/change-color-of-elements-with-view-and-data-api.html by Daniel Du.
But the problem is when running I got this
The error Pict
And this the function :
Autodesk.Viewing.Viewer3D.prototype.setColorMaterial = function(objectIds, color) {
var material = addMaterial(color);
for (var i=0; i<objectIds.length; i++) {
var dbid = objectIds[i];
//from dbid to node, to fragid
viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, function () {
var it = viewer.model.getData().instanceTree;
console.log(it);
it.enumNodeFragments(dbid, function (fragId) {
var renderProxy = viewer.impl.getRenderProxy(viewer.model, fragId);
console.log("r prox : " + renderProxy);
renderProxy.meshProxy = new THREE.Mesh(renderProxy.geometry, renderProxy.material);
renderProxy.meshProxy.matrix.copy(renderProxy.matrixWorld);
renderProxy.meshProxy.matrixWorldNeedsUpdate = true;
renderProxy.meshProxy.matrixAutoUpdate = false;
renderProxy.meshProxy.frustumCulled = false;
viewer.impl.addOverlay(overlayName, renderProxy.meshProxy);
viewer.impl.invalidate(true);
}, false);
});
}
}
Hopefully, anyone has the solution to this problem...
Most likely you are running this code before the instance tree has been loaded, which provokes the error Cannot read property 'enumNodeFragments' of undefined on it variable. You would need to wait for the Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT before running that code.
Take also a look at previous question about modifying materials in the viewer.
Related
Good day.
My question is quite dumb, I guess, but I'm not familiar enough with the termins, to ask it properly (and to get an answer from Google).
So - please help...
Shortly - I'm trying to create some major class, which will be insanitated by instances, which will describe some methods, and some fields.
Major logick will be implemented in parent class.
So, lets say I have a parent
function CRUD_Grid_model(){
//Settings part
this.GridElement = "" ;
this.editModeFlagElement = "" ;
this.newRowElement = "";
//Save logicks all lies here.
this.commit = function (){
alert("PLEASE REDEFINE COMMIT FUNCTION IN YOUR CODE");
}
;
//Settings part
//Some more code.
}
And a way I'll use it
//Das modell
var JobberCRUD = new CRUD_Grid_model();
JobberCRUD.GridElement = $('#jobbers_dg');
JobberCRUD.editModeFlagElement = $('#jobbers_tb_edit');
JobberCRUD.newRowElement = {jobb_name:'Enter new unique name',jobb_status:'Y'};
JobberCRUD.commit = function (){
if (this.endEditing()){
var addrows = this.GridElement.datagrid('getChanges','inserted');
var remrows = this.GridElement.datagrid('getChanges','deleted');
var updrows = this.GridElement.datagrid('getChanges','updated');
console.log(addrows);
console.log(remrows);
console.log(updrows);
//Send changes?
alert("Got total of " +addrows.length + remrows.length + updrows.length + " rows changed.");
//Commit changes at local level
this.GridElement.datagrid('acceptChanges');
}
};
And, what I'd like to do, is smoething like this
I want a parent.commit function to allow me to do this in child
JobberCRUD.commit = function (apdrows,updrows,remrows){
//Send changes?
alert("Got total of " +addrows.length + remrows.length + updrows.length + " rows changed.");
};
So, I have no ideas what shoudl I do to achieve that. Please advice me with some tags, what it is at least :)
Thanks in advance.
There is not exactly what you need in JavaScript, but I would tend to use this pattern :
function CRUD_Grid_model() {
...
this.onCommit = null;
this.commit = function (){
if (this.endEditing()){
var addrows = this.GridElement.datagrid('getChanges','inserted');
var remrows = this.GridElement.datagrid('getChanges','deleted');
var updrows = this.GridElement.datagrid('getChanges','updated');
if(this.onCommit != null) this.onCommit(addrows,updrows,remrows);
this.GridElement.datagrid('acceptChanges');
}
}
...
}
var JobberCRUD = new CRUD_Grid_model();
JobberCRUD.onCommit = function(apdrows,updrows,remrows) {
alert("Got total of " +addrows.length + remrows.length + updrows.length + " rows changed.");
};
JobberCRUD.GridElement = ...
Javascript doesn't have a built in notion of interfaces. A javascript object effectively "implements an interface" by having all the needed methods defined, but there's no language "interface" construct
You could use "extends" like so:
Object.prototype.extends = function(clazz) {
var o = new clazz();
for (var f in o) {
if(f === "extends") {
continue;
}
this[f] = o[f];
}
this.super = o;
}
Now could type something like this:
var JobberCRUD = function() {
this.extends(CRUD_Grid_model);
var privateFunction = function() {
//...
}
// You probably don't want to do that,
// but you could override
this.commit = function() {
//...
}
// ...
}
Hope, that helps.
Edit: forgot, that you may call super.commit() then.
You can not have something similar like C# or Java interface or even class with Javascript.
Javascript is just a dynamic scripting language.
I'm getting the following error when attempting to get an enumerator for a collection of lists: "Uncaught Error: The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested."
It happens on the line var listEnumerator = lists.getEnumerator(); it seems to me that there is an issue in my attempt to load lists into the client object with context.load(lists);
Here's the portion of my code that's causing the problem. I've marked the place just before the error is thrown.
//____________________________Required function for accessing the host site's info.___________________________________
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
//____________________________Begin checking for list_________________________
function checkForList(listToFind, typeOfListToCreateIfTheListIsMissing)
{
var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var hostcontext = new SP.AppContextSite(context, hostUrl);
var hostweb = hostcontext.get_web();
var lists = hostweb.get_lists();
context.load(lists);
context.executeQueryAsync(checkIfListExistsUsingEnumerator(listToFind, lists, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
}
//Failed to get lists for some reason
function onQueryFailed(sender, args) {
alert('We failed to retrieve lists. \n' + args.get_message() + '\n' + args.get_stackTrace());
}
//____________________________Does list exist?____________________________
function checkIfListExistsUsingEnumerator(listToFind, lists, hostweb, typeOfList)
{
var listExists = false;
//!!!!!!!!!!!!!!! ERROR HERE !!!!!!!!!!!!!!!!
var listEnumerator = lists.getEnumerator();
var title;
while (listEnumerator.moveNext())
{
title = listEnumerator.get_current().get_title();
if (title == listToFind)
{
listExists = true;
}
}
if (!listExists)
{
alert("It appears that a required list does not already exist. \nClick ok, and we'll automatically create one for you.");
//Create a new list
createList(listToFind, hostweb, typeOfList);
}
else if (listExists)
{
//Do nothing.
}
}
//____________________________If it doesn't, create one on the local site____________________________
function createList(nameOfNewList, hostweb, typeOfList) {
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(nameOfNewList);
if (typeOfList === "events")
{
listCreationInfo.set_templateType(SP.ListTemplateType.events);
}
else if (typeOfList === "contacts")
{
listCreationInfo.set_templateType(SP.ListTemplateType.contacts);
}
var lists = hostweb.get_lists();
var newList = lists.add(listCreationInfo);
context.load(newList);
context.executeQueryAsync(onListCreationSuccess, onListCreationFail);
}
function onListCreationSuccess() {
alert('List created successfully!');
}
function onListCreationFail(sender, args) {
alert('Failed to create the list. ' + args.get_message());
}
I've looked at this question sharepoint javascript collection not initialized error which seems to be fairly similar to mine, but I'm having trouble implementing the solution provided there, making me think my error may be have a different cause.
I've also tried querying for the lists inside of the function that is throwing the error, but that doesn't seem to solve anything.
For a little background, these functions are attempting to read all lists from the app's host site, check to see if a specified list exists, and create a list if no matching list exists. If there's a better way of doing that than what I'm attempting, I'd be open to that too.
Any pointers?
Some things I've tried that don't seem to work:
Changing the Asynchronous query
context.executeQueryAsync(checkIfListExists(listToFind, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
to a Synchronous one.
context.executeQuery(checkIfListExists(listToFind, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
I've figured out an alternate, and shorter way to method of achieving the same goal I was trying to achieve before.
Instead of checking to see if a list does not already exist, I just try to create a list, and the Query fails to create a list if one is already there. (That's good because I don't want to overwrite the list if it is already there.)
I'm not totally sure if there are any undesired side effects of what I'm doing here, but in my tests it produced the desired behavior.
//____________________________Required function for accessing the host site's info.___________________________________
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
//____________________________Create a list if one does not already exist_________________________
function createList(listToCreate, typeOfList)
{
// Create an announcement SharePoint list with the name that the user specifies.
var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var hostContext = new SP.AppContextSite(currentContext, hostUrl);
var hostweb = hostContext.get_web();
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(listToCreate);
if (typeOfList === "events")
{
listCreationInfo.set_templateType(SP.ListTemplateType.events);
}
else if (typeOfList === "contacts")
{
listCreationInfo.set_templateType(SP.ListTemplateType.contacts);
}
var lists = hostweb.get_lists();
var newList = lists.add(listCreationInfo);
currentContext.load(newList);
currentContext.executeQueryAsync(onListCreationSuccess, onListCreationFail);
}
function onListCreationSuccess() {
alert("We've created a list since one doesn't exist yet." );
}
function onListCreationFail(sender, args) {
alert("We didn't create the list. Here's why: " + args.get_message());
}
basically so far i have this code trying to make it work crossbrowser. im trying to get an alternative to selectnodes but getting stuck with it only returning one item in the array I make when there meant to be more (as works in IE an currently getting 7) due to erroring after first iterate next. im unsure if im missing something in how im doing this?
try {
var oNodeDefinitions = XMLResponse.selectNodes("//Definitions/Definition");
}
catch (err) {
node = XMLResponse;
var xpe = new XPathEvaluator();
var nsResolver = xpe.createNSResolver(node.ownerDocument == null ? node.documentElement : node.ownerDocument.documentElement);
oNodeDef = xpe.evaluate("//Definitions/Definition", oAJAXRequest.XMLResponse, nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
a = 0;
b = 0;
var nodes = new Array();
while (oNodeDef) {
try {
nodes[a] = oNodeDef;
oNodeDef = oNodeDef.iterateNext();
a = a + 1;
}
catch(err) {
oNodeDef = false;
}
}
}
alert("a");
I've written a Google apps script which first creates and displays a line chart within the UI app and then re-draws the graph based on selected list box values using a Click-button event handler to trigger when the graph "refreshes".
The issue I'm trying to resolve is that when published as a web application when triggering the click event I receive:
Error Encountered: An unexpected error occurred
The code runs perfectly from a spreadsheet (except for some pesky permissions issues where other users are asked to download the panel object; I'll get to that later), and I'm really stuck as to why it won't translate.
Here's the code for what it's worth:
function doGet(){
var app = UiApp.createApplication().setWidth(800).setHeight(650).setTitle('FLEET Chart');
var e = 'undefined';
lb(app);
return click(e, app);
}
function lb(app){
var lb = app.createListBox(true).setId('myId').setName('myLbName');// add items to ListBox
var lb2 = app.createListBox(true).setId('myId2').setName('myLbName2');
var lb3 = app.createListBox(true).setId('myId3').setName('myLbName3');
var bttn = app.createButton('Refresh').setId('myBttn');
lb3.addItem('2011').addItem('2012');
lb2.addItem('January')
.addItem('February')
.addItem('March')
.addItem('April')
.addItem('May')
.addItem('June')
.addItem('July')
.addItem('August')
.addItem('September')
.addItem('October')
.addItem('November')
.addItem('December');
lb.addItem('Drug1')
.addItem('Drug2')
.addItem('Drug3')
.addItem('Drug4');
var mypanel = app.createHorizontalPanel().setVisible(true);
mypanel.add(lb).add(lb2).add(lb3).add(bttn);
app.add(mypanel);
var handler = app.createServerChangeHandler('click').addCallbackElement(mypanel);
handler.addCallbackElement(bttn);
bttn.addClickHandler(handler);
}
function click(e, app) {
var valuelb = new Array('Drug1','Drug2','Drug3','Drug4');
var valuelb2 = new Array ('January','February','March','April','May','June','July','August','September','October','November','December');
var valuelb3 = new Array('2011','2012');
var SS = SpreadsheetApp.openById('0Am8DRqAEaxH7dF9NWFJLSTdWZGRxeEFfMkFjNlFCT2c');
var sheeteff = SS.getSheetByName('Efficiency');
var data = sheeteff.getDataRange().getValues();
if (String(e) != 'undefined') {
app.setWidth(800).setHeight(650).setTitle('FLEET Chart');
var valuelb = String(e.parameter.myLbName);
if (valuelb.indexOf(',') != -1) {
var valuelb = e.parameter.myLbName.split(',');
}
var valuelb2 = String(e.parameter.myLbName2);
if (valuelb2.indexOf(',') != -1) {
var valuelb2 = e.parameter.myLbName2.split(',');
}
var valuelb3 = String(e.parameter.myLbName3);
if (valuelb3.indexOf(',') != -1) {
var valuelb3 = e.parameter.myLbName3.split(',');
}
SS.getSheetByName('Sheet2').getRange(1,1).setValue(String(valuelb2) + ' ' + valuelb.indexOf(','));//for unformation purposes
lb(app);
}else{
SS.getSheetByName('Sheet2').getRange(1,1).setValue(String(e));//for information purposes
}
var usedata = ArrayLib.filterByText(ArrayLib.filterByText(ArrayLib.filterByText(data, 3, valuelb), 1, valuelb2), 0, valuelb3);
//Build data table
var dataTable = Charts.newDataTable();
//Add Column types
dataTable.addColumn(Charts.ColumnType.DATE, data[0][2]);
dataTable.addColumn(Charts.ColumnType.NUMBER, data[0][9]);
dataTable.addColumn(Charts.ColumnType.NUMBER, data[0][8]);
//Add rows
for(var j=0; j<usedata.length; j++){
dataTable.setValue(j, 0, usedata[j][2]);
dataTable.setValue(j, 1, usedata[j][9]);
dataTable.setValue(j, 2, usedata[j][8]);
}
//Create and build chart
var chart = Charts.newLineChart()
.setDataTable(dataTable)
.setTitle('Efficiency over Time \nConfiguration: [' + valuelb + ']\n' + 'Month: [' + valuelb2 + ']\n' + 'Year: [' + valuelb3 + ']')
.setXAxisTitle('Time')
.setYAxisTitle('Percentage')
.setDimensions(750, 600)
.setPointStyle(Charts.PointStyle.MEDIUM)
.build();
app.add(chart);
return app;
}
I've not gone through your entire code but definitely see this wrong - you have set doGet as the function to be called on a handler. No problems with that except you try to call UiApp.createApplication() for the second time which isn't allowed.
I suggest you change the handler to call another function (lb, maybe) instead of doGet.
I also have "Unexpected Errors" in my code. To fix them, I wrote a simple library which helps to find problems in server handlers. Here is an example demonstrating how to use the library. The example source code is here. To add the library to a script is necessary to use the Mr6TKHuVEJGjYr-NnLUNbEkFO7CoOZA03 project key in the Resources->Manage Libraries dialog. The library uses the ScriptProperties Service to store own internal variables.
I am trying to make my first JS-based adobe air app.
But I've stuck at a point.
Here's the code which is causing the error
var RunUrl = 'http://www.lilpirate.net';
var firstRunUrl = 'http://www.netbloo.com';
var snxApp = air.EncryptedLocalStore.getItem( 'snxApp' );
var semail = snxApp.readUTFBytes( snxApp.bytesAvailable );
if( semail!='786') {
data = new air.ByteArray();
data.writeUTFBytes( '786' );
air.EncryptedLocalStore.setItem( 'snxApp', data );
var snxUrlToLoad = firstRunUrl;
}
else
var snxUrlToLoad = RunUrl;
When compiling it from adl, it throws error -
TypeError: Result of expression 'snxApp' [null] is not an object.
Help!
You are accessing properties (bytesAvailable and readUTFBytes) of snxApp without checking to make sure it exists first. If you haven't used setItem to store anything with that name yet, it will be null.
Here's an example of how it would look with an if statement:
var snxApp = ...;
var semail;
if (snxApp !== null) {
semail = snxApp.readUTFBytes( snxApp.bytesAvailable );
}
...