React - Rending JSON as UI objects and allowing any user changes to these UI objects to update the JSON - json

We have an internal tooling system that uses JSON to specify various actions, tasks etc. I'm making a single page web application to visualise this information. The web application contains a text area for editing/pasting JSON and another area which renders the JSON into UI elements.
So I want to take JSON from the text area and visualize it. But also, I want the user to be able to interact with this render visualization, making changes/configuring options and have it update the JSON immediately. I guess one could call that two-way binding.
While going from JSON -> HTML DOM elements is easy, I'm not sure how to do the reverse and go DOM -> JSON. Let's say we have some JSON
{"task1" : {
"canFail" : true,
"autoRestart" : false,
"connectionPropertys" : {
... }
}
}
I would visualize task1 as some UI element with check boxes for canFail and autoRestart. I want the user to be able to both
edit the JSON "canFail" value to 'true' or 'false' and have that
immediately render (this is easy - just re-render the entire JSON)
check or uncheck the canFail checkbox and have the JSON be
automatically updated (hard part - where I'm stuck)
In React we pass state/properties down the the children, so the component rending the checkbox(es) would only know about canFail or autoRestart... it might not know about "task1". If the checkbox is changed, sure I can have some handler function fire, but it doesn't actually know what key/value in the JSON this corresponds to (e.g. it knows nothing of task1 and there could be multiple task1s).
Interested to know what a good approach would be here to tackle this.
Thanks :)

Related

Check if Model has any default hidden elements in Forge's 3D Viewer

Some background:
I'm using Forge to visualize IFC models. Some of my uploaded models have IfcOpeningElements which seems to be hidden in Forge by default, at least when setting ghosting to false via viewer.setGhosting(false). I'm also having functionality to hide normal elements in the viewer (viewer.hide(dbIds, model)), and to show/hide all elements (model.setAllVisibility(show)).
The problem I'm having is that I want to be able to show/hide the IfcOpeningElements regardless of showing and hiding "normal" elements.
The approach I tried, which is not working very well is to call model.visibilityManager.getHiddenNodes(). The problem with this approach is that, even for models with IfcOpeningElements, getHiddenNodes only returns a non-empty array after ~15 seconds (probably varies with the size of the model). In the meantime, if the user does anything that makes the app call model.setAllVisibility(true), I'm no longer able to detect the original hidden IfcOpeningElements.
Furthermore, when calling getHiddenNodes after an arbitrary waiting period after the model has loaded, I'm not sure if it returns an empty array because the model is not "ready" to detect hidden elements from IfcOpeningElements or if the model simply does not have any IfcOpeningElements.
So, Is there any good way to detect if a model has any "default" hidden elements without having to wait long after the model is loaded? Or perhaps there is a way to call change the visibility of the entire model without changing the visibility of the IfcOpeningElements?
I'm aware of the possibility to listen to the HIDE_EVENT event, but since I'm not sure if it will fire at all (since I'm not sure if the model has any IfcOpeningElements), I cannot block the application from calling model.setAllVisibility(true) which in turn would make getHiddenNodes() return an empty array even if there was hidden elements to begin with.
How about just skipping loading IfcOpeningElements' geometries? To do so, pass skipHiddenFragments: true to the 3rd argument of Viewer3D#loadDocumentNode
viewer.loadDocumentNode(
doc,
viewable,
{
skipHiddenFragments: true
}
);
This approach will skip loading the IfcOpeningElements' meshes, but you can still see their properties while selecting IfcOpeningElements on the model structure panel. On the other hand, you cannot access their bounding boxes and geometries with this approach.
Regarding how to check default hidden elements, try to call this code after all geometries are loaded. The hiddenDbIds are elements hidden by default.
let model = viewer.getAllModels()[0]; //!<< Check the first model just for demo
let fragList = model.getFragmentList();
let hiddenDbIds = Object.keys( fragList.vizflags ).filter(fragId => !fragList.isFragVisible( fragId )).map(fragId => fragList.getDbIds( fragId ) );
// hiddenDbIds.forEach(dbId => viewer.getProperties(dbId, console.log))
Note. The visible flag will also be changed after changing the objects' visibility. So, ensure that run the above before changing the visibilities.

Using JSON to store template driven form data in Angular

I need to use JSON to store the form data, but I'm not sure how to go about it. I know I need to store all of the data that is gathered from text fields and radio buttons and then I need to make a form that displays the data. Can anyone point me to good resources for this? Or know how I can do this? I also need to know how I can access the data for another page since this is an application with two pages. One is for gathering data and the other is for displaying.
So basically to store form datas to JSON is simply create a JSON object and assign the form value to specified property inside that object.
my method is simple like this, on submit i add new object
let newValue = {
inputValue : this.form.value.input,
selectValue : this.form.value.select,
}
thats just for an example, assignin form value to the property of our new object. then to push the data to api simply like this
pushToAPIFunc(newValue);
and the result will be like this
{
"newValue" :{
"inputValue" : "inputValue",
"selectValue" : "selectValue"
}
}
to display that data, for example u have an edit page, u can use patchValue() of that JSON to your form, or assigning that data manually to each formControlName

Polymer two-way data binding and Facebook callback

I am very new to JavaScript and Polymer. I do like the PWA concept but now hit some roadblocks.
I tried to use polymerfire <firebase-auth> and was able to do google provider logins. But got blocked as I don't know how to do Facebook provider login and didn't find anywhere on how to use the tag as I wish to provide Facebook login too in JavaScript. If someone guides me to a source that works I will then not need part 2 of the question.
So, I tried facebook login via Graph API FB.login(). FB.login() has callback and I was not able to extract the response.name, public_profile and set it to Polymer attribute say {{user}} like
var userName = response.name; and then this.user = {displayName : userName};
I noticed that as soon as I exit FB.login() callback on successful login, I lose the changes done in assignment in callback to 'this.user ' object.
My question is - I am not able to make two way binding work in polymer. How can I change the object in child element and then it propagates to all the pages / polymer elements?
How can I change the object in child element and then it propagates to all the pages / polymer elements?
Well really that depends on how you set up all the pages. If you're in the parent, you can pass functions, variables, and objects to the child element by passing it in the component.
<ChildElement details={{_details}}/> // If you want to pass a details object to the child
<ChildElement sqft={{square(size)}}/> // This will call the square function inside your ChildElement and pass in the parameter size
Use the latter to call a function in your child and that function will have access to all the elements within that scope.
If you're in the child and you want to change something in the parent, you can do a callback with this.fire(someFunction()), and then create a function in your parent that with the same name. It's not too bad when you're just passing from parent to child or vice versa but if you're passing it everywhere, then you might want to look into some sort of state management. Passing things from one place to everywhere else will get ugly real fast.

How to write Javascript code for model browser while using autodesk-forge-viewer API

I am trying to replicate a part of demo shown here using autodesk-forge-viewer api. Particularly, I am not able to find code snippet around how can I do navigation for a particular area of 3D model. For example, if render 3D model is house, I require that If a click on "Bed Room" which is a link somewhere in browser, 3D rendered model should show me that "Bed Room". In sample app shown, they are providing the same as a feature of "Model Browser".
Could anyone please help me with that?
You first need to know the dbId's of the nodes you are interested in, most viewer API methods take dbIds as input. You get those either by listening to selection events, see that post, or by parsing the instance tree and checking the properties of the nodes to see if those are the ones you looking for.
You can then use methods such as viewer.fitToView([dbIds]), viewer.hide([dbIds]), viewer.show([dbIds]) ... Here is another article that might be useful: Hidding completely viewer nodes (no ghosting).
Hope that helps.

Retrieving all address information along Google Maps route

I am developing an Windows Forms application using VB.NET that offers the user to lookup addresses on Google Maps through a Web Browser. I can also successfully show the directions between two points to the user, as well as allow the user to drag the route as he/she pleases. My question now is - is it possible for me to get the lattitude/longitude information of the route, i.e. the overview_polyline array of encoded lattitude/longitude points and save it to e.g. a text file on my computer? Or is it possible to get a list of all the addresses located both sides of the route over the entire length of the route, and then save the data to a file on my computer? I'm using HTML files to access and display the Google Maps data in the Web Browser item.
Thank you
This is actually pretty simple if your just looking for the screen coordinates.
// this probably should be in your form initialization
this.MouseClick += new MouseEventHandler(MouseClickEvent);
void MouseClickEvent(object sender, MouseEventArgs e)
{
// do whatever you need with e.Location
}
if your strictly looking for the point in the browser, you need to consider the functions
browser.PointToClient();
browser.PointToScreen();
So, this method is usable if you know exactly where your form is (easy to get its coords) and where you webbrowser control is (easy to get coords of this as well since it's just a control in your form) and then, as long as you know how many pixels from the left or right, and from the top or bottom the image will be displayed, once you get the global mouse click coords (which is easy) you can predict where it was clicked on the image.
Alternatively, there are some scarier or uglier ways to do it here...
You can use the ObjectForScripting property to embed code to do this in the webbrowser. It's ugly to say the least. MSDN has some documentation on the process here: http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx
Because its really ugly, maybe a better solution is to use AxWebBrowser - it's ugly too but not so scary.
In addition, I found this post of someone wanting to do it on a pdf document, and a MSFT person saying its not possible, but really what he is trying to say is that it isn't built in, even with a pdf document its still possible to predict with high to certain accuracy where it was clicked if you use the first method i described. Here is the post anyway: http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/2c41b74a-d140-4533-9009-9fcb382dcb60
However, it is possible, and there are a few ways to do it, so don't get scared from that last link I gave ya.
Also, this post may help if you want to do it in javascript:
http://www.devx.com/tips/Tip/29285
Basically, you can add an attribute on the image through methods available in the webbrowser control, you can add something like onclick="GetCoords();" so when it is clicked, the JavaScript function will get the coords, and then you can use javascript to place the values in a hidden input field (input type="hidden") which you can add through the webbrowser control, or if there is one already on the page, you can use that. So, once you place the coords using javacript into that input field, you can easily grab the value in that using the webbrowser control, eg:
webbrowser1.document.getElementById("myHiddenInputField").value
That will get the value in that field, which you've set through JavaScript. Also, the "GetCoords()" function i mentioned is called SetValues() in the javascript method link i provided above (in the devx.com site) but I named it GetCoords because it makes more sense and didn't want to confuse you with the actual name they used, you can change this to any name you want of course. Here is the javascript they were using, this only gets the coords into a variable, doesn't put it into a hidden input field, we will need to do that in addition (at the end of the javascript SetValues/GetCoords function).
function SetValues()
{
var s = 'X=' + window.event.clientX + ' Y=' + window.event.clientY ;
document.getElementById('divCoord').innerText = s;
}
These guys are just saving it inside a div element, which is visible to users, but you can make the div invisible if you want to use a div field, there is no advantage or disadvantage in doing that, you would just need to set the visible property to false using javascript or css, but still, it is easier to use a hidden input field so you don't need to mess with any of that.
Let me know how you get along.