Create your own widgets with ThingStudio.

in features

While we provide a basic set of widgets to get you up and running, we know we can't solve every use case for your apps, so we've created a powerful widget system to let you code your own.

We’ve a lot of requests from people who want to create their own widgets with ThingStudio. So, here is a tutorial on creating new, reusable graphical controls with ThingStudio.

Today, we’ll create a Thermometer widget like this:
finished

There are four steps to creating a widget:

  1. First, make a static template which draws the required widget with placeholder values for all the dyamic data.
  2. Second, write the underlying javascript which will provide the need dynamic data to the widget
  3. Third, replace the placeholder values in the widget template with calls to the javascript helper
  4. Forth, fill in the properties of the widget to create its documentation and example invocation.

Let’s get started.

Step 1: Create the static template

All widgets in ThingStudio start as templates, so create a new template.

I’m very keen on SVG  as my primary way of drawing as it gives fully scalable graphics and works on the majority of platforms. I can’t give a full tutorial on SVG here, but if you’ll find lots of material on the web. You can try http://www.svgbasics.com/ for a kickoff, but I’m happy to post other recommendations if you leave questions in the comments below.

Anyway, SVG gives you vector graphics primitives for drawing and coloring all kinds of shapes, still allows you to use CSS, and has event handlers for creating buttons and sliders. I find that the W3.org is invaluable for clear concise docs and this page http://www.w3.org/TR/SVG/ is always open when I’m making widgets.

NOTE: Always edit in safe edit mode, see tips at the end of the post!

The first thing you should put into your widget template is the SVG element itself.

This establishes the ‘bounding box’ for the SVG, everything will be drawn inside this box, with a coordinate system defined by the viewBox attribute, that is, x from 0 to 200 and y from 0 to 570.

NOTE: I don’t advise using a drawing program to generate your SVG, I haven’t found one yet that makes good use of the SVG primitives to make SVG code that is easy to animate. You can still use a drawing program to sketch out your initial ideas.

If left to itself, this will render inconveniently large as we are developing, so as a temporary measure, we’ll enclose it in a fixed height div to keep it under control.  We must remember to remove this div at the end to allow for scaling to work properly.

Be very aware that SVG coordinates run from top right downwards and rightwards, so 0,0 is at the top right!

Next, we’ll draw the body of the thermometer. We’ll use the SVG path command, which will draw a closed path, and has several sub-commands inside it.

It should look like this….

1st step

Briefly, the M sub -command moves the virtual pen to an absolute location, the a command draws an arc, the l commands draw lines and the z command closes the path. Calculating paths is definitely the most tricky bit of the entire operation, but the command is so powerful that its worth taking the time to master it.

Next, we’ll put the “mercury” in the thermometer, this is the part that will move in line with the value passed into the widget. It looks like this…

And we’ll get…

2nd step

Basically, this path is just a reduced size version of the outside of the thermometer. You’ll see two values  of 111 and -111.  Those are the values we’ll replace with dynamic values from handlebars helpers, but as we don’t have them at the moment, I’ve put in fixed values until we’ve got the drawing right.

Finally, we’ll put in the text for the maximum and minimum values, the current value and the legend (label).

3rd step

Great, we have a pretty fair thermometer, but obviously, its just a picture with static values, the next section deals with animating it.

Step 2: The Javascript for your widget

Move to the Javascript tab of your template.

Let’s start by initialising all the dynamic data that we are going to need.

This bit of magic specifies the function that should be run when a copy (instance) of this template/widget is created.

All the code here is pure Meteor, which is the underlying technology that ThingStudio uses. You can find detailed documentation for this function and all the other Meteor functionality at http://docs.meteor.com/#/full/. Specifically the onCreated function is defined here. http://docs.meteor.com/#/full/template_onCreated

The function we are going to run is fairly self explanatory, all it does is set default values for the widget’s data. For instance, if you don’t set the legend, it will be “Main Oven”, and so on for all the values.

Next, we’ll define the helpers. These are the functions that transform the dynamic data passed in from ThingStudio into a form useful to the widget.

You can read about template helpers in great detail on the Meteor site here: http://docs.meteor.com/#/full/template_helpers, the only difference from the Meteor docs being that the invocation should always be Template[name].helpers as this is how the internals of ThingStudio need the call.

So, we have two helpers, mappedValue and mercuryColor. mappedValue takes a parameter which is the dynamic value passed in, usually from a feed. It then uses the library routine mapValue to transform the temperature, let’s say 22.3 to a value between 0 and 300. This is because the mercury in the thermometer is 300 units high and we need to convert the actual temperature to a value between 0 and 300. mapValue library function which is a shameless lift from the Arduino API, documented here https://www.arduino.cc/en/Reference/Map.

Remember, these are NOT pixels, they are SVG units that will be scaled to pixels as appropriate.

The other helper, mercuryColor, provides an HTML color string depending on the current value and the greenvalue and orangevalue parmeters we set up in the onCreated function.

Step 3: Replace the static values with Javascript helpers

Now we have defined our javascript, we can go back to the html template and replace our temporary, static values with ones that will be calculated dynamically by the system.

So, you will see that the values of ‘111’ which are the height of the mercury have been changed to {{mappedValue value}}, the fill value of the mercury column is now {{mercuryColor value}} and the maximum and minimum values have been set by the values we set up at creation time.

That’s all the hard work. Now we just need to set up the widget parameters.

Step 4: Create the widget parameters

Go to widgets on the side nav and click on ‘create a new widget’. Its name will be Thermometer, the type will be ‘Web Component’ and the base template will be ‘ Thermometer’.

NOTE: At the moment, the name of the widget must be the same as the template it is based on.

Click on the tick mark to create it. If you now go to the ‘My  Widgets’ tab you will see your widget listed. Click in the pencil to finish setting the widget up. First click on the ‘properties’ tab. You should see a screen like this….

propertysheet

Scrolling down , you find a field for any special instructions on how to use this widget.

widgetinstructions

The tag name property should have a hyphen in it. This is an HTML5 restriction. All ‘official’ ThingStudio widgets are prefixed  with ‘ts-‘, but you should prefix yours with some string that is likely to be unique to you, so if your company name is Acme, call it ‘acme-thermometer.

Finally, we’ll fill in the widget’s parameters. Filling these in has no effect on the actual widget, but does generate the documentation you see on the widget summary page. I suggest you do fill these in, although your widget may only be for your use now, it’s surprising how quickly you can forget the name of the correct parameters for your widget. Also, in later versions of ThingStudio, we’ll be introducing the ability to share widgets with other users, and they will need the documentation.

widgetproperties

The various fields of the widget parameter are fairly self-explanatory, though you  may be puzzled by the ‘dummy value’ field. This field is used in the summary sheet and an example of a valid input for that parameter and is seen in the example invocation at the top of the widget summary sheet. Which should now look like this…

widgetsummary

And now….

You have finished your widget!

Of course, this is a reasonably long process and prone to errors, so here are some tips about how sucessfully develop a widget.

You will be actually editing live javascript, and if/when you cause a javascript exception, any window displaying the widget can freeze, including the edit tab. So, rather than editing the widget in ‘live preview’ mode, (thats the pencil icon), you should edit in ‘safe edit’ mode, (the eye with a bar through), and display the widget in another window. That way, even if the widget code is causing exceptions you can still edit your way out of trouble.

The HTML5 RegisterComponent API only allows you to register a component once in the lifetime of the DOM (there is no DeRegisterComponent!), so when you are trying out your widget in another template, you will need to refresh that page in order to see changes. Sorry, that’s just HTML5.

Remember KISS, Keep it Simple, create the absolute minimum version of your widget, its much easier to add features to an existing working widget, than try to get all the features working.

Use the browser developers tools. Chrome, Firefox and Safari, have great debugging tools, and they are a great help when debugging a TS widget.

Using Widgets in Your Templates

Now you can navigate to your new widget page, click on the eye icon to get the preview screen, and cut and paste the sample invocation that you have generated with the widget property sheet. When you substitute dynamic data into your sample code, you should see your shiny new widget animated in your own templates! You can see examples of widget invocation in the example App.

Ask for help, preferably post any questions to our forum on forum.thingstud.io so the community can benefit from your experience, but you can always mail directly for assistance.

Live long and prosper.

Mike

I make stuff.

4 Comments

  1. Gilson

    Hi Mike,
    Nice post!
    Since I have no artistic skills at all I was wondering if there are SVG libraries with basic objects that you can recommend…
    Regards,
    Gilson

    1. Mike Karliner

      Its a good question, as I have much the same problem!

      Googling ‘svg nameofobject is always a good start,
      although ‘vector nameofobject’ may also help.

      Just looking at other peoples work helps, for instance, the
      JustDial widget is a copy of a control called JustGauge, although
      the code is completely independent. This is because ThingStudio
      widget tend to be much simpler to write because of the underlying
      power of meteor.

      Although I advised against it in the article, you can use
      a drawing program to help you generate an initial image,
      especially if it comes with some clip art or standard shapes.
      However, as I said, you may find that the generated SVG is not
      always easy to animate, as their code generators are aimed at
      easy of generation rather than super clean code, so you may
      find easier to write the svg from scratch.

      Also, you should remember that you are not obliged to use SVG,
      any valid HTML can be turned into a widget. So, if you really
      don’t want to draw things, you can just have a widget that renders
      different canned icons or images.

      Finally, you may find as I did, that its the idea of drawing
      that is intimidating, and once you have tried it, the results
      come out better than you think.

      Hope that helps.
      Mike

  2. Andrea Prunić

    Hi Mike, great work, maybe even I, not so much of a programmer, could use these instructions to make my own widgets.
    But, I have a couple of questions :
    – will there be a library of pre-made widgets done by Thingstudio (you?) which we could use and skip this whole process? Just like the few that already exist, only more… I think we’re missing the buttons and light bulb indicators now…
    – will we be able to make a copy of widgets from the library and then change them in some way, like changing colours or adding elements and then use them as our own, with our name?
    – would we be able to have personal library of widgets which would have our own widgets, made from scratch, modified ones by copying and editing the ones from Thingstudio’s library, and unmodified ones as well?
    – is it possible (or would be) to make “combined” widgets which would be sort of a container for more basic widgets and which could be used as one object? For example, thermometer and indicator together, so when thermometer goes above certain temperature, inicator starts to blink or something…

    Thanks, Andrea

    1. Mike Karliner

      Hi Andrea, glad you like the post.
      In answer to your questions:
      1) Yes, we will be making more widgets and we are happy to get suggestions.
      We have been busy on putting in more transports (HTTP etc) so the core
      has taken up our time lately, but we’ll be getting back to widgets.
      2)Yes, you will be able to clone widgets. Originally, we had the source code for
      each widget in summary page, but it confused people so we took it out. Internally,
      we already have a widget dump and load, we’ll be making that available when we
      have finished refactoring the widget system to make it simpler. What we intend
      is a more general facility that allows you to check your code in and out of git(hub).
      3) Yes – you can make a library of widgets today. If you populate an app with just
      widgets then you can base other apps on that and they will inherit the widgets.
      We have plans to allow you to share your widgets with other users, maybe for money.
      4)Yes, you should be able to stack up widgets. I haven’t tried it, but I see no reason it wouldn’t
      work today. With the new widget system it will definitely work.

      Mike

Leave a Reply

Your email address will not be published. Required fields are marked *