Weather Cal
This is a Scriptable widget that lets you display, position, and format multiple elements without writing any Javascript code. There are many built-in widget items, including events, reminders, weather, battery, and much more. Weather Cal also fully supports custom items, and you can even embed existing widgets into Weather Cal layouts.
Table of contents
Setup
Setting up Weather Cal is easy:
-
Copy the code in weather-cal.js. (You don't need to do anything with weather-cal-code.js.)
-
Paste the code into a new Scriptable script. This is the widget script.
-
Run the script. It will download the code script in the background and walk you through each step of the setup process.
Once Weather Cal is set up, you can make multiple widgets by duplicating the widget script. You only need one copy of the Weather Cal code script.
If you want a transparent or translucent widget, use the Widget Blur script. At the end of that script, select "Export to Photos", and then use the photo as your widget background.
Settings
Once you've set up Weather Cal, run the widget script again to access the settings menu, where you can:
- Show a preview in the Scriptable app
- Change the background
- Edit your preferences for the widget
- Re-enter your OpenWeather API key
- Update the backend code for Weather Cal
- Reset your widget back to default settings
In the preferences menu, you can change the overall widget settings, customize the font, size, color, and language of text, and adjust settings for each individual widget item.
Layout
The only aspect of the widget that you can't change in the settings menu is the layout. Luckily, it's easy to do. In the widget script, you'll see a section that looks similar to this:
row
column
date
sunset
battery
space
events
column(90)
current
future
The layout is just a list of widget items and layout items. Keep reading to find out which items are available and how to position them on the widget.
Widget items
You can add the following items to your widget:
battery
covid
date
events
greeting
reminders
sunrise
, which shows the sunrise or sunset time automatically- custom
text
, by writingtext(Your text here)
- Weather items
current
conditionsfuture
weather (next hour or next day)hourly
forecast listdaily
forecast list
week
- week number for current Date
If you want to change how an item looks, run the widget script and choose "Edit preferences". Most items allow you to adjust how they display.
Spacing and alignment
You can change the layout of the widget using the following layout items:
-
The
row
andcolumn
items create the structure of the widget. You can add or remove rows and columns, just remember that you always need at least one row and one column, and every row has to start with a column. If you want to specify the size of a row or column, use parentheses:row(50)
orcolumn(100)
. -
You can add an alignment item (
left
,right
, orcenter
) anywhere in the layout, and it will align everything after it. -
Using
space
will add a space that automatically expands to fill the vertical space, pushing the items above and below it. You can make fixed-sized spaces using parentheses, like this:space(50)
.
ASCII
If you want to draw your widget using ASCII, delete all of the items and draw your widget like this:
-------------------
|date | 90 |
|battery |current |
|sunrise |future |
| | |
-------------------
| events|
-------------------
A full line of -
(dashes) starts and ends the widget, or makes a new row. Put |
(pipes) around each column. The spaces around each element name will determine the alignment (left, right, or center). For example, events
are aligned to the right in the example above. Adding a row with nothing in it will add a flexible space. Starting a column with a number will set it to that width. (The right-hand column in the example above has a width of 90.)
Technical details
Weather Cal consists of the following components:
- A container script (weather-cal.js) that houses the user's layout, settings, and any customizations.
- A modular code script (weather-cal-code.js) with the following elements:
- A layout generator that converts simple, text-based layout descriptions into logical
WidgetStack
structures. - A collection of commonly-used widget items, including the date, upcoming events, and weather information.
- A preferences editor that lets users customize how each item looks and behaves.
- A set of helper functions for the built-in features that can also be used by custom elements.
- A layout generator that converts simple, text-based layout descriptions into logical
Additional documentation will be in the wiki, once it is ready.
Custom elements
You can create custom backgrounds and widget items that are not deleted when you update the Weather Cal code script. You can override any of the built-in widget items, and you can even embed existing widgets.
To begin, copy and paste const custom = { }
right after const code
is declared. Your code should look like this:
const code = importModule(codeFilename)
const custom = { }
Then, modify the entire line that begins with const widget
so it looks like this:
const widget = await code.createWidget(layout, Script.name(), iCloudInUse, custom)
The "Update code" feature never modifies the weather-cal.js file, so your customizations will remain even after you update. Just make sure not to use the "Reset widget" feature, or it will overwrite your code.
Custom backgrounds
If you want to write your own code for the widget background, just declare a background
method in your custom
object. This method must have a single widget
argument, which Weather Cal uses to pass the ListWidget
object. If this method exists, it will override the background setting of your widget. Here's a simple example:
const custom = {
background(widget) {
widget.backgroundColor = Color.black()
},
}
Custom items
You can create your own widget items or even override the functionality of a built-in item. Declare a method in the custom
object with the name of the element you'd like to create or override. Give it has a single column
argument, which represents the WidgetStack
object that the item will be added to. For example:
const custom = {
item(column) {
// Your code here
},
}
You can use any of Weather Cal's shared objects and helper functions through the code
object. For example, you can use the provideText
function and the format
object to display text using one of the built-in formats, like this:
const custom = {
item(column) {
code.provideText("My text here", column, code.format.smallDate)
},
}
This code will display "My text here" using the small date format that's specified in the preferences.
Documentation for Weather Cal's helper functions will be available in the wiki once it is ready.
Embed existing widgets
Weather Cal supports embedding other Scriptable widgets. This allows you to position them alongisde Weather Cal elements to create more flexible layouts. For example, showing Weather Cal, PurpleAir Air Quality, and Random Scriptable API would normally take three separate widgets. By embedding the widgets into Weather Cal, we can acheive this with a single large widget and only one "Scriptable" label:
Here's how it works:
- Before you start, follow these directions to enable custom elements.
- Copy weather-cal-converter.js into Scriptable and run it.
- Choose a name. This is the word you'll be adding to the Weather Cal layout.
- Select the file containing the widget script.
- When it displays the code, use the share icon in the top right to copy the text.
- Open a Weather Cal widget script and paste the code into the custom object after the comment. If you're pasting multiple items, make sure to paste it after the previous comma but before the final bracket.
- In your Weather Cal layout, add the name of your new widget item.
Note: Using the conversion script will almost certainly break the "Show widget preview" function in WeatherCal. Your widget should still render correctly on your home screen. If you're comfortable editing Javascript directly, you just need to remove code that detects when the widget is running in the Scriptable app (usually an if statement with config.runsInWidget
or config.runsInApp
).