Skip to Content
Author's profile photo Karol Kalisz

How to “paint” a Thermometer Component

Purpose

Visualize Data in Design Studio as “Thermometer” in standard installation – without using an SDK development. This thermometer is for percentage values 0 to 100 %.

Basics

This component is created using the tips from my Blog “Painting” with Design Studio via CSS3.

Setting Values

There is no automatic connection to any data source, but you can set the values as shown in attached application.

     Set the “base line”

     “Base line” is a line which sets some custom value, you can move this between 0 and 100


// baseline between 0 and 100
var valueAsIntegerBetween0and100 = Convert.stringToInt(INPUTFIELD_2.getValue());
// baseline is aline positioned in the scale using bottom margin value
PANEL_TH_BASELINE.setBottomMargin(valueAsIntegerBetween0and100 * 2 + 100);



     Set the “value”

     “Value” is the visualization of the current percentage. Between 0 and 100.


// here the value must be manually calculated
var valueAsIntegerBetween0and100 = Convert.stringToInt(INPUTFIELD_1.getValue());
// the value is visualized by the hight of the corresponding PANEL
PANEL_TH_VALUE.setHeight(valueAsIntegerBetween0and100 * 2);
// assuming the base line is already set, here the "back" calculation from bottom margin to percentage value
var baselineValueBwtween0and100 = PANEL_TH_BASELINE.getBottomMargin();
baselineValueBwtween0and100 = baselineValueBwtween0and100 - 100;
baselineValueBwtween0and100 = baselineValueBwtween0and100 / 2;
// based on the difference between base line and value, different css styles can be set
if(valueAsIntegerBetween0and100 >= baselineValueBwtween0and100) {
  PANEL_TH_BASE.setCSSClass("th-base th-good");
  PANEL_TH_VALUE.setCSSClass("th-value th-good");
  PANEL_TH_DOT.setCSSClass("th-dot th-good");
} else {
  PANEL_TH_BASE.setCSSClass("th-base th-bad");
  PANEL_TH_VALUE.setCSSClass("th-value th-bad");
  PANEL_TH_DOT.setCSSClass("th-dot th-bad");
}



Example


Thermometer with “good” visualization

th_good.PNG

Thermometer with “good” visualization

th-bad.PNG

Used CSS



.th-border-top {
  border-top: 1px solid #cccccc;
}
.th-border-top-baseline {
  border-top: 3px solid black;
}
.th-base {
}
.th-value {
}
.th-dot {
  border-radius: 40px 40px 40px 40px / 40px 40px 40px 40px;
  border: 1px solid #cccccc;
}
.th-bad {
  background-color: red;
}
.th-good {
  background-color: green;
}


Scripts for Data Binding


Read from data and convert to Integer



// here the value must be manually calculated
var dataValue = DS_1.getData("4FW8RN37GL043NF22OTQFXYL3", {
  "0BC_PERS1": "00020"
});
// read the value from the data cell
var dataValueFull = dataValue.value;
// use formatting to get the number w/o decimal places
var dataValueString = Convert.floatToString(dataValueFull,  "###");
// convert to integer and save
var valueAsIntegerBetween0and100Original = Convert.stringToInt(dataValueString);
// calculate
var valueAsIntegerBetween0and100 = valueAsIntegerBetween0and100Original;
valueAsIntegerBetween0and100 = valueAsIntegerBetween0and100 * 2;


Apllication as Example

Example Application can be downloaded from GitHub:

Update: use the newest version to have the application updated by two new buttons:

Link to ZIP: Release 1.1.1: Updating thermometer Example by Data Binding · KarolKalisz/DesignStudioBiAppRepository · GitHub

You need to change of course the query.

data-bound.PNG

I hope you have fun with this component.

Assigned Tags

      22 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Hi Karol

      I have given this a try, I downloaded the Zip file and uploaded the app but its not working as expected.

      inputting values into the boxes and pressing the relevant button does nothing.

      If I manually insert some figures and put them in my on startup code it works well.

      However when trying to set the value from a Datasource it doesn't like it at all, just gives an error and in the error log I can see these lines

      Message: org.mozilla.javascript.WrappedException: Wrapped java.lang.NullPointerException (BIAL Script#3)

      Error during script processing: "PANEL_TH_BASELINE.setBottomMargin(90 * 2 + 100);

      Error during script processing. Contact the Application Designer to resolve the issue

      If I remove the reference to my DS_1 datasource I don't get these errors so im a little baffled. If I remove the line it is moaning about or comment it out it still moans about the first part of the script.

      Any ideas?

      Here is the line I have edited

      valueAsIntegerBetween0and100 = Convert.stringToInt(DS_1.getDataAsString("DIEEMDTX6CJC94HO28BWVYMZQ", {"0DIVISION":"39"}));

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      Hi, I will try also with data source. but in the meantime:

      * which release / SP are you on?

      * please open the exception window and paste the callstack with nullpointer.

      * perhaps you can add one more line before:

      var integetToSet = valueAsIntegerBetween0and100 * 2 + 100;

      PANEL_TH_BASELINE.setBottomMargin(integetToSet);

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Hi Karol

      I am on 1.3 SP01.

      com.sap.ip.bi.zen.rt.framework.jsengine.JsEngineException: org.mozilla.javascript.WrappedException: Wrapped java.lang.NullPointerException (BIAL Script#3)

      at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoJsEngine.handleError(RhinoJsEngine.java:141)

      at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoJsEngine.doResumeScript(RhinoJsEngine.java:119)

      at com.sap.ip.bi.zen.rt.framework.jsengine.JsEngine.resumeScript(JsEngine.java:53)

      at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoScriptInterpreterBialService.interprete(RhinoScriptInterpreterBialService.java:193)

      at com.sap.ip.bi.base.command.impl.Command.interprete(Command.java:189)

      at com.sap.ip.bi.webapplications.runtime.impl.page.Page.processCommandSequence(Page.java:4662)

      at com.sap.ip.bi.webapplications.runtime.impl.page.Page.doProcessRequest(Page.java:2618)

      at com.sap.ip.bi.webapplications.runtime.impl.page.Page._processRequest(Page.java:774)

      at com.sap.ip.bi.webapplications.runtime.impl.page.Page.processRequest(Page.java:5080)

      at com.sap.ip.bi.webapplications.runtime.impl.page.Page.processRequest(Page.java:5073)

      at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller.doProcessRequest(Controller.java:1238)

      at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller._processRequest(Controller.java:1088)

      at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller.processRequest(Controller.java:1054)

      at com.sap.ip.bi.webapplications.runtime.impl.controller.Controller.processRequest(Controller.java:1)

      at com.sap.ip.bi.server.runtime.sevice.impl.BIRuntimeServerService._handleRequest(BIRuntimeServerService.java:538)

      at com.sap.ip.bi.server.runtime.sevice.impl.BIRuntimeServerService.handleRequest(BIRuntimeServerService.java:943)

      at com.sap.ip.bi.server.execution.engine.runtime.BIExecutionEngineRuntime.executeRequest(BIExecutionEngineRuntime.java:48)

      at com.sap.ip.bi.framework.base.execution.impl.BIExecutionService.executeRequest(BIExecutionService.java:54)

      at com.sap.ip.bi.client.execution.AbstractExecutionServlet.handleRequest(AbstractExecutionServlet.java:161)

      at com.sap.ip.bi.client.servlet.BIPrivateServlet.handleRequest(BIPrivateServlet.java:36)

      at com.sap.ip.bi.client.execution.AbstractExecutionServlet.doPost(AbstractExecutionServlet.java:140)

      at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)

      at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)

      at org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61)

      at org.eclipse.equinox.http.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:38)

      at com.sap.ip.bi.zen.webserver.internal.ZenSessionFilter.doFilter(ZenSessionFilter.java:34)

      at org.eclipse.equinox.http.servlet.internal.FilterRegistration.doFilter(FilterRegistration.java:81)

      at org.eclipse.equinox.http.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:35)

      at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:132)

      at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:60)

      at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)

      at org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet.service(HttpServerManager.java:386)

      at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)

      at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:457)

      at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229)

      at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)

      at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)

      at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)

      at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)

      at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)

      at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)

      at org.eclipse.jetty.server.Server.handle(Server.java:368)

      at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)

      at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:953)

      at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1014)

      at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:861)

      at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)

      at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)

      at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)

      at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)

      at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)

      at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)

      at java.lang.Thread.run(Unknown Source)

      Caused by: org.mozilla.javascript.WrappedException: Wrapped java.lang.NullPointerException (BIAL Script#3)

      at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1786)

      at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:183)

      at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:247)

      at org.mozilla.javascript.Delegator.call(Delegator.java:229)

      at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.shared.CustomFunction.call(CustomFunction.java:36)

      at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:1701)

      at org.mozilla.javascript.Interpreter.restartContinuation(Interpreter.java:914)

      at org.mozilla.javascript.NativeContinuation.call(NativeContinuation.java:80)

      at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:426)

      at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.CustomContextFactory.doTopCall(CustomContextFactory.java:54)

      at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3178)

      at org.mozilla.javascript.Interpreter.restartContinuation(Interpreter.java:895)

      at org.mozilla.javascript.Context.resumeContinuation(Context.java:1246)

      at com.sap.ip.bi.zen.rt.framework.jsengine.rhino.RhinoJsEngine.doResumeScript(RhinoJsEngine.java:109)

      ... 51 more

      Caused by: java.lang.NullPointerException

      at com.sap.ip.bi.zen.rt.components.ds.impl.DataSourceCommandResolver.getCell(DataSourceCommandResolver.java:1239)

      at com.sap.ip.bi.zen.rt.components.ds.impl.DataSourceCommandResolver.getDataAsString(DataSourceCommandResolver.java:1095)

      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

      at java.lang.reflect.Method.invoke(Unknown Source)

      at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:161)

      ... 63 more

      Tried the additional line but hasn't made any difference

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      looks like you have an issue with the cell celection.

      please check updated content of the example, 2 new buttons are in

      Perhaps you can find the issue by checking the code step by step. At least I could pass the value from the query to the integer.

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      I could do with a debugger in here to see what each variable is displaying each step of the way!

      I have downloaded the new version and still none of the buttons do anything? I changed the datasource and the query.

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      try following:

      after every line you can add

           APPLICATION.createErrorMessage(...);

      there you can print out the values.

      you need to find the line which is making "nullpointer".

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Doesn't work! all I get is

      Error during script processing. Contact the Application Designer to resolve the issue

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      hmm, then one of the line is causing validation error. the only way will be to start creation of this script line by line. I mean, place first line - and the addErrorMessage() line below and execute. if works, add second line etc. at some line you will get validation isssue. what is the line?

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      perhaps first you can also try to pass the cell value to a simle text component to see if the selection is working well and how it is formated

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      It does look to be the cell selection causing issues as you said.

      If I create  button and add the following code and run the app and press said button I get an error saying Dum dum dum. Please Note NOTIFY is a custom component that I have loaded from SCN 🙂

      NOTIFY_1.error(" Dum dum dum");

      If I change code and put the following before it.

      Var dataValue = DS_1.getDataAsString("DIEEMDTX6CJC94HO28BWVYMZQ", {


      "0DIVISION": "39" });

      Then run app and press same button, I no longer get my Error message but a Script error and to contact the admin 🙂

      Not too sure how I could debug this further.


      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      how are you initializing the data source?

      try to check the code with getData() and not with getDataAsString(). when you add after every line the "APPLICATION.createErrorMessage()" then you will see all messages in the popup - this is how you can find the line which is breaking.

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      also, check if  "39" is the key - if this is a text and the key is like "0039" or similar, then the cell cannot be found

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      If I put 039 as the key I get a prompt in script editor to say its not found any info for it, With 39 and hovering over it the script editor shows me the text for that item.

      I think its safe to say the data is there and it can see it but its the calling of the data it doesn't like.

      I have changed to getData and the same problem happens?

      Its very strange, are you also using SP01? And are you in local mode or Connected Mode?

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Its the line for retrieving the data that is giving the issue.

      The below is attached to a button, I don't get the first message or the second, I just get he script error!

      var dataValue = DS_1.getDataAsString("DIEESCJSRAKYB230F23L4Q8YU", { "0DIVISION" :"39" });
      APPLICATION.createErrorMessage("Got Data");
      INPUTFIELD_1.setValue(dataValue);
      APPLICATION.createErrorMessage("Set Value");

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      I reply to the top one for better reading.

      you must see an validation error when working in designer, like this one:

      errro.PNG

      mouse-over says: cannot convert from datacell to string.

      correct script would be:

      // here the value must be manually calculated

      var dataValue = DS_1.getData("4FW8RN37GL043NF22OTQFXYL3", {

        "0BC_PERS1": "00020"

      });

      // read the value from the data cell

      var dataValueFull = dataValue.value;

      // use formatting to get the number w/o decimal places

      var dataValueString = Convert.floatToString(dataValueFull,  "###");

      INPUTFIELD_3.setValue(dataValueString);

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      I don't have validation errors like that I have corrected them 🙂

      I copied the example you have given but I just get nothing when clicking on the button.

      I have a meeting now so will have to carry on with this later or tomorrow! Thanks for all your help though, I do appreciate it.

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      I see you still using the script "getDataAsString", please use the script I have provided with "getData" and then convert..

      if you do not manage, we can make short call on private.

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Hi Karol, Sorry I didn't get back to you sooner been quite busy today 🙂

      I had getData as you supplied in the last script and nothing happens.

      Putting an error message after the first line to retrieve the data does not display any error.

      This is very weird!

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Karol

      There seems to be other threads with a similar issue to mine

      What OS Version/architecture are you using?

      What Design Studio Version/SP Are you using?

      Thanks

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      plz contact me on karol.kalisz@sap.com - I will send you a meeting request, ok?

      Author's profile photo Alex Cruickshank
      Alex Cruickshank

      Hi Karol

      Panic over! I was selecting 0MATERIAL_0DIVISION in my initial view and not 0DIVISION.

      I didn't have 0DIVISION in my Bex Query though so not sure how Design Studio validated that I could use it?!

      However once adding it to my bex query its now working 🙂

      The buttons you created still don't work for me though, if I take the code and put it in on startup it works fine though.

      Thanks very much for all your help and for the thermometer it has helped me massively!

      All the best

      Author's profile photo Karol Kalisz
      Karol Kalisz
      Blog Post Author

      good to hear that it is used.