├── .github
└── workflows
│ └── mdbook.yml
├── .gitignore
├── README.txt
├── book.toml
└── src
├── 404.md
├── README.md
├── SUMMARY.md
├── firmware
├── README.md
├── building.md
├── download
│ ├── alt_time-blue.uf2
│ ├── alt_time-green.uf2
│ ├── deep_space_now-blue.uf2
│ ├── deep_space_now-green.uf2
│ ├── focus-blue.uf2
│ ├── focus-green.uf2
│ ├── standard-blue.uf2
│ ├── standard-green.uf2
│ ├── the_athlete-blue.uf2
│ ├── the_athlete-green.uf2
│ ├── the_backpacker-blue.uf2
│ ├── the_backpacker-green.uf2
│ ├── the_stargazer-blue.uf2
│ └── the_stargazer-green.uf2
├── emulator.md
├── prebuilt.md
└── simulate
│ ├── alt_time
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
│ ├── deep_space_now
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
│ ├── focus
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
│ ├── standard
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
│ ├── the_athlete
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
│ ├── the_backpacker
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
│ └── the_stargazer
│ ├── index.html
│ ├── watch.js
│ └── watch.wasm
├── images
└── sensor-watch.jpg
├── movement
└── README.md
├── segmap.html
├── sensorboards
├── README.md
├── images
│ ├── sensor-board.png
│ └── temperature-gpio-sensor-board.png
└── temperature.md
├── tooltipster
├── LICENSE
└── dist
│ ├── css
│ ├── plugins
│ │ └── tooltipster
│ │ │ └── sideTip
│ │ │ └── themes
│ │ │ ├── tooltipster-sideTip-borderless.min.css
│ │ │ ├── tooltipster-sideTip-light.min.css
│ │ │ ├── tooltipster-sideTip-noir.min.css
│ │ │ ├── tooltipster-sideTip-punk.min.css
│ │ │ └── tooltipster-sideTip-shadow.min.css
│ ├── tooltipster.bundle.css
│ ├── tooltipster.bundle.min.css
│ ├── tooltipster.main.css
│ └── tooltipster.main.min.css
│ └── js
│ ├── plugins
│ └── tooltipster
│ │ └── SVG
│ │ ├── tooltipster-SVG.js
│ │ └── tooltipster-SVG.min.js
│ ├── tooltipster.bundle.js
│ ├── tooltipster.bundle.min.js
│ ├── tooltipster.main.js
│ └── tooltipster.main.min.js
├── watchfaces
├── README.md
├── clock.md
├── complication.md
├── demo.md
├── sensor.md
└── settings.md
└── wig
├── README.md
├── bigpicture.md
├── display.md
└── images
├── accelerometer-example.png
├── activity-example.png
├── casio-basics.png
├── clock-7-up.png
├── clock-apogee.png
├── clock-example.png
├── clock-high-tide.png
├── clock-ranked-pixel.png
├── clock-shared-segments.png
├── clock-with-without-colon.png
├── day-example.png
├── day-shared-segments.png
├── indicators.png
├── positions-labeled.png
├── segments-labeled.png
├── sunrise-sunset-example.png
├── temperature-app.png
├── temperature-log-app-1.png
├── temperature-log-app-timestamp.png
├── temperature-log-app.png
├── tide-app.png
└── weekday-shared-segments.png
/.github/workflows/mdbook.yml:
--------------------------------------------------------------------------------
1 | name: Deploy mdBook
2 | on: [push]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v2
8 | - uses: XAMPPRocky/deploy-mdbook@v1.1
9 | with:
10 | token: ${{ secrets.GITHUB_TOKEN }}
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | book
3 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | This repisotory is archived and no longer updated.
2 |
3 | For the latest documentation, visit https://www.sensorwatch.net/docs/
4 |
5 | To contribute to that documentation, open a pull request here: https://github.com/joeycastillo/sensorwatch.net
6 |
--------------------------------------------------------------------------------
/book.toml:
--------------------------------------------------------------------------------
1 | [output.html]
2 | site-url = "/Sensor-Watch-Documentation/"
3 |
--------------------------------------------------------------------------------
/src/404.md:
--------------------------------------------------------------------------------
1 | File Not Found
2 | ==============
3 |
4 | Looking for the Sensor Watch Doxygen docs? They've moved! [Look over here](https://joeycastillo.github.io/Sensor-Watch/).
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | The Sensor Watch
2 | ================
3 |
4 | The Sensor Watch is a board replacement for the classic Casio F‑91W wristwatch. It is powered by a Microchip SAM L22 microcontroller with built-in segment LCD controller. You can write your own programs for the watch using the provided watch library, program the watch over USB using the built-in UF2 bootloader, and then install the board in your existing watch case to run your own software on your wrist.
5 |
6 | 
7 |
8 | Features:
9 | * ARM Cortex M0+ microcontroller
10 | * 32KHz crystal for real-time clock with alarm function
11 | * Ten digit segment LCD, plus five indicator segments
12 | * Three interrupt capable buttons
13 | * Red / green PWM’able LED backlight
14 | * Optional piezo buzzer (requires some light soldering)
15 | * On-board USB Micro B connector
16 | * Reset button with double-tap UF2 bootloader
17 | * Nine-pin flex PCB connector
18 |
--------------------------------------------------------------------------------
/src/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | - [The Sensor Watch](README.md)
4 | - [Firmware Info](firmware/README.md)
5 | - [Prebuilt Firmware for Sensor Watch](firmware/prebuilt.md)
6 | - [Building Sensor Watch Firmware]()
7 | - [Building for the Sensor Watch Emulator]()
8 | - [Watch Interface Guidelines (WIG)](wig/README.md)
9 | - [Big Picture Stuff](wig/bigpicture.md)
10 | - [Sensor Watch Display](wig/display.md)
11 | - [Sensor Watch Buttons]()
12 | - [Sensor Watch Power Management]()
13 | - [Putting It All Together]()
14 | - [Watch Face Documentation](watchfaces/README.md)
15 | - [Clocks](watchfaces/clock.md)
16 | - [Complications](watchfaces/complication.md)
17 | - [Sensor Data](watchfaces/sensor.md)
18 | - [Settings](watchfaces/settings.md)
19 | - [Demos](watchfaces/demo.md)
20 | - [More about Movement](movement/README.md)
21 | - [Writing a watch face for Movement]()
22 | - [Contributing to the Community Firmware]()
23 | - [Tips and tricks for Movement]()
24 | - [Sensor Boards](sensorboards/README.md)
25 | - [Temperature + GPIO Sensor Board](sensorboards/temperature.md)
26 |
--------------------------------------------------------------------------------
/src/firmware/README.md:
--------------------------------------------------------------------------------
1 | Sensor Watch Firmware
2 | =====================
3 |
4 | While you can build any number of bare-metal applications for Sensor Watch, when we refer to the Sensor Watch firmware, we're really talking about _Movement_, the community firmware for Sensor Watch. You can read more about Movement [here](); for now, the important thing to know is that it manages a series of _watch faces_ that you advance through using the _mode_ button. It's a very similar idiom to the classic Casio F-91W, which advances from `Clock -> Alarm -> Stopwatch -> Time Set`, and then wraps around to `Clock`.
5 |
6 | Movement offers many more watch faces — some of which, like World Clock, you can include more than once! Still: you'd be pressing the Mode button for hours if we included them all, so instead, we only build a subset of the available faces into any given firmware. This means that you can [download an alternate firmware]() that includes the kind of functionality you want, or [build custom firmware]() that includes just the watch faces you desire.
7 |
8 | * [Download prebuilt firmware for Sensor Watch](prebuilt.md)
9 | * [Building custom firmware for Sensor Watch](building.md)
10 | * [Building custom firmware for the Sensor Watch Emulator](emulator.md)
11 |
--------------------------------------------------------------------------------
/src/firmware/building.md:
--------------------------------------------------------------------------------
1 | Building Custom Movement Firmware for Sensor Watch
2 | ==================================================
3 |
4 | TODO
--------------------------------------------------------------------------------
/src/firmware/download/alt_time-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/alt_time-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/alt_time-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/alt_time-green.uf2
--------------------------------------------------------------------------------
/src/firmware/download/deep_space_now-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/deep_space_now-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/deep_space_now-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/deep_space_now-green.uf2
--------------------------------------------------------------------------------
/src/firmware/download/focus-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/focus-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/focus-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/focus-green.uf2
--------------------------------------------------------------------------------
/src/firmware/download/standard-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/standard-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/standard-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/standard-green.uf2
--------------------------------------------------------------------------------
/src/firmware/download/the_athlete-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/the_athlete-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/the_athlete-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/the_athlete-green.uf2
--------------------------------------------------------------------------------
/src/firmware/download/the_backpacker-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/the_backpacker-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/the_backpacker-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/the_backpacker-green.uf2
--------------------------------------------------------------------------------
/src/firmware/download/the_stargazer-blue.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/the_stargazer-blue.uf2
--------------------------------------------------------------------------------
/src/firmware/download/the_stargazer-green.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/download/the_stargazer-green.uf2
--------------------------------------------------------------------------------
/src/firmware/emulator.md:
--------------------------------------------------------------------------------
1 | Building Firmware for the Sensor Watch Emulator
2 | ===============================================
3 |
4 | TODO
--------------------------------------------------------------------------------
/src/firmware/prebuilt.md:
--------------------------------------------------------------------------------
1 | Prebuilt Alternative Firmware for Sensor Watch
2 | ==============================================
3 |
4 | This section contains the stock firmware for Sensor Watch, as well as several prebuilt firmware images featuring an alternative set of watch faces.
5 |
6 | ### Prebuilt Firmwares
7 |
8 | Note that each fimware comes in two flavors, depending on the color of your circuit board. This is because blue boards have a red/blue LED and green boards have a red/green LED, and the pins are swapped. No damage will result from loading the wrong firmware onto your board, but the LED colors will be wrong.
9 |
10 | Also note that all of these have the "Preferences" and "Time Set" screens at the end; for brevity they aren't included in this listing, but you will always have access to them.
11 |
12 | * [Movement Standard](#movement-standard): Simple Clock, World Clock, Sunrise/Sunset, Moon Phase, Temperature
13 | * [Focus](#focus): Simple Clock, Tomato Timer, Stopwatch, Countdown
14 | * [The Athlete](#the-athlete): Simple Clock, Stopwatch, Countdown, Exercise Counter, Pulsometer
15 | * [The Backpacker](#the-backpacker): Simple Clock, Sunrise/Sunset, Temperature, Temperature Log, Blinky Light
16 | * [The Stargazer](#the-stargazer): Simple Clock, Astronomy, Sunrise/Sunset, Moon Phase
17 | * [Deep Space Now](#deep-space-now): Simple Clock, Mars Time, World Clock x3
18 | * [alt.time](#alttime): Simple Clock, Beat Time, Day One
19 |
20 | Movement Standard
21 | -----------------
22 |
23 | **Required Sensor Board:** Temperature Sensor
24 |
25 | This is the standard firmware for Movement. It's packed, but not jam-packed:
26 |
27 | * Simple Clock - A basic clock with date for timekeeping.
28 | * World Clock - You can configure this with a custom two-letter title and any time zone.
29 | * Sunrise/Sunset - Local sunrise and sunset times.
30 | * Moon Phase - Tonight's moon phase. (press Alarm to see days in the future)
31 | * Temperature - As measured from the temperature sensor board. (Alarm toggles C or F)
32 |
33 | Download it now: for [Green Boards](download/standard-green.uf2) and [Blue Boards](download/standard-blue.uf2)
34 |
35 | Try it out: [Sensor Watch Emulator](simulate/standard/)
36 |
37 | Focus
38 | -----
39 |
40 | **Required Mod:** Tomato and countdown timer requires soldering the buzzer connector.
41 |
42 | For folks who want to use the watch for productivity.
43 |
44 | * Simple Clock - A basic clock with date for timekeeping.
45 | * Tomato Timer (by Wesley Ellis) - A productivity timer varietal.
46 | * Stopwatch (by Wesley Ellis) - A simple stopwatch with one-second resolution.
47 | * Countdown (by Wesley Ellis) - A simple countdown timer for eggs, tea or tasks.
48 |
49 | Download it now: for [Green Boards](download/focus-green.uf2) and [Blue Boards](download/focus-blue.uf2)
50 |
51 | Try it out: [Sensor Watch Emulator](simulate/focus/)
52 |
53 | The Athlete
54 | -----------
55 |
56 | **Required Mod:** Countdown timer requires soldering the buzzer connector.
57 |
58 | For folks who want to use the watch for fitness.
59 |
60 | * Simple Clock - A basic clock with date for timekeeping.
61 | * Stopwatch (by Wesley Ellis) - It counts up.
62 | * Countdown (by Wesley Ellis) - It counts down.
63 | * Exercise Counter (by Shogo Okamoto) - Designed for tracking a number of exercises by pressing the Alarm button.
64 | * Pulsometer - Hold the Alarm button while touching a vein on your neck, and count 30 beats. Release for your heart rate.
65 |
66 | Download it now: for [Green Boards](download/the_athlete-green.uf2) and [Blue Boards](download/the_athlete-blue.uf2)
67 |
68 | Try it out: [Sensor Watch Emulator](simulate/the_athlete/)
69 |
70 | The Backpacker
71 | --------------
72 |
73 | **Required Sensor Board:** Temperature Sensor
74 |
75 | This watch face is focused on helping you when out in the backcountry.
76 |
77 | * Simple Clock - A basic clock with date for timekeeping.
78 | * Sunrise/Sunset - Local sunrise and sunset times. Don't get caught in the dark!
79 | * Moon Phase - Tonight's moon phase. For when the sun fails you.
80 | * Temperature - As measured from the temperature sensor board. (Alarm button toggles C or F)
81 | * Temperature Log - A 36-hour log. Toss the watch outside your tent to measure overnight lows.
82 | * Blinky Light - This will chew through your battery, but could be useful in an emergency.
83 |
84 | Download it now: for [Green Boards](download/the_backpacker-green.uf2) and [Blue Boards](download/the_backpacker-blue.uf2)
85 |
86 | Try it out: [Sensor Watch Emulator](simulate/the_backpacker/)
87 |
88 | The Stargazer
89 | -------------
90 |
91 | For folks who think space is the place!
92 |
93 | * Simple Clock - A basic clock with date for timekeeping.
94 | * Astronomy - Calculates altitude, azimuth, right ascension and declination for all planets
95 | * Sunrise/Sunset - Local sunrise and sunset times.
96 | * Moon Phase - Today's moon phase. (press Alarm to see days in the future)
97 |
98 | Download it now: for [Green Boards](download/the_stargazer-green.uf2) and [Blue Boards](download/the_stargazer-blue.uf2)
99 |
100 | Try it out: [Sensor Watch Emulator](simulate/the_stargazer/)
101 |
102 | Deep Space Now
103 | --------------
104 |
105 | For folks who work in deep space. (no, really!)
106 |
107 | * Simple Clock - A basic clock with date for timekeeping.
108 | * Mars Time - Displays Mars Standard Time, or local mean solar time and mission sol for each active mission on Mars.
109 | * World Clock - One slot for the ground station in Goldstone (California, USA)
110 | * World Clock - One slot for the ground station in Madrid (Spain)
111 | * World Clock - One slot for the ground station in Canberra (Australia)
112 | * Day One - Counts the number of days from a given date. Try plugging in the start of a mission (i.e. August 20, 1977) to get mission day.
113 |
114 | Download it now: for [Green Boards](download/deep_space_now-green.uf2) and [Blue Boards](download/deep_space_now-blue.uf2)
115 |
116 | Try it out: [Sensor Watch Emulator](simulate/deep_space_now/)
117 |
118 | alt.time
119 | --------
120 |
121 | For fans of alternative timekeeping systems.
122 |
123 | * Simple Clock - A basic clock with date for timekeeping.
124 | * Beat Time (by Wesley Ellis) - AKA Swatch Internet Time, a decimal time standard centered on Switzerland.
125 | * Day One - Counts the number of days from a given date. Try plugging in your birthday!
126 |
127 | I hope to expand this face in the future. (International Fixed Calendar, anyone?)
128 |
129 | Download it now: for [Green Boards](download/alt_time-green.uf2) and [Blue Boards](download/alt_time-blue.uf2)
130 |
131 | Try it out: [Sensor Watch Emulator](simulate/alt_time/)
132 |
--------------------------------------------------------------------------------
/src/firmware/simulate/alt_time/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/alt_time/watch.wasm
--------------------------------------------------------------------------------
/src/firmware/simulate/deep_space_now/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/deep_space_now/watch.wasm
--------------------------------------------------------------------------------
/src/firmware/simulate/focus/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/focus/watch.wasm
--------------------------------------------------------------------------------
/src/firmware/simulate/standard/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/standard/watch.wasm
--------------------------------------------------------------------------------
/src/firmware/simulate/the_athlete/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/the_athlete/watch.wasm
--------------------------------------------------------------------------------
/src/firmware/simulate/the_backpacker/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/the_backpacker/watch.wasm
--------------------------------------------------------------------------------
/src/firmware/simulate/the_stargazer/watch.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/firmware/simulate/the_stargazer/watch.wasm
--------------------------------------------------------------------------------
/src/images/sensor-watch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/images/sensor-watch.jpg
--------------------------------------------------------------------------------
/src/movement/README.md:
--------------------------------------------------------------------------------
1 | Movement: The Community Firmware for Sensor Watch
2 | =================================================
3 |
4 | _Movement_ is an application that manages the display of different screens of content on the watch. These screens are called _watch faces_. Watch faces can be passive displays of information like a clock or a calendar, or they can be fully interactive user interfaces like the Preferences face, which allows the user to customize Movement's behavior.
5 |
6 | Movement handles the instantiation of your watch face and manages transitions between screens. It also provides a low-power sleep mode, triggered after a period of inactivity, to preserve the watch battery.
7 |
8 | Several faces are provided that offer baseline functionality like a clock, a settings screen and an interface for setting the time. You can change and reorder the watch faces that Movement displays by editing movement_config.h, and you can write your own watch face using the guidance in this chapter.
9 |
10 | Sections (TODO)
11 | ---------------
12 |
13 | - Writing a watch face for Movement
14 | - Contributing to the Community Firmware
15 | - Tips and tricks for Movement
16 |
--------------------------------------------------------------------------------
/src/sensorboards/README.md:
--------------------------------------------------------------------------------
1 | Sensor Watch Accessory Boards (aka Sensor Boards)
2 | =================================================
3 |
4 | 
5 |
6 | You may have noticed that there are no sensors on this board. That is by design: rather than pick sensors for you, the goal is to add a tiny flexible PCB with the sensors YOU want, and interface them over the nine-pin connector. The connector provides the following options for power and connectivity:
7 |
8 | * 3V power (nominal voltage from a CR2016 coin cell, can drop to ~2.7V)
9 | * An I²C interface with built-in pull-up resistors
10 | * Five general purpose IO pins, which can be configured as:
11 | * Five analog inputs
12 | * Five interrupt-capable digital inputs, with internal pull-up or pull-down resistors
13 | * Five digital outputs
14 | * SPI controller (with one spare analog / GPIO pin leftover)
15 | * One UART TX/RX pair (with three GPIO leftover)
16 | * Up to four PWM pins on two independent TC instances
17 | * Two external wake inputs that can wake from the ultra-low-power BACKUP mode
18 |
19 | | **Pin** | **Digital** | **Interrupt** | **Analog** | **I2C** | **SPI** | **UART** | **PWM** | **Ext. Wake** |
20 | | :-----: | :---------: | :-------------: | :-----------: | :-----------------: | :------------------: | :----------------------: | :------: | :-----------: |
21 | | **A0** | PB04 | EIC/EXTINT\[4\] | ADC/AIN\[12\] | — | — | — | — | — |
22 | | **SCL** | — | — | — | SCL
SERCOM1\[1\] | — | — | — | — |
23 | | **SDA** | — | — | — | SDA
SERCOM1\[0\] | — | — | — | — |
24 | | **A1** | PB01 | EIC/EXTINT\[1\] | ADC/AIN\[9\] | — | SCK
SERCOM3\[3\] | RX
SERCOM3\[3\] | TC3\[1\] | — |
25 | | **A2** | PB02 | EIC/EXTINT\[2\] | ADC/AIN\[10\] | — | MOSI
SERCOM3\[0\] | TX or RX
SERCOM3\[0\] | TC2\[0\] | RTC/IN\[1\] |
26 | | **A3** | PB03 | EIC/EXTINT\[3\] | ADC/AIN\[11\] | — | CS
SERCOM3\[1\] | RX
SERCOM3\[1\] | TC2\[1\] | — |
27 | | **A4** | PB00 | EIC/EXTINT\[0\] | ADC/AIN\[8\] | — | MISO
SERCOM3\[2\] | TX or RX
SERCOM3\[2\] | TC3\[0\] | RTC/IN\[0\] |
28 |
29 | These tiny “sensor boards” have a set outline, and the available area for your electronics is quite small (5.7 × 5.7 × 1 mm). Still, this is plenty of room for an environmental sensor, MEMS accelerometer or magnetometer and a couple of decoupling capacitors. Note that you will likely be limited to QFN and LGA type parts; SOICs are too large, and even SSOP packages are generally too thick. You can find reference designs for several sensor boards in [the PCB/Sensor Boards directory](https://github.com/joeycastillo/Sensor-Watch/tree/main/PCB/Sensor%20Boards) in the Sensor Watch repository.
30 |
--------------------------------------------------------------------------------
/src/sensorboards/images/sensor-board.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/sensorboards/images/sensor-board.png
--------------------------------------------------------------------------------
/src/sensorboards/images/temperature-gpio-sensor-board.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/sensorboards/images/temperature-gpio-sensor-board.png
--------------------------------------------------------------------------------
/src/sensorboards/temperature.md:
--------------------------------------------------------------------------------
1 | Sensor Watch Accessory Board: Temperarure + GPIO
2 | ================================================
3 |
4 | 
5 |
6 | This sensor board shipped (or will ship) to all Sensor Watch Crowd Supply backers. It is also available for separate purchase at the Sensor Watch page on Crowd Supply.
7 |
8 | Temperature
9 | -----------
10 |
11 | The Temperature and GPIO board includes two passive components on the front, a very precise 10 kΩ resistor and a 10 kΩ thermistor, that together form a voltage divider. While the resistance of the 10 kΩ resistor stays very close to 10 kΩ at all temperatures, the thermistor's resistance goes down as the temperature rises, and goes up as the temperature falls. This changes the voltage that's measured at the middle of the voltage divider, and with some clever math, we can turn that voltage into a very precise temperature reading.
12 |
13 | While the watch library's thermistor driver is preconfigured with all required parameters for this calculation, we'll repeat them here for completeness:
14 |
15 | * The resistor has a value of 10 kilo-ohms with a tolerance of 0.1%
16 | * The thermistor has a nominal value of 10 kilo-ohms at 25° C, and a B coefficient of 3380K
17 |
18 | GPIO
19 | ----
20 |
21 | In addition, this sensor board breaks out test points on the underside for six nets: power and ground, the I2C pins SDA and SCL, as well as two GPIO pins, A1 and A4. It will be fiddly, but you can solder fine enamel wires to these test points to connect other kinds of gadgets to your Sensor Watch, whether to test out possibilities for future sensor boards or to bodge in a device with additional functions you want.
22 |
23 | **Note that if you solder to these test pads, you must cover the five test points on the Sensor Watch board with tape!** It's possible for the solder bumps you create on the underside of the sensor board to touch the main Sensor Watch board, so you must electrically isolate them with tape.
24 |
25 | The A1 and A4 pins are very versatile. You can use these two pins as:
26 |
27 | * General purpose digital IO to drive a low current device like a sensor or LED
28 | * Analog inputs to read an analog value from a circuit like a phototransistor
29 | * PWM output (they are both on the same TC3 peripheral)
30 | * Input to the TC3 counter peripheral for frequency measurement
31 | * UART transmit (A4) and receive (A1)
32 | * External interrupt inputs
33 |
34 | In addition, you can use pin A4 as an external wake interrupt, which can wake the watch from the ultra-low-power BACKUP mode.
35 |
--------------------------------------------------------------------------------
/src/tooltipster/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2012,2016 Caleb Jacob and Louis Ameline
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-borderless.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-sidetip.tooltipster-borderless .tooltipster-box{border:none;background:#1b1b1b;background:rgba(10,10,10,.9)}.tooltipster-sidetip.tooltipster-borderless.tooltipster-bottom .tooltipster-box{margin-top:8px}.tooltipster-sidetip.tooltipster-borderless.tooltipster-left .tooltipster-box{margin-right:8px}.tooltipster-sidetip.tooltipster-borderless.tooltipster-right .tooltipster-box{margin-left:8px}.tooltipster-sidetip.tooltipster-borderless.tooltipster-top .tooltipster-box{margin-bottom:8px}.tooltipster-sidetip.tooltipster-borderless .tooltipster-arrow{height:8px;margin-left:-8px;width:16px}.tooltipster-sidetip.tooltipster-borderless.tooltipster-left .tooltipster-arrow,.tooltipster-sidetip.tooltipster-borderless.tooltipster-right .tooltipster-arrow{height:16px;margin-left:0;margin-top:-8px;width:8px}.tooltipster-sidetip.tooltipster-borderless .tooltipster-arrow-background{display:none}.tooltipster-sidetip.tooltipster-borderless .tooltipster-arrow-border{border:8px solid transparent}.tooltipster-sidetip.tooltipster-borderless.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#1b1b1b;border-bottom-color:rgba(10,10,10,.9)}.tooltipster-sidetip.tooltipster-borderless.tooltipster-left .tooltipster-arrow-border{border-left-color:#1b1b1b;border-left-color:rgba(10,10,10,.9)}.tooltipster-sidetip.tooltipster-borderless.tooltipster-right .tooltipster-arrow-border{border-right-color:#1b1b1b;border-right-color:rgba(10,10,10,.9)}.tooltipster-sidetip.tooltipster-borderless.tooltipster-top .tooltipster-arrow-border{border-top-color:#1b1b1b;border-top-color:rgba(10,10,10,.9)}.tooltipster-sidetip.tooltipster-borderless.tooltipster-bottom .tooltipster-arrow-uncropped{top:-8px}.tooltipster-sidetip.tooltipster-borderless.tooltipster-right .tooltipster-arrow-uncropped{left:-8px}
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-light.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-sidetip.tooltipster-light .tooltipster-box{border-radius:3px;border:1px solid #ccc;background:#ededed}.tooltipster-sidetip.tooltipster-light .tooltipster-content{color:#666}.tooltipster-sidetip.tooltipster-light .tooltipster-arrow{height:9px;margin-left:-9px;width:18px}.tooltipster-sidetip.tooltipster-light.tooltipster-left .tooltipster-arrow,.tooltipster-sidetip.tooltipster-light.tooltipster-right .tooltipster-arrow{height:18px;margin-left:0;margin-top:-9px;width:9px}.tooltipster-sidetip.tooltipster-light .tooltipster-arrow-background{border:9px solid transparent}.tooltipster-sidetip.tooltipster-light.tooltipster-bottom .tooltipster-arrow-background{border-bottom-color:#ededed;top:1px}.tooltipster-sidetip.tooltipster-light.tooltipster-left .tooltipster-arrow-background{border-left-color:#ededed;left:-1px}.tooltipster-sidetip.tooltipster-light.tooltipster-right .tooltipster-arrow-background{border-right-color:#ededed;left:1px}.tooltipster-sidetip.tooltipster-light.tooltipster-top .tooltipster-arrow-background{border-top-color:#ededed;top:-1px}.tooltipster-sidetip.tooltipster-light .tooltipster-arrow-border{border:9px solid transparent}.tooltipster-sidetip.tooltipster-light.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#ccc}.tooltipster-sidetip.tooltipster-light.tooltipster-left .tooltipster-arrow-border{border-left-color:#ccc}.tooltipster-sidetip.tooltipster-light.tooltipster-right .tooltipster-arrow-border{border-right-color:#ccc}.tooltipster-sidetip.tooltipster-light.tooltipster-top .tooltipster-arrow-border{border-top-color:#ccc}.tooltipster-sidetip.tooltipster-light.tooltipster-bottom .tooltipster-arrow-uncropped{top:-9px}.tooltipster-sidetip.tooltipster-light.tooltipster-right .tooltipster-arrow-uncropped{left:-9px}
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-noir.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-sidetip.tooltipster-noir .tooltipster-box{border-radius:0;border:3px solid #000;background:#fff}.tooltipster-sidetip.tooltipster-noir .tooltipster-content{color:#000}.tooltipster-sidetip.tooltipster-noir .tooltipster-arrow{height:11px;margin-left:-11px;width:22px}.tooltipster-sidetip.tooltipster-noir.tooltipster-left .tooltipster-arrow,.tooltipster-sidetip.tooltipster-noir.tooltipster-right .tooltipster-arrow{height:22px;margin-left:0;margin-top:-11px;width:11px}.tooltipster-sidetip.tooltipster-noir .tooltipster-arrow-background{border:11px solid transparent}.tooltipster-sidetip.tooltipster-noir.tooltipster-bottom .tooltipster-arrow-background{border-bottom-color:#fff;top:4px}.tooltipster-sidetip.tooltipster-noir.tooltipster-left .tooltipster-arrow-background{border-left-color:#fff;left:-4px}.tooltipster-sidetip.tooltipster-noir.tooltipster-right .tooltipster-arrow-background{border-right-color:#fff;left:4px}.tooltipster-sidetip.tooltipster-noir.tooltipster-top .tooltipster-arrow-background{border-top-color:#fff;top:-4px}.tooltipster-sidetip.tooltipster-noir .tooltipster-arrow-border{border-width:11px}.tooltipster-sidetip.tooltipster-noir.tooltipster-bottom .tooltipster-arrow-uncropped{top:-11px}.tooltipster-sidetip.tooltipster-noir.tooltipster-right .tooltipster-arrow-uncropped{left:-11px}
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-punk.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-sidetip.tooltipster-punk .tooltipster-box{border-radius:5px;border:none;border-bottom:3px solid #f71169;background:#2a2a2a}.tooltipster-sidetip.tooltipster-punk.tooltipster-top .tooltipster-box{margin-bottom:7px}.tooltipster-sidetip.tooltipster-punk .tooltipster-content{color:#fff;padding:8px 16px}.tooltipster-sidetip.tooltipster-punk .tooltipster-arrow-background{display:none}.tooltipster-sidetip.tooltipster-punk.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#2a2a2a}.tooltipster-sidetip.tooltipster-punk.tooltipster-left .tooltipster-arrow-border{border-left-color:#2a2a2a}.tooltipster-sidetip.tooltipster-punk.tooltipster-right .tooltipster-arrow-border{border-right-color:#2a2a2a}.tooltipster-sidetip.tooltipster-punk.tooltipster-top .tooltipster-arrow-border{border-top-color:#f71169}
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-shadow.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-box{border:none;border-radius:5px;background:#fff;box-shadow:0 0 10px 6px rgba(0,0,0,.1)}.tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-box{margin-top:6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-box{margin-right:6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-box{margin-left:6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-top .tooltipster-box{margin-bottom:6px}.tooltipster-sidetip.tooltipster-shadow .tooltipster-content{color:#8d8d8d}.tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow{height:6px;margin-left:-6px;width:12px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-arrow,.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow{height:12px;margin-left:0;margin-top:-6px;width:6px}.tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow-background{display:none}.tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow-border{border:6px solid transparent}.tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-arrow-border{border-left-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow-border{border-right-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-top .tooltipster-arrow-border{border-top-color:#fff}.tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-arrow-uncropped{top:-6px}.tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow-uncropped{left:-6px}
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/tooltipster.bundle.css:
--------------------------------------------------------------------------------
1 | /* This is the core CSS of Tooltipster */
2 |
3 | /* GENERAL STRUCTURE RULES (do not edit this section) */
4 |
5 | .tooltipster-base {
6 | /* this ensures that a constrained height set by functionPosition,
7 | if greater that the natural height of the tooltip, will be enforced
8 | in browsers that support display:flex */
9 | display: flex;
10 | pointer-events: none;
11 | /* this may be overriden in JS for fixed position origins */
12 | position: absolute;
13 | }
14 |
15 | .tooltipster-box {
16 | /* see .tooltipster-base. flex-shrink 1 is only necessary for IE10-
17 | and flex-basis auto for IE11- (at least) */
18 | flex: 1 1 auto;
19 | }
20 |
21 | .tooltipster-content {
22 | /* prevents an overflow if the user adds padding to the div */
23 | box-sizing: border-box;
24 | /* these make sure we'll be able to detect any overflow */
25 | max-height: 100%;
26 | max-width: 100%;
27 | overflow: auto;
28 | }
29 |
30 | .tooltipster-ruler {
31 | /* these let us test the size of the tooltip without overflowing the window */
32 | bottom: 0;
33 | left: 0;
34 | overflow: hidden;
35 | position: fixed;
36 | right: 0;
37 | top: 0;
38 | visibility: hidden;
39 | }
40 |
41 | /* ANIMATIONS */
42 |
43 | /* Open/close animations */
44 |
45 | /* fade */
46 |
47 | .tooltipster-fade {
48 | opacity: 0;
49 | -webkit-transition-property: opacity;
50 | -moz-transition-property: opacity;
51 | -o-transition-property: opacity;
52 | -ms-transition-property: opacity;
53 | transition-property: opacity;
54 | }
55 | .tooltipster-fade.tooltipster-show {
56 | opacity: 1;
57 | }
58 |
59 | /* grow */
60 |
61 | .tooltipster-grow {
62 | -webkit-transform: scale(0,0);
63 | -moz-transform: scale(0,0);
64 | -o-transform: scale(0,0);
65 | -ms-transform: scale(0,0);
66 | transform: scale(0,0);
67 | -webkit-transition-property: -webkit-transform;
68 | -moz-transition-property: -moz-transform;
69 | -o-transition-property: -o-transform;
70 | -ms-transition-property: -ms-transform;
71 | transition-property: transform;
72 | -webkit-backface-visibility: hidden;
73 | }
74 | .tooltipster-grow.tooltipster-show {
75 | -webkit-transform: scale(1,1);
76 | -moz-transform: scale(1,1);
77 | -o-transform: scale(1,1);
78 | -ms-transform: scale(1,1);
79 | transform: scale(1,1);
80 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
81 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
82 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
83 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
84 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
85 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
86 | }
87 |
88 | /* swing */
89 |
90 | .tooltipster-swing {
91 | opacity: 0;
92 | -webkit-transform: rotateZ(4deg);
93 | -moz-transform: rotateZ(4deg);
94 | -o-transform: rotateZ(4deg);
95 | -ms-transform: rotateZ(4deg);
96 | transform: rotateZ(4deg);
97 | -webkit-transition-property: -webkit-transform, opacity;
98 | -moz-transition-property: -moz-transform;
99 | -o-transition-property: -o-transform;
100 | -ms-transition-property: -ms-transform;
101 | transition-property: transform;
102 | }
103 | .tooltipster-swing.tooltipster-show {
104 | opacity: 1;
105 | -webkit-transform: rotateZ(0deg);
106 | -moz-transform: rotateZ(0deg);
107 | -o-transform: rotateZ(0deg);
108 | -ms-transform: rotateZ(0deg);
109 | transform: rotateZ(0deg);
110 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1);
111 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
112 | -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
113 | -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
114 | -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
115 | transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
116 | }
117 |
118 | /* fall */
119 |
120 | .tooltipster-fall {
121 | -webkit-transition-property: top;
122 | -moz-transition-property: top;
123 | -o-transition-property: top;
124 | -ms-transition-property: top;
125 | transition-property: top;
126 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
127 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
128 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
129 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
130 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
131 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
132 | }
133 | .tooltipster-fall.tooltipster-initial {
134 | top: 0 !important;
135 | }
136 | .tooltipster-fall.tooltipster-show {
137 | }
138 | .tooltipster-fall.tooltipster-dying {
139 | -webkit-transition-property: all;
140 | -moz-transition-property: all;
141 | -o-transition-property: all;
142 | -ms-transition-property: all;
143 | transition-property: all;
144 | top: 0 !important;
145 | opacity: 0;
146 | }
147 |
148 | /* slide */
149 |
150 | .tooltipster-slide {
151 | -webkit-transition-property: left;
152 | -moz-transition-property: left;
153 | -o-transition-property: left;
154 | -ms-transition-property: left;
155 | transition-property: left;
156 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
157 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
158 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
159 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
160 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
161 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
162 | }
163 | .tooltipster-slide.tooltipster-initial {
164 | left: -40px !important;
165 | }
166 | .tooltipster-slide.tooltipster-show {
167 | }
168 | .tooltipster-slide.tooltipster-dying {
169 | -webkit-transition-property: all;
170 | -moz-transition-property: all;
171 | -o-transition-property: all;
172 | -ms-transition-property: all;
173 | transition-property: all;
174 | left: 0 !important;
175 | opacity: 0;
176 | }
177 |
178 | /* Update animations */
179 |
180 | /* We use animations rather than transitions here because
181 | transition durations may be specified in the style tag due to
182 | animationDuration, and we try to avoid collisions and the use
183 | of !important */
184 |
185 | /* fade */
186 |
187 | @keyframes tooltipster-fading {
188 | 0% {
189 | opacity: 0;
190 | }
191 | 100% {
192 | opacity: 1;
193 | }
194 | }
195 |
196 | .tooltipster-update-fade {
197 | animation: tooltipster-fading 400ms;
198 | }
199 |
200 | /* rotate */
201 |
202 | @keyframes tooltipster-rotating {
203 | 25% {
204 | transform: rotate(-2deg);
205 | }
206 | 75% {
207 | transform: rotate(2deg);
208 | }
209 | 100% {
210 | transform: rotate(0);
211 | }
212 | }
213 |
214 | .tooltipster-update-rotate {
215 | animation: tooltipster-rotating 600ms;
216 | }
217 |
218 | /* scale */
219 |
220 | @keyframes tooltipster-scaling {
221 | 50% {
222 | transform: scale(1.1);
223 | }
224 | 100% {
225 | transform: scale(1);
226 | }
227 | }
228 |
229 | .tooltipster-update-scale {
230 | animation: tooltipster-scaling 600ms;
231 | }
232 |
233 | /**
234 | * DEFAULT STYLE OF THE SIDETIP PLUGIN
235 | *
236 | * All styles are "namespaced" with .tooltipster-sidetip to prevent
237 | * conflicts between plugins.
238 | */
239 |
240 | /* .tooltipster-box */
241 |
242 | .tooltipster-sidetip .tooltipster-box {
243 | background: #565656;
244 | border: 2px solid black;
245 | border-radius: 4px;
246 | }
247 |
248 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-box {
249 | margin-top: 8px;
250 | }
251 |
252 | .tooltipster-sidetip.tooltipster-left .tooltipster-box {
253 | margin-right: 8px;
254 | }
255 |
256 | .tooltipster-sidetip.tooltipster-right .tooltipster-box {
257 | margin-left: 8px;
258 | }
259 |
260 | .tooltipster-sidetip.tooltipster-top .tooltipster-box {
261 | margin-bottom: 8px;
262 | }
263 |
264 | /* .tooltipster-content */
265 |
266 | .tooltipster-sidetip .tooltipster-content {
267 | color: white;
268 | line-height: 18px;
269 | padding: 6px 14px;
270 | }
271 |
272 | /* .tooltipster-arrow : will keep only the zone of .tooltipster-arrow-uncropped that
273 | corresponds to the arrow we want to display */
274 |
275 | .tooltipster-sidetip .tooltipster-arrow {
276 | overflow: hidden;
277 | position: absolute;
278 | }
279 |
280 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow {
281 | height: 10px;
282 | /* half the width, for centering */
283 | margin-left: -10px;
284 | top: 0;
285 | width: 20px;
286 | }
287 |
288 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow {
289 | height: 20px;
290 | margin-top: -10px;
291 | right: 0;
292 | /* top 0 to keep the arrow from overflowing .tooltipster-base when it has not
293 | been positioned yet */
294 | top: 0;
295 | width: 10px;
296 | }
297 |
298 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow {
299 | height: 20px;
300 | margin-top: -10px;
301 | left: 0;
302 | /* same as .tooltipster-left .tooltipster-arrow */
303 | top: 0;
304 | width: 10px;
305 | }
306 |
307 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow {
308 | bottom: 0;
309 | height: 10px;
310 | margin-left: -10px;
311 | width: 20px;
312 | }
313 |
314 | /* common rules between .tooltipster-arrow-background and .tooltipster-arrow-border */
315 |
316 | .tooltipster-sidetip .tooltipster-arrow-background, .tooltipster-sidetip .tooltipster-arrow-border {
317 | height: 0;
318 | position: absolute;
319 | width: 0;
320 | }
321 |
322 | /* .tooltipster-arrow-background */
323 |
324 | .tooltipster-sidetip .tooltipster-arrow-background {
325 | border: 10px solid transparent;
326 | }
327 |
328 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background {
329 | border-bottom-color: #565656;
330 | left: 0;
331 | top: 3px;
332 | }
333 |
334 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background {
335 | border-left-color: #565656;
336 | left: -3px;
337 | top: 0;
338 | }
339 |
340 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background {
341 | border-right-color: #565656;
342 | left: 3px;
343 | top: 0;
344 | }
345 |
346 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background {
347 | border-top-color: #565656;
348 | left: 0;
349 | top: -3px;
350 | }
351 |
352 | /* .tooltipster-arrow-border */
353 |
354 | .tooltipster-sidetip .tooltipster-arrow-border {
355 | border: 10px solid transparent;
356 | left: 0;
357 | top: 0;
358 | }
359 |
360 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border {
361 | border-bottom-color: black;
362 | }
363 |
364 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border {
365 | border-left-color: black;
366 | }
367 |
368 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border {
369 | border-right-color: black;
370 | }
371 |
372 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border {
373 | border-top-color: black;
374 | }
375 |
376 | /* tooltipster-arrow-uncropped */
377 |
378 | .tooltipster-sidetip .tooltipster-arrow-uncropped {
379 | position: relative;
380 | }
381 |
382 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped {
383 | top: -10px;
384 | }
385 |
386 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped {
387 | left: -10px;
388 | }
389 |
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/tooltipster.bundle.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-fall,.tooltipster-grow.tooltipster-show{-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1);-moz-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-ms-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-o-transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-base{display:flex;pointer-events:none;position:absolute}.tooltipster-box{flex:1 1 auto}.tooltipster-content{box-sizing:border-box;max-height:100%;max-width:100%;overflow:auto}.tooltipster-ruler{bottom:0;left:0;overflow:hidden;position:fixed;right:0;top:0;visibility:hidden}.tooltipster-fade{opacity:0;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;-ms-transition-property:opacity;transition-property:opacity}.tooltipster-fade.tooltipster-show{opacity:1}.tooltipster-grow{-webkit-transform:scale(0,0);-moz-transform:scale(0,0);-o-transform:scale(0,0);-ms-transform:scale(0,0);transform:scale(0,0);-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-backface-visibility:hidden}.tooltipster-grow.tooltipster-show{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-o-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-swing{opacity:0;-webkit-transform:rotateZ(4deg);-moz-transform:rotateZ(4deg);-o-transform:rotateZ(4deg);-ms-transform:rotateZ(4deg);transform:rotateZ(4deg);-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform}.tooltipster-swing.tooltipster-show{opacity:1;-webkit-transform:rotateZ(0);-moz-transform:rotateZ(0);-o-transform:rotateZ(0);-ms-transform:rotateZ(0);transform:rotateZ(0);-webkit-transition-timing-function:cubic-bezier(.23,.635,.495,1);-webkit-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-moz-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-ms-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-o-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);transition-timing-function:cubic-bezier(.23,.635,.495,2.4)}.tooltipster-fall{-webkit-transition-property:top;-moz-transition-property:top;-o-transition-property:top;-ms-transition-property:top;transition-property:top;-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-fall.tooltipster-initial{top:0!important}.tooltipster-fall.tooltipster-dying{-webkit-transition-property:all;-moz-transition-property:all;-o-transition-property:all;-ms-transition-property:all;transition-property:all;top:0!important;opacity:0}.tooltipster-slide{-webkit-transition-property:left;-moz-transition-property:left;-o-transition-property:left;-ms-transition-property:left;transition-property:left;-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-moz-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-ms-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-o-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-slide.tooltipster-initial{left:-40px!important}.tooltipster-slide.tooltipster-dying{-webkit-transition-property:all;-moz-transition-property:all;-o-transition-property:all;-ms-transition-property:all;transition-property:all;left:0!important;opacity:0}@keyframes tooltipster-fading{0%{opacity:0}100%{opacity:1}}.tooltipster-update-fade{animation:tooltipster-fading .4s}@keyframes tooltipster-rotating{25%{transform:rotate(-2deg)}75%{transform:rotate(2deg)}100%{transform:rotate(0)}}.tooltipster-update-rotate{animation:tooltipster-rotating .6s}@keyframes tooltipster-scaling{50%{transform:scale(1.1)}100%{transform:scale(1)}}.tooltipster-update-scale{animation:tooltipster-scaling .6s}.tooltipster-sidetip .tooltipster-box{background:#565656;border:2px solid #000;border-radius:4px}.tooltipster-sidetip.tooltipster-bottom .tooltipster-box{margin-top:8px}.tooltipster-sidetip.tooltipster-left .tooltipster-box{margin-right:8px}.tooltipster-sidetip.tooltipster-right .tooltipster-box{margin-left:8px}.tooltipster-sidetip.tooltipster-top .tooltipster-box{margin-bottom:8px}.tooltipster-sidetip .tooltipster-content{color:#fff;line-height:18px;padding:6px 14px}.tooltipster-sidetip .tooltipster-arrow{overflow:hidden;position:absolute}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow{height:10px;margin-left:-10px;top:0;width:20px}.tooltipster-sidetip.tooltipster-left .tooltipster-arrow{height:20px;margin-top:-10px;right:0;top:0;width:10px}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow{height:20px;margin-top:-10px;left:0;top:0;width:10px}.tooltipster-sidetip.tooltipster-top .tooltipster-arrow{bottom:0;height:10px;margin-left:-10px;width:20px}.tooltipster-sidetip .tooltipster-arrow-background,.tooltipster-sidetip .tooltipster-arrow-border{height:0;position:absolute;width:0}.tooltipster-sidetip .tooltipster-arrow-background{border:10px solid transparent}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background{border-bottom-color:#565656;left:0;top:3px}.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background{border-left-color:#565656;left:-3px;top:0}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background{border-right-color:#565656;left:3px;top:0}.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background{border-top-color:#565656;left:0;top:-3px}.tooltipster-sidetip .tooltipster-arrow-border{border:10px solid transparent;left:0;top:0}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#000}.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border{border-left-color:#000}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border{border-right-color:#000}.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border{border-top-color:#000}.tooltipster-sidetip .tooltipster-arrow-uncropped{position:relative}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped{top:-10px}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped{left:-10px}
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/tooltipster.main.css:
--------------------------------------------------------------------------------
1 | /* This is the core CSS of Tooltipster */
2 |
3 | /* GENERAL STRUCTURE RULES (do not edit this section) */
4 |
5 | .tooltipster-base {
6 | /* this ensures that a constrained height set by functionPosition,
7 | if greater that the natural height of the tooltip, will be enforced
8 | in browsers that support display:flex */
9 | display: flex;
10 | pointer-events: none;
11 | /* this may be overriden in JS for fixed position origins */
12 | position: absolute;
13 | }
14 |
15 | .tooltipster-box {
16 | /* see .tooltipster-base. flex-shrink 1 is only necessary for IE10-
17 | and flex-basis auto for IE11- (at least) */
18 | flex: 1 1 auto;
19 | }
20 |
21 | .tooltipster-content {
22 | /* prevents an overflow if the user adds padding to the div */
23 | box-sizing: border-box;
24 | /* these make sure we'll be able to detect any overflow */
25 | max-height: 100%;
26 | max-width: 100%;
27 | overflow: auto;
28 | }
29 |
30 | .tooltipster-ruler {
31 | /* these let us test the size of the tooltip without overflowing the window */
32 | bottom: 0;
33 | left: 0;
34 | overflow: hidden;
35 | position: fixed;
36 | right: 0;
37 | top: 0;
38 | visibility: hidden;
39 | }
40 |
41 | /* ANIMATIONS */
42 |
43 | /* Open/close animations */
44 |
45 | /* fade */
46 |
47 | .tooltipster-fade {
48 | opacity: 0;
49 | -webkit-transition-property: opacity;
50 | -moz-transition-property: opacity;
51 | -o-transition-property: opacity;
52 | -ms-transition-property: opacity;
53 | transition-property: opacity;
54 | }
55 | .tooltipster-fade.tooltipster-show {
56 | opacity: 1;
57 | }
58 |
59 | /* grow */
60 |
61 | .tooltipster-grow {
62 | -webkit-transform: scale(0,0);
63 | -moz-transform: scale(0,0);
64 | -o-transform: scale(0,0);
65 | -ms-transform: scale(0,0);
66 | transform: scale(0,0);
67 | -webkit-transition-property: -webkit-transform;
68 | -moz-transition-property: -moz-transform;
69 | -o-transition-property: -o-transform;
70 | -ms-transition-property: -ms-transform;
71 | transition-property: transform;
72 | -webkit-backface-visibility: hidden;
73 | }
74 | .tooltipster-grow.tooltipster-show {
75 | -webkit-transform: scale(1,1);
76 | -moz-transform: scale(1,1);
77 | -o-transform: scale(1,1);
78 | -ms-transform: scale(1,1);
79 | transform: scale(1,1);
80 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
81 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
82 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
83 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
84 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
85 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
86 | }
87 |
88 | /* swing */
89 |
90 | .tooltipster-swing {
91 | opacity: 0;
92 | -webkit-transform: rotateZ(4deg);
93 | -moz-transform: rotateZ(4deg);
94 | -o-transform: rotateZ(4deg);
95 | -ms-transform: rotateZ(4deg);
96 | transform: rotateZ(4deg);
97 | -webkit-transition-property: -webkit-transform, opacity;
98 | -moz-transition-property: -moz-transform;
99 | -o-transition-property: -o-transform;
100 | -ms-transition-property: -ms-transform;
101 | transition-property: transform;
102 | }
103 | .tooltipster-swing.tooltipster-show {
104 | opacity: 1;
105 | -webkit-transform: rotateZ(0deg);
106 | -moz-transform: rotateZ(0deg);
107 | -o-transform: rotateZ(0deg);
108 | -ms-transform: rotateZ(0deg);
109 | transform: rotateZ(0deg);
110 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1);
111 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
112 | -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
113 | -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
114 | -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
115 | transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4);
116 | }
117 |
118 | /* fall */
119 |
120 | .tooltipster-fall {
121 | -webkit-transition-property: top;
122 | -moz-transition-property: top;
123 | -o-transition-property: top;
124 | -ms-transition-property: top;
125 | transition-property: top;
126 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
127 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
128 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
129 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
130 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
131 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
132 | }
133 | .tooltipster-fall.tooltipster-initial {
134 | top: 0 !important;
135 | }
136 | .tooltipster-fall.tooltipster-show {
137 | }
138 | .tooltipster-fall.tooltipster-dying {
139 | -webkit-transition-property: all;
140 | -moz-transition-property: all;
141 | -o-transition-property: all;
142 | -ms-transition-property: all;
143 | transition-property: all;
144 | top: 0 !important;
145 | opacity: 0;
146 | }
147 |
148 | /* slide */
149 |
150 | .tooltipster-slide {
151 | -webkit-transition-property: left;
152 | -moz-transition-property: left;
153 | -o-transition-property: left;
154 | -ms-transition-property: left;
155 | transition-property: left;
156 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
157 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
158 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
159 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
160 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
161 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15);
162 | }
163 | .tooltipster-slide.tooltipster-initial {
164 | left: -40px !important;
165 | }
166 | .tooltipster-slide.tooltipster-show {
167 | }
168 | .tooltipster-slide.tooltipster-dying {
169 | -webkit-transition-property: all;
170 | -moz-transition-property: all;
171 | -o-transition-property: all;
172 | -ms-transition-property: all;
173 | transition-property: all;
174 | left: 0 !important;
175 | opacity: 0;
176 | }
177 |
178 | /* Update animations */
179 |
180 | /* We use animations rather than transitions here because
181 | transition durations may be specified in the style tag due to
182 | animationDuration, and we try to avoid collisions and the use
183 | of !important */
184 |
185 | /* fade */
186 |
187 | @keyframes tooltipster-fading {
188 | 0% {
189 | opacity: 0;
190 | }
191 | 100% {
192 | opacity: 1;
193 | }
194 | }
195 |
196 | .tooltipster-update-fade {
197 | animation: tooltipster-fading 400ms;
198 | }
199 |
200 | /* rotate */
201 |
202 | @keyframes tooltipster-rotating {
203 | 25% {
204 | transform: rotate(-2deg);
205 | }
206 | 75% {
207 | transform: rotate(2deg);
208 | }
209 | 100% {
210 | transform: rotate(0);
211 | }
212 | }
213 |
214 | .tooltipster-update-rotate {
215 | animation: tooltipster-rotating 600ms;
216 | }
217 |
218 | /* scale */
219 |
220 | @keyframes tooltipster-scaling {
221 | 50% {
222 | transform: scale(1.1);
223 | }
224 | 100% {
225 | transform: scale(1);
226 | }
227 | }
228 |
229 | .tooltipster-update-scale {
230 | animation: tooltipster-scaling 600ms;
231 | }
232 |
--------------------------------------------------------------------------------
/src/tooltipster/dist/css/tooltipster.main.min.css:
--------------------------------------------------------------------------------
1 | .tooltipster-fall,.tooltipster-grow.tooltipster-show{-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1);-moz-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-ms-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-o-transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-base{display:flex;pointer-events:none;position:absolute}.tooltipster-box{flex:1 1 auto}.tooltipster-content{box-sizing:border-box;max-height:100%;max-width:100%;overflow:auto}.tooltipster-ruler{bottom:0;left:0;overflow:hidden;position:fixed;right:0;top:0;visibility:hidden}.tooltipster-fade{opacity:0;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;-ms-transition-property:opacity;transition-property:opacity}.tooltipster-fade.tooltipster-show{opacity:1}.tooltipster-grow{-webkit-transform:scale(0,0);-moz-transform:scale(0,0);-o-transform:scale(0,0);-ms-transform:scale(0,0);transform:scale(0,0);-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-backface-visibility:hidden}.tooltipster-grow.tooltipster-show{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-o-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-swing{opacity:0;-webkit-transform:rotateZ(4deg);-moz-transform:rotateZ(4deg);-o-transform:rotateZ(4deg);-ms-transform:rotateZ(4deg);transform:rotateZ(4deg);-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform}.tooltipster-swing.tooltipster-show{opacity:1;-webkit-transform:rotateZ(0);-moz-transform:rotateZ(0);-o-transform:rotateZ(0);-ms-transform:rotateZ(0);transform:rotateZ(0);-webkit-transition-timing-function:cubic-bezier(.23,.635,.495,1);-webkit-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-moz-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-ms-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-o-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);transition-timing-function:cubic-bezier(.23,.635,.495,2.4)}.tooltipster-fall{-webkit-transition-property:top;-moz-transition-property:top;-o-transition-property:top;-ms-transition-property:top;transition-property:top;-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-fall.tooltipster-initial{top:0!important}.tooltipster-fall.tooltipster-dying{-webkit-transition-property:all;-moz-transition-property:all;-o-transition-property:all;-ms-transition-property:all;transition-property:all;top:0!important;opacity:0}.tooltipster-slide{-webkit-transition-property:left;-moz-transition-property:left;-o-transition-property:left;-ms-transition-property:left;transition-property:left;-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1);-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-moz-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-ms-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-o-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-slide.tooltipster-initial{left:-40px!important}.tooltipster-slide.tooltipster-dying{-webkit-transition-property:all;-moz-transition-property:all;-o-transition-property:all;-ms-transition-property:all;transition-property:all;left:0!important;opacity:0}@keyframes tooltipster-fading{0%{opacity:0}100%{opacity:1}}.tooltipster-update-fade{animation:tooltipster-fading .4s}@keyframes tooltipster-rotating{25%{transform:rotate(-2deg)}75%{transform:rotate(2deg)}100%{transform:rotate(0)}}.tooltipster-update-rotate{animation:tooltipster-rotating .6s}@keyframes tooltipster-scaling{50%{transform:scale(1.1)}100%{transform:scale(1)}}.tooltipster-update-scale{animation:tooltipster-scaling .6s}
--------------------------------------------------------------------------------
/src/tooltipster/dist/js/plugins/tooltipster/SVG/tooltipster-SVG.js:
--------------------------------------------------------------------------------
1 | (function (root, factory) {
2 | if (typeof define === 'function' && define.amd) {
3 | // AMD. Register as an anonymous module unless amdModuleId is set
4 | define(["tooltipster"], function (a0) {
5 | return (factory(a0));
6 | });
7 | } else if (typeof exports === 'object') {
8 | // Node. Does not work with strict CommonJS, but
9 | // only CommonJS-like environments that support module.exports,
10 | // like Node.
11 | module.exports = factory(require("tooltipster"));
12 | } else {
13 | factory(jQuery);
14 | }
15 | }(this, function ($) {
16 |
17 | (function (root, factory) {
18 | if (typeof define === 'function' && define.amd) {
19 | // AMD. Register as an anonymous module unless amdModuleId is set
20 | define(["jquery"], function (a0) {
21 | return (factory(a0));
22 | });
23 | } else if (typeof exports === 'object') {
24 | // Node. Does not work with strict CommonJS, but
25 | // only CommonJS-like environments that support module.exports,
26 | // like Node.
27 | module.exports = factory(require("jquery"));
28 | } else {
29 | factory(jQuery);
30 | }
31 | }(this, function ($) {
32 |
33 | var pluginName = 'tooltipster.SVG';
34 |
35 | $.tooltipster._plugin({
36 | name: pluginName,
37 | core: {
38 | __init: function() {
39 |
40 | $.tooltipster._on('init', function(event) {
41 |
42 | var win = $.tooltipster._env.window;
43 |
44 | if ( win.SVGElement
45 | && event.origin instanceof win.SVGElement
46 | ) {
47 |
48 | // auto-activation of the plugin on the instance
49 | event.instance._plug(pluginName);
50 | }
51 | });
52 | }
53 | },
54 | instance: {
55 | __init: function(instance) {
56 |
57 | var self = this;
58 |
59 | //list of instance variables
60 | self.__hadTitleTag = false;
61 | self.__instance = instance;
62 |
63 | // jQuery < v3.0's addClass and hasClass do not work on SVG elements.
64 | // However, $('.tooltipstered') does find elements having the class.
65 | if (!self.__instance._$origin.hasClass('tooltipstered')) {
66 |
67 | var c = self.__instance._$origin.attr('class') || '';
68 |
69 | if (c.indexOf('tooltipstered') == -1) {
70 | self.__instance._$origin.attr('class', c + ' tooltipstered');
71 | }
72 | }
73 |
74 | // if there is no content yet, let's look for a
child element
75 | if (self.__instance.content() === null) {
76 |
77 | // TODO: when there are several tags (not supported in
78 | // today's browsers yet though, still an RFC draft), pick the right
79 | // one based on its "lang" attribute
80 | var $title = self.__instance._$origin.find('>title');
81 |
82 | if ($title[0]) {
83 |
84 | var title = $title.text();
85 |
86 | self.__hadTitleTag = true;
87 | self.__instance._$origin.data('tooltipster-initialTitle', title);
88 | self.__instance.content(title);
89 |
90 | $title.remove();
91 | }
92 | }
93 |
94 | // rectify the geometry if SVG.js and its screenBBox plugin have been included
95 | self.__instance
96 | ._on('geometry.'+ self.namespace, function(event) {
97 |
98 | var win = $.tooltipster._env.window;
99 |
100 | // SVG coordinates may need fixing but we need svg.screenbox.js
101 | // to provide it. SVGElement is IE8+
102 | if (win.SVG.svgjs) {
103 |
104 | if (!win.SVG.parser) {
105 | win.SVG.prepare();
106 | }
107 |
108 | var svgEl = win.SVG.adopt(event.origin);
109 |
110 | // not all figures need (and have) screenBBox
111 | if (svgEl && svgEl.screenBBox) {
112 |
113 | var bbox = svgEl.screenBBox();
114 |
115 | event.edit({
116 | height: bbox.height,
117 | left: bbox.x,
118 | top: bbox.y,
119 | width: bbox.width
120 | });
121 | }
122 | }
123 | })
124 | // if jQuery < v3.0, we have to remove the class ourselves
125 | ._on('destroy.'+ self.namespace, function() {
126 | self.__destroy();
127 | });
128 | },
129 |
130 | __destroy: function() {
131 |
132 | var self = this;
133 |
134 | if (!self.__instance._$origin.hasClass('tooltipstered')) {
135 | var c = self.__instance._$origin.attr('class').replace('tooltipstered', '');
136 | self.__instance._$origin.attr('class', c);
137 | }
138 |
139 | self.__instance._off('.'+ self.namespace);
140 |
141 | // if the content was provided as a title tag, we may need to restore it
142 | if (self.__hadTitleTag) {
143 |
144 | // this must happen after Tooltipster restored (or not) the title attr
145 | self.__instance.one('destroyed', function() {
146 |
147 | // if a title attribute was restored, we just need to replace it with a tag
148 | var title = self.__instance._$origin.attr('title');
149 |
150 | if (title) {
151 |
152 | // must be namespaced to work
153 | $(document.createElementNS('http://www.w3.org/2000/svg', 'title'))
154 | .text(title)
155 | .appendTo(self.__instance._$origin);
156 |
157 | self.__instance._$origin.removeAttr('title');
158 | }
159 | });
160 | }
161 | }
162 | }
163 | });
164 |
165 | /* a build task will add "return $;" here */
166 | return $;
167 |
168 | }));
169 |
170 |
171 | }));
172 |
--------------------------------------------------------------------------------
/src/tooltipster/dist/js/plugins/tooltipster/SVG/tooltipster-SVG.min.js:
--------------------------------------------------------------------------------
1 | !function(a,b){"function"==typeof define&&define.amd?define(["tooltipster"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("tooltipster")):b(jQuery)}(this,function(a){!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b="tooltipster.SVG";return a.tooltipster._plugin({name:b,core:{__init:function(){a.tooltipster._on("init",function(c){var d=a.tooltipster._env.window;d.SVGElement&&c.origin instanceof d.SVGElement&&c.instance._plug(b)})}},instance:{__init:function(b){var c=this;if(c.__hadTitleTag=!1,c.__instance=b,!c.__instance._$origin.hasClass("tooltipstered")){var d=c.__instance._$origin.attr("class")||"";-1==d.indexOf("tooltipstered")&&c.__instance._$origin.attr("class",d+" tooltipstered")}if(null===c.__instance.content()){var e=c.__instance._$origin.find(">title");if(e[0]){var f=e.text();c.__hadTitleTag=!0,c.__instance._$origin.data("tooltipster-initialTitle",f),c.__instance.content(f),e.remove()}}c.__instance._on("geometry."+c.namespace,function(b){var c=a.tooltipster._env.window;if(c.SVG.svgjs){c.SVG.parser||c.SVG.prepare();var d=c.SVG.adopt(b.origin);if(d&&d.screenBBox){var e=d.screenBBox();b.edit({height:e.height,left:e.x,top:e.y,width:e.width})}}})._on("destroy."+c.namespace,function(){c.__destroy()})},__destroy:function(){var b=this;if(!b.__instance._$origin.hasClass("tooltipstered")){var c=b.__instance._$origin.attr("class").replace("tooltipstered","");b.__instance._$origin.attr("class",c)}b.__instance._off("."+b.namespace),b.__hadTitleTag&&b.__instance.one("destroyed",function(){var c=b.__instance._$origin.attr("title");c&&(a(document.createElementNS("http://www.w3.org/2000/svg","title")).text(c).appendTo(b.__instance._$origin),b.__instance._$origin.removeAttr("title"))})}}}),a})});
--------------------------------------------------------------------------------
/src/tooltipster/dist/js/tooltipster.bundle.min.js:
--------------------------------------------------------------------------------
1 | /*! tooltipster v4.2.8 */!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){function b(a){this.$container,this.constraints=null,this.__$tooltip,this.__init(a)}function c(b,c){var d=!0;return a.each(b,function(a,e){return void 0===c[a]||b[a]!==c[a]?(d=!1,!1):void 0}),d}function d(b){var c=b.attr("id"),d=c?h.window.document.getElementById(c):null;return d?d===b[0]:a.contains(h.window.document.body,b[0])}function e(){if(!g)return!1;var a=g.document.body||g.document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e0?e=c.__plugins[d]:a.each(c.__plugins,function(a,b){return b.name.substring(b.name.length-d.length-1)=="."+d?(e=b,!1):void 0}),e}if(b.name.indexOf(".")<0)throw new Error("Plugins must be namespaced");return c.__plugins[b.name]=b,b.core&&c.__bridge(b.core,c,b.name),this},_trigger:function(){var a=Array.prototype.slice.apply(arguments);return"string"==typeof a[0]&&(a[0]={type:a[0]}),this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,a),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,a),this},instances:function(b){var c=[],d=b||".tooltipstered";return a(d).each(function(){var b=a(this),d=b.data("tooltipster-ns");d&&a.each(d,function(a,d){c.push(b.data(d))})}),c},instancesLatest:function(){return this.__instancesLatestArr},off:function(){return this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},origins:function(b){var c=b?b+" ":"";return a(c+".tooltipstered").toArray()},setDefaults:function(b){return a.extend(f,b),this},triggerHandler:function(){return this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},a.tooltipster=new i,a.Tooltipster=function(b,c){this.__callbacks={close:[],open:[]},this.__closingTime,this.__Content,this.__contentBcr,this.__destroyed=!1,this.__$emitterPrivate=a({}),this.__$emitterPublic=a({}),this.__enabled=!0,this.__garbageCollector,this.__Geometry,this.__lastPosition,this.__namespace="tooltipster-"+Math.round(1e6*Math.random()),this.__options,this.__$originParents,this.__pointerIsOverOrigin=!1,this.__previousThemes=[],this.__state="closed",this.__timeouts={close:[],open:null},this.__touchEvents=[],this.__tracker=null,this._$origin,this._$tooltip,this.__init(b,c)},a.Tooltipster.prototype={__init:function(b,c){var d=this;if(d._$origin=a(b),d.__options=a.extend(!0,{},f,c),d.__optionsFormat(),!h.IE||h.IE>=d.__options.IEmin){var e=null;if(void 0===d._$origin.data("tooltipster-initialTitle")&&(e=d._$origin.attr("title"),void 0===e&&(e=null),d._$origin.data("tooltipster-initialTitle",e)),null!==d.__options.content)d.__contentSet(d.__options.content);else{var g,i=d._$origin.attr("data-tooltip-content");i&&(g=a(i)),g&&g[0]?d.__contentSet(g.first()):d.__contentSet(e)}d._$origin.removeAttr("title").addClass("tooltipstered"),d.__prepareOrigin(),d.__prepareGC(),a.each(d.__options.plugins,function(a,b){d._plug(b)}),h.hasTouchCapability&&a(h.window.document.body).on("touchmove."+d.__namespace+"-triggerOpen",function(a){d._touchRecordEvent(a)}),d._on("created",function(){d.__prepareTooltip()})._on("repositioned",function(a){d.__lastPosition=a.position})}else d.__options.disabled=!0},__contentInsert:function(){var a=this,b=a._$tooltip.find(".tooltipster-content"),c=a.__Content,d=function(a){c=a};return a._trigger({type:"format",content:a.__Content,format:d}),a.__options.functionFormat&&(c=a.__options.functionFormat.call(a,a,{origin:a._$origin[0]},a.__Content)),"string"!=typeof c||a.__options.contentAsHTML?b.empty().append(c):b.text(c),a},__contentSet:function(b){return b instanceof a&&this.__options.contentCloning&&(b=b.clone(!0)),this.__Content=b,this._trigger({type:"updated",content:b}),this},__destroyError:function(){throw new Error("This tooltip has been destroyed and cannot execute your method call.")},__geometry:function(){var b=this,c=b._$origin,d=b._$origin.is("area");if(d){var e=b._$origin.parent().attr("name");c=a('img[usemap="#'+e+'"]')}var f=c[0].getBoundingClientRect(),g=a(h.window.document),i=a(h.window),j=c,k={available:{document:null,window:null},document:{size:{height:g.height(),width:g.width()}},window:{scroll:{left:h.window.scrollX||h.window.document.documentElement.scrollLeft,top:h.window.scrollY||h.window.document.documentElement.scrollTop},size:{height:i.height(),width:i.width()}},origin:{fixedLineage:!1,offset:{},size:{height:f.bottom-f.top,width:f.right-f.left},usemapImage:d?c[0]:null,windowOffset:{bottom:f.bottom,left:f.left,right:f.right,top:f.top}}};if(d){var l=b._$origin.attr("shape"),m=b._$origin.attr("coords");if(m&&(m=m.split(","),a.map(m,function(a,b){m[b]=parseInt(a)})),"default"!=l)switch(l){case"circle":var n=m[0],o=m[1],p=m[2],q=o-p,r=n-p;k.origin.size.height=2*p,k.origin.size.width=k.origin.size.height,k.origin.windowOffset.left+=r,k.origin.windowOffset.top+=q;break;case"rect":var s=m[0],t=m[1],u=m[2],v=m[3];k.origin.size.height=v-t,k.origin.size.width=u-s,k.origin.windowOffset.left+=s,k.origin.windowOffset.top+=t;break;case"poly":for(var w=0,x=0,y=0,z=0,A="even",B=0;By&&(y=C,0===B&&(w=y)),w>C&&(w=C),A="odd"):(C>z&&(z=C,1==B&&(x=z)),x>C&&(x=C),A="even")}k.origin.size.height=z-x,k.origin.size.width=y-w,k.origin.windowOffset.left+=w,k.origin.windowOffset.top+=x}}var D=function(a){k.origin.size.height=a.height,k.origin.windowOffset.left=a.left,k.origin.windowOffset.top=a.top,k.origin.size.width=a.width};for(b._trigger({type:"geometry",edit:D,geometry:{height:k.origin.size.height,left:k.origin.windowOffset.left,top:k.origin.windowOffset.top,width:k.origin.size.width}}),k.origin.windowOffset.right=k.origin.windowOffset.left+k.origin.size.width,k.origin.windowOffset.bottom=k.origin.windowOffset.top+k.origin.size.height,k.origin.offset.left=k.origin.windowOffset.left+k.window.scroll.left,k.origin.offset.top=k.origin.windowOffset.top+k.window.scroll.top,k.origin.offset.bottom=k.origin.offset.top+k.origin.size.height,k.origin.offset.right=k.origin.offset.left+k.origin.size.width,k.available.document={bottom:{height:k.document.size.height-k.origin.offset.bottom,width:k.document.size.width},left:{height:k.document.size.height,width:k.origin.offset.left},right:{height:k.document.size.height,width:k.document.size.width-k.origin.offset.right},top:{height:k.origin.offset.top,width:k.document.size.width}},k.available.window={bottom:{height:Math.max(k.window.size.height-Math.max(k.origin.windowOffset.bottom,0),0),width:k.window.size.width},left:{height:k.window.size.height,width:Math.max(k.origin.windowOffset.left,0)},right:{height:k.window.size.height,width:Math.max(k.window.size.width-Math.max(k.origin.windowOffset.right,0),0)},top:{height:Math.max(k.origin.windowOffset.top,0),width:k.window.size.width}};"html"!=j[0].tagName.toLowerCase();){if("fixed"==j.css("position")){k.origin.fixedLineage=!0;break}j=j.parent()}return k},__optionsFormat:function(){return"number"==typeof this.__options.animationDuration&&(this.__options.animationDuration=[this.__options.animationDuration,this.__options.animationDuration]),"number"==typeof this.__options.delay&&(this.__options.delay=[this.__options.delay,this.__options.delay]),"number"==typeof this.__options.delayTouch&&(this.__options.delayTouch=[this.__options.delayTouch,this.__options.delayTouch]),"string"==typeof this.__options.theme&&(this.__options.theme=[this.__options.theme]),null===this.__options.parent?this.__options.parent=a(h.window.document.body):"string"==typeof this.__options.parent&&(this.__options.parent=a(this.__options.parent)),"hover"==this.__options.trigger?(this.__options.triggerOpen={mouseenter:!0,touchstart:!0},this.__options.triggerClose={mouseleave:!0,originClick:!0,touchleave:!0}):"click"==this.__options.trigger&&(this.__options.triggerOpen={click:!0,tap:!0},this.__options.triggerClose={click:!0,tap:!0}),this._trigger("options"),this},__prepareGC:function(){var b=this;return b.__options.selfDestruction?b.__garbageCollector=setInterval(function(){var c=(new Date).getTime();b.__touchEvents=a.grep(b.__touchEvents,function(a,b){return c-a.time>6e4}),d(b._$origin)||b.close(function(){b.destroy()})},2e4):clearInterval(b.__garbageCollector),b},__prepareOrigin:function(){var a=this;if(a._$origin.off("."+a.__namespace+"-triggerOpen"),h.hasTouchCapability&&a._$origin.on("touchstart."+a.__namespace+"-triggerOpen touchend."+a.__namespace+"-triggerOpen touchcancel."+a.__namespace+"-triggerOpen",function(b){a._touchRecordEvent(b)}),a.__options.triggerOpen.click||a.__options.triggerOpen.tap&&h.hasTouchCapability){var b="";a.__options.triggerOpen.click&&(b+="click."+a.__namespace+"-triggerOpen "),a.__options.triggerOpen.tap&&h.hasTouchCapability&&(b+="touchend."+a.__namespace+"-triggerOpen"),a._$origin.on(b,function(b){a._touchIsMeaningfulEvent(b)&&a._open(b)})}if(a.__options.triggerOpen.mouseenter||a.__options.triggerOpen.touchstart&&h.hasTouchCapability){var b="";a.__options.triggerOpen.mouseenter&&(b+="mouseenter."+a.__namespace+"-triggerOpen "),a.__options.triggerOpen.touchstart&&h.hasTouchCapability&&(b+="touchstart."+a.__namespace+"-triggerOpen"),a._$origin.on(b,function(b){!a._touchIsTouchEvent(b)&&a._touchIsEmulatedEvent(b)||(a.__pointerIsOverOrigin=!0,a._openShortly(b))})}if(a.__options.triggerClose.mouseleave||a.__options.triggerClose.touchleave&&h.hasTouchCapability){var b="";a.__options.triggerClose.mouseleave&&(b+="mouseleave."+a.__namespace+"-triggerOpen "),a.__options.triggerClose.touchleave&&h.hasTouchCapability&&(b+="touchend."+a.__namespace+"-triggerOpen touchcancel."+a.__namespace+"-triggerOpen"),a._$origin.on(b,function(b){a._touchIsMeaningfulEvent(b)&&(a.__pointerIsOverOrigin=!1)})}return a},__prepareTooltip:function(){var b=this,c=b.__options.interactive?"auto":"";return b._$tooltip.attr("id",b.__namespace).css({"pointer-events":c,zIndex:b.__options.zIndex}),a.each(b.__previousThemes,function(a,c){b._$tooltip.removeClass(c)}),a.each(b.__options.theme,function(a,c){b._$tooltip.addClass(c)}),b.__previousThemes=a.merge([],b.__options.theme),b},__scrollHandler:function(b){var c=this;if(c.__options.triggerClose.scroll)c._close(b);else if(d(c._$origin)&&d(c._$tooltip)){var e=null;if(b.target===h.window.document)c.__Geometry.origin.fixedLineage||c.__options.repositionOnScroll&&c.reposition(b);else{e=c.__geometry();var f=!1;if("fixed"!=c._$origin.css("position")&&c.__$originParents.each(function(b,c){var d=a(c),g=d.css("overflow-x"),h=d.css("overflow-y");if("visible"!=g||"visible"!=h){var i=c.getBoundingClientRect();if("visible"!=g&&(e.origin.windowOffset.lefti.right))return f=!0,!1;if("visible"!=h&&(e.origin.windowOffset.topi.bottom))return f=!0,!1}return"fixed"==d.css("position")?!1:void 0}),f)c._$tooltip.css("visibility","hidden");else if(c._$tooltip.css("visibility","visible"),c.__options.repositionOnScroll)c.reposition(b);else{var g=e.origin.offset.left-c.__Geometry.origin.offset.left,i=e.origin.offset.top-c.__Geometry.origin.offset.top;c._$tooltip.css({left:c.__lastPosition.coord.left+g,top:c.__lastPosition.coord.top+i})}}c._trigger({type:"scroll",event:b,geo:e})}return c},__stateSet:function(a){return this.__state=a,this._trigger({type:"state",state:a}),this},__timeoutsClear:function(){return clearTimeout(this.__timeouts.open),this.__timeouts.open=null,a.each(this.__timeouts.close,function(a,b){clearTimeout(b)}),this.__timeouts.close=[],this},__trackerStart:function(){var a=this,b=a._$tooltip.find(".tooltipster-content");return a.__options.trackTooltip&&(a.__contentBcr=b[0].getBoundingClientRect()),a.__tracker=setInterval(function(){if(d(a._$origin)&&d(a._$tooltip)){if(a.__options.trackOrigin){var e=a.__geometry(),f=!1;c(e.origin.size,a.__Geometry.origin.size)&&(a.__Geometry.origin.fixedLineage?c(e.origin.windowOffset,a.__Geometry.origin.windowOffset)&&(f=!0):c(e.origin.offset,a.__Geometry.origin.offset)&&(f=!0)),f||(a.__options.triggerClose.mouseleave?a._close():a.reposition())}if(a.__options.trackTooltip){var g=b[0].getBoundingClientRect();g.height===a.__contentBcr.height&&g.width===a.__contentBcr.width||(a.reposition(),a.__contentBcr=g)}}else a._close()},a.__options.trackerInterval),a},_close:function(b,c,d){var e=this,f=!0;if(e._trigger({type:"close",event:b,stop:function(){f=!1}}),f||d){c&&e.__callbacks.close.push(c),e.__callbacks.open=[],e.__timeoutsClear();var g=function(){a.each(e.__callbacks.close,function(a,c){c.call(e,e,{event:b,origin:e._$origin[0]})}),e.__callbacks.close=[]};if("closed"!=e.__state){var i=!0,j=new Date,k=j.getTime(),l=k+e.__options.animationDuration[1];if("disappearing"==e.__state&&l>e.__closingTime&&e.__options.animationDuration[1]>0&&(i=!1),i){e.__closingTime=l,"disappearing"!=e.__state&&e.__stateSet("disappearing");var m=function(){clearInterval(e.__tracker),e._trigger({type:"closing",event:b}),e._$tooltip.off("."+e.__namespace+"-triggerClose").removeClass("tooltipster-dying"),a(h.window).off("."+e.__namespace+"-triggerClose"),e.__$originParents.each(function(b,c){a(c).off("scroll."+e.__namespace+"-triggerClose")}),e.__$originParents=null,a(h.window.document.body).off("."+e.__namespace+"-triggerClose"),e._$origin.off("."+e.__namespace+"-triggerClose"),e._off("dismissable"),e.__stateSet("closed"),e._trigger({type:"after",event:b}),e.__options.functionAfter&&e.__options.functionAfter.call(e,e,{event:b,origin:e._$origin[0]}),g()};h.hasTransitions?(e._$tooltip.css({"-moz-animation-duration":e.__options.animationDuration[1]+"ms","-ms-animation-duration":e.__options.animationDuration[1]+"ms","-o-animation-duration":e.__options.animationDuration[1]+"ms","-webkit-animation-duration":e.__options.animationDuration[1]+"ms","animation-duration":e.__options.animationDuration[1]+"ms","transition-duration":e.__options.animationDuration[1]+"ms"}),e._$tooltip.clearQueue().removeClass("tooltipster-show").addClass("tooltipster-dying"),e.__options.animationDuration[1]>0&&e._$tooltip.delay(e.__options.animationDuration[1]),e._$tooltip.queue(m)):e._$tooltip.stop().fadeOut(e.__options.animationDuration[1],m)}}else g()}return e},_off:function(){return this.__$emitterPrivate.off.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_on:function(){return this.__$emitterPrivate.on.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_one:function(){return this.__$emitterPrivate.one.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_open:function(b,c){var e=this;if(!e.__destroying&&d(e._$origin)&&e.__enabled){var f=!0;if("closed"==e.__state&&(e._trigger({type:"before",event:b,stop:function(){f=!1}}),f&&e.__options.functionBefore&&(f=e.__options.functionBefore.call(e,e,{event:b,origin:e._$origin[0]}))),f!==!1&&null!==e.__Content){c&&e.__callbacks.open.push(c),e.__callbacks.close=[],e.__timeoutsClear();var g,i=function(){"stable"!=e.__state&&e.__stateSet("stable"),a.each(e.__callbacks.open,function(a,b){b.call(e,e,{origin:e._$origin[0],tooltip:e._$tooltip[0]})}),e.__callbacks.open=[]};if("closed"!==e.__state)g=0,"disappearing"===e.__state?(e.__stateSet("appearing"),h.hasTransitions?(e._$tooltip.clearQueue().removeClass("tooltipster-dying").addClass("tooltipster-show"),e.__options.animationDuration[0]>0&&e._$tooltip.delay(e.__options.animationDuration[0]),e._$tooltip.queue(i)):e._$tooltip.stop().fadeIn(i)):"stable"==e.__state&&i();else{if(e.__stateSet("appearing"),g=e.__options.animationDuration[0],e.__contentInsert(),e.reposition(b,!0),h.hasTransitions?(e._$tooltip.addClass("tooltipster-"+e.__options.animation).addClass("tooltipster-initial").css({"-moz-animation-duration":e.__options.animationDuration[0]+"ms","-ms-animation-duration":e.__options.animationDuration[0]+"ms","-o-animation-duration":e.__options.animationDuration[0]+"ms","-webkit-animation-duration":e.__options.animationDuration[0]+"ms","animation-duration":e.__options.animationDuration[0]+"ms","transition-duration":e.__options.animationDuration[0]+"ms"}),setTimeout(function(){"closed"!=e.__state&&(e._$tooltip.addClass("tooltipster-show").removeClass("tooltipster-initial"),e.__options.animationDuration[0]>0&&e._$tooltip.delay(e.__options.animationDuration[0]),e._$tooltip.queue(i))},0)):e._$tooltip.css("display","none").fadeIn(e.__options.animationDuration[0],i),e.__trackerStart(),a(h.window).on("resize."+e.__namespace+"-triggerClose",function(b){var c=a(document.activeElement);(c.is("input")||c.is("textarea"))&&a.contains(e._$tooltip[0],c[0])||e.reposition(b)}).on("scroll."+e.__namespace+"-triggerClose",function(a){e.__scrollHandler(a)}),e.__$originParents=e._$origin.parents(),e.__$originParents.each(function(b,c){a(c).on("scroll."+e.__namespace+"-triggerClose",function(a){e.__scrollHandler(a)})}),e.__options.triggerClose.mouseleave||e.__options.triggerClose.touchleave&&h.hasTouchCapability){e._on("dismissable",function(a){a.dismissable?a.delay?(m=setTimeout(function(){e._close(a.event)},a.delay),e.__timeouts.close.push(m)):e._close(a):clearTimeout(m)});var j=e._$origin,k="",l="",m=null;e.__options.interactive&&(j=j.add(e._$tooltip)),e.__options.triggerClose.mouseleave&&(k+="mouseenter."+e.__namespace+"-triggerClose ",l+="mouseleave."+e.__namespace+"-triggerClose "),e.__options.triggerClose.touchleave&&h.hasTouchCapability&&(k+="touchstart."+e.__namespace+"-triggerClose",l+="touchend."+e.__namespace+"-triggerClose touchcancel."+e.__namespace+"-triggerClose"),j.on(l,function(a){if(e._touchIsTouchEvent(a)||!e._touchIsEmulatedEvent(a)){var b="mouseleave"==a.type?e.__options.delay:e.__options.delayTouch;e._trigger({delay:b[1],dismissable:!0,event:a,type:"dismissable"})}}).on(k,function(a){!e._touchIsTouchEvent(a)&&e._touchIsEmulatedEvent(a)||e._trigger({dismissable:!1,event:a,type:"dismissable"})})}e.__options.triggerClose.originClick&&e._$origin.on("click."+e.__namespace+"-triggerClose",function(a){e._touchIsTouchEvent(a)||e._touchIsEmulatedEvent(a)||e._close(a)}),(e.__options.triggerClose.click||e.__options.triggerClose.tap&&h.hasTouchCapability)&&setTimeout(function(){if("closed"!=e.__state){var b="",c=a(h.window.document.body);e.__options.triggerClose.click&&(b+="click."+e.__namespace+"-triggerClose "),e.__options.triggerClose.tap&&h.hasTouchCapability&&(b+="touchend."+e.__namespace+"-triggerClose"),c.on(b,function(b){e._touchIsMeaningfulEvent(b)&&(e._touchRecordEvent(b),e.__options.interactive&&a.contains(e._$tooltip[0],b.target)||e._close(b))}),e.__options.triggerClose.tap&&h.hasTouchCapability&&c.on("touchstart."+e.__namespace+"-triggerClose",function(a){e._touchRecordEvent(a)})}},0),e._trigger("ready"),e.__options.functionReady&&e.__options.functionReady.call(e,e,{origin:e._$origin[0],tooltip:e._$tooltip[0]})}if(e.__options.timer>0){var m=setTimeout(function(){e._close()},e.__options.timer+g);e.__timeouts.close.push(m)}}}return e},_openShortly:function(a){var b=this,c=!0;if("stable"!=b.__state&&"appearing"!=b.__state&&!b.__timeouts.open&&(b._trigger({type:"start",event:a,stop:function(){c=!1}}),c)){var d=0==a.type.indexOf("touch")?b.__options.delayTouch:b.__options.delay;d[0]?b.__timeouts.open=setTimeout(function(){b.__timeouts.open=null,b.__pointerIsOverOrigin&&b._touchIsMeaningfulEvent(a)?(b._trigger("startend"),b._open(a)):b._trigger("startcancel")},d[0]):(b._trigger("startend"),b._open(a))}return b},_optionsExtract:function(b,c){var d=this,e=a.extend(!0,{},c),f=d.__options[b];return f||(f={},a.each(c,function(a,b){var c=d.__options[a];void 0!==c&&(f[a]=c)})),a.each(e,function(b,c){void 0!==f[b]&&("object"!=typeof c||c instanceof Array||null==c||"object"!=typeof f[b]||f[b]instanceof Array||null==f[b]?e[b]=f[b]:a.extend(e[b],f[b]))}),e},_plug:function(b){var c=a.tooltipster._plugin(b);if(!c)throw new Error('The "'+b+'" plugin is not defined');return c.instance&&a.tooltipster.__bridge(c.instance,this,c.name),this},_touchIsEmulatedEvent:function(a){for(var b=!1,c=(new Date).getTime(),d=this.__touchEvents.length-1;d>=0;d--){var e=this.__touchEvents[d];if(!(c-e.time<500))break;e.target===a.target&&(b=!0)}return b},_touchIsMeaningfulEvent:function(a){return this._touchIsTouchEvent(a)&&!this._touchSwiped(a.target)||!this._touchIsTouchEvent(a)&&!this._touchIsEmulatedEvent(a)},_touchIsTouchEvent:function(a){return 0==a.type.indexOf("touch")},_touchRecordEvent:function(a){return this._touchIsTouchEvent(a)&&(a.time=(new Date).getTime(),this.__touchEvents.push(a)),this},_touchSwiped:function(a){for(var b=!1,c=this.__touchEvents.length-1;c>=0;c--){var d=this.__touchEvents[c];if("touchmove"==d.type){b=!0;break}if("touchstart"==d.type&&a===d.target)break}return b},_trigger:function(){var b=Array.prototype.slice.apply(arguments);return"string"==typeof b[0]&&(b[0]={type:b[0]}),b[0].instance=this,b[0].origin=this._$origin?this._$origin[0]:null,b[0].tooltip=this._$tooltip?this._$tooltip[0]:null,this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,b),a.tooltipster._trigger.apply(a.tooltipster,b),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,b),this},_unplug:function(b){var c=this;if(c[b]){var d=a.tooltipster._plugin(b);d.instance&&a.each(d.instance,function(a,d){c[a]&&c[a].bridged===c[b]&&delete c[a]}),c[b].__destroy&&c[b].__destroy(),delete c[b]}return c},close:function(a){return this.__destroyed?this.__destroyError():this._close(null,a),this},content:function(a){var b=this;if(void 0===a)return b.__Content;if(b.__destroyed)b.__destroyError();else if(b.__contentSet(a),null!==b.__Content){if("closed"!==b.__state&&(b.__contentInsert(),b.reposition(),b.__options.updateAnimation))if(h.hasTransitions){var c=b.__options.updateAnimation;b._$tooltip.addClass("tooltipster-update-"+c),setTimeout(function(){"closed"!=b.__state&&b._$tooltip.removeClass("tooltipster-update-"+c)},1e3)}else b._$tooltip.fadeTo(200,.5,function(){"closed"!=b.__state&&b._$tooltip.fadeTo(200,1)})}else b._close();return b},destroy:function(){var b=this;if(b.__destroyed)b.__destroyError();else{"closed"!=b.__state?b.option("animationDuration",0)._close(null,null,!0):b.__timeoutsClear(),b._trigger("destroy"),b.__destroyed=!0,b._$origin.removeData(b.__namespace).off("."+b.__namespace+"-triggerOpen"),a(h.window.document.body).off("."+b.__namespace+"-triggerOpen");var c=b._$origin.data("tooltipster-ns");if(c)if(1===c.length){var d=null;"previous"==b.__options.restoration?d=b._$origin.data("tooltipster-initialTitle"):"current"==b.__options.restoration&&(d="string"==typeof b.__Content?b.__Content:a("").append(b.__Content).html()),d&&b._$origin.attr("title",d),b._$origin.removeClass("tooltipstered"),b._$origin.removeData("tooltipster-ns").removeData("tooltipster-initialTitle")}else c=a.grep(c,function(a,c){return a!==b.__namespace}),b._$origin.data("tooltipster-ns",c);b._trigger("destroyed"),b._off(),b.off(),b.__Content=null,b.__$emitterPrivate=null,b.__$emitterPublic=null,b.__options.parent=null,b._$origin=null,b._$tooltip=null,a.tooltipster.__instancesLatestArr=a.grep(a.tooltipster.__instancesLatestArr,function(a,c){return b!==a}),clearInterval(b.__garbageCollector)}return b},disable:function(){return this.__destroyed?(this.__destroyError(),this):(this._close(),this.__enabled=!1,this)},elementOrigin:function(){return this.__destroyed?void this.__destroyError():this._$origin[0]},elementTooltip:function(){return this._$tooltip?this._$tooltip[0]:null},enable:function(){return this.__enabled=!0,this},hide:function(a){return this.close(a)},instance:function(){return this},off:function(){return this.__destroyed||this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},open:function(a){return this.__destroyed?this.__destroyError():this._open(null,a),this},option:function(b,c){return void 0===c?this.__options[b]:(this.__destroyed?this.__destroyError():(this.__options[b]=c,this.__optionsFormat(),a.inArray(b,["trigger","triggerClose","triggerOpen"])>=0&&this.__prepareOrigin(),"selfDestruction"===b&&this.__prepareGC()),this)},reposition:function(a,b){var c=this;return c.__destroyed?c.__destroyError():"closed"!=c.__state&&d(c._$origin)&&(b||d(c._$tooltip))&&(b||c._$tooltip.detach(),c.__Geometry=c.__geometry(),c._trigger({type:"reposition",event:a,helper:{geo:c.__Geometry}})),c},show:function(a){return this.open(a)},status:function(){return{destroyed:this.__destroyed,enabled:this.__enabled,open:"closed"!==this.__state,state:this.__state}},triggerHandler:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},a.fn.tooltipster=function(){var b=Array.prototype.slice.apply(arguments),c="You are using a single HTML element as content for several tooltips. You probably want to set the contentCloning option to TRUE.";if(0===this.length)return this;if("string"==typeof b[0]){var d="#*$~&";return this.each(function(){var e=a(this).data("tooltipster-ns"),f=e?a(this).data(e[0]):null;if(!f)throw new Error("You called Tooltipster's \""+b[0]+'" method on an uninitialized element');if("function"!=typeof f[b[0]])throw new Error('Unknown method "'+b[0]+'"');this.length>1&&"content"==b[0]&&(b[1]instanceof a||"object"==typeof b[1]&&null!=b[1]&&b[1].tagName)&&!f.__options.contentCloning&&f.__options.debug&&console.log(c);var g=f[b[0]](b[1],b[2]);return g!==f||"instance"===b[0]?(d=g,!1):void 0}),"#*$~&"!==d?d:this}a.tooltipster.__instancesLatestArr=[];var e=b[0]&&void 0!==b[0].multiple,g=e&&b[0].multiple||!e&&f.multiple,h=b[0]&&void 0!==b[0].content,i=h&&b[0].content||!h&&f.content,j=b[0]&&void 0!==b[0].contentCloning,k=j&&b[0].contentCloning||!j&&f.contentCloning,l=b[0]&&void 0!==b[0].debug,m=l&&b[0].debug||!l&&f.debug;return this.length>1&&(i instanceof a||"object"==typeof i&&null!=i&&i.tagName)&&!k&&m&&console.log(c),this.each(function(){var c=!1,d=a(this),e=d.data("tooltipster-ns"),f=null;e?g?c=!0:m&&(console.log("Tooltipster: one or more tooltips are already attached to the element below. Ignoring."),console.log(this)):c=!0,c&&(f=new a.Tooltipster(this,b[0]),e||(e=[]),e.push(f.__namespace),d.data("tooltipster-ns",e),d.data(f.__namespace,f),f.__options.functionInit&&f.__options.functionInit.call(f,f,{origin:this}),f._trigger("init")),a.tooltipster.__instancesLatestArr.push(f)}),this},b.prototype={__init:function(b){this.__$tooltip=b,this.__$tooltip.css({left:0,overflow:"hidden",position:"absolute",top:0}).find(".tooltipster-content").css("overflow","auto"),this.$container=a('').append(this.__$tooltip).appendTo(h.window.document.body)},__forceRedraw:function(){var a=this.__$tooltip.parent();this.__$tooltip.detach(),this.__$tooltip.appendTo(a)},constrain:function(a,b){return this.constraints={width:a,height:b},this.__$tooltip.css({display:"block",height:"",overflow:"auto",width:a}),this},destroy:function(){this.__$tooltip.detach().find(".tooltipster-content").css({display:"",overflow:""}),this.$container.remove()},free:function(){return this.constraints=null,this.__$tooltip.css({display:"",height:"",overflow:"visible",width:""}),this},measure:function(){this.__forceRedraw();var a=this.__$tooltip[0].getBoundingClientRect(),b={size:{height:a.height||a.bottom-a.top,width:a.width||a.right-a.left}};if(this.constraints){var c=this.__$tooltip.find(".tooltipster-content"),d=this.__$tooltip.outerHeight(),e=c[0].getBoundingClientRect(),f={height:d<=this.constraints.height,width:a.width<=this.constraints.width&&e.width>=c[0].scrollWidth-1};b.fits=f.height&&f.width}return h.IE&&h.IE<=11&&b.size.width!==h.window.document.documentElement.clientWidth&&(b.size.width=Math.ceil(b.size.width)+1),b}};var j=navigator.userAgent.toLowerCase();-1!=j.indexOf("msie")?h.IE=parseInt(j.split("msie")[1]):-1!==j.toLowerCase().indexOf("trident")&&-1!==j.indexOf(" rv:11")?h.IE=11:-1!=j.toLowerCase().indexOf("edge/")&&(h.IE=parseInt(j.toLowerCase().split("edge/")[1]));var k="tooltipster.sideTip";return a.tooltipster._plugin({name:k,instance:{__defaults:function(){return{arrow:!0,distance:6,functionPosition:null,maxWidth:null,minIntersection:16,minWidth:0,position:null,side:"top",viewportAware:!0}},__init:function(a){var b=this;b.__instance=a,b.__namespace="tooltipster-sideTip-"+Math.round(1e6*Math.random()),b.__previousState="closed",b.__options,b.__optionsFormat(),b.__instance._on("state."+b.__namespace,function(a){"closed"==a.state?b.__close():"appearing"==a.state&&"closed"==b.__previousState&&b.__create(),b.__previousState=a.state}),b.__instance._on("options."+b.__namespace,function(){b.__optionsFormat()}),b.__instance._on("reposition."+b.__namespace,function(a){b.__reposition(a.event,a.helper)})},__close:function(){this.__instance.content()instanceof a&&this.__instance.content().detach(),this.__instance._$tooltip.remove(),this.__instance._$tooltip=null},__create:function(){var b=a('');this.__options.arrow||b.find(".tooltipster-box").css("margin",0).end().find(".tooltipster-arrow").hide(),this.__options.minWidth&&b.css("min-width",this.__options.minWidth+"px"),this.__options.maxWidth&&b.css("max-width",this.__options.maxWidth+"px"),
2 | this.__instance._$tooltip=b,this.__instance._trigger("created")},__destroy:function(){this.__instance._off("."+self.__namespace)},__optionsFormat:function(){var b=this;if(b.__options=b.__instance._optionsExtract(k,b.__defaults()),b.__options.position&&(b.__options.side=b.__options.position),"object"!=typeof b.__options.distance&&(b.__options.distance=[b.__options.distance]),b.__options.distance.length<4&&(void 0===b.__options.distance[1]&&(b.__options.distance[1]=b.__options.distance[0]),void 0===b.__options.distance[2]&&(b.__options.distance[2]=b.__options.distance[0]),void 0===b.__options.distance[3]&&(b.__options.distance[3]=b.__options.distance[1])),b.__options.distance={top:b.__options.distance[0],right:b.__options.distance[1],bottom:b.__options.distance[2],left:b.__options.distance[3]},"string"==typeof b.__options.side){var c={top:"bottom",right:"left",bottom:"top",left:"right"};b.__options.side=[b.__options.side,c[b.__options.side]],"left"==b.__options.side[0]||"right"==b.__options.side[0]?b.__options.side.push("top","bottom"):b.__options.side.push("right","left")}6===a.tooltipster._env.IE&&b.__options.arrow!==!0&&(b.__options.arrow=!1)},__reposition:function(b,c){var d,e=this,f=e.__targetFind(c),g=[];e.__instance._$tooltip.detach();var h=e.__instance._$tooltip.clone(),i=a.tooltipster._getRuler(h),j=!1,k=e.__instance.option("animation");switch(k&&h.removeClass("tooltipster-"+k),a.each(["window","document"],function(d,k){var l=null;if(e.__instance._trigger({container:k,helper:c,satisfied:j,takeTest:function(a){l=a},results:g,type:"positionTest"}),1==l||0!=l&&0==j&&("window"!=k||e.__options.viewportAware))for(var d=0;d=h.outerSize.width&&c.geo.available[k][n].height>=h.outerSize.height?h.fits=!0:h.fits=!1:h.fits=p.fits,"window"==k&&(h.fits?"top"==n||"bottom"==n?h.whole=c.geo.origin.windowOffset.right>=e.__options.minIntersection&&c.geo.window.size.width-c.geo.origin.windowOffset.left>=e.__options.minIntersection:h.whole=c.geo.origin.windowOffset.bottom>=e.__options.minIntersection&&c.geo.window.size.height-c.geo.origin.windowOffset.top>=e.__options.minIntersection:h.whole=!1),g.push(h),h.whole)j=!0;else if("natural"==h.mode&&(h.fits||h.size.width<=c.geo.available[k][n].width))return!1}})}}),e.__instance._trigger({edit:function(a){g=a},event:b,helper:c,results:g,type:"positionTested"}),g.sort(function(a,b){if(a.whole&&!b.whole)return-1;if(!a.whole&&b.whole)return 1;if(a.whole&&b.whole){var c=e.__options.side.indexOf(a.side),d=e.__options.side.indexOf(b.side);return d>c?-1:c>d?1:"natural"==a.mode?-1:1}if(a.fits&&!b.fits)return-1;if(!a.fits&&b.fits)return 1;if(a.fits&&b.fits){var c=e.__options.side.indexOf(a.side),d=e.__options.side.indexOf(b.side);return d>c?-1:c>d?1:"natural"==a.mode?-1:1}return"document"==a.container&&"bottom"==a.side&&"natural"==a.mode?-1:1}),d=g[0],d.coord={},d.side){case"left":case"right":d.coord.top=Math.floor(d.target-d.size.height/2);break;case"bottom":case"top":d.coord.left=Math.floor(d.target-d.size.width/2)}switch(d.side){case"left":d.coord.left=c.geo.origin.windowOffset.left-d.outerSize.width;break;case"right":d.coord.left=c.geo.origin.windowOffset.right+d.distance.horizontal;break;case"top":d.coord.top=c.geo.origin.windowOffset.top-d.outerSize.height;break;case"bottom":d.coord.top=c.geo.origin.windowOffset.bottom+d.distance.vertical}"window"==d.container?"top"==d.side||"bottom"==d.side?d.coord.left<0?c.geo.origin.windowOffset.right-this.__options.minIntersection>=0?d.coord.left=0:d.coord.left=c.geo.origin.windowOffset.right-this.__options.minIntersection-1:d.coord.left>c.geo.window.size.width-d.size.width&&(c.geo.origin.windowOffset.left+this.__options.minIntersection<=c.geo.window.size.width?d.coord.left=c.geo.window.size.width-d.size.width:d.coord.left=c.geo.origin.windowOffset.left+this.__options.minIntersection+1-d.size.width):d.coord.top<0?c.geo.origin.windowOffset.bottom-this.__options.minIntersection>=0?d.coord.top=0:d.coord.top=c.geo.origin.windowOffset.bottom-this.__options.minIntersection-1:d.coord.top>c.geo.window.size.height-d.size.height&&(c.geo.origin.windowOffset.top+this.__options.minIntersection<=c.geo.window.size.height?d.coord.top=c.geo.window.size.height-d.size.height:d.coord.top=c.geo.origin.windowOffset.top+this.__options.minIntersection+1-d.size.height):(d.coord.left>c.geo.window.size.width-d.size.width&&(d.coord.left=c.geo.window.size.width-d.size.width),d.coord.left<0&&(d.coord.left=0)),e.__sideChange(h,d.side),c.tooltipClone=h[0],c.tooltipParent=e.__instance.option("parent").parent[0],c.mode=d.mode,c.whole=d.whole,c.origin=e.__instance._$origin[0],c.tooltip=e.__instance._$tooltip[0],delete d.container,delete d.fits,delete d.mode,delete d.outerSize,delete d.whole,d.distance=d.distance.horizontal||d.distance.vertical;var l=a.extend(!0,{},d);if(e.__instance._trigger({edit:function(a){d=a},event:b,helper:c,position:l,type:"position"}),e.__options.functionPosition){var m=e.__options.functionPosition.call(e,e.__instance,c,l);m&&(d=m)}i.destroy();var n,o;"top"==d.side||"bottom"==d.side?(n={prop:"left",val:d.target-d.coord.left},o=d.size.width-this.__options.minIntersection):(n={prop:"top",val:d.target-d.coord.top},o=d.size.height-this.__options.minIntersection),n.valo&&(n.val=o);var p;p=c.geo.origin.fixedLineage?c.geo.origin.windowOffset:{left:c.geo.origin.windowOffset.left+c.geo.window.scroll.left,top:c.geo.origin.windowOffset.top+c.geo.window.scroll.top},d.coord={left:p.left+(d.coord.left-c.geo.origin.windowOffset.left),top:p.top+(d.coord.top-c.geo.origin.windowOffset.top)},e.__sideChange(e.__instance._$tooltip,d.side),c.geo.origin.fixedLineage?e.__instance._$tooltip.css("position","fixed"):e.__instance._$tooltip.css("position",""),e.__instance._$tooltip.css({left:d.coord.left,top:d.coord.top,height:d.size.height,width:d.size.width}).find(".tooltipster-arrow").css({left:"",top:""}).css(n.prop,n.val),e.__instance._$tooltip.appendTo(e.__instance.option("parent")),e.__instance._trigger({type:"repositioned",event:b,position:d})},__sideChange:function(a,b){a.removeClass("tooltipster-bottom").removeClass("tooltipster-left").removeClass("tooltipster-right").removeClass("tooltipster-top").addClass("tooltipster-"+b)},__targetFind:function(a){var b={},c=this.__instance._$origin[0].getClientRects();if(c.length>1){var d=this.__instance._$origin.css("opacity");1==d&&(this.__instance._$origin.css("opacity",.99),c=this.__instance._$origin[0].getClientRects(),this.__instance._$origin.css("opacity",1))}if(c.length<2)b.top=Math.floor(a.geo.origin.windowOffset.left+a.geo.origin.size.width/2),b.bottom=b.top,b.left=Math.floor(a.geo.origin.windowOffset.top+a.geo.origin.size.height/2),b.right=b.left;else{var e=c[0];b.top=Math.floor(e.left+(e.right-e.left)/2),e=c.length>2?c[Math.ceil(c.length/2)-1]:c[0],b.right=Math.floor(e.top+(e.bottom-e.top)/2),e=c[c.length-1],b.bottom=Math.floor(e.left+(e.right-e.left)/2),e=c.length>2?c[Math.ceil((c.length+1)/2)-1]:c[c.length-1],b.left=Math.floor(e.top+(e.bottom-e.top)/2)}return b}}}),a});
--------------------------------------------------------------------------------
/src/tooltipster/dist/js/tooltipster.main.min.js:
--------------------------------------------------------------------------------
1 | /*! tooltipster v4.2.8 */!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){function b(a){this.$container,this.constraints=null,this.__$tooltip,this.__init(a)}function c(b,c){var d=!0;return a.each(b,function(a,e){return void 0===c[a]||b[a]!==c[a]?(d=!1,!1):void 0}),d}function d(b){var c=b.attr("id"),d=c?h.window.document.getElementById(c):null;return d?d===b[0]:a.contains(h.window.document.body,b[0])}function e(){if(!g)return!1;var a=g.document.body||g.document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e0?e=c.__plugins[d]:a.each(c.__plugins,function(a,b){return b.name.substring(b.name.length-d.length-1)=="."+d?(e=b,!1):void 0}),e}if(b.name.indexOf(".")<0)throw new Error("Plugins must be namespaced");return c.__plugins[b.name]=b,b.core&&c.__bridge(b.core,c,b.name),this},_trigger:function(){var a=Array.prototype.slice.apply(arguments);return"string"==typeof a[0]&&(a[0]={type:a[0]}),this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,a),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,a),this},instances:function(b){var c=[],d=b||".tooltipstered";return a(d).each(function(){var b=a(this),d=b.data("tooltipster-ns");d&&a.each(d,function(a,d){c.push(b.data(d))})}),c},instancesLatest:function(){return this.__instancesLatestArr},off:function(){return this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},origins:function(b){var c=b?b+" ":"";return a(c+".tooltipstered").toArray()},setDefaults:function(b){return a.extend(f,b),this},triggerHandler:function(){return this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},a.tooltipster=new i,a.Tooltipster=function(b,c){this.__callbacks={close:[],open:[]},this.__closingTime,this.__Content,this.__contentBcr,this.__destroyed=!1,this.__$emitterPrivate=a({}),this.__$emitterPublic=a({}),this.__enabled=!0,this.__garbageCollector,this.__Geometry,this.__lastPosition,this.__namespace="tooltipster-"+Math.round(1e6*Math.random()),this.__options,this.__$originParents,this.__pointerIsOverOrigin=!1,this.__previousThemes=[],this.__state="closed",this.__timeouts={close:[],open:null},this.__touchEvents=[],this.__tracker=null,this._$origin,this._$tooltip,this.__init(b,c)},a.Tooltipster.prototype={__init:function(b,c){var d=this;if(d._$origin=a(b),d.__options=a.extend(!0,{},f,c),d.__optionsFormat(),!h.IE||h.IE>=d.__options.IEmin){var e=null;if(void 0===d._$origin.data("tooltipster-initialTitle")&&(e=d._$origin.attr("title"),void 0===e&&(e=null),d._$origin.data("tooltipster-initialTitle",e)),null!==d.__options.content)d.__contentSet(d.__options.content);else{var g,i=d._$origin.attr("data-tooltip-content");i&&(g=a(i)),g&&g[0]?d.__contentSet(g.first()):d.__contentSet(e)}d._$origin.removeAttr("title").addClass("tooltipstered"),d.__prepareOrigin(),d.__prepareGC(),a.each(d.__options.plugins,function(a,b){d._plug(b)}),h.hasTouchCapability&&a(h.window.document.body).on("touchmove."+d.__namespace+"-triggerOpen",function(a){d._touchRecordEvent(a)}),d._on("created",function(){d.__prepareTooltip()})._on("repositioned",function(a){d.__lastPosition=a.position})}else d.__options.disabled=!0},__contentInsert:function(){var a=this,b=a._$tooltip.find(".tooltipster-content"),c=a.__Content,d=function(a){c=a};return a._trigger({type:"format",content:a.__Content,format:d}),a.__options.functionFormat&&(c=a.__options.functionFormat.call(a,a,{origin:a._$origin[0]},a.__Content)),"string"!=typeof c||a.__options.contentAsHTML?b.empty().append(c):b.text(c),a},__contentSet:function(b){return b instanceof a&&this.__options.contentCloning&&(b=b.clone(!0)),this.__Content=b,this._trigger({type:"updated",content:b}),this},__destroyError:function(){throw new Error("This tooltip has been destroyed and cannot execute your method call.")},__geometry:function(){var b=this,c=b._$origin,d=b._$origin.is("area");if(d){var e=b._$origin.parent().attr("name");c=a('img[usemap="#'+e+'"]')}var f=c[0].getBoundingClientRect(),g=a(h.window.document),i=a(h.window),j=c,k={available:{document:null,window:null},document:{size:{height:g.height(),width:g.width()}},window:{scroll:{left:h.window.scrollX||h.window.document.documentElement.scrollLeft,top:h.window.scrollY||h.window.document.documentElement.scrollTop},size:{height:i.height(),width:i.width()}},origin:{fixedLineage:!1,offset:{},size:{height:f.bottom-f.top,width:f.right-f.left},usemapImage:d?c[0]:null,windowOffset:{bottom:f.bottom,left:f.left,right:f.right,top:f.top}}};if(d){var l=b._$origin.attr("shape"),m=b._$origin.attr("coords");if(m&&(m=m.split(","),a.map(m,function(a,b){m[b]=parseInt(a)})),"default"!=l)switch(l){case"circle":var n=m[0],o=m[1],p=m[2],q=o-p,r=n-p;k.origin.size.height=2*p,k.origin.size.width=k.origin.size.height,k.origin.windowOffset.left+=r,k.origin.windowOffset.top+=q;break;case"rect":var s=m[0],t=m[1],u=m[2],v=m[3];k.origin.size.height=v-t,k.origin.size.width=u-s,k.origin.windowOffset.left+=s,k.origin.windowOffset.top+=t;break;case"poly":for(var w=0,x=0,y=0,z=0,A="even",B=0;By&&(y=C,0===B&&(w=y)),w>C&&(w=C),A="odd"):(C>z&&(z=C,1==B&&(x=z)),x>C&&(x=C),A="even")}k.origin.size.height=z-x,k.origin.size.width=y-w,k.origin.windowOffset.left+=w,k.origin.windowOffset.top+=x}}var D=function(a){k.origin.size.height=a.height,k.origin.windowOffset.left=a.left,k.origin.windowOffset.top=a.top,k.origin.size.width=a.width};for(b._trigger({type:"geometry",edit:D,geometry:{height:k.origin.size.height,left:k.origin.windowOffset.left,top:k.origin.windowOffset.top,width:k.origin.size.width}}),k.origin.windowOffset.right=k.origin.windowOffset.left+k.origin.size.width,k.origin.windowOffset.bottom=k.origin.windowOffset.top+k.origin.size.height,k.origin.offset.left=k.origin.windowOffset.left+k.window.scroll.left,k.origin.offset.top=k.origin.windowOffset.top+k.window.scroll.top,k.origin.offset.bottom=k.origin.offset.top+k.origin.size.height,k.origin.offset.right=k.origin.offset.left+k.origin.size.width,k.available.document={bottom:{height:k.document.size.height-k.origin.offset.bottom,width:k.document.size.width},left:{height:k.document.size.height,width:k.origin.offset.left},right:{height:k.document.size.height,width:k.document.size.width-k.origin.offset.right},top:{height:k.origin.offset.top,width:k.document.size.width}},k.available.window={bottom:{height:Math.max(k.window.size.height-Math.max(k.origin.windowOffset.bottom,0),0),width:k.window.size.width},left:{height:k.window.size.height,width:Math.max(k.origin.windowOffset.left,0)},right:{height:k.window.size.height,width:Math.max(k.window.size.width-Math.max(k.origin.windowOffset.right,0),0)},top:{height:Math.max(k.origin.windowOffset.top,0),width:k.window.size.width}};"html"!=j[0].tagName.toLowerCase();){if("fixed"==j.css("position")){k.origin.fixedLineage=!0;break}j=j.parent()}return k},__optionsFormat:function(){return"number"==typeof this.__options.animationDuration&&(this.__options.animationDuration=[this.__options.animationDuration,this.__options.animationDuration]),"number"==typeof this.__options.delay&&(this.__options.delay=[this.__options.delay,this.__options.delay]),"number"==typeof this.__options.delayTouch&&(this.__options.delayTouch=[this.__options.delayTouch,this.__options.delayTouch]),"string"==typeof this.__options.theme&&(this.__options.theme=[this.__options.theme]),null===this.__options.parent?this.__options.parent=a(h.window.document.body):"string"==typeof this.__options.parent&&(this.__options.parent=a(this.__options.parent)),"hover"==this.__options.trigger?(this.__options.triggerOpen={mouseenter:!0,touchstart:!0},this.__options.triggerClose={mouseleave:!0,originClick:!0,touchleave:!0}):"click"==this.__options.trigger&&(this.__options.triggerOpen={click:!0,tap:!0},this.__options.triggerClose={click:!0,tap:!0}),this._trigger("options"),this},__prepareGC:function(){var b=this;return b.__options.selfDestruction?b.__garbageCollector=setInterval(function(){var c=(new Date).getTime();b.__touchEvents=a.grep(b.__touchEvents,function(a,b){return c-a.time>6e4}),d(b._$origin)||b.close(function(){b.destroy()})},2e4):clearInterval(b.__garbageCollector),b},__prepareOrigin:function(){var a=this;if(a._$origin.off("."+a.__namespace+"-triggerOpen"),h.hasTouchCapability&&a._$origin.on("touchstart."+a.__namespace+"-triggerOpen touchend."+a.__namespace+"-triggerOpen touchcancel."+a.__namespace+"-triggerOpen",function(b){a._touchRecordEvent(b)}),a.__options.triggerOpen.click||a.__options.triggerOpen.tap&&h.hasTouchCapability){var b="";a.__options.triggerOpen.click&&(b+="click."+a.__namespace+"-triggerOpen "),a.__options.triggerOpen.tap&&h.hasTouchCapability&&(b+="touchend."+a.__namespace+"-triggerOpen"),a._$origin.on(b,function(b){a._touchIsMeaningfulEvent(b)&&a._open(b)})}if(a.__options.triggerOpen.mouseenter||a.__options.triggerOpen.touchstart&&h.hasTouchCapability){var b="";a.__options.triggerOpen.mouseenter&&(b+="mouseenter."+a.__namespace+"-triggerOpen "),a.__options.triggerOpen.touchstart&&h.hasTouchCapability&&(b+="touchstart."+a.__namespace+"-triggerOpen"),a._$origin.on(b,function(b){!a._touchIsTouchEvent(b)&&a._touchIsEmulatedEvent(b)||(a.__pointerIsOverOrigin=!0,a._openShortly(b))})}if(a.__options.triggerClose.mouseleave||a.__options.triggerClose.touchleave&&h.hasTouchCapability){var b="";a.__options.triggerClose.mouseleave&&(b+="mouseleave."+a.__namespace+"-triggerOpen "),a.__options.triggerClose.touchleave&&h.hasTouchCapability&&(b+="touchend."+a.__namespace+"-triggerOpen touchcancel."+a.__namespace+"-triggerOpen"),a._$origin.on(b,function(b){a._touchIsMeaningfulEvent(b)&&(a.__pointerIsOverOrigin=!1)})}return a},__prepareTooltip:function(){var b=this,c=b.__options.interactive?"auto":"";return b._$tooltip.attr("id",b.__namespace).css({"pointer-events":c,zIndex:b.__options.zIndex}),a.each(b.__previousThemes,function(a,c){b._$tooltip.removeClass(c)}),a.each(b.__options.theme,function(a,c){b._$tooltip.addClass(c)}),b.__previousThemes=a.merge([],b.__options.theme),b},__scrollHandler:function(b){var c=this;if(c.__options.triggerClose.scroll)c._close(b);else if(d(c._$origin)&&d(c._$tooltip)){var e=null;if(b.target===h.window.document)c.__Geometry.origin.fixedLineage||c.__options.repositionOnScroll&&c.reposition(b);else{e=c.__geometry();var f=!1;if("fixed"!=c._$origin.css("position")&&c.__$originParents.each(function(b,c){var d=a(c),g=d.css("overflow-x"),h=d.css("overflow-y");if("visible"!=g||"visible"!=h){var i=c.getBoundingClientRect();if("visible"!=g&&(e.origin.windowOffset.lefti.right))return f=!0,!1;if("visible"!=h&&(e.origin.windowOffset.topi.bottom))return f=!0,!1}return"fixed"==d.css("position")?!1:void 0}),f)c._$tooltip.css("visibility","hidden");else if(c._$tooltip.css("visibility","visible"),c.__options.repositionOnScroll)c.reposition(b);else{var g=e.origin.offset.left-c.__Geometry.origin.offset.left,i=e.origin.offset.top-c.__Geometry.origin.offset.top;c._$tooltip.css({left:c.__lastPosition.coord.left+g,top:c.__lastPosition.coord.top+i})}}c._trigger({type:"scroll",event:b,geo:e})}return c},__stateSet:function(a){return this.__state=a,this._trigger({type:"state",state:a}),this},__timeoutsClear:function(){return clearTimeout(this.__timeouts.open),this.__timeouts.open=null,a.each(this.__timeouts.close,function(a,b){clearTimeout(b)}),this.__timeouts.close=[],this},__trackerStart:function(){var a=this,b=a._$tooltip.find(".tooltipster-content");return a.__options.trackTooltip&&(a.__contentBcr=b[0].getBoundingClientRect()),a.__tracker=setInterval(function(){if(d(a._$origin)&&d(a._$tooltip)){if(a.__options.trackOrigin){var e=a.__geometry(),f=!1;c(e.origin.size,a.__Geometry.origin.size)&&(a.__Geometry.origin.fixedLineage?c(e.origin.windowOffset,a.__Geometry.origin.windowOffset)&&(f=!0):c(e.origin.offset,a.__Geometry.origin.offset)&&(f=!0)),f||(a.__options.triggerClose.mouseleave?a._close():a.reposition())}if(a.__options.trackTooltip){var g=b[0].getBoundingClientRect();g.height===a.__contentBcr.height&&g.width===a.__contentBcr.width||(a.reposition(),a.__contentBcr=g)}}else a._close()},a.__options.trackerInterval),a},_close:function(b,c,d){var e=this,f=!0;if(e._trigger({type:"close",event:b,stop:function(){f=!1}}),f||d){c&&e.__callbacks.close.push(c),e.__callbacks.open=[],e.__timeoutsClear();var g=function(){a.each(e.__callbacks.close,function(a,c){c.call(e,e,{event:b,origin:e._$origin[0]})}),e.__callbacks.close=[]};if("closed"!=e.__state){var i=!0,j=new Date,k=j.getTime(),l=k+e.__options.animationDuration[1];if("disappearing"==e.__state&&l>e.__closingTime&&e.__options.animationDuration[1]>0&&(i=!1),i){e.__closingTime=l,"disappearing"!=e.__state&&e.__stateSet("disappearing");var m=function(){clearInterval(e.__tracker),e._trigger({type:"closing",event:b}),e._$tooltip.off("."+e.__namespace+"-triggerClose").removeClass("tooltipster-dying"),a(h.window).off("."+e.__namespace+"-triggerClose"),e.__$originParents.each(function(b,c){a(c).off("scroll."+e.__namespace+"-triggerClose")}),e.__$originParents=null,a(h.window.document.body).off("."+e.__namespace+"-triggerClose"),e._$origin.off("."+e.__namespace+"-triggerClose"),e._off("dismissable"),e.__stateSet("closed"),e._trigger({type:"after",event:b}),e.__options.functionAfter&&e.__options.functionAfter.call(e,e,{event:b,origin:e._$origin[0]}),g()};h.hasTransitions?(e._$tooltip.css({"-moz-animation-duration":e.__options.animationDuration[1]+"ms","-ms-animation-duration":e.__options.animationDuration[1]+"ms","-o-animation-duration":e.__options.animationDuration[1]+"ms","-webkit-animation-duration":e.__options.animationDuration[1]+"ms","animation-duration":e.__options.animationDuration[1]+"ms","transition-duration":e.__options.animationDuration[1]+"ms"}),e._$tooltip.clearQueue().removeClass("tooltipster-show").addClass("tooltipster-dying"),e.__options.animationDuration[1]>0&&e._$tooltip.delay(e.__options.animationDuration[1]),e._$tooltip.queue(m)):e._$tooltip.stop().fadeOut(e.__options.animationDuration[1],m)}}else g()}return e},_off:function(){return this.__$emitterPrivate.off.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_on:function(){return this.__$emitterPrivate.on.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_one:function(){return this.__$emitterPrivate.one.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_open:function(b,c){var e=this;if(!e.__destroying&&d(e._$origin)&&e.__enabled){var f=!0;if("closed"==e.__state&&(e._trigger({type:"before",event:b,stop:function(){f=!1}}),f&&e.__options.functionBefore&&(f=e.__options.functionBefore.call(e,e,{event:b,origin:e._$origin[0]}))),f!==!1&&null!==e.__Content){c&&e.__callbacks.open.push(c),e.__callbacks.close=[],e.__timeoutsClear();var g,i=function(){"stable"!=e.__state&&e.__stateSet("stable"),a.each(e.__callbacks.open,function(a,b){b.call(e,e,{origin:e._$origin[0],tooltip:e._$tooltip[0]})}),e.__callbacks.open=[]};if("closed"!==e.__state)g=0,"disappearing"===e.__state?(e.__stateSet("appearing"),h.hasTransitions?(e._$tooltip.clearQueue().removeClass("tooltipster-dying").addClass("tooltipster-show"),e.__options.animationDuration[0]>0&&e._$tooltip.delay(e.__options.animationDuration[0]),e._$tooltip.queue(i)):e._$tooltip.stop().fadeIn(i)):"stable"==e.__state&&i();else{if(e.__stateSet("appearing"),g=e.__options.animationDuration[0],e.__contentInsert(),e.reposition(b,!0),h.hasTransitions?(e._$tooltip.addClass("tooltipster-"+e.__options.animation).addClass("tooltipster-initial").css({"-moz-animation-duration":e.__options.animationDuration[0]+"ms","-ms-animation-duration":e.__options.animationDuration[0]+"ms","-o-animation-duration":e.__options.animationDuration[0]+"ms","-webkit-animation-duration":e.__options.animationDuration[0]+"ms","animation-duration":e.__options.animationDuration[0]+"ms","transition-duration":e.__options.animationDuration[0]+"ms"}),setTimeout(function(){"closed"!=e.__state&&(e._$tooltip.addClass("tooltipster-show").removeClass("tooltipster-initial"),e.__options.animationDuration[0]>0&&e._$tooltip.delay(e.__options.animationDuration[0]),e._$tooltip.queue(i))},0)):e._$tooltip.css("display","none").fadeIn(e.__options.animationDuration[0],i),e.__trackerStart(),a(h.window).on("resize."+e.__namespace+"-triggerClose",function(b){var c=a(document.activeElement);(c.is("input")||c.is("textarea"))&&a.contains(e._$tooltip[0],c[0])||e.reposition(b)}).on("scroll."+e.__namespace+"-triggerClose",function(a){e.__scrollHandler(a)}),e.__$originParents=e._$origin.parents(),e.__$originParents.each(function(b,c){a(c).on("scroll."+e.__namespace+"-triggerClose",function(a){e.__scrollHandler(a)})}),e.__options.triggerClose.mouseleave||e.__options.triggerClose.touchleave&&h.hasTouchCapability){e._on("dismissable",function(a){a.dismissable?a.delay?(m=setTimeout(function(){e._close(a.event)},a.delay),e.__timeouts.close.push(m)):e._close(a):clearTimeout(m)});var j=e._$origin,k="",l="",m=null;e.__options.interactive&&(j=j.add(e._$tooltip)),e.__options.triggerClose.mouseleave&&(k+="mouseenter."+e.__namespace+"-triggerClose ",l+="mouseleave."+e.__namespace+"-triggerClose "),e.__options.triggerClose.touchleave&&h.hasTouchCapability&&(k+="touchstart."+e.__namespace+"-triggerClose",l+="touchend."+e.__namespace+"-triggerClose touchcancel."+e.__namespace+"-triggerClose"),j.on(l,function(a){if(e._touchIsTouchEvent(a)||!e._touchIsEmulatedEvent(a)){var b="mouseleave"==a.type?e.__options.delay:e.__options.delayTouch;e._trigger({delay:b[1],dismissable:!0,event:a,type:"dismissable"})}}).on(k,function(a){!e._touchIsTouchEvent(a)&&e._touchIsEmulatedEvent(a)||e._trigger({dismissable:!1,event:a,type:"dismissable"})})}e.__options.triggerClose.originClick&&e._$origin.on("click."+e.__namespace+"-triggerClose",function(a){e._touchIsTouchEvent(a)||e._touchIsEmulatedEvent(a)||e._close(a)}),(e.__options.triggerClose.click||e.__options.triggerClose.tap&&h.hasTouchCapability)&&setTimeout(function(){if("closed"!=e.__state){var b="",c=a(h.window.document.body);e.__options.triggerClose.click&&(b+="click."+e.__namespace+"-triggerClose "),e.__options.triggerClose.tap&&h.hasTouchCapability&&(b+="touchend."+e.__namespace+"-triggerClose"),c.on(b,function(b){e._touchIsMeaningfulEvent(b)&&(e._touchRecordEvent(b),e.__options.interactive&&a.contains(e._$tooltip[0],b.target)||e._close(b))}),e.__options.triggerClose.tap&&h.hasTouchCapability&&c.on("touchstart."+e.__namespace+"-triggerClose",function(a){e._touchRecordEvent(a)})}},0),e._trigger("ready"),e.__options.functionReady&&e.__options.functionReady.call(e,e,{origin:e._$origin[0],tooltip:e._$tooltip[0]})}if(e.__options.timer>0){var m=setTimeout(function(){e._close()},e.__options.timer+g);e.__timeouts.close.push(m)}}}return e},_openShortly:function(a){var b=this,c=!0;if("stable"!=b.__state&&"appearing"!=b.__state&&!b.__timeouts.open&&(b._trigger({type:"start",event:a,stop:function(){c=!1}}),c)){var d=0==a.type.indexOf("touch")?b.__options.delayTouch:b.__options.delay;d[0]?b.__timeouts.open=setTimeout(function(){b.__timeouts.open=null,b.__pointerIsOverOrigin&&b._touchIsMeaningfulEvent(a)?(b._trigger("startend"),b._open(a)):b._trigger("startcancel")},d[0]):(b._trigger("startend"),b._open(a))}return b},_optionsExtract:function(b,c){var d=this,e=a.extend(!0,{},c),f=d.__options[b];return f||(f={},a.each(c,function(a,b){var c=d.__options[a];void 0!==c&&(f[a]=c)})),a.each(e,function(b,c){void 0!==f[b]&&("object"!=typeof c||c instanceof Array||null==c||"object"!=typeof f[b]||f[b]instanceof Array||null==f[b]?e[b]=f[b]:a.extend(e[b],f[b]))}),e},_plug:function(b){var c=a.tooltipster._plugin(b);if(!c)throw new Error('The "'+b+'" plugin is not defined');return c.instance&&a.tooltipster.__bridge(c.instance,this,c.name),this},_touchIsEmulatedEvent:function(a){for(var b=!1,c=(new Date).getTime(),d=this.__touchEvents.length-1;d>=0;d--){var e=this.__touchEvents[d];if(!(c-e.time<500))break;e.target===a.target&&(b=!0)}return b},_touchIsMeaningfulEvent:function(a){return this._touchIsTouchEvent(a)&&!this._touchSwiped(a.target)||!this._touchIsTouchEvent(a)&&!this._touchIsEmulatedEvent(a)},_touchIsTouchEvent:function(a){return 0==a.type.indexOf("touch")},_touchRecordEvent:function(a){return this._touchIsTouchEvent(a)&&(a.time=(new Date).getTime(),this.__touchEvents.push(a)),this},_touchSwiped:function(a){for(var b=!1,c=this.__touchEvents.length-1;c>=0;c--){var d=this.__touchEvents[c];if("touchmove"==d.type){b=!0;break}if("touchstart"==d.type&&a===d.target)break}return b},_trigger:function(){var b=Array.prototype.slice.apply(arguments);return"string"==typeof b[0]&&(b[0]={type:b[0]}),b[0].instance=this,b[0].origin=this._$origin?this._$origin[0]:null,b[0].tooltip=this._$tooltip?this._$tooltip[0]:null,this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,b),a.tooltipster._trigger.apply(a.tooltipster,b),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,b),this},_unplug:function(b){var c=this;if(c[b]){var d=a.tooltipster._plugin(b);d.instance&&a.each(d.instance,function(a,d){c[a]&&c[a].bridged===c[b]&&delete c[a]}),c[b].__destroy&&c[b].__destroy(),delete c[b]}return c},close:function(a){return this.__destroyed?this.__destroyError():this._close(null,a),this},content:function(a){var b=this;if(void 0===a)return b.__Content;if(b.__destroyed)b.__destroyError();else if(b.__contentSet(a),null!==b.__Content){if("closed"!==b.__state&&(b.__contentInsert(),b.reposition(),b.__options.updateAnimation))if(h.hasTransitions){var c=b.__options.updateAnimation;b._$tooltip.addClass("tooltipster-update-"+c),setTimeout(function(){"closed"!=b.__state&&b._$tooltip.removeClass("tooltipster-update-"+c)},1e3)}else b._$tooltip.fadeTo(200,.5,function(){"closed"!=b.__state&&b._$tooltip.fadeTo(200,1)})}else b._close();return b},destroy:function(){var b=this;if(b.__destroyed)b.__destroyError();else{"closed"!=b.__state?b.option("animationDuration",0)._close(null,null,!0):b.__timeoutsClear(),b._trigger("destroy"),b.__destroyed=!0,b._$origin.removeData(b.__namespace).off("."+b.__namespace+"-triggerOpen"),a(h.window.document.body).off("."+b.__namespace+"-triggerOpen");var c=b._$origin.data("tooltipster-ns");if(c)if(1===c.length){var d=null;"previous"==b.__options.restoration?d=b._$origin.data("tooltipster-initialTitle"):"current"==b.__options.restoration&&(d="string"==typeof b.__Content?b.__Content:a("").append(b.__Content).html()),d&&b._$origin.attr("title",d),b._$origin.removeClass("tooltipstered"),b._$origin.removeData("tooltipster-ns").removeData("tooltipster-initialTitle")}else c=a.grep(c,function(a,c){return a!==b.__namespace}),b._$origin.data("tooltipster-ns",c);b._trigger("destroyed"),b._off(),b.off(),b.__Content=null,b.__$emitterPrivate=null,b.__$emitterPublic=null,b.__options.parent=null,b._$origin=null,b._$tooltip=null,a.tooltipster.__instancesLatestArr=a.grep(a.tooltipster.__instancesLatestArr,function(a,c){return b!==a}),clearInterval(b.__garbageCollector)}return b},disable:function(){return this.__destroyed?(this.__destroyError(),this):(this._close(),this.__enabled=!1,this)},elementOrigin:function(){return this.__destroyed?void this.__destroyError():this._$origin[0]},elementTooltip:function(){return this._$tooltip?this._$tooltip[0]:null},enable:function(){return this.__enabled=!0,this},hide:function(a){return this.close(a)},instance:function(){return this},off:function(){return this.__destroyed||this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},open:function(a){return this.__destroyed?this.__destroyError():this._open(null,a),this},option:function(b,c){return void 0===c?this.__options[b]:(this.__destroyed?this.__destroyError():(this.__options[b]=c,this.__optionsFormat(),a.inArray(b,["trigger","triggerClose","triggerOpen"])>=0&&this.__prepareOrigin(),"selfDestruction"===b&&this.__prepareGC()),this)},reposition:function(a,b){var c=this;return c.__destroyed?c.__destroyError():"closed"!=c.__state&&d(c._$origin)&&(b||d(c._$tooltip))&&(b||c._$tooltip.detach(),c.__Geometry=c.__geometry(),c._trigger({type:"reposition",event:a,helper:{geo:c.__Geometry}})),c},show:function(a){return this.open(a)},status:function(){return{destroyed:this.__destroyed,enabled:this.__enabled,open:"closed"!==this.__state,state:this.__state}},triggerHandler:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},a.fn.tooltipster=function(){var b=Array.prototype.slice.apply(arguments),c="You are using a single HTML element as content for several tooltips. You probably want to set the contentCloning option to TRUE.";if(0===this.length)return this;if("string"==typeof b[0]){var d="#*$~&";return this.each(function(){var e=a(this).data("tooltipster-ns"),f=e?a(this).data(e[0]):null;if(!f)throw new Error("You called Tooltipster's \""+b[0]+'" method on an uninitialized element');if("function"!=typeof f[b[0]])throw new Error('Unknown method "'+b[0]+'"');this.length>1&&"content"==b[0]&&(b[1]instanceof a||"object"==typeof b[1]&&null!=b[1]&&b[1].tagName)&&!f.__options.contentCloning&&f.__options.debug&&console.log(c);var g=f[b[0]](b[1],b[2]);return g!==f||"instance"===b[0]?(d=g,!1):void 0}),"#*$~&"!==d?d:this}a.tooltipster.__instancesLatestArr=[];var e=b[0]&&void 0!==b[0].multiple,g=e&&b[0].multiple||!e&&f.multiple,h=b[0]&&void 0!==b[0].content,i=h&&b[0].content||!h&&f.content,j=b[0]&&void 0!==b[0].contentCloning,k=j&&b[0].contentCloning||!j&&f.contentCloning,l=b[0]&&void 0!==b[0].debug,m=l&&b[0].debug||!l&&f.debug;return this.length>1&&(i instanceof a||"object"==typeof i&&null!=i&&i.tagName)&&!k&&m&&console.log(c),this.each(function(){var c=!1,d=a(this),e=d.data("tooltipster-ns"),f=null;e?g?c=!0:m&&(console.log("Tooltipster: one or more tooltips are already attached to the element below. Ignoring."),console.log(this)):c=!0,c&&(f=new a.Tooltipster(this,b[0]),e||(e=[]),e.push(f.__namespace),d.data("tooltipster-ns",e),d.data(f.__namespace,f),f.__options.functionInit&&f.__options.functionInit.call(f,f,{origin:this}),f._trigger("init")),a.tooltipster.__instancesLatestArr.push(f)}),this},b.prototype={__init:function(b){this.__$tooltip=b,this.__$tooltip.css({left:0,overflow:"hidden",position:"absolute",top:0}).find(".tooltipster-content").css("overflow","auto"),this.$container=a('').append(this.__$tooltip).appendTo(h.window.document.body)},__forceRedraw:function(){var a=this.__$tooltip.parent();this.__$tooltip.detach(),this.__$tooltip.appendTo(a)},constrain:function(a,b){return this.constraints={width:a,height:b},this.__$tooltip.css({display:"block",height:"",overflow:"auto",width:a}),this},destroy:function(){this.__$tooltip.detach().find(".tooltipster-content").css({display:"",overflow:""}),this.$container.remove()},free:function(){return this.constraints=null,this.__$tooltip.css({display:"",height:"",overflow:"visible",width:""}),this},measure:function(){this.__forceRedraw();var a=this.__$tooltip[0].getBoundingClientRect(),b={size:{height:a.height||a.bottom-a.top,width:a.width||a.right-a.left}};if(this.constraints){var c=this.__$tooltip.find(".tooltipster-content"),d=this.__$tooltip.outerHeight(),e=c[0].getBoundingClientRect(),f={height:d<=this.constraints.height,width:a.width<=this.constraints.width&&e.width>=c[0].scrollWidth-1};b.fits=f.height&&f.width}return h.IE&&h.IE<=11&&b.size.width!==h.window.document.documentElement.clientWidth&&(b.size.width=Math.ceil(b.size.width)+1),b}};var j=navigator.userAgent.toLowerCase();-1!=j.indexOf("msie")?h.IE=parseInt(j.split("msie")[1]):-1!==j.toLowerCase().indexOf("trident")&&-1!==j.indexOf(" rv:11")?h.IE=11:-1!=j.toLowerCase().indexOf("edge/")&&(h.IE=parseInt(j.toLowerCase().split("edge/")[1]))});
--------------------------------------------------------------------------------
/src/watchfaces/README.md:
--------------------------------------------------------------------------------
1 | Watch Face Documentation
2 | ========================
3 |
4 | This section includes detailed documentation for each of the watch faces available in Movement.
5 | - [Clocks](clock.md)
6 | - [Simple Clock](clock.md#simple-clock)
7 | - [World Clock](clock.md#world-clock)
8 | - [Beat Time](clock.md#beat-time)
9 | - [Mars Time](clock.md#mars-time)
10 | - [Complications](complication.md)
11 | - [Sunrise/Sunset](complication.md#sunrisesunset)
12 | - [Moon Phase](complication.md#moon-phase)
13 | - [Stopwatch](complication.md#stopwatch)
14 | - [Countdown](complication.md#countdown)
15 | - [Counter](complication.md#counter)
16 | - [Pulsometer](complication.md#pulsometer)
17 | - [Tomato Productivity Timer](complication.md#tomato-productivity-timer)
18 | - [TOTP Generator](complication.md#totp-generator)
19 | - [Day One](complication.md#day-one)
20 | - [Blinky Light](complication.md#blinky-light)
21 | - [Astronomy](complication.md#astronomy)
22 | - [Orrery](complication.md#orrery)
23 | - [Sensors](sensor.md)
24 | - [Voltage](sensor.md#voltage)
25 | - [Temperature Display](sensor.md#temperature-display)
26 | - [Temperature Log](sensor.md#temperature-log)
27 | - [Temperature Testing](sensor.md#temperature-testing)
28 | - [LIS2DW Accelerometer Data Logger](sensor.md#lis2dw-accelerometer-data-logger)
29 | - [Settings](settings.md)
30 | - [Preferences](settings.md#preferences)
31 | - [Time Set](settings.md#time-set)
32 | - [Demo](demo.md)
33 | - [Character Set](demo.md#character-set)
34 | - [Demo](demo.md#demo)
35 |
--------------------------------------------------------------------------------
/src/watchfaces/clock.md:
--------------------------------------------------------------------------------
1 | Clocks
2 | ======
3 |
4 | The core function of a watch is telling time. All of the watch faces in this category tell time in one form or another.
5 |
6 | * [Simple Clock](#simple-clock)
7 | * [World Clock](#world-clock)
8 | * [Beat Time](#beat-time)
9 | * [Mars Time](#mars-time)
10 |
11 | Simple Clock
12 | ------------
13 |
14 | The Simple Clock watch face echoes the classic time and date display of the stock F-91W. It displays the day of the week and day of the month on the top line, along with the current time on the bottom line. Pressing the Light button illuminates the LED so that you can read the display in the dark. Holding the Light button keeps the LED on while the button is held.
15 |
16 | If you soldered the buzzer connector to your Sensor Watch board, you may also toggle the Hourly Chime feature by pressing and holding the Alarm button. When you release the Alarm button, the Signal indicator will turn on, indicating that the hourly chime is enabled.
17 |
18 | The Simple Clock face also incorporates a low battery warning: this watch face will display the LAP indicator when it detects that the battery voltage is low. This does not mean that power failure is imminent, but it does mean that your battery has only about 5% of its original capacity remaining and you should start thinking about a replacement. The battery is a CR2016 coin cell.
19 |
20 | World Clock
21 | -----------
22 |
23 | The World Clock watch face looks similar to the Simple Clock watch face, but you'll notice that at first launch the day of week indicators are blank. That's because this watch face does not display the day of the week. Instead, you may customize these letters to display the name of a time zone of your choosing.
24 |
25 | To customize this watch face, press and hold the Alarm button. The first letter in the top row will begin flashing. Press the Alarm button repeatedly to advance through the available letters in the first slot, then press the Light button to move to the second letter. Finally, press Light again to move to the time zone setting, and press Alarm to cycle through the available time zones. Press Light one last time to return to the world clock display.
26 |
27 | Note that the second slot cannot display all letters or numbers. Also note that at this time, time zones do not automatically update for daylight saving time; you will need to manually adjust this field each spring and fall.
28 |
29 | Beat Time
30 | ---------
31 |
32 | The Beat Time face displays the current Swatch Internet Time, or .beat time. This is a decimal time system that divides the day into 1000 beats.
33 |
34 | The three large digits in the bottom row indicate the current beat, and the two smaller digits (normally the seconds in Simple Clock) indicate the fractional beat; so for example you can read “67214” as “beat 672.14”.
35 |
36 | Mars Time
37 | ---------
38 |
39 | This watch face is dedicated to Martian timekeeping. It has several modes, and can display either a time or a date. Pressing the Alarm button cycles through different time zones on Mars:
40 |
41 | * MC - Mars Coordinated Time, the time at Airy-0 Crater on the Martian prime meridian
42 | * ZH - Local mean solar time for the Zhurong rover
43 | * PE - LMST for the Perseverance rover
44 | * IN - LMST for the Insight lander
45 | * CU - LMST for the Curiousity rover
46 |
47 | Press the Light button to toggle between displaying time and date:
48 |
49 | * MC S - the Mars Sol Date, Martian days since December 29, 1873
50 | * ZH Sol - Mission sol for the Zhurong rover
51 | * PE Sol - Mission sol for the Perseverance rover
52 | * IN S - Mission sol for the InSight lander
53 | * CU S - Mission sol for the Curiousity rover
54 |
55 | Note that where the mission sol is below 1000, this watch face displays the word “Sol” on the bottom line. When the mission sol is over 1000, the word “Sol” will not fit and so it displays a stylized letter S at the top right.
56 |
--------------------------------------------------------------------------------
/src/watchfaces/complication.md:
--------------------------------------------------------------------------------
1 | Complications
2 | =============
3 |
4 | In horology, a complication is an additional set of gears in a mechanical watch movenent that enables a secondary function, such as a sunrise/sunset dial. The watch faces in this category do just that.
5 |
6 | * [Sunrise/Sunset](#sunrisesunset)
7 | * [Moon Phase](#moon-phase)
8 | * [Stopwatch](#stopwatch)
9 | * [Stock Stopwatch](#stock-stopwatch)
10 | * [Countdown](#countdown)
11 | * [Counter](#counter)
12 | * [Interval](#interval)
13 | * [Alarm](#alarm)
14 | * [Pulsometer](#pulsometer)
15 | * [Tomato Productivity Timer](#tomato-productivity-timer)
16 | * [TOTP Generator](#totp-generator)
17 | * [Day One](#day-one)
18 | * [Blinky Light](#blinky-light)
19 | * [Astronomy](#astronomy)
20 | * [Orrery](#orrery)
21 |
22 | Sunrise/Sunset
23 | --------------
24 |
25 | This watch face displays local sunrise and sunset times. During the day, it displays today's sunset; at night, it displays tomorrow's sunrise.
26 |
27 | When you first see this watch face, it will display “No Loc”, or No Location. This is because your latitude and longitude are required to calculate sunrise and sunset. When on this screen, you can set your location in a similar way to the World Clock screen.
28 |
29 | Press and hold Alarm to enter location setting mode. The top line will read “LA” (Latitude), and the bottom line “+ 0000”. The large digits are the whole number part of the latitude, and the smaller digits (in the seconds place) are the fractional part. Enter your latitude and longitude (“LO”) by pressing the Alarm button to change the sign or advance the digits, and the Light button to move to the next character; for example, a latitude of 40.73° N would be “+ 4073”, and a longitude of 73.94° W would be “–07394”.
30 |
31 | Once you have set your latitude and longitude, the Sunrise/Sunset face will display the next sunrise or sunset on the bottom row, and the day of that sunrise or sunset at the top right.
32 |
33 | A short press on the Alarm button will advance to the following sunrise or sunset: for example, on Monday afternoon, it will display Monday evening’s sunset, but a short press on the Alarm button will display Tuesday morning’s sunrise.
34 |
35 | If you made a mistake while entering your location, or if you simply wish to change your location, you can re-enter location setting mode with another long press on the Alarm button.
36 |
37 | [\[Back to top\]](#complications)
38 |
39 | Moon Phase
40 | ----------
41 |
42 | The Moon Phase face is similar to the Sunrise/Sunset face: it displays the current phase of the moon, along with the day of the month and a graphical representation of the moon on the top row.
43 |
44 | This graphical representation is a bit abstract. The segments that turn on represent the shape of the moon, waxing from the bottom right and waning at the top left. A small crescent at the bottom right will grow into a larger crescent, then add lines in the center for a quarter and half moon. All segments are on during a full moon. Then gradually the segments at the bottom right will turn off, until all that remains is a small waning crescent at the top left.
45 |
46 | All segments turn off during a new moon.
47 |
48 | On this screen you may press the Alarm button repeatedly to move forward in time: the day of the month at the top right will advance by one day for each button press, and both the text and the graphical representation will display the moon phase for that day. Try pressing the Alarm button 27 times now, just to visualize what the moon will look like over the next month.
49 |
50 | [\[Back to top\]](#complications)
51 |
52 | Stopwatch
53 | ---------
54 |
55 | The Stopwatch face provides basic stopwatch functionality: you can start and stop the stopwatch with the alarm button. Pressing the light button when the timer is stopped resets it. This face does not count sub-seconds.
56 |
57 | [\[Back to top\]](#complications)
58 |
59 | Stock Stopwatch
60 | ---------------
61 |
62 | The Stock Stopwatch face implements the original F-91W stopwatch functionality including counting hundredths of seconds and lap timing.
63 | * Use the alarm button to start and stop the stopwatch.
64 | * Pressing the light button on a running timer shows the lap time. (The stopwatch continues running in the background, indicated by a blinking colon).
65 | * Pressing the light button again switches back to the running stopwatch.
66 | * Pressing the light button when the timekeeping is stopped resets the stopwatch.
67 |
68 | There are two improvements compared to the original F-91W:
69 | 1. When reaching 59:59 the counter does not simply jump back to zero, but keeps track of hours in the upper right hand corner. (Up to 24h)
70 | 2. Long pressing the light button toggles the led behaviour: it either turns on on each button press or it doesn't.
71 |
72 | [\[Back to top\]](#complications)
73 |
74 | Countdown
75 | ---------
76 |
77 | TODO
78 |
79 | Counter
80 | -------
81 |
82 | TODO
83 |
84 | Interval
85 | --------
86 |
87 | The Interal face provides 9 customizable interval timers, which can be used as hiit training device and/or for time management techniques.
88 |
89 | - There are 9 interval timers, you can cycle through these with the alarm button (short press). For each timer slot, the relevant details are shown in a "slideshow-manner" (like length of each phase - see below).
90 |
91 | - To start an interval timer, press and hold the alarm button.
92 |
93 | - To pause a running timer, press the alarm button (short press).
94 |
95 | - To completely abort a running timer, press and hold the alarm button.
96 |
97 | - Press and hold the light button to enter settings mode for the current interval timer.
98 |
99 | - Each interval timer has 1 to 4 phases of customizable length like so:\
100 | `(1) prepare/warm up --> (2) work --> (3) break --> (4) cool down`\
101 | When setting up or running a timer, each of these phases is indicated by the letters "PR" (prepare), "WO" (work), "BR" (break), or "CD" (cool down).
102 |
103 | - Each of these phases is optional, you can set the corresponding minutes and seconds to zero. If you want to use the timer, at least one phase needs to be set to a non-zero value.
104 |
105 | - You can define the number of rounds either only for the work phase and/or for the combination of work + break phase. Let's say you want an interval timer that counts 3 rounds of 30 seconds work, followed by 20 seconds rest:\
106 | work 30s --> work 30s --> work 30s --> break 20s\
107 | You can do this by setting 30s for the "WO"rk phase and setting a 3 in the lower right hand corner of the work page. The "LAP" indicator lights up at this position, to explain that we are setting laps here. After that, set the "BR"eak phase to 20s and leave the rest as it is.
108 |
109 | - If you want to set up a certain number of "full rounds", consisting of work phase(s) plus breaks, you can do so at the "BR"eak page. The number in the lower right hand corner determines the number of full rounds to be counted. A "-" means, that there is no limit and the timer keeps alternating between work and break phases.
110 |
111 | - This watch face comes with several pre-defined interval timers, suitable for hiit training (timer slots 1 to 4) as well as doing work according to the pomodoro principle (timer slots 5 to 6). Feel free to adjust the timer slots to your own needs (or completely wipe them).
112 |
113 | [\[Back to top\]](#complications)
114 |
115 | Alarm
116 | -----
117 |
118 | The Alarm face implements 16 customizable alarms on the sensor watch.
119 |
120 | Usage:
121 | - In normal mode, the alarm button cycles through all 16 alarms.
122 | - Pressing the alarm button long in normal mode toggles the corresponding alarm on or off.
123 | (Whereas pressing the alarm button extra long jumps back to the first alarm.)
124 | - Pressing the light button enters settings mode and cycles through the settings of each alarm.
125 | (Long pressing the light button enters settings mode without illuminating the led.)
126 | - In settings mode an alarm slot is selected by pressing the alarm button when the slot number
127 | in the upper right corner is blinking.
128 | - For each alarm slot, you can select the day. These are the day modes:
129 | - ED = the alarm rings every day
130 | - 1t = the alarm fires only one time and is erased afterwards
131 | - MF = the alarm fires Mondays to Fridays
132 | - WN = the alarm fires on weekends (Sa/Su)
133 | - MO to SU = the alarm fires only on the given day of week
134 | - You can fast cycle through hour or minute setting via long press of the alarm button.
135 | - You can select the tone in which the alarm is played. (Three pitch levels available.)
136 | - You can select how many "beep rounds" are played for each alarm. 1 to 9 rounds, plus extra
137 | long ('L') and extra short ('o') alarms.
138 | - The simple watch face indicates if any alarm is set within the next 24h by showing the signal
139 | indicator.
140 |
141 | [\[Back to top\]](#complications)
142 |
143 | Pulsometer
144 | ----------
145 |
146 | The Pulsometer is an implementation of a sort of a classic mechanical watch complication. A [classic pulsometer complication](https://watchtime.me/news/features/article/1424/what-is-a-pulsometer-scale-7-cool-doctor-s-watches) involves a chronograph with a scale calibrated for counting a certain number of heartbeats (often 30). You start it and begin counting heartbeats, and stop it after counting the specified number of beats. Once stopped, the needle will point to your heart rate.
147 |
148 | The pulsometer on Sensor Watch flashes its instructions at launch: “Hold Alarm + count 30 beats.” Using the hand on the side where you wear your watch, touch your carotid artery (in your neck) and feel for your pulse. Once you find it, use your other hand to press and hold the Alarm button, and count your heartbeats. When you reach 30 beats, release the Alarm button. The display will show a number such as “60 bpm”; this is your heart rate in beats per minute.
149 |
150 | Two notes:
151 |
152 | 1. For the first few seconds of a measurement, the display will read “Hi”. This indicates that it's too early for the measured value to be a valid heart rate. Once the measurement is below 240 bpm, the display will update.
153 | 2. If you hold the button down for more than 45 seconds, the display will read “Lo”. If it took this long for you to count 30 heartbeats, this indicates that your heart rate is below 40 beats per minute.
154 |
155 | [\[Back to top\]](#complications)
156 |
157 | Tomato Productivity Timer
158 | -------------------------
159 |
160 | TODO
161 |
162 | [\[Back to top\]](#complications)
163 |
164 | TOTP Generator
165 | --------------
166 |
167 | This watchface generates time based one time passwords (two factor auth codes) allowing you to sign in securely to many popular websites (e.g. Google, Github). Time-based one-time password (TOTP) is a computer algorithm that generates a one-time password (OTP) that uses the current time as a source of uniqueness.
168 |
169 | Press the Alarm button to cycle between your configured websites / TOTP secrets.
170 |
171 | The watchface supports multiple websites / TOTP secrets, which need to be extracted from TOTP QR codes and added to the source code for the watchface as follows:
172 |
173 | 1. Obtain a TOTP secret or QR ode from the website you want to generate codes for.
174 | 2. If you have just the QR code, [Stefan Sundin's web site](https://stefansundin.github.io/2fa-qr/) will allow you to extract the secret - it will be an alphanumeric string around 32 characters long, which is the TOTP secret encoded in Base32.
175 | 3. To add the secret to the watchface code, you need to convert it to hexadecimal bytes. This [cryptii.com](https://cryptii.com/pipes/base32-to-hex) page will allow you to do that conversion. Note you'll have to enter your TOTP secret in uppercase.
176 | 4. Finally, you'll need to take the Hexadecimal bytes and add them to the TOTP watchface source code and recompile movement:
177 |
178 | ### Edit `totp_face.c`
179 | You may want to remove the demo keys. Assuming you want to add a key to the end of the list:
180 |
181 | ```
182 | static const uint8_t num_keys = 2;
183 | ```
184 | Add one to the number on this line.
185 |
186 | ```
187 | static uint8_t keys[] = {
188 | // Add the hex bytes for your key
189 | };
190 | ```
191 | Add the hexadecimal bytes from step 3 to the end of this array, comma separated and each one preceeded by `0x`. Don't forget to add a comma after the previous final byte.
192 | ```
193 | static const uint8_t key_sizes[] = {
194 | ```
195 | Add the size of your secret (the number of hex bytes you just added) to the end of this array.
196 | ```
197 | static const uint32_t timesteps[] = {
198 | ```
199 | Add another `30` entry to the end of this array.
200 | ```
201 | static const char labels[][2] = {
202 | ```
203 | Add a label for your secret... E.g. if it's for your Google account you might want to add `{ 'g', 'o' }` as a friendly label.
204 |
205 | That's it - enjoy the convenience of TOTP codes on your wrist!
206 |
207 |
208 | [\[Back to top\]](#complications)
209 |
210 | Day One
211 | -------
212 |
213 | This watch face displays the number of days since a given date. It was originally designed to display the number of days you've been alive, but technically it can count up from any date in the 20th century or the 21st century, so far.
214 |
215 | Long press on the Alarm button to enter customization mode. The text "YR" will appear, and will allow you to set the year starting from 1959. Press Alarm repeatedly to advance the year. If your birthday is before 1959, advance beyond the current year and it will wrap around to 1900. Once you have set the year, press Light to set the month ("MO") and day ("DA"), advancing the value by pressing Alarm repeatedly.
216 |
217 | Note that at this time, the Day One face does not display the sleep indicator in sleep mode, which may make the watch appear to be unresponsive in sleep mode. You can still press the Alarm button to wake the watch. This UI quirk will be addressed in a future update.
218 |
219 | [\[Back to top\]](#complications)
220 |
221 | Blinky Light
222 | ------------
223 |
224 | The blinky light watch face was designed as a tutorial for making a watch face in Movement, but it actually might be useful to have a blinking light in a pinch.
225 |
226 | The screen displays the name of the watch face (”BL”), as well as an S at the top right for slow blink or an F for fast blink. The bottom line selects the color: green, red or yellow. You can change the speed of the blinking light by pressing the Alarm button, and change the color with the Light button. A long press on the Alarm button starts the blinking light, and another long press stops it.
227 |
228 | **Note that this will chew through your battery!** The green LED uses about 450µA at full brightness, which is 45 times the normal power consumption of the watch. The red LED is an order of magnitude less efficient (4500 µA), and the yellow setting lights both LEDs, which chews through nearly 5 milliamperes. This means that one hour of yellow blinking is likely to eat up between 2 and 3 percent of the battery's usable life! Still, if you need to signal your location to someone in a dark forest, this watch face could come in handy.
229 |
230 | Just try to use the green LED as much as you can.
231 |
232 | [\[Back to top\]](#complications)
233 |
234 | Astronomy
235 | ---------
236 |
237 | The Astronomy watch face is among the most complex watch faces in the Movement collection. It allows you to calculate the locations of celestial bodies in the sky, as well as distance in astronomical units (or, in the case of the Moon, distance in kilometers).
238 |
239 | When you arrive at the Astronomy watch face, you'll see its name (“Astro”) and an animation of two objects orbiting each other. You will also see "SO" (for Sol) flashing in the top left. The flashing letters indicate the currently selected celestial body. Short press Alarm to advance through the available celestial bodies:
240 |
241 | * SO - Sol, the sun
242 | * ME - Mercury
243 | * VE - Venus
244 | * LU - Luna, the Earth's moon
245 | * MA - Mars
246 | * JU - Jupiter
247 | * SA - Saturn
248 | * UR - Uranus
249 | * NE - Neptune
250 |
251 | Once you've selected the celestial body whose parameters you wish to calculate, long press the Alarm button and relase it. The letter “C” will flash while the calculation is performed.
252 |
253 | When the calculation is complete, the screen will display the altitude (“aL”) of the celestial body. You can cycle through the available parameters with repeated short presses on the Alarm button:
254 |
255 | * aL - Altitude (in degrees), the elevation over the horizon. If negative, it is below the horizon.
256 | * aZ - Azimuth (in degrees), the cardinal direction relative to true north.
257 | * rA - Right Ascension (in hours/minutes/seconds)
258 | * dE - Declination (in degrees/minutes/seconds)
259 | * di - Distance (the digits in the top right will display either aU for astronomical units, or K for kilometers)
260 |
261 | Long press on the Alarm button to select another celestial body.
262 |
263 | [\[Back to top\]](#complications)
264 |
265 | Orrery
266 | ------
267 |
268 | The Orrery watch face is similar to the Astronomy watch face in that it calculates properties of the planets, but instead of calculating their positions in the sky, this watch face calculates their absolute locations in the solar system. This is only useful if you want to plot the planets on graph paper, but hey, you never know!
269 |
270 | The controls are identical to the Astronomy watch face: while the title screen (“Orrery”) is displayed, you can advance through the available planets with repeated short presses on the Alarm button. The available planets:
271 |
272 | * ME - Mercury
273 | * VE - Venus
274 | * EA - Earth
275 | * LU - Luna, the Earth's moon
276 | * MA - Mars
277 | * JU - Jupiter
278 | * SA - Saturn
279 | * UR - Uranus
280 | * NE - Neptune
281 |
282 | Note that the sun is not available in this menu, as the sun is always at (0,0,0) in this calculation.
283 |
284 | Long press on the Alarm button to calculate the planet's location, and after a flashing “C” (for Calculating), you will be presented with the planet's X coordinate in astronomical units. Short press Alarm to cycle through the X, Y and Z coordinates, and then long press Alarm to return to planet selection.
285 |
286 | The large numbers represent the whole number part, and the two smaller numbers (in the seconds place) represent the decimal portion. So if you see “SA X 736” and “SA Y -662”, you can read that as an X coordinate of 7.36 AU and a Y coordinate of -6.62 AU. You can literally draw a dot at (0, 0) to represent the sun, and a dot at (7.36, -6.62) to represent Saturn. (the Z coordinates tend to be pretty close to zero, as the planets largely orbit on a single plane, the ecliptic)
287 |
288 | [\[Back to top\]](#complications)
289 |
--------------------------------------------------------------------------------
/src/watchfaces/demo.md:
--------------------------------------------------------------------------------
1 | Demo Faces
2 | ==========
3 |
4 | * [Character Set](#character-set)
5 | * [Demo](#demo)
6 |
7 | These watch faces demonstrate functionality of the watch, and aren't generally watch faces you'd build into a working firmware.
8 |
9 | Character Set
10 | -------------
11 |
12 | This watch face displays all of the characters in the Sensor Watch character set. You can advance from one character to the next with a short press of the Alarm button.
13 |
14 | This watch face may be useful to watch face developers, in that it can help them to understand which characters will work in different positions.
15 |
16 | Demo
17 | ----
18 |
19 | This watch was designed for the Crowd Supply marketing team, so they could photograph the various functions of Sensor Watch. The Alarm button advances through static screens that simulate different watch faces.
20 |
21 | This watch face may only be useful to you if you need to photograph Sensor Watch, i.e. for a blog post.
22 |
--------------------------------------------------------------------------------
/src/watchfaces/sensor.md:
--------------------------------------------------------------------------------
1 | Sensors
2 | =======
3 |
4 | Sensor Watch is designed to display data from sensors. The watch faces in this category read sensor data and present it in a useful way.
5 |
6 | * [Voltage](#voltage)
7 | * [Temperature Display](#temperature-display)
8 | * [Temperature Log](#temperature-log)
9 | * [Temperature Testing](#temperature-testing)
10 | * [LIS2DW Accelerometer Data Logger](#lis2dw-accelerometer-data-logger)
11 |
12 | Voltage
13 | -------
14 |
15 | This watch face is very simple and has no controls to speak of. It displays the battery voltage as measured by the SAM L22's ADC.
16 |
17 | Note that the Simple Clock watch face includes a low battery warning, so you don't technically need to this watch face unless you want to track the battery level.
18 |
19 | Temperature Display
20 | -------------------
21 |
22 | This watch face is designed to work with either the Temperature + GPIO sensor board or the Temperature + Light sensor board. It reads the current temperature from the thermistor voltage divider on the sensor board, and displays the current temperature in degrees Celsius.
23 |
24 | When the watch is on your wrist, your body heat interferes with an ambient temperature reading, but if you set it on a bedside table, strap it to your bike handlebars or place it outside of your tent while camping, this watch face can act as a digital thermometer for displaying ambient conditions.
25 |
26 | The temperature sensor watch face automatically samples the temperature once every five seconds, and it illuminates the Signal indicator just before taking a reading.
27 |
28 | Pressing the Alarm button toggles the unit display from Celsius to Fahrenheit. Technically this sets the global “Metric / Imperial” flag, so any other watch face that displays localizable units will display them in the system selected here.
29 |
30 | Temperature Log
31 | ---------------
32 |
33 | This watch face automatically logs the temperature once an hour, and maintains a 36-hour log of readings. This watch face is admittedly rather complex, and bears some explanation.
34 |
35 | The main display shows the letters “TL” in the top left, indicating the name of the watch face. At the top right, it displays the index of the reading; 0 represents the most recent reading taken, 1 represents one hour earlier, etc. The bottom line in this mode displays the logged temperature.
36 |
37 | A short press of the “Alarm” button advances to the next oldest reading; you will see the number at the top right advance from 0 to 1 to 2, all the way to 35, the oldest reading available.
38 |
39 | A short press of the “Light” button will briefly display the timestamp of the reading. The letters at the top left will display the word "At", and the main line will display the timestamp of the currently displayed data point. The number in the top right will display the day of the month for the given data point; for example, you can read “At 22 3:00 PM” as ”At 3:00 PM on the 22nd”.
40 |
41 | If you need to illuminate the LED to read the data point, long press the Light button and release it.
42 |
43 | Temperature Testing
44 | -------------------
45 |
46 | This watch face is similar to the Temperature watch face, but it updates the temperature several times per second. You likely don't need this watch face, but it is useful for testing the temperature sensor boards.
47 |
48 | LIS2DW Accelerometer Data Logger
49 | --------------------------------
50 |
51 | This is an experimental watch face for logging data on the “Sensor Watch Motion Express” board. I will add more documentation for this watch face once this sensor board is more widely available.
52 |
--------------------------------------------------------------------------------
/src/watchfaces/settings.md:
--------------------------------------------------------------------------------
1 | Settings
2 | ========
3 |
4 | The watch faces in this section relate to watch configuration.
5 |
6 | * [Preferences](#preferences)
7 | * [Time Set](#time-set)
8 |
9 | Preferences
10 | -----------
11 |
12 | The Preferences watch face allows you to configure various options on your Sensor Watch. Like all other screens, you advance the field you’re setting with the Light button, and advance its value with the Alarm button. The Preferences watch face labels each setting with a two-letter code on the top row; the following list describes each setting and their options:
13 |
14 | CL - Clock mode. This setting allows you to select a 12-or 24-hour clock display. All watch faces that support displaying the time will respect this setting; for example, both Simple Clock, World Clock and Sunrise/Sunset will display the time in 24 hour format if the 24 hour clock is selected here.
15 |
16 | BT - Button tone. This setting is only relevant if you installed the buzzer connector, and it toggles the beep when changing modes. If Y, the buzzer will sound a tone when Mode is pressed. Change to N to make the Mode button silent.
17 |
18 | TO - Timeout. Sets the time until screens that time out (like Settings and Time Set) snap back to the first screen. 60 seconds is a good default for the stock firmware, but if you choose a custom firmware with faces that you’d like to keep on screen for longer, you can set that here.
19 |
20 | LE - Low Energy mode. Sets the time until the watch enters its low energy sleep mode. Options range from 1 hour to 7 days, or Never. The more often Sensor Watch goes to sleep, the longer its battery will last — but you will lose the seconds indicator while it is asleep. This setting allows you to make a tradeoff between the device’s responsiveness and its longevity.
21 |
22 | LT - Light. This setting has three screens:
23 |
24 | * The first lets you choose how long the LED should stay lit when the Light button is pressed. Options are 1 second, 3 seconds and 5 seconds, or “No LED” to disable the LED entirely.
25 | * The second screen, titled “blu”, sets the intensity of the blue LED. Values range from 0 (off) to 15 (full intensity)
26 | * The third screen, “red”, sets the intensity of the red LED, again from 0 to 15.
27 | On the last two screens, the LED remains on so that you can see the effect of mixing the two LED colors. On the Special Edition boards, you’ll have red, blue and a variety of shades of pink and purple to experiment with!
28 |
29 |
30 | Time Set
31 | --------
32 |
33 | The Time Set watch face allows you to set the time on Sensor Watch. Use the Light button to advance through the field you are setting, and the Alarm button to change the value in that field. The fields are, in order: Hour, Minute, Second, Year, Month, Day and Time Zone.
34 |
35 | For features like World Clock and Sunrise/Sunset to work correctly, you must set the time to your local time, and the time zone to your local time zone. This allows Sensor Watch to correctly offset the time. This also means that when daylight savings time starts or ends, you must update both the time and the time zone on this screen.
--------------------------------------------------------------------------------
/src/wig/README.md:
--------------------------------------------------------------------------------
1 | Watch Interface Guidelines (WIG)
2 | ================================
3 |
4 | This document outlines best practices for developing watch faces for Movement, the community firmware for the Sensor Watch. While this is a rather specific scope, many of these concepts will be relevant to writing a bare-metal Sensor Watch app as well. After reading this document, you should have a sense for the hardware capabilities and limitations of Sensor Watch, the kinds of applications that are well-suited to the hardware, and the interaction models that tend to make for a rich and usable watch face.
5 |
6 | Before we get to details, there are two major points that underlie every piece of guidance in this document:
7 |
8 | #### Sensor Watch is a watch
9 |
10 | You’ll wear Sensor Watch on your wrist, and you’ll interact with it to answer questions about your day and the world around you. “When does the sun set this evening?” “How late is it in Berlin right now?” “What’s the high tide today?” These are the kinds of questions that Sensor Watch can excel at answering quickly and clearly.
11 |
12 | 
13 |
14 | *Example: a tide prediction app, showing the time of the high tide and its predicted height.*
15 |
16 | Even when you add sensors like a thermometer, light sensor or accelerometer, you should think about how your watch face can answer these kinds of simple questions. “How cold was it last night?” “What shutter speed should I use in this lighting?” “Was I active enough today?”
17 |
18 | Keeping these prompts simple keeps the focus on the things that Sensor Watch can do well, because:
19 |
20 | #### Sensor Watch is not a smart watch
21 |
22 | While Sensor Watch can have sensors added to it to measure things like temperature, light or acceleration, it’s not generally designed to synchronize these measurements to another device like a smart phone; in fact, by default, it has no way of syncing data to or from a device. This makes Sensor Watch less well suited to answering complex questions that require external data or a longer data trail; questions like “Will it rain tomorrow” require data the watch does not have, and questions like “How active was I last month?“ may be too complex to answer on a small watch with only a few buttons.
23 |
24 | There are three key hardware differences between Sensor Watch and a smart watch:
25 |
26 | * Whereas a smart watch has a high-resolution screen capable of displaying arbitrary graphics, Sensor Watch has a segment LCD with a fixed layout.
27 | * Whereas a smart watch generally has a touch screen, Sensor Watch has just three buttons for input: the Light, Mode and Alarm (Wake) buttons.
28 | * Whereas a smart watch has powerful processor and a battery that can be recharged daily, Sensor Watch has a much simpler processor, and a battery that must be discarded and replaced.
29 |
30 | These differences have implications for how a watch face displays content, how the wearer will interact with a watch face, and how the watch face goes about running its logic:
31 |
32 | * You will need to think carefully about how to format the information you want to display and make it work within the constraints of the segment LCD layout.
33 | * You will need to make the most of the limited button inputs, especially since all of these buttons have default functions like changing the mode or illuminating the LED.
34 | * You must take care to ensure that your watch face does not consume too much battery power. In addition, your watch face must be able to work gracefully with Movement’s low energy mode.
35 |
36 | Road Map
37 | --------
38 |
39 | This document is divided into five sections. First, we’ll talk about [the “big picture” stuff](bigpicture.md): some of the concepts you should keep in mind when designing watch faces for Sensor Watch, some of what it does well, and some of what it doesn’t. Next, we’ll have three sections dedicated to each of those three key areas of functionality: the display, the buttons, and the low-power microcontroller. Finally, we’ll bring all of these concepts together to make a very simple watch face that says hello.
40 |
--------------------------------------------------------------------------------
/src/wig/bigpicture.md:
--------------------------------------------------------------------------------
1 | Big Picture Stuff
2 | =================
3 |
4 | The Casio F‑91W, the donor watch on which Sensor Watch is based, is one of Casio’s smallest and simplest wristwatch designs. It is designed to show very basic information: the date and time. As we walk through the device’s hardware capabilities, we can see how it is tailored carefully to that use case:
5 |
6 | * It has a small segment liquid crystal display with ten digits.
7 | * It has a dim backlight on the left side of the display that mostly illuminates the hours and minutes.
8 | * It has a buzzer for firing a single alarm, as well as an hourly alert.
9 | * The three buttons on the watch offer very basic inputs:
10 | * the “Light” button illuminates the watch face,
11 | * the “Mode” button cycles through the four modes that the watch offers,
12 | * and the “Alarm” button is the only truly multi-function button: it turns the alarms on or off when the alarm face is active, and swaps the main 12/24 hour mode when the main clock is active.
13 |
14 | 
15 |
16 | Sensor Watch inherits many of the same hardware limitations of the F‑91W: the screen is small, the layout is designed to display no more than ten characters at a time, and we have only those three buttons to work with (one of which is dedicated to switching modes). This leads to some broad guidelines that will be useful to think about when designing your watch face:
17 |
18 | * Your watch face’s main interface should focus on presenting a single screen of useful information.
19 | * If possible, your most important information should appear on the left side of the screen, since the LED will illuminate the left side more brightly than the right.
20 | * You should feel free to use every character position and every indicator segment to its maximum potential! You have ten characters to work with; use them to the fullest.
21 | * If you have more than one screen of information to display, you should hide it behind a press of either the “Alarm” or “Light” buttons...
22 | * ...because your watch face should be prepared to resign immediately when the wearer presses the “Mode” button. (More on this in the “buttons” section!)
23 |
24 | Let’s look at some of the watch faces that come with Sensor Watch to see how these guidelines are implemented in practice.
25 |
26 | The Temperature Watch Face
27 | --------------------------
28 |
29 | 
30 |
31 | This is the Temperature watch face. It displays the current temperature, as read from a thermistor voltage divider on a Sensor Watch accessory board.
32 |
33 | This watch face is relatively simple. It's dominated by a single large piece of information: the current temperature. The wearer is able to absorb this information quickly and easily. The temperature data itself is left-justified. If the LED only illuminated the first two digits, the wearer would at least know that the temperature is in the range of 68 degrees. The fractional part, while useful, is not essential to a quick read of the conditions.
34 |
35 | Also note that the “signal” indicator segment, used on the main watch face to indicate the status of the hourly beep, is here repurposed to indicate when a new reading is being taken. Don’t be afraid to use these indicators for your own purposes! Whereas the bell indicator might signal that an alarm is enabled on an alarm watch face, you may want to use it to signal an error or warning condition on another face. This is totally fine: the wearer will over time grow familiar with the layout of your watch face, and make the correct associations between icons and concepts.
36 |
37 | The temperature display face is relatively simple; let’s take a look at a more complex watch face.
38 |
39 | The Temperature Log Watch Face
40 | ------------------------------
41 |
42 | 
43 |
44 | This watch face stores a 36-hour log of temperature values, which the wearer can read back to get a sense of high and low temperatures over time. This seems at first glance like it might be a formidable challenge for a watch face with only ten digits, but by thinking carefully about the design, we can fit a lot of information on this small screen.
45 |
46 | Let’s revisit the first guideline. This screen displays a useful, information-dense readout of the most recent temperature logged: the “TL” indicates the mode (Temperature Log), and the “0” at the top right indicates that this is the zeroth (i.e. most recent) reading taken. The whole bottom line is dedicated to a large, clear display of the logged temperature.
47 |
48 | For clarity, it would be nice for this screen to display not just the index of the temperature reading, but also the time that the temperature reading was taken. There isn’t room for that on the display, but by pressing the “Light” button, the wearer can temporarily move the watch face into a mode that displays the timestamp of the reading:
49 |
50 | 
51 |
52 | This mode simply displays the timestamp for a second or so — this reading was taken at 12:00 AM on the 25th day of the month — and then returns the wearer to the temperature reading at that timestamp. This is a simple way to stack two aspects of the data point into one screen. If you had multiple aspects (say, temperature, humidity and timestamp) you might consider using the light button to cycle through those three aspects of the data point.
53 |
54 | This handles the most recent temperature and timestamp. But what about our 36 hour log? The answer there lies in the other button, the “Alarm” button. Pressing the “Alarm” button moves one index back in the list of readings:
55 |
56 | 
57 |
58 | Once again, we’ve managed to fit more information onto the screen by hiding it behind a button press. The index at the top right makes clear that this is data point 1 (not data point 0), and again, pressing the “Light” button on this screen will display the timestamp for this reading: 11:00 PM on the 24th. Repeated presses of the “Alarm” button move the wearer back in time. At any time, the wearer can press the “Light” button to view the timestamp. And of course, the wearer can press “Mode” at any time to move from the temperature log face to the next face in the list.
59 |
60 | Note that while the wearer is likely to develop familiarity with your watch face’s unique visual layout over time, they will likely expect the buttons to behave consistently between watch faces. They will always expect the “Mode” button, for example, to advance the watch face, and for the “Alarm” button to toggle settings or change values. Generally speaking, you should use the “Alarm” button to move through time or advance a value, and use the “Light” button to move between sub-modes within the watch face (and illuminate the LED, as appropriate). The “Time Set” watch face, for example, uses the “Light” button to move between setting the hour, minute and second, and uses the Alarm button to change the value in each field.
61 |
62 | Wrapping Up
63 | -----------
64 |
65 | When designing watch face visuals for the Sensor Watch, you should aim to present one screen of content with clarity:
66 |
67 | * Don’t shy from information density; use as many digits and indicators as you need.
68 | * Try to fit more crucial information on the left side of the screen, and put less pressing information on the right.
69 | * Don’t worry about how segments or digits are used on other watch faces; when your watch face is on screen, you are in control.
70 |
71 | When designing interactions for the Sensor Watch, you should aim for consistency with other watch faces:
72 |
73 | * Your watch face should resign immediately when the “Mode” button is pressed and pass control to the next watch face in the list.
74 | * If your watch face has multiple modes, you should use the “Light” button to toggle or advance through them.
75 | * If your watch face presents multiple data points or advances through multiple values, you should use the “Alarm” button to advance through those.
76 |
--------------------------------------------------------------------------------
/src/wig/display.md:
--------------------------------------------------------------------------------
1 | The Sensor Watch Display
2 | ========================
3 |
4 | Before we talk about the Sensor Watch display, let’s go through some key terminology to clarify our discussion:
5 |
6 | * Segment - A single addressable element on the liquid crystal display
7 | * Indicator - A segment like “PM”, “24H” or the bell icon that indicates status
8 | * Digit - A grouping of segments that can display a number, character or glyph
9 | * Position - The placement of a digit on the display; for example, the first digit at the left of the top row is Position 0
10 |
11 | We also tend to label the segments of each digit clockwise from the top segment: the top segment is segment A, top right is B, bottom right is C, all the way to the center digit which is segment G:
12 |
13 | 
14 |
15 | In this image of a clock, you can see where the 8 has all segments (A-G) energized. You can display a 1 by energizing only segments B and C, and a 2 by energizing segments A, B, D, E and G.
16 |
17 | The Sensor Watch has five indicators, ten digits, and one segment dedicated to the colon in the time display. We choose to number the digits as follows:
18 |
19 | * Positions 0-1 - The digits in the top middle, usually used to display the current mode or the weekday. We can call these the “Weekday” digits.
20 | * Positions 2-3 - The digits at the top right, usually used to display the day of the month. The “Day” digits.
21 | * Positions 4-9 - The digits on the bottom row, usually used to display the time; the “Clock” digits.
22 | * Positions 4-5 are normally the hours display.
23 | * Positions 6-7 are normally the minutes display.
24 | * Positions 8-9 are normally the seconds display, and are slightly smaller than the other digits on the bottom row.
25 |
26 | 
27 |
28 | As alluded to in the “Big Picture” section, this document is not going to be prescriptive about how you use the digits in these positions; there is no “must” about how you display information on your watch face. Still, there are some broad guidelines on where these digits can be most useful:
29 |
30 | * The “Weekday” digits are particularly useful for displaying alphanumeric information.
31 | * The “Day” digits are best for displaying a single number from 0-39, such as a day, an index or a countdown.
32 | * The “Clock” digits are well suited for the main informational display of your watch face.
33 |
34 | You are going to need flexibility to adapt the information you want to display to the Sensor Watch LCD. This section is merely going to walk through some useful patterns, some limitations, and some best practices.
35 |
36 | The Weekday Digits
37 | ------------------
38 |
39 | The digits in these first two positions, positions 0 and 1, have some extra segments that make them useful for displaying letters. The stock F‑91W uses these positions to display the day of the week (SU, MO, TU, etc). If you have some alphanumeric information to relay on your watch face, it would make sense to look to these first; the tide prediction concept in the previous section, for example, imagined labeling the displayed prediction with “HT” for high tide and “LT” for low tide.
40 |
41 | If you have no data to put in these segments, they can also serve as a useful spot to title your watch face, so that the wearer is clear what information they are looking at. The “Temperature” watch face, for example, uses these digits to display “TE”. This distinguishes it from the “Temperature Log” watch face, which titles itself “TL”.
42 |
43 | Note that you are not limited to keeping the same characters in this position the whole time your watch face is on screen! The “Temperature Log” watch face displays “TL” most of the time, but when the wearer enters timestamp mode, it displays the word “AT” in these positions, signaling that the data point was logged “at” the displayed time and date.
44 |
45 | 
46 |
47 | Consider: when the wearer presses the “Mode” button and sees the watch face for the first time, “TL” tells them which watch face they are viewing. Once they have that information, they know they will remain in this watch face until they press “Mode” again, so you can feel free to change it after a short delay or in response to a button press. It’s done its job, and given the wearer the context they need to use the watch in the current mode.
48 |
49 | Of course, you could use these segments in a completely different way. The LIS2DH accelerometer test face (which we’ll look at a bit later) uses these two positions to indicate the presence of an interrupt on the X or Y axes, lighting up “Y” and/or “X” when an interrupt is asserted, and remaining blank otherwise.
50 |
51 | ### Limitations of the Weekday Digits
52 |
53 | On a stock Casio F‑91W, the digits in these two positions normally display one of just nine values: abbreviations for the seven days of the week, the text “AL” for alarm mode, or the text “ST” for stopwatch mode. If you break this down, position 0 will only ever display one of the characters A, F, M, S, T or W, and position 1 will only display the letters A, E, H, L, O, R, T, or U. The Sensor Watch aims to display many more characters in these positions, and in the case of position 0, we can do it! With the exception of an uppercase R, the digit in position 0 can display any character in the Sensor Watch character set.
54 |
55 | 
56 |
57 | Position 1 is a bit more trouble. Looking closely at the position 1 letters above, you’ll notice that segments B/C and E/F never have to operate independently (as they would to, say, display the letter S or the number 2). Thus, to save pins on the LCD, the designers of the F‑91W tied these two pairs of segments together. This means you can only display a limited set of characters in position 1: the letters A, B, C, D, E, F, H, I, J, L, N, O, R, T, U and X, and the numbers 0, 1, 3, 7 and 8.
58 |
59 | All of this is to say that you may need to think about terminology that makes sense for your watch face, and tweak it to fit the constraints. For example, the “Settings” watch face requires changing a setting related to Movement’s low power mode, but the ‘P’ in “LP” cannot be displayed in position 1. To address this limitation, the setting is instead called “Low Energy” mode, which abbreviates to “LE”.
60 |
61 | The theme of limitations will come up in each of these groups.
62 |
63 | The Day Digits
64 | --------------
65 |
66 | On a stock Casio F‑91W, these two digits normally display the day of the month. This makes this position very useful for displaying values from 0-39:
67 |
68 | * The Clock and World Clock face use this area to display the day of the month.
69 | * The TOTP watch face uses this area for a 30-second countdown, indicating the validity window for the displayed code
70 | * The Temperature Log uses this area to display the index of the logged measurement, from 0 to 35
71 |
72 | 
73 |
74 | ### Limitations of the Day digits
75 |
76 | While the digit in position 3 is a full-featured 7-segment display that can display any number and just about any letter, the digit in position 2 is the most limited digit on the watch: it can only display the numbers 1, 2 and 3. This constraint relates to the fact that it is missing one segment (segment F), and that segments A, D and G are all tied together.
77 |
78 | 
79 |
80 | There’s not much to say about these digits because they are pretty limited: if you have a single letter or a number from 0-39, you can display it here. If not, you can leave these digits blank.
81 |
82 | The Clock Digits
83 | ----------------
84 |
85 | The bottom row of digits, positions 4-9, comprise the clock display on a stock F‑91W. This is the main event: you can display a ton of information here. But before we look at some of the ways we might want to use this display, let’s take a look at some of the subtler properties of these digits:
86 |
87 | 
88 |
89 | * First, note that the digits in positions 8-9, the seconds, are slightly smaller than the rest. This makes it obvious even without a colon that they are the seconds on a clock.
90 | * Next, note the way that the colon separates positions 5 and 6 in the display on the left. This clarifies the separation of the hours and the minutes on the clock.
91 | * Now look at the display on the right, where the colon is turned off. Note that in the absence of a colon, these digits are not evenly spaced: there is a gap between them.
92 |
93 | 
94 |
95 | These details are useful to keep in mind as you think about the data you want to display, as these subtleties lend themselves to some non-obvious strategies. For example:
96 |
97 | * Consider how the visual weighting of the seconds digits could make them useful for displaying the decimal part of a floating point number, as shown in the display on the left (87.2°).
98 | * Also on the left: consider how the colon might be useful both as a separator in a clock display, and as a punctuation mark separating two concepts, like the high temperature label and the measured temperature.
99 | * Consider how the spacing of these digits might let you treat this line not as one six-digit display, but as three distinct two-digit displays. For example: 10, 20 and 30 could represent three separate data points in the display in the middle.
100 | * Also consider how the wearer’s eye would read across the display if a full word were placed there, as in the display on the right. Do your eyes notice the gap, or does the word “Sunset” read legibly?
101 |
102 | You saw this guideline before in the “Big Picture” section, but it bears repeating: over time, the wearer will become familiar with the layout of your watch face, so don’t be afraid to use these digits in an unorthodox way.
103 |
104 | ### Limitations of the Clock digits
105 |
106 | As you might have expected, there are some limitations to the clock digits. The first limitation applies to all of them: these are 7-segment displays meant to display numbers, not letters. As such, characters like ‘M’ and ‘W’ are not available; they will render as an ‘N’ or a ‘U’ respectively. Additionally, some letters aren’t available in their preferred case; uppercase ‘R’, for example, will appear as a lowercase ‘r’. Finally, some of these characters may look a bit awkward. ‘K’, for example, requires a little bit of imagination, and ‘X’ requires a lot of imagination; the screens below are meant to display the words “Ranked” and “PIXEL”:
107 |
108 | 
109 |
110 | The second limitation has to do specifically with digits 4 and 6: the top and bottom segments of these digits (segments A and D) are tied together:
111 |
112 | 
113 |
114 | The Sensor Watch display library will try to work around this limitation in some cases. For example, some letters may have their case changed: in displaying the word “Apogee” below, the Sensor Watch will render the “a” in lowercase and the ‘O’ in uppercase — “apOgee” — to work around the constraints on positions 4 and 6. This is because position 4 cannot turn off segment D without also turning off segment A, as would be required for an uppercase ‘A’, and position 6 cannot turn on segment D without also turning on segment A, as would be required for a lowercase ‘o’.
115 |
116 | 
117 |
118 | Other characters may take on slightly different forms in these positions: for example, a 7 in position 4 or 6 will render as a short “lowercase” 7, and characters that require a segment on the top or bottom may be shifted up or down to make the best use of the position.
119 |
120 | 
121 |
122 | With some extra care, you can sometimes dodge this limitation. In the two screens above, for example, you can see that displaying the name of this popular soft drink in positions 4-7 results in a lowercase 7, and a U that’s shifted up to the top half of the digit. But by shifting it over to positions 5-8, both the 7 and the U get displayed normally.
123 |
124 | 
125 |
126 | Note however that in some cases, you cannot dodge this limitation. Letters that can only be displayed by energizing segments A and D independently will not display correctly. In the above example, the lowercase ‘t’ in ‘Hi tide’ will not work in position 4 or 6. It will display as an uppercase E, “Hi Eide”, because segment D also controls the state of segment A. You will have to figure out another way to convey this concept, either by shifting the ‘t’ to a position that can display it, or re-imagining the way the information is presented to the wearer.
127 |
128 | Regardless of case, the following characters are fully unsupported in positions 4 and 6: F, K, P, Q, T, X and Y, as well as the underscore and a few other punctuation marks. In addition, the decimal point appears as a hyphen; this may lead to confusion when displaying negative numbers, so you may have to work around this as well.
129 |
130 | The Indicator Segments
131 | ----------------------
132 |
133 | In addition to the three major segmented display areas, the watch has five indicator segments: “Signal”, “Bell”, “PM”, “24H” and “LAP”. You can energize these indicator segments to convey information or status to the user. In the stock F‑91W, these have some fairly obvious uses: Signal and Bell indicate whether the hourly signal and alarm are active, and PM and 24H relate to the clock display. “LAP” only operates in stopwatch mode, where it indicates when the stopwatch is showing a lap time. Still, when looking at these indicators, you should consider what concepts people might have associated with these icons.
134 |
135 | 
136 |
137 | The “Signal” indicator takes the form of a series of bars moving from thick to thin. It does convey the sound waves of an hourly indicator, but consider other possible meanings: they could represent radio waves, sensor activity or the reading of data from an accessory board. The Temperature watch face, for example, energizes this segment to indicate that a new reading is being taken from the thermistor.
138 |
139 | The “Bell” conveys the concept of an alarm bell, but consider alternate meanings like the presence of a notification or a warning condition. For example, a tide prediction face could energize this segment when high tide is very near — an important thing to know if you are walking along a remote stretch of beach!
140 |
141 | The PM indicator has the narrowest use case: if you are displaying a time value that is in the afternoon, you should activate this segment. This guidance also applies to the 24H indicator. Also note that Movement has a global setting that will tell you whether the user has selected 24H mode; you should respect this whenever displaying time values.
142 |
143 | Finally, the LAP indicator. This indicator has a very specific meaning for a stopwatch face, and almost no meaning anywhere else. The Stopwatch face uses this segment for its expected use case, but beyond that, it’s not a great semantic fit for most others. Having said that, if you need to indicate a rare warning or error condition, and none of the other indicators are a good fit, the LAP indicator might make sense. For example, the Simple Clock face energizes this segment when a low power condition is detected. It’s awkward, but it works.
144 |
145 | Putting It All Together
146 | -----------------------
147 |
148 | While the previous sections outlined how each of these bits of the display worked on their own, the fact is, you will mix and match these strategies. We’ve seen how the Temperature and Temperature Log watch faces use the Weekday digits to display their name (TE, TL) and a data point. But a Sunrise/Sunset face could use those characters to display something about the data point: that this is a sunSEt at 5:42 PM on the 5th, and a sunRIse at 6:24 AM on the 6th:
149 |
150 | 
151 |
152 | The accelerometer test face uses all of these areas in a radically different way. It uses the top row to indicate the presence of a Y, X or Z interrupt, and a single digit in the top right to count the last ten seconds to the logging of the next data point. The bottom line counts interrupts per minute, and displays the most recent three minutes’ counts in three two-digit groups on the clock line:
153 |
154 | 
155 |
156 | There’s also nothing that says you have to use these displays for digits at all. Here we imagine using the 12 vertical bars in the clock display to show an activity log over the last 12 hours, where the presence of a short bar indicates some activity in that hour, and a tall bar indicates more. You can imagine toggling this watch face between different timeframes, which could be displayed in the top right: 6/12/24, or 1d/2d/3d.
157 |
158 | 
159 |
160 | Final Notes
161 | -----------
162 |
163 | The Sensor Watch display is both powerful and limited: we can push it to do things that a stock F‑91W couldn’t dream of, but it also inherits some of the limitations inherent to the donor watch. Still, armed with these guidelines, you should feel empowered to build useful and information-rich watch faces. The important things to remember:
164 |
165 | * Keep in mind how the segments are grouped, and think about how you can make the information you want to display fit into those groups.
166 | * Be mindful of the limitations of various digits and groups, and prepare to be flexible when naming things or laying out text.
167 | * Don’t be afraid of information-dense displays or unorthodox uses of the LCD. The wearer using your watch face will develop a mental model for the information you’re presenting to them.
168 | * Use indicators to signal various conditions, and keep in mind creative ways of using them to convey meaning to the wearer.
169 |
--------------------------------------------------------------------------------
/src/wig/images/accelerometer-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/accelerometer-example.png
--------------------------------------------------------------------------------
/src/wig/images/activity-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/activity-example.png
--------------------------------------------------------------------------------
/src/wig/images/casio-basics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/casio-basics.png
--------------------------------------------------------------------------------
/src/wig/images/clock-7-up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-7-up.png
--------------------------------------------------------------------------------
/src/wig/images/clock-apogee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-apogee.png
--------------------------------------------------------------------------------
/src/wig/images/clock-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-example.png
--------------------------------------------------------------------------------
/src/wig/images/clock-high-tide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-high-tide.png
--------------------------------------------------------------------------------
/src/wig/images/clock-ranked-pixel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-ranked-pixel.png
--------------------------------------------------------------------------------
/src/wig/images/clock-shared-segments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-shared-segments.png
--------------------------------------------------------------------------------
/src/wig/images/clock-with-without-colon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/clock-with-without-colon.png
--------------------------------------------------------------------------------
/src/wig/images/day-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/day-example.png
--------------------------------------------------------------------------------
/src/wig/images/day-shared-segments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/day-shared-segments.png
--------------------------------------------------------------------------------
/src/wig/images/indicators.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/indicators.png
--------------------------------------------------------------------------------
/src/wig/images/positions-labeled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/positions-labeled.png
--------------------------------------------------------------------------------
/src/wig/images/segments-labeled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/segments-labeled.png
--------------------------------------------------------------------------------
/src/wig/images/sunrise-sunset-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/sunrise-sunset-example.png
--------------------------------------------------------------------------------
/src/wig/images/temperature-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/temperature-app.png
--------------------------------------------------------------------------------
/src/wig/images/temperature-log-app-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/temperature-log-app-1.png
--------------------------------------------------------------------------------
/src/wig/images/temperature-log-app-timestamp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/temperature-log-app-timestamp.png
--------------------------------------------------------------------------------
/src/wig/images/temperature-log-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/temperature-log-app.png
--------------------------------------------------------------------------------
/src/wig/images/tide-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/tide-app.png
--------------------------------------------------------------------------------
/src/wig/images/weekday-shared-segments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joeycastillo/Sensor-Watch-Documentation/d4bc8b0995a4decd9c8b868988263e356b8d1fdf/src/wig/images/weekday-shared-segments.png
--------------------------------------------------------------------------------