How to set source and target in JSPlumb dynamically - json

I am using jsplumb go show pictorial view of all devices connected to switch. I am following below approach, please comment in case if it's not as per standard.
Creating map of all the devices which are connected in the network, and dynamically create all devices on screen using innerHtml.
Create mapping json which contain which devices are connected to which device.
I now iterate json using javascript and create source and target for all devices on screen.
Problem:
When I iterate through json, source and target is not able to set in the below code.
var result = JSON.parse(devicePaths);
for (var i in result) {
var _source = new String(result[i]["source"]);
var _target = new String(result[i]["target"]);
var _endpoint = new String(result[i]["endpoint"]);
console.log('_source ' + _source); //this gives me proper value
console.log('_target ' + _target); //this gives me proper value
console.log('_endpoint ' + _endpoint);
instance = jsPlumb.getInstance({
PaintStyle : {
lineWidth : 1,
strokeStyle : "#567567",
outlineColor : "black",
outlineWidth : 1
}
});
common = {
anchors : [ "BottomCenter", "BottomCenter" ],
endpoints : [ "Dot", "Blank" ]
}
instance.connect({
source : _source,
target : _target,
detachable : false,
endpoint : _endpoint
}, common);
instance.draggable(_source);
}
});
Same works if I hardcode source and target values as source : rx_1 and target masterSwitch.

Related

Use Data Visualization Extension multiple times

I have two separate extensions visualizing different "datapoints" from different domains (measurements like temperature, humidity, ... and image locations). These extensions should remain separated (and should not know each other).
There is no problem when using the extensions independent of each other. But problems occur, if both extensions are used at the same time (for the same model) in the Forge Viewer.
Both extensions try to get an existing instance of the DataVis-extension and load the extension if it is not available (call to viewer.loadExtension in each custom extension no difference).
The extensions create ViewableData and add viewables to it (sharing a single instance of ViewableData makes no difference).
After adding viewables await viewableData.finish() is called and the addViewables-method of the DataVis-extension is called.
One of the main problems is, that method changeOcclusion changes the occlusion only of the viewables which were added last. The other viewables remain visible at any time.
Probably because the pointMaterial in the DataVis-extension is overwritten any time the addViewables extension is called.
Is there a way to instantiate the extension multiple times, so that it is guaranteed that there are no side-effects when using it from within different custom extensions? Or maybe other mechanisms?
After consulting our engineering team, we submitted an issue report, LMV-6574, for tracking this issue. Please take note of the LMV prefixed id for tracking. We're welcome to ask for updates in the future by sending the issue id to forge (DOT) help (AT) autodesk (DOT) com.
However, we don't want to stop your development, so here is a workaround.
As I mentioned in the above comments area, SpriteViewable's constructor accepts an argument, ViewableStyles, that is used to set up the sprite icon. So, you don't need to call DataVisualization.addViewables(data) twice. Before finishing the ViewableData, you can add viewables with different ViewableStyles without a doubt.
Back to your use case, you want to reuse the DataVisualization extension for different data sources. To do so, I would advise you to store your device (sensor) data separately (e.g. device container). When you need to add/remove devices, just modify the device container, clear viewables, and then add new viewalbe data among your device container.
Here are some code snippets demonstrating this idea:
Example code for initializing:
let sensorStyleDefinitions = {
co2: {
url: "http://localhost:3000/assets-1/images/co2.svg",
color: 0xffffff,
},
temperature: {
url: "http://localhost:3000/assets-1/images/thermometer.svg",
color: 0xffffff,
},
default: {
url: "http://localhost:3000/assets-1/images/circle.svg",
color: 0xffffff,
},
};
// Create model-to-style map from style definitions.
let styleMap = {};
Object.entries(sensorStyleDefinitions).forEach(([type, styleDef]) => {
styleMap[type] = new Autodesk.DataVisualization.Core.ViewableStyle(
Autodesk.DataVisualization.Core.ViewableType.SPRITE,
new THREE.Color(styleDef.color),
styleDef.url
);
});
let devices = [
{
id: "Hall I",
position: {
x: -14.297511041164398,
y: -77.6432056427002,
z: 11.31889820098877,
},
type: "temperature",
sensorTypes: ["temperature"],
},
{
id: "Hall IV",
position: {
x: 60.53697395324707,
y: -74.6432056427002,
z: 11.31889820098877,
},
type: "co2",
sensorTypes: ["co2"],
},
];
const viewableData = new Autodesk.DataVisualization.Core.ViewableData();
viewableData.spriteSize = 16;
// Add viewables
devices.forEach((device, index) => {
const style = styleMap[device.type] || styleMap["default"];
const viewable = new Autodesk.DataVisualization.Core.SpriteViewable(
device.position,
style,
index + 1
);
viewableData.addViewable(viewable);
});
await viewableData.finish();
dataVizExt.addViewables(viewableData);
Example code for adding a device(sensor)
devices.push({
id: "Hall XII",
position: {
x: -15,
y: -70,
z: 50,
},
type: "temperature",
sensorTypes: ["temperature"],
});
// Remove existing sprites
dataVizExt.removeAllViewables();
const viewableData = new Autodesk.DataVisualization.Core.ViewableData();
viewableData.spriteSize = 16;
// re-add viewables
devices.forEach((device, index) => {
const style = styleMap[device.type] || styleMap["default"];
const viewable = new Autodesk.DataVisualization.Core.SpriteViewable(
device.position,
style,
index + 1
);
viewableData.addViewable(viewable);
});
await viewableData.finish();
dataVizExt.addViewables(viewableData);
Example code for removing a device(sensor)
devices = devices.splice(1, 1);
// Remove existing sprites
dataVizExt.removeAllViewables();
const viewableData = new Autodesk.DataVisualization.Core.ViewableData();
viewableData.spriteSize = 16;
// re-add viewables
devices.forEach((device, index) => {
const style = styleMap[device.type] || styleMap["default"];
const viewable = new Autodesk.DataVisualization.Core.SpriteViewable(
device.position,
style,
index + 1
);
viewableData.addViewable(viewable);
});
await viewableData.finish();
dataVizExt.addViewables(viewableData);

Google Slides: newly inserted table not found

I´m wondering what is going on. I have two functions which both are working good when called one after one:
function createTable() {
var slidesPage = SlidesApp.openById('1QWRV4eQzGNNBz4SkR3WPurTL3O60oGYxQpBu63KrUoI').getSlides()[0];
var table = slidesPage.insertTable(7, 4);
}
function changeColumnWidth() {
var slidesPage = SlidesApp.openById('1QWRV4eQzGNNBz4SkR3WPurTL3O60oGYxQpBu63KrUoI').getSlides()[0];
var tableId = slidesPage.getTables()[0].getObjectId();
var requests = [{
updateTableColumnProperties: {
objectId: tableId,
"columnIndices": [ 1, 3],
"tableColumnProperties": {
"columnWidth": {
"magnitude": 80,
"unit": "PT"
}
},
"fields": "columnWidth"
}
}];
var createSlideResponse = Slides.Presentations.batchUpdate({
requests: requests
}, '1QWRV4eQzGNNBz4SkR3WPurTL3O60oGYxQpBu63KrUoI');
}
But trying to combine these two functions like:
function combined() {
createTable();
changeColumnWidth();
}
I´m getting Error:
Invalid requests[0].updateTableColumnProperties: The object (SLIDES_API456304911_0) could not be found.
Wondering if the insertTable method is asynchronous and therefore the created table is not ready?
Thanks for any help.
How about this modification? Please think of this as one of several workarounds. In my workaround, I used saveAndClose() for your situation. Using this, I thought to separate the process of SlidesApp and Slides API.
Modification points :
Save and close the slide using saveAndClose() after the table was inserted.
Return an object ID of inserted table to use at changeColumnWidth().
At changeColumnWidth(), the table is modified by Slides API using the received object ID.
Modified script :
function combined() {
var tableId = createTable(); // Modified
changeColumnWidth(tableId); // Modified
}
function createTable() {
var slide = SlidesApp.openById('1QWRV4eQzGNNBz4SkR3WPurTL3O60oGYxQpBu63KrUoI'); // Modified
var slidesPage = slide.getSlides()[9]; // Modified
var table = slidesPage.insertTable(7, 4);
slide.saveAndClose(); // Added
return table.getObjectId();
}
function changeColumnWidth(tableId) { // Modified
// var slidesPage = SlidesApp.openById('1QWRV4eQzGNNBz4SkR3WPurTL3O60oGYxQpBu63KrUoI').getSlides()[0]; // This line is not used.
// var tableId = slidesPage.getTables()[0].getObjectId(); // This line is not used because slidesPage.getTables().length becomes 0.
var requests = [{
updateTableColumnProperties: {
objectId: tableId,
"columnIndices": [ 1, 3],
"tableColumnProperties": {
"columnWidth": {
"magnitude": 80,
"unit": "PT"
}
},
"fields": "columnWidth"
}
}];
var createSlideResponse = Slides.Presentations.batchUpdate({
requests: requests
}, '1QWRV4eQzGNNBz4SkR3WPurTL3O60oGYxQpBu63KrUoI');
}
Note :
For the slide which is saved and closed by saveAndClose(), when the slide is reopened, the inserted table cannot be retrieved. When the table is tried to be retrieved using getTables() again, the length becomes 0. But at Slides API, the object ID of table can be retrieved. So I thought that the issue might be able to be solved by returning the object ID of table after the table was inserted.
But I couldn't understand about the reason that the values retrieved by getTables() from the reopened Slide become "0" yet. I'm sorry.
Reference :
saveAndClose()
If this workaround was not what you want, I'm sorry.
To achieve your goal - create a table with a specified layout and specific column sizes in one function - you should use the Slides API for the entire task. The Slides API lets you both create and modify the same element in the same batch request, if you provided a unique object ID for it. Otherwise, you have to first create the element, then send the modification request using the objectId found in the response to the first request. This second approach is essentially the behavior you were experiencing when the function calls were done separately.
There are restrictions on user-supplied IDs, naturally:
objectId string: A user-supplied object ID.If you specify an ID, it must be unique among all pages and page elements in the presentation. The ID must start with an alphanumeric character or an underscore (matches regex [a-zA-Z0-9_] ); remaining characters may include those as well as a hyphen or colon (matches regex [a-zA-Z0-9_-:] ). The length of the ID must not be less than 5 or greater than 50.If you don't specify an ID, a unique one is generated.
Given that hyphens are allowed, we can use the Utilites.getUuid() method to help supply our own unique object IDs.
When mixing SlidesApp and Slides, it is very likely that internal Google optimizations (e.g. write-caching) change the operation order. By restricting to a single service for related task operations, we can ensure that the objects we need are available when needed.
This example uses two methods that make Request objects for batchUpdate and ultimately creates a presentation, adds a blank slide, adds a table and modifies it, and then creates another blank slide.
function makeCreateTableRequest_(slideId, rows, columns, shouldSupplyID) {
const tablerq = {
rows: rows,
columns: columns,
elementProperties: {
pageObjectId: slideId,
/** size: {
height: {...},
width: {...}
},
transform: { ... } */
}
};
// If asked to use a custom ID (e.g. also going to modify this table), use a unique one.
if (shouldSupplyID)
tablerq.objectId = ("table" + Utilities.getUuid()).slice(0, 50);
return {createTable: tablerq};
}
function makeModifyTableColumnPropsRequest_(tableId, newWidthDimension, indicesArray) {
const rq = {
objectId: tableId,
fields: "columnWidth" // There are no other fields for this request as of 2018-07
};
if (newWidthDimension && newWidthDimension.magnitude !== undefined && newWidthDimension.unit)
rq.tableColumnProperties = { columnWidth: newWidthDimension };
if (indicesArray && indicesArray.length)
rq.columnIndices = indicesArray;
return {updateTableColumnProperties: rq};
}
function createPresentation_() {
const newPres = { title: "API-created Presentation" };
// Presentations are huge... limit the metadata sent back to us.
const fields = "presentationId,pageSize,title"
+ ",slides(objectId,pageType,pageElements(objectId,size,title,description))"
+ ",masters(objectId,pageType,pageElements(objectId,size,title,description))"
+ ",layouts(objectId,pageType,pageElements(objectId,size,title,description))";
const createdMetadata = Slides.Presentations.create(newPres, {fields: fields});
console.log({message:"Created a Presentation", response: createdMetadata});
return createdMetadata;
}
function addSlide_(pId) {
const response = Slides.Presentations.batchUpdate({ requests: [{ createSlide: {} }] }, pId);
return response.replies[0].createSlide.objectId;
}
function foo() {
const pres = createPresentation_();
const newSlideId = addSlide_(pres.presentationId);
// Get requests to add and to modify tables.
const openingTableRq = makeCreateTableRequest_(pres.slides[0].objectId, 2, 4);
const newTableRq = makeCreateTableRequest_(newSlideId, 7, 4, true);
const changeWidthRq = makeModifyTableColumnPropsRequest_(newTableRq.createTable.objectId, {magnitude: 80, unit: "PT"}, [0]);
// Add and update the desired table, then create a new slide.
var response = Slides.Presentations.batchUpdate({
requests: [
openingTableRq, // will have reply
newTableRq, // will have reply
changeWidthRq, // no reply
{ createSlide: {} } // will have reply
]
}, pres.presentationId);
console.log({message: "Performed updates to the created presentation", response: response});
}

Electron, new BrowserWindow load values

I try load and pass from a json file the x,y position and width, height. Here is my code
const electron = require('electron')
const {app, BrowserWindow} = electron
var fs = require('fs');
var loadsttngs = JSON.parse(fs.readFileSync('settings.json', 'utf8'));
console.log(loadsttngs.width);
let win
function createWindow () {
win = new BrowserWindow({
x: loadsttngs.x,
y: loadsttngs.y,
width: loadsttngs.width,
height: loadsttngs.height,
frame: false})
win.setMenu(null)
win.loadURL(`file://${__dirname}/index.html`)
win.webContents.openDevTools()
// Emitted when the window is closed.
win.on('closed', () => {
//var bounds = win.getBounds();
win = null
})
}
the console.log(loadsttngs.width); return the right value, so there is no problem with reading the file but in the new BrowserWindow does not be used(like using some defaults values). If I write the values directly to new BrowserWindow works fine.
settings.json
{
"x" : "50",
"y" : "50",
"width" : "1200",
"height" : "200",
"maximized": "false"
}
Your x and y values are strings not numbers.
Should be:
"x":50
Maximized is also a string not a Boolean.

JSON parse issue in Titanium

I am working on simple task read the data from url which is in JSON format and display those fields in Table
i written code like as
var Win = Titanium.UI.currentWindow;
//SEARCH BAR
var xhr = Titanium.Network.createHTTPClient();
tableData=[];
Win.open();
xhr.onload = function() {
alert('res'+this.responseData);
var json = this.responseText;
var response = JSON.parse(json);
//-- Mail was sent
alert('respoinse length : '+response.result.length);
tableData=[];
for (i = 0; i < response.result.length; i++) {
sresult = response.result[i];
//alert('City'+ sresult.city);
var row = Ti.UI.createTableViewRow({
rowID: i,
color:'#222',
left:70, top:44,
width:360,
text:sresult.County
});
tableData.push(row);
}
table.setData(tableData);
};
var table = Titanium.UI.createTableView({
top:60,
data:tableData
});
Win.add(table);
//xhr.open('GET', 'https://www.clia.livestockid.ca/CLTS/public/division/CCIA/en/splash_logo.jpg');
xhr.open('GET', 'http://gomashup.com/json.php?fds=geo/usa/zipcode/city/STERLING');
xhr.send();
i run it on Titanium - the first alert showing the JSON data. after that its not getting alert of second one not sure ... why its not moving to next step... please help me on this is there any mistakes in code or else parsing issue.
Thanks
Devendar
The "JSON" returned by the url you gave (http://gomashup.com/json.php?fds=geo/usa/zipcode/city/STERLING) is invalid. (http://jsonlint.com is a useful resource for checking that sort of thing.) It starts with a ( and ends with a ), like this:
({
"result":[
{
"Longitude" : "-071.939375",
"Zipcode" : "01564",
"ZipClass" : "STANDARD",
"County" : "WORCESTER",
"City" : "STERLING",
"State" : "MA",
"Latitude" : "+42.366765"
}
]}
)
(I've omitted a lot from that.)
JSON documents start with either [ or {, and end with the corresponding ] or }.
The above would be valid without the ( at the beginning and ) at the end, so you could always remove them before parsing, but the real answer is to fix the feed.

How do I make an Ext.Panel show a DataView using a JsonStore and XTemplate?

This seems like it should be simple. Here is my data store declaration:
var dataStore = new Ext.data.JsonStore({
autoLoad : true,
url : '#mvclink(' json.getCostReportsJsonData ')#&layout_type=txt',
root : 'data',
id : 'dataStoreId',
fields : ['project', 'cost']
});
The url is actually generated by ColdFusion, which calls the query and converts it to Json format. I think everything works correctly here, because the Json object comes back as:
{"recordcount":1,"columnlist":"project,cost","data":[{"project":"ABC","cost":2250}]}
I have dummy data in there for now, so just one row is returned.
Next, I declare an Ext.Panel with a DataView in it:
var myPanel = new Ext.Panel({
layout : 'fit',
id : 'myPanel',
title : "My Panel",
monitorResize : true,
deferredRender : false,
items : new Ext.DataView({
store : dataStore,
tpl : costReportTemplate
}),
renderTo : Ext.getBody()
});
The template referenced is an XTemplate:
var costReportTemplate = new Ext.XTemplate(
'<tpl for=".">',
'<p><b>{project}</b>: {cost:this.format}</p>',
'</tpl>', {
format : function (v) {
var s = Ext.util.Format.usMoney(v);
return s.substring(0, s.indexOf('.'));
}
});
Upon rendering the page, I can see the panel, but it's completely empty, and I get no errors in Firebug. What am I doing wrong?
I figured it out! I hadn't used a dummy cost value with a decimal point, so the format function wasn't working properly. I wasn't getting any errors, though. I changed it to check if (s.indexOf('.') != -1) and everything is fine now.