Autodesk Forge How to get dbid from name - javascript

I have an extension which loads a docking panel with a text field and a button. The functionality of this button would be to display the DB-ID of the item name given in the text field.
Something like:
Rubber = 2130
where Rubber is the input and 2130(db-id) will be the output
How can I achieve this?
Thanks in advance.

Would suggest using .search() method, which is a supported way:
viewer.search('Rubber', function(dbIds){
// here the dbIds is a list of dbIds, you can handle it
callback(dbIds); // handle the results async
}, function(error){
// handle errors here...
}, ['name'] /* this array indicates the filter: search only on 'Name'*/
)
And look here on how to improve performance on search.

There is no such API available currently, but a workaround can be used in this case. It's shown as the following:
//-- For the element type or element category like "Floor [" or "Floor"
var it = viewer.model.getData().instanceTree;
var strIdx = it.nodeAccess.strings.indexOf( "Floor [" );
// var strIdx = it.nodeAccess.strings.indexOf( "Floor" );
var nameIdx = it.nodeAccess.names.indexOf( strIdx );
for( var key in it.nodeAccess.dbIdToIndex ) {
if( it.nodeAccess.dbIdToIndex[key] === nameIdx ) console.log( key )
}
//-- For element name like "Floor[766598]":
var it = viewer.model.getData().instanceTree;
var eidIndex = it.nodeAccess.nameSuffixes.indexOf( 766598 );
for( let key in it.nodeAccess.dbIdToIndex ) {
if( it.nodeAccess.dbIdToIndex[key] === eidIndex ) console.log( key )
}
P.S. Since this is just a workaround, not the formal solution. You would have to use it at your own risk.

If you want to avoid using the search() method, you could also create your own Object that maps the name to ID's. This is a temporary workaround until Autodesk implements its own method.
var instanceTree = viewer.model.getData().instanceTree; // Get model tree
var allDbIds = Object.keys(instanceTree.nodeAccess.names); //get array of all ID's
var forgeNameMap = {} //Empty array for mapping names
allDbIds.map(function(id) {
forgeNameMap[instanceTree.getNodeName(id)] = id
})
let rubberID = forgeNameMap["Rubber"]

Related

Stringify a key value pair in Javascript and session storage

I have code as follows:
var employee = {};
employee["fullname"] = document.userForm.fullname.value;
employee["license"] = document.userForm.license.value;
employee["address"] = document.userForm.address.value;
employee["dob"] = document.userForm.dob.value;
employee["city"] = document.userForm.city.value;
employee["state"] = document.userForm.state.value;
employee["zip"] = document.userForm.zip.value;
employee["sex"] = document.userForm.sex.value;
sessionStorage.setItem("session", JSON.stringify({"employees": [employee]}));
Is it correct to store it this way? Also if this is correct , how do I retrieve the information using getItem?
retrieve it with :
var mySessionData = sessionStorage.getItem("session");
var mySessionDataParsed = JSON.parse( mySessionData );
edit
Is it correct to store it this way
//sessionStorage.setItem("session", JSON.stringify({"employees": [employee]}));
sessionStorage.setItem("session", JSON.stringify( employee ) );
// this way is suffisant !
// but if you prefer an array you can go with your way too !
You can also use dot and/or bracket notation.
sessionStorage["session"] = JSON.stringify({"employees": [employee]});
// or
sessionStorage.session = JSON.stringify({"employees": [employee]});
and the same goes for the right hand side of an assignment.
data = sessionStorage["session"];
// or
data = sessionStorage.session;
No need to invoke the get and set item methods as you just add needless overhead.

Null Values in array of objects

I am creating objects when textbox having some values (using ng-blur and textbox.value!==undefined) and then putting these objects in an array (all working fine here).
When I click on checkbox (checkbox model bind with textbox ng-required) I need to delete that particular object having that textbox value.
I am using:
arr.splice(index,1);
to remove that particular object from array (by matching it's name like "monthly" or "quarterly" etc.), but it is creating null at that particular position.
for e.g. [object,object,object]
[
{name:"monthly",
amount:1000 },
{name:"quarterly",
amount:1200 },
{name:"yearly",
amount:1300 }
]
after removing all element it shows [] and when I add another new object it displays [3:object] and it's content as [null,null,null,object];
or
if I remove middle object say name:"quarterly", it shows [object,object] but after adding a new object it display array as [object,object,null,object] with length of array as 4.
Why is there null and how can I remove that from array. (don't want to iterate again to check null).
It is difficult to say why your code creates the null values without have a look to it.
But I can say you that it is not the expected behaviour.
You can see this example to get some inspiration:
var data = [
{name:"monthly",
amount:1000 },
{name:"quarterly",
amount:1200 },
{name:"yearly",
amount:1300 }
];
var newObjectToBeAdded = { name: "daily", amount:"100" }
function showObjects()
{
document.body.innerHTML += data + '<hr>';
}
function deleteObjectByName( objectName )
{
for( var i = 0; i < data.length; i++ )
{
if( data[ i ].name == objectName )
{
data.splice(i, 1);
}
}
}
function addObjectToData( newObject )
{
data.push( newObject );
}
showObjects();
deleteObjectByName( "quarterly" );
showObjects();
addObjectToData( newObjectToBeAdded );
showObjects();
Just to throw a guess out, maybe you are accidentally duplicating the array. Maybe in some point of your code you are doing something like this:
var new_array = original_array.splice( index );
Or creating the new array in the loop you use to find the target object, or using some kind of intermediate array, etc.
Hope it helps!
var arrayWithoutNulls = myArray.filter(function(val) {
if (val) {
return val;
}
});

Birt: access content of dataset from beforeFactory

Im trying (desperately) to access the content of a dataset by script in the beforeFactory.
The task at hand is to create design elements from a linked library and place them in a certain cell of a grid. Everything works fine except for the "place them in a certain cell of a grid"-part.
The information about which element is to be created and where it is to be placed is available in a dataset (dsDesignInformation), which contains three columns: targetRow, targetColumn, targetContent. targetContent contains a string, which is used to find an element in the library.
For example: There is a grid placed on the body (grdMasterGrid), with two rows and two columns. If the dsDesignInformation would contain a row like (1,1,"testObjectName"), I want to create the element "testObject" from a linked library and place it in the intersection of row 1 and column 1 of my grdMasterGrid.
The code for creating and placing the element:
importPackage(org.eclipse.birt.report.model.api);
var myLibraryHandle = reportContext.getDesignHandle().getLibrary("myLibraryName");
var myElementFactory = reportContext.getDesignHandle().getElementFactory();
// should be the objectname as defined in the dsDesignInformation
var myTargetElementHandle = myLibraryHandle.findElement("testObjectName");
var myCreatedElementHandle = myElementFactory.newElementFrom(myTargetElementHandle , "someUniqueElementName");
var myMasterGridHandle = reportContext.getDesignHandle().findElement("grdMasterGrid");
// should be target coordinates as defined in dsDesignInformation
var myTargetCellHandle= myMasterGridHandle.getCell(1,1);
myTargeCellHandle.getContent().add(myCreatedElementHandle);
This works like a charm when used with hard coded target-information and placed in the beforeFactory of the report design.
I do however need to access the contents of dsDesignInformation and pass them on to the script above. So far (4 days in) I had zero (as in null) success.
I would be glad for any help or ideas on the topic.
Regards,
maggutz
It is possible to do this, but with some severe restrictions.
The main restriction is: You cannot use your DataSource and your DataSet directly.
Instead, you'll have to copy them and work with the copy.
Don't ask my why this is, because I don't know. But I learned it the hard way during hours and days of trying...
The next restriction is: You cannot access report parameter values, unfortunately. This is not a problem if your query works without parameters.
Otherwise, you'll have to find a way to access the parameter value anyhow. Depending on how your report is integrated into the app, you could try writing the value into the appContext before calling BIRT, for example.
Here is a fragment of working code (in the beforeFactory event) to show you how to workaround this limitation:
importPackage( Packages.org.eclipse.birt.report.model.api );
importPackage(Packages.org.eclipse.birt.data.engine.api);
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.data.engine.api.querydefn);
importPackage(Packages.org.eclipse.birt.data.engine.core);
importPackage( Packages.org.eclipse.birt.report.model.api );
var myconfig = reportContext.getReportRunnable().getReportEngine().getConfig();
var de = DataEngine.newDataEngine( myconfig, null );
var dsrc = reportContext.getDesignHandle().findDataSource("lisa");
// This is the existing data source.
var odaDataSource = new OdaDataSourceDesign( "Test Data Source" );
// We create a new DataSource which is only to be used in this event
// Now we copy the relevant properties from the existing DataSource to the new one.
var dbUrl = dsrc.getProperty("odaURL").toString();
var dbUsr = dsrc.getProperty("odaUser").toString();
var dbPwd = dsrc.getProperty("odaPassword").toString();
var dbDrv = dsrc.getProperty("odaDriverClass").toString();
odaDataSource.setExtensionID( "org.eclipse.birt.report.data.oda.jdbc" );
odaDataSource.addPublicProperty( "odaURL", dbUrl );
odaDataSource.addPublicProperty( "odaDriverClass", dbDrv);
odaDataSource.addPublicProperty( "odaUser", dbUsr );
odaDataSource.addPublicProperty( "odaPassword", dbPwd );
// log.info("odaURL=" + dbUrl); // Only if you have a logging framework at hand
// Now create a new DataSet and set its query etc.
// I suppose that it is possible to copy the properties from an existing DataSet instead.
// However, I didn't try that.
var odaDataSet = new OdaDataSetDesign( "Test Data Set" );
odaDataSet.setDataSource( odaDataSource.getName() );
odaDataSet.setExtensionID( "org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" );
// This is the SQL query (in my application).
// You'll have to modify this as needed.
odaDataSet.setQueryText( " select STEDA.TEDA_ID, STBST.LANGTEXT" +
" from STEDA, STBST" +
" where STEDA.ZUSATZ_1 = 'MATRIX'" +
" and STBST.TBST_ID = STEDA.TEDA_ID");
// Tell the DataEngine about the new objects.
de.defineDataSource( odaDataSource );
de.defineDataSet( odaDataSet );
// Now execute the query:
// This seems overly complicated, but hey: it works.
var queryDefinition = new QueryDefinition( );
queryDefinition.setDataSetName( odaDataSet.getName() );
queryDefinition.setAutoBinding(true);
var pq = de.prepare( queryDefinition );
var qr = pq.execute( null );
rowcount=0;
var elementFactory = reportContext.getDesignHandle().getElementFactory()
var ri = qr.getResultIterator( );
// Our application is using the query to generate a layout structure
// into an (already existing) placeholder element "Layout MATRIX".
var containerGrid = reportContext.getDesignHandle().findElement("Layout MATRIX");
// Iterate through the query results
while ( ri.next( ) )
{
// get the actual values of the query output columns
var tedaId = ri.getString("TEDA_ID");
var langtext = ri.getString("LANGTEXT");
// log.info("langtext: " + langtext);
rowcount++;
// Do something with the current result row.
... myModifyLayout(containerGrid, tedaId, langtext); ...
}
// Cleanup
ri.close( );
qr.close( );
de.shutdown( );
// You may want to save the modified design file while developing.
// That way you can check the mresults in the Report Designer.
if (false) {
reportContext.getDesignHandle().saveAs("c:/temp/modified.rptdesign");
}

jQuery Join Object Values

I am trying to join the values of an object/associative array to make changes to my code easier but I can't figure out how to properly join them. Here is my code:
$( document ).on( "click", ".taskstatus a", function ( event ) {
event.preventDefault();
classes = {
'OPEN': 'state_open',
'COMPLETED': 'state_completed',
'SKIPPED': 'state_skipped',
'REJECTED': 'state_rejected'
};
joinedClasses = classes.map(function(value, key){ return key; }).join(' ');
state = $(this).data('state');
taskID = $(this).closest('.task').attr('id').replace( 'task_', '' );
// Update checkbox icon
$(this).closest('.taskwrap').find('.taskcheckbox').data( 'icon', $(this).data('icon') );
// Update task class
alert( joinedClasses );
$(this).closest('.task').removeClass( joinedClasses ).addClass( classes[state] );
});
This code breaks at the map function since it doesn't see it as an array, whats the best way to accomplish joining the values of class so that they look like this: "state_open state_completed state_skipped state_rejected"?
You can use jQuery.map function. It is more forgiving and therefore allows usage on an associative array (like yours) as well as a traditional array:
joinedClasses = $.map(classes, function(e){
return e;
});
result:
["state_open", "state_completed", "state_skipped", "state_rejected"]
live example: http://jsfiddle.net/MK4f7/
this can then be joined using a space in the same way as your original:
joinedClasses = $.map(classes, function(e){
return e;
}).join(' ');
Since it's not an array you can use map. You need to use a for loop like below:
var classes = {
'OPEN': 'state_open',
'COMPLETED': 'state_completed',
'SKIPPED': 'state_skipped',
'REJECTED': 'state_rejected'
};
// Create a tmp array for the join
var joined = [];
// Loop over the object Literal.
// the var key is now the prop in the object.
for (var key in classes) {
var val = classes[key]; // gets the value by looking for the key in the object
joined.push(val);
}
// Join the array with a space.
joined = joined.join(' ');
Working fiddle
EDIT: accepted answer is better if you want to do it with jQuery, cheers.
If you can load linq.js, try this code:
joinedClasses = Enumerable.From(classes).Select("$.Value").ToArray().join(' ');

HTML table data to javascript array

I have a html table to show images displayed on my site in a carousel. The images have a position in which they are displayed and this is shown in the table.
One of the features of this table is that it uses the jQuery .sortable() function. If an image is moved to the top of the table, the position of that image is changed to 0 and the subsequent positions are altered.
This is all working fine and I am able to capture the position in a variable.
However, what I now need to do is jQuery POST the data in the table, so I can update the fields in my database with the new positions any any other information that has been updated.
Ideally I need to be able to post an javascript associative array with the ID of the image as the key, and then the image information such as position and location in the sub array.
if it where php I imagine it would look something like this.
Array
(
[45] => Array
(
[name] => Image 45
[location] => img/Banner-45.jpg
[url] => http://www.exampleurl2.com
[position] => 0
)
[56] => Array
(
[name] => Image 56
[location] => img/Image-56.jpg
[url] => http://www.exampleurl2.com
[position] => 1
)
)
which I could loop through and update the values in the table.
All my attempts to create an array with this similar format in javascript/jquery have failed so far.
I have this loop which captures the details in jQuery
$("#banners tbody tr").each(function () {
var id = $('td:first', $(this)).text();
var name = $('td:nth(1)', $(this)).text();
var pos = $('td:nth(2)', $(this)).text();
var url = $('td:nth(3)', $(this)).text();
var loc = $('td:nth(5)', $(this)).text();
});
I understand that this is not the most efficient method of capturing the data from the tables but I am relatively new to jQuery.
Now I need to insert these into some form of associative array with the ID as the key within the loop.
Any pointers in the right direction or a more effective method would be greatly appreciated.
You can use jquery map function to traverse all <tr>'s from the table and create data for rows, then traverse all <td>'s inside the current <tr> for the column data :
var data = [];
var headers = [];
var tb = $('table.table');
var thead = tb.find('thead');
var tbody = tb.find('tbody');
thead.find('th').map(function(i,el){
var $el = $(el);
headers.push($el.attr('class'));
});
tbody.find('tr').map(function(i,el){
var $el = $(el);
var row = {};
$el.find('td').map(function(i,el){
var col = $(el).text();
row[headers[i]] = col;
});
data.push(row);
});
sample jsfiddle : http://jsfiddle.net/v6ZLj/1/
There are no associate arrays in JavaScript so to speak. In JavaScript arrays are one dimensional, you retrieve items based on their index within the array. You are talking about objects or object literals. I've coded an example and example structure for you below.
var saveObj = {}; //Setup a blank object for the data;
$("#banners tbody tr").each(function () {
var id = $('td:first', $(this)).text();
saveObj[id] = {
name : $('td:nth(1)', $(this)).text(),
pos : $('td:nth(2)', $(this)).text(),
url : $('td:nth(3)', $(this)).text(),
loc : $('td:nth(5)', $(this)).text()
};
});
This sets up a blank object literal first called saveObj. This is your blank canvas so to speak. Then within your loop you are grabbing the id as normal. This will be your key within the object and the value for the key will be another object literal which we create dynamically within the loop. using the same keys as your variables (name, pos, url, loc) with their data values in the same way you are grabbing them now. Your structure will be like this
var saveObj = {
"12" : {
name : "YourName",
pos : "YourPos",
url : "YourUrl",
loc : "YourLoc"
},
"16" : {
name : "YourName2",
pos : "YourPos2",
url : "YourUrl2",
loc : "YourLoc2"
}
};

Categories