GB JavaScript Tips
- 1 Tips
- 1.1 Query Outside of builder
- 1.2 runProgram
- 1.2.1 Examples
- 1.3 context.source.name
- 1.4 Invoke Actions
- 1.4.1 Invoke Actions Code
- 1.4.2 Other Examples
- 1.5 setTimeout() (delay)
- 1.6 Program to run on Start
- 2 Programs
- 2.1 How to command a bool point by clicking on label
- 2.2 How to command point with Prompt popup
- 2.3 Hide a component based on value of another point
- 2.4 Increment Value
- 2.5 How to add a shadow/glow on objects
- 2.6 Change color on smart label based on a numeric value
- 2.7 Change color on smart label based on a boolean value
- 2.8 Component Value (Numeric/Boolean/Reversed)
- 2.9 Hide/Show based on current User
- 2.10 Weather Data
- 2.11 Weather Data (Query)
- 2.12 Override Count
- 2.13 Heat Pump Program (Compressor & Reversing Valve)
- 2.14 Enum Status Color Labels
- 2.15 Button Toggle (using forEach)
- 2.16 Controlling Fan with Enum Point
- 2.17 On/Off Switch (No Action Panel)
- 2.18 Pie Chart with Related Bubbles
- 2.19 Floorplan: Show Equip with lowest Temp
- 2.20 Date & Time on Graphic (with refresh)
- 2.20.1 Scalable Date Time Model
- 2.21 Time Remaining (milliseconds)
- 2.22 Open Related Bubbles (Equip Bubbles)
- 2.23 Point Bubbles
- 2.24 Point Actions Command
- 2.25 Mouse Over/Out - Hide/Show using My Filter
- 2.26 Mouse Over / Mouse Out: Hide & Show object
- 2.27 Auto Overrides from within a Graphic
- 2.28 Reset Translator
- 2.29 Hide Image when Boolean is Off (Must have virtualPointRef on image)
- 2.30 Toggle: Hide/Show
- 2.31 Toggle: Hide/Show (hides other shown layer)
- 2.32 Get Min/Max/Average With Labels
- 2.33 Upload & Download FIN5 Graphics Manually (finBackupRecord/finRestoreRecord)
- 2.34 HeatMap
- 2.35 Show/Hide Based on Enum Value
- 2.36 Displaying Schedule Data on Graphic
- 2.37 Open relative Schedule
- 2.38 Hide Right Menu when loading a graphic
- 3 Property Tags
- 4 Console commands
Tips
Query Outside of builder
The query below allows you to query outside of builder
var c = finGraphics.GetWorldControllerById(document.body.firstElementChild.id)
c.database.queryAll("virtualPoint")runProgram
The function signature is:
runProgram(programName, target, ignoreViewEvents);
programName= Name of program
target= target component to run the task on
ignoreViewEvents= true if you do not want to run any programs attached to the view such as a click.
Examples
This will run the program on every component that it is bound to it. It is executed on worldStart. if this program is a click handler it will run it. (this can run n number of times depending on how many components are found by the programOn)
runProgram("Jasons Program")
This will run the program on the myComponent, if myComponent satisfies the program's programOn filter. (this will run zero or one time)
runProgram("Jasons Program", myComponent);
This will run the program on every component that it is bound to if this program is a click handler it will NOT run it. (this can run n number of times depending on how many components are found by the programOn)
runProgram("Jasons Program", null, true);
This will run the program on the myComponent if myComponent satisfies the program's programOn filter and is NOT attached to a view event such as click. (this will run zero or one time)
runProgram("Jasons Program", myComponent, true);This allows you to see the name of the event that fired. You can see On/Off Switch section to see this in use.
Invoke Actions
This program runs on "button and foo" which are marker tags on a button. We set 'this' (which will is the button with all it's properties) to invoke the program on a mouse click.
We also created a variable called 'point'. It will be the point that the button is connected to (virtualPointRef). id==$virtualPointRef - this will go through all the objects in the graphic whose id matched the virtualPointRef on the button.
(The commented-out line is an example of how do the same thing without using the options on the right in the screenshot below. possibly helpful if you decide to create an event on the button rather than to use a program.)
Every point has two ids:
id: this is the id within the graphicpointId: this is the points actual id that can be found in the FIN Stack db.
So in the eval/invoke statement, we use the pointId since it will look through the FS db. We also added another tag on the button called invokeValue that is a number tag. In this case it is just a static value that will always change the value of the connected point to it's value when the button is clicked. You could do the same thing for the duration by adding an appropriate tag on each button. (for ex ample for duration it would look like this: duration:'+this.durationValue+'hr. Which then you would add a number tag on the button called durationValue.)
Invoke Actions Code
//var curPointId = query("id == "+this.virtualPointRef);
finstack.eval('invoke('+point.pointId+',"Manual Set", {self:'+point.pointId+',val:'+this.invokeValue+',duration:1hr})');Other Examples
finstack.eval(sprintf('invoke($1, "Manual Set", {self:$1, val:$2, duration:$2hr})', myPoint.pointId, valueLabel.value)); //takes into account user permissions
finstack.eval('readById('+myPoint.pointId+').pointOverride(14, 1min)'); //doesn't take into account user permissions, so it won't work based on user types
finstack.eval(sprintf('readById($1).pointOverride($2, 1min)', myPoint.pointId, valueLabel.value));
setTimeout() (delay)
Below is an example on how to delay something to x time. Put what you want to delay inside the curly brackets.
setTimeout(function(){refreshPoints(point);}, 5000);Program to run on Start
To get your program to run at the start of the graphic do the following:
Open your program to edit
Click on the 3 vertical dots in the upper right corner and then click the "Variables" option to show the "Program Vars" panel:
Enable the this variable to trigger the program by toggling the "Invokes the Function?" toggle to on.
Select "Custom Event" from the drop-down menu
Type in "start"
Click "Save" next to the red "Cancel" button
The this variable is always the result of item found through the "Program Target Filter". So if you had a button or buttons with the tag foo added onto it/them and you want them to be the program's target, the value of "Program Target Filter" should be foo.
To trigger the program whenever a curVal of a specific virtual point changes:
Repeat steps 1-2 above
Click on the "+" button next to the "Program Vars" label new panel
Name the new variable in the first text input, I'll use
virtualPointIn the second text area add the binding for this variable, usually its something like
id==$virtualPointRef(this essentially the same as having the linevar virtualPoint = query("id=="+this.virtualPointRef);, but this way you can make the variable trigger the program).Enable the
virtualPointvariable to trigger the program by toggling the "Invokes the Function?" toggle to on.Select "Tag Change" from the drop-down menu
Type in
curValin the text area.Click "Save" next to the red "Cancel" button
The above steps will work assuming you have a virtual point assigned the result of "Program Target Filter". With this set, the program should run anytime the curVal of the virtual point assigned to that graphic component changes.
This "Tag Change" option can be done with pretty much any property/tag on result of that variable's binding.
Programs
How to command a bool point by clicking on label
This command toggles between true and false every time the label is clicked on. Its an example of a boolean and manual command. It can be modified for other point types and commands.
Tag label component as foo in the Program Target Filter input
Bind point to label
var act = "Manual On";
var pid = point.pointId;
if(point.curVal)
act = "Manual Off";
finstack.eval('invoke('+pid+', "'+act+'", {self:'+pid+',duration: null})');How to command point with Prompt popup
In this example, we are creating an event to call a browser prompt popup and enter a value to command point instead of using gear icon.
Code
var myPoint = query('foo and virtualPoint'); //this queries for virtualPoint tagged as foo and virtualPoint
var newValue = prompt("Please enter value:", "0");
if (!newValue || isNaN(Number(newValue)))
alert("Not a valid number: " + newValue);
else
finstack.eval(sprintf('invoke($1, "Manual Set", {self:$1, val:$2, duration: null})', myPoint.pointId, newValue)); //this invokes point that has "Manual Set" action and writes whatever value we enter in the prompt.Here is an example in a Program instead of Event and for a string point not a number. It makes it dynamic based on the virtualPointRef on the component. (Doesn't work for smartLabels)
Hide a component based on value of another point
Below is an example program of how to hide a component based on the value of another point not bound to the component.
foo = tag program runs on and its the tag on the component to hide
fooPoint and virtualPoint = tags found on the virtualPoint in Graphics Builder to use to hide component (we just named the variable "point" but it can be anything you want)
In our example, the point to use is a boolean. If value is true, make the component visible, else hide it.
Increment Value
Below is an example of how to click on a button to increment to the value of a point by 1.
Setup:
Tag button as
addUp(incrementing up)Bind point to button that will be commanded
Create program that runs on
addUpand contains below variables and logicthis (variable) - invokes function on click
point (variable) - is set as
id==$virtualPointReflogic -
finstack.eval(sprintf('invoke($1, "Set Default", {self:$1, val:$2+1})', point.pointId, point.curVal));
How to add a shadow/glow on objects
Below is an example property to use to add a shadow/glow to the objects you want. Its the same as what we use for our shadow/glow.
filter is the property and drop-shadow(0 0 7px red) is the value.
filter = drop-shadow(0 0 7px red)";
Example: If value is true, set it shadow/glow to red, else no shadow/glow.
Change color on smart label based on a numeric value
Example Program: numStatusColor.json
The user can just upload the above file and tag the numeric point smartLabels as numStatusColor and it just work. They can modify the program code to specify their logic and colors.
(numStatusColor is the tag that this is running on, you can change that to be whatever you want. That will be the tag that you add to your smart labels for this to take effect on)
(Be sure to create your "point" variable which in this scenario we made it based on the virtualPointRef of the particular smart label)
// targets the smartlabel models "value label"
var smartLabelValue = getPath("valueGroup.valueLabel");
// point is based on whatever is bound to the label
if(point.curVal >= 90){
smartLabelValue.style.backgroundColor = "#ff0000"; //red
} else if (point.curVal <= 90 && point.curVal >=70){
smartLabelValue.style.backgroundColor = "#ffa500"; //orange
} else {
smartLabelValue.style.backgroundColor = null; //default
}Another example.
// targets the smartlabel models "value label"
var smartLabelValue = getPath("valueGroup.valueLabel");
// point is based on whatever is bound to the label
if(point.curVal <= 70 || point.curVal >= 78){
smartLabelValue.style.backgroundColor = "#ff0000";
}
else{
smartLabelValue.style.backgroundColor = null;
}Change color on smart label based on a boolean value
Example Program: boolStatusColor.json
Similar to the above but for booleans. The user can just upload the above file and tag the boolean point smartLabels as boolStatusColor and it just work. They can modify the program code to specify their logic and colors.
(boolStatusColor is the tag that this is running on, you can change that to be whatever you want. That will be the tag that you add to your smart labels for this to take effect on)
(Be sure to create your "point" variable which in this scenario we made it based on the virtualPointRef of the particular smart label)
// targets the smartlabel models "value label"
var smartLabelValue = getPath("valueGroup.valueLabel");
// point is based on whatever is bound to the label
if(point.curVal === true){
smartLabelValue.style.backgroundColor = "#ff0000"; //red
} else {
smartLabelValue.style.backgroundColor = null; //default
}Component Value (Numeric/Boolean/Reversed)
This program is an example that can be used to make a component work with both Numeric & Boolean points and also allows for them to utilize the "reverse" functionality.
Example program: BallValveProgram.json
if (point.kind ==="Number"){
if ("reverse" in this) {
this.valvePosition = fin.Utils.ResetBAS(point.curVal, 0, 100, 100, 0);
}
else
{
this.valvePosition = point.curVal || 0;
}
}
else if (point.kind ==="Bool") {
if ("reverse" in this) {
this.valvePosition = point.curVal ? 0:100;
}
else
{
this.valvePosition = point.curVal ? 100:0;
}
}Hide/Show based on current User
This program allows for the user to hide/show (or any other options) based on what user is logged in.
Variables needed:
point → id==$virtualPointRef→ invoked by "Tag Change" →curVal
var myPoint = point.curVal.toObj()[0];
if(myPoint.username == "su") {
this.style.visibility = "hidden";
}
else {
this.style.visibility = "";
}Instructions
on your components add the following tags
query:"context()" (String Tag)
toObj (Marker Tag)
create a new program that runs on your components. You may want to add a unique marker tag to your components so the program runs only on them.
paste in the code above
create a "point" variable, and make the value be
id==$virtualPointRef, enable "invoke function" and select "Tag Change" and have that be "curVal"
in the code where it says
if(myPoint.username=== "su") you will need to fill in the user that you want it to hide for.
Weather Data
If the user would like to include the current weather data info on a graphic. They can choose which piece of data they would like display. Requires that weatherstationRef is populated on the site required.
1. Upload the "WeatherDataProgram" and "WeatherDataPoint" json files via the graphic when it is open in the right menu Copy Records → Upload.
2. Then drag out some labels depending on what data you want.
3. Tag each label with the weatherData marker tag
4. Then depending on which data you want per label, add the following unique marker tag: temp or humidity or weatherCond or weatherTime or weatherIcon
Note: The "weatherTime" is based on what is provided by the weather forecast, so it is not the current time but last time provided by the weather provider.
5. That should be it. Try it out.
By default this works on any record below the site level. If you want to add this on the site level, after uploading this to the site level graphic, do the below:
1. Open the Virtual Points panel on the left
2. Find the "Weather Data Point" and expand it
3. You’ll find the query property tag
4. Change the value part where it says "$siteRef" to "$id" and save
5. That’s it.
Weather Data (Query)
We have a new function in axon called finWeatherData. You now can make a model, and add a `query` tag to it with a value like this read(site).finWeatherData and/or you could also do this read(id==$siteRef).finWeatherData
The function weather data actually returns the icons too. Once you have the data, you can pretty it up and arrange it however you like.
Graphic Example: weatherGraphics.zip (both examples included, query & virtualPoint)
Program Example: weatherData(query).json
var myPoint = point.curVal.toObj()[0];
curTempLabel.value = myPoint.cur_temp + ' '+ myPoint.cur_tempUnit;
curHumidityLabel.value = myPoint.cur_humidity + ' '+ myPoint.cur_humidityUnit;
curTempDesc.value = myPoint.iconText;
curTime.value = moment(myPoint.cur_time, 'h:mm:ss').format('h:mm A');
todayCondDesc.value = myPoint.forecast[0].iconText;
todayHigh.value = myPoint.forecast[0].tempMax + ' '+ myPoint.forecast[0].tempMaxUnit;
todayLow.value = myPoint.forecast[0].tempMin + ' '+ myPoint.forecast[0].tempMinUnit;
todaySunrise.value = moment(myPoint.forecast[0].sunrise, 'h:mm:ss').format('h:mm A');
todaySunset.value = moment(myPoint.forecast[0].sunset, 'h:mm:ss').format('h:mm A');
todayDate.value = moment(myPoint.forecast[0].date, 'MM/DD/YY').format('dddd MMM Do, YYYY');
tomCondDesc.value = myPoint.forecast[1].iconText;
tomHigh.value = myPoint.forecast[1].tempMax + ' '+ myPoint.forecast[1].tempMaxUnit;
tomLow.value = myPoint.forecast[1].tempMin + ' '+ myPoint.forecast[1].tempMinUnit;
tomSunrise.value = moment(myPoint.forecast[1].sunrise, 'h:mm:ss').format('h:mm A');
tomSunset.value = moment(myPoint.forecast[1].sunset, 'h:mm:ss').format('h:mm A');
tomDate.value = moment(myPoint.forecast[1].date, 'MM/DD/YY').format('dddd MMM Do, YYYY');
thirdCondDesc.value = myPoint.forecast[2].iconText;
thirdHigh.value = myPoint.forecast[2].tempMax + ' '+ myPoint.forecast[2].tempMaxUnit;
thirdLow.value = myPoint.forecast[2].tempMin + ' '+ myPoint.forecast[2].tempMinUnit;
thirdSunrise.value = moment(myPoint.forecast[2].sunrise, 'h:mm:ss').format('h:mm A');
thirdSunset.value = moment(myPoint.forecast[2].sunset, 'h:mm:ss').format('h:mm A');
thirdDate.value = moment(myPoint.forecast[2].date, 'MM/DD/YY').format('dddd MMM Do, YYYY');
thirdDay.value = moment(myPoint.forecast[2].date, 'MM/DD/YY').format('dddd');
var labelNode = curTempIcon.view.querySelector("label");
labelNode.className = myPoint.icon;
var labelNode0 = todayCondIcon.view.querySelector("label");
labelNode0.className = myPoint.forecast[0].icon;
var labelNode1 = tomCondIcon.view.querySelector("label");
labelNode1.className = myPoint.forecast[1].icon;
var labelNode2 = thirdCondIcon.view.querySelector("label");
labelNode2.className = myPoint.forecast[2].icon;
setTimeout(function(){refreshPoints(point);}, 300000);This what finWeatherData returns:
[{
"cur_temp": 66,
"cur_tempUnit": "°F",
"cur_time": "09:37:00",
"forecast": [{
"date": "11/16/16",
"tempMax": 65,
"tempMaxUnit": "°F",
"sunrise": "06:24:00",
"iconText": "Slight Showers",
"sunset": "16:47:00",
"icon": "wi-sprinkle",
"cond": 4,
"tempMin": 52,
"tempMinUnit": "°F"
}, {
"date": "11/17/16",
"tempMax": 73,
"tempMaxUnit": "°F",
"sunrise": "06:25:00",
"iconText": "Clear Sky",
"sunset": "16:47:00",
"icon": "wi-day-sunny",
"cond": 1,
"tempMin": 52,
"tempMinUnit": "°F"
}, {
"date": "11/18/16",
"tempMax": 75,
"tempMaxUnit": "°F",
"sunrise": "06:26:00",
"iconText": "Clear Sky",
"sunset": "16:46:00",
"icon": "wi-day-sunny",
"cond": 1,
"tempMin": 50,
"tempMinUnit": "°F"
}],
"cur_cond": 2
}]Override Count
Below is an example of how to get the override count on the target equip. Tag label as our example "overrideVal" and create the program that runs on it.
var target = query('targetPoint');
var fooVar = query('overrideVal and label');
var promise = finstack.eval('readAll((write1 or write8) and equipRef=='+target.pointId+').size');
promise.then(function(event)
{
fooVar.value = event.result.toObj()[0].val;
}.bind(this));Heat Pump Program (Compressor & Reversing Valve)
Video: heatPumpProgram.mp4
Download: heatpumpProgram.json
if (compPoint.curVal === false)
{
heatImage.style.visibility = "";
heatImage.value = 0;
coolImage.style.visibility = "hidden";
coolImage.value = 100;
}
else
{
if (compPoint.curVal && rvPoint.curVal)
{
heatImage.style.visibility = "hidden";
heatImage.value = 0;
coolImage.style.visibility = "";
coolImage.value = 100;
}
else
{
heatImage.style.visibility = "";
heatImage.value = 100;
coolImage.style.visibility = "hidden";
coolImage.value = 0;
}
}
Enum Status Color Labels
Download: circularStatus.zip
if (point.curVal === "Warning"){
this.className = 'round view-superman-value status-down';
this.value === "NULL";
}
else if (point.curVal === "ALARM"){
this.className = 'round view-superman-value status-alarm';
this.value === "NULL";
}
else {
this.className = 'round view-superman-value status-ok';
this.value === "NULL";
}
top.app.ShowRelatedBubbles(point.pointId,myZone.pointId,false);Button Toggle (using forEach)
Download: buttontoggleprogram.json
Run On:
fooVariable: Variable this should be invoked by "click"
var fooAll = queryAll('foo');
var myButton = this;
fooAll.forEach(function(item){
if (myButton.id == item.id) {myButton.classNames = "view-default focus";}
else {item.classNames = "view-default"
}});Controlling Fan with Enum Point
If you have an enum point and would like to turn a boolean component (ie: fan) to on/off, then here is an example program that says if the enum is "Off" set fan to false ("off"). If its anything else other than "Off", set it to true ("on").
All you have to do is bind enum point to boolean component like a fan and tag it "enumFan".
Note: Another thing you might have to do is remove the ductProgram tag from the boolean component that gets auto added to it.
Here is the code, but make sure to add the program variable "point" with its settings as you see in the screenshot above.
Fan Status based on Enum Point
if(point.curVal === "Off") {
this.value = false;
}
else{
this.value = true;
}You can download and upload the program here.
On/Off Switch (No Action Panel)
Download: toggleSwitch.zip or toggleButton.zip
Upload the attached zip through folio "restore" (screenshot)
Open your graphic
Open the component panel search for
switchToggle(or locate it by scrolling tot he bottom of the list under models)Drag it out,
Bind a point to the model
Add the following tag to the model:
disableRelatedBubblesProgram
var eventName = context.source.name || "notFound"
if (eventName === "onSwitch") {
bgUnselected.x = "0%";
onSwitch.classNames ="view-superman-value";
offSwitch.classNames ="view-superman-label";
finstack.eval('invoke('+point.pointId+',"Manual On", {self:'+point.pointId+',val:'+true+',duration:1hr})');
}
else if (eventName === "offSwitch") {
bgUnselected.x = "50%";
onSwitch.classNames ="view-superman-label";
offSwitch.classNames ="view-superman-value";
finstack.eval('invoke('+point.pointId+',"Manual Off", {self:'+point.pointId+',val:'+false+',duration:1hr})');
}
else {
bgUnselected.x = point.curVal ? "0%":"50%";
}
Pie Chart with Related Bubbles
1. Create a new Virtual Point Query - Example: readAll(site)
2. In your left panel, switch the view to "events" and add a new custom event that runsOn: world
3. bring out a amGauge and hide it.
4. Bring out an amChart and tag it "foo" or whatever you query in the myChart var code below
var myChart = query('foo');
var myQuery = query('virtualPoint and query');
function handleZoom(ev){
var myPointId = ev.dataItem.dataContext.id;
top.app.ShowRelatedBubbles(myPointId,myPointId,false);
}
var chart = AmCharts.makeChart( myChart.view, {
"type": "pie",
"theme": "light",
"dataProvider": myQuery.curVal.toObj(),
"valueField": "area",
"titleField": "dis",
"balloon":{
"fixedPosition":true
},
"export": {
"enabled": true
},
"listeners": [ {
"event": "clickSlice",
"method": handleZoom
}]
} );Floorplan: Show Equip with lowest Temp
Add the following code to any button/object as an event on a Floorplan.
Once added, the object (when clicked on) will bring up the magic bubbles for the equipment with the lowest Temperature value.
Instructions:
1. Bring out a button
2. Right+Click on the button and add the following Event: Mouse Over > Click
3. Take the code below and paste it into the event window
Show Equip with lowest temp
/// Find all temp sensors used on the floor plan
var tempSensors = queryAll('virtualPoint and sensor and curVal');
// Function that will be called to find which virtualPoint has the lowest curVal
var minCallback = function(a, b)
{
return a.curVal <= b.curVal ? a : b;
};
//// myZone is the virtualPoint that has the lowest curVal
var myZone = tempSensors.reduce(minCallback);
/// Open the magic bubbles for the zone with thelowest curVal
top.app.ShowRelatedBubbles(myZone.pointId,myZone.pointId,false);Date & Time on Graphic (with refresh)
http://momentjs.com/ (website reference for date/time formats)
Use the following program to add date & time on a graphic using the now() axon query.
Go to virtual points and create a new virtual point named "My Date Time" or whatever you might prefer
Right click on your new virtual point > apply batch tags > select your new point > and apply
dateTimePoint query:"now()"Bring out a label and add a
dateTimeLabeltag to itBring out a timer and add a
dateTimeTimertag to it (we recommend you refresh every 10-30 seconds instead of every second, so set delay property on timer to 20000)Create a new program called Date Time Program and make it run on
dateTimeLabelCreate a variable called
myTimerand have it use thedateTimeTimertag and set it to run on custom event 'timer' (screenshot)create variable to query your
dateTimepointvar dateTime = query('dateTimePoint');Then to format your label value add a moment().format() ....example:
this.value = moment(dateTime.val).format('MMMM Do YYYY, h:mm a');
Doing the above will update the dateTime value based on the timer. If the user wants to make the label display the dateTime when the graphic loads. they can add a another program that looks like below.
Program Name = Date Time Startup (or whatever you might prefer)
Program Target Filter = world
Code:
var myLabel = query('dateTimeLabel'); //this gets the label component var dateTime = query('dateTimePoint'); //this gets the dateTimePoint myLabel.value = moment(dateTime.val).format('MMMM Do YYYY, h:mm a'); //this adds the dateTime to the label value
Scalable Date Time Model
Here is a scalable date time model we created if you would like to use it: Date Time Model
Restore that in Graphics Builder > Graphics > Miscellaneous > Restore.
Then it can be found in the Components panel under Models towards the bottom called "Date Time"
Drag out and adjust accordingly
Drag out a timer if one doesn't already exist on the graphic and recommend to set for 20000 sec
Time Remaining (milliseconds)
Here is an example program that returns the remaining time from a point that has value in milliseconds.
var sec = point.curVal / 1000;
var days = sec / 86400;
var hours = (days-Math.floor(days))*24;
var minutes = (hours-Math.floor(hours))*60;
this.value = "Next Shift "+Math.floor(days)+" days, "+Math.floor(hours)+" hrs, "+Math.floor(minutes)+" mins";Open Related Bubbles (Equip Bubbles)
We have a tool for this called Add MagicBubbles.
Point Bubbles
If the user is looking to add point magic bubbles. They can upload this program called "Point Bubbles" and tag their component as pointBubbles. Make sure point is bound to component.
Point Actions Command
If the user wants to bring up the actions command popup like the gear icon does for commandable points on smartLabels but for simple label, then they just need to tag the components as "commandable".
Note: Need to make sure "Allow Commanding" program exists on the graphic for this to work. If it doesn't exist, you can right click on world > Tools > Resources > Add Remote > and select to add Allow Commanding.
Mouse Over/Out - Hide/Show using My Filter
This program allows you to put a "myFilter:fooBag" string tag on any object, which will then hide/show anything else that has the same tag you put in the "myFilter"
Program: showAndHideMyFilter.json (upload via right side menu in Graphics Builder → Copy Records → Upload)
example set up:
Icon has "myFilter:fooBag" (string) and “foo” (marker)
Note: “fooBag” in myFilter can be replaced with anything. Whatever is chosen, that will be added to the other components instead.svg1 has fooBag (marker)
svg2 has fooBag (marker)
When we mouse over the icon, both svg1 and svg2 show and hide
Mouse Over / Mouse Out: Hide & Show object
This method uses Mouse Over / Mouse Out actions to hide and show your objects.
1. Name your text labels (what you name them doesn't matter, as as long as you are consistent in the code below)
2. Draw your poly? (or whatever object you will be mousing over to hide/show the labels.
3. Right click on it, select Event > Mouse > Mouse Over (or mouse out)
4. copy paste "mouse over" code shown below
5. change the red portion, getByName("insertYourHideShowObjectsNameHere"), to be the name of what you are showing/hiding
6. Rinse repeat for mouse out
Mouse Over Code:
this.fill = "rgba(41, 136, 243, 0.30)";
var myObject = getByName("F1-S3-RMS");
myObject.style.visibility = "";
Mouse Out Code:
this.fill = "rgba(41, 136, 243, 0)";
var myObject = getByName("F1-S3-RMS");
myObject.style.visibility = "hidden";Auto Overrides from within a Graphic
finstack.eval(`finCommandAuto("point", [1, 8])`);
Reset Translator
var myPoint = query('foo');
var myDamper = query('myDamper');
myDamper.value = fin.Utils.ResetBAS(myPoint.curVal, 0, 100, 100, 0);Hide Image when Boolean is Off (Must have virtualPointRef on image)
download the program below, add hidePoint to the boolean point(s) and add hideImage to image(s).
DOWNLOAD PROGRAM: BoolShowHide.json
if(point.curVal === false) {
this.style.visibility = "hidden";
}
else {
this.style.visibility = "";
}
Toggle: Hide/Show
var foobag = queryAll('foo');
//toggle visibility
foobag.forEach(function(item){
item.style.visibility = (item.style.visibility === "") ? "hidden":"";
});
Toggle: Hide/Show (hides other shown layer)
Toggle Hide Show
var fooA = queryAll('fooOne');
var fooB = queryAll('fooTwo');
fooA.forEach(function(item){
item.style.visibility = (item.style.visibility === "") ? "hidden":"";
});
fooB.forEach(function(item){
item.style.visibility = "hidden";
});Get Min/Max/Average With Labels
1. Navigate to the location they want to display the Graphic since FIN is content-sensitive
2. Once navigated to the desired location, select the App Launcher button located on the top left corner
3. Select the Graphics Builder tile
4. When selected, it will slide out and give the user 3 options
In this case, select on Menu
5. Click on the Graphics Builder button.
6. Click on the Launch button.
7. You will be taken to a screen that looks like this:
8. Click on the New Project button near the top left corner.
9. Then click on the little menu button in the top right corner.
10. In the menu that pops up on the right, click on the Copy Records button.
11. Then click on the Upload button.
12. A file selection prompt will open up based on the client OS.
You will need to download the myTimer.json program file and upload it to that prompt.
DOWNLOAD: myTimer.json
13. You can then view the program by clicking the little menu button on the bottom half of the left side menu, selecting programs, and clicking the gear on the myTimer program.
14. A window will pop up looking like this:
This is JavaScript code which dictates the actions of the components we will be adding to the graphic.
In order for this to work, the points must be tagged with zone and temp and sensor and curVal.
15. Press the Cancel button at the bottom right of the JavaScript window.
16. Drag a timer component from the top half of the left side menu to the middle of the canvas.
17. In the bottom half of the left side menu, click the menu button and select Properties (timer must be selected).
18. Change the delay value to 2000 (2000 ms or 2 sec).
19. Drag 3 label components from the top half of the left side menu to the center of the canvas.
20. Click the middle label, click the little tag icon, and give it a tag called foo, then click enter.
21. Click the top label, click the little tag icon, and give it a tag called mymax, then click enter.
22. Click the bottom label, click the little tag icon, and give it a tag called mymin, then click enter.
23. Finally click the Preview button near the top left corner.
24. A window will pop up showing the labels with dynamically updating values.
25. You may have to wait a few seconds for the value of the labels to change from Label to a number.
The values update once every 2 seconds, this can be changed by changing the timer delay.